New upstream snapshot.
Debian Janitor
2 years ago
0 | # Makefile.in generated by automake 1.16.1 from Makefile.am. | |
0 | # Makefile.in generated by automake 1.16.4 from Makefile.am. | |
1 | 1 | # @configure_input@ |
2 | 2 | |
3 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. | |
3 | # Copyright (C) 1994-2021 Free Software Foundation, Inc. | |
4 | 4 | |
5 | 5 | # This Makefile.in is free software; the Free Software Foundation |
6 | 6 | # gives unlimited permission to copy and/or distribute it, |
167 | 167 | $(am__extra_recursive_targets) |
168 | 168 | AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ |
169 | 169 | cscope distdir distdir-am dist dist-all distcheck |
170 | am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ | |
171 | $(LISP)config.h.in | |
170 | am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ | |
171 | config.h.in | |
172 | 172 | # Read a list of newline-separated strings from the standard input, |
173 | 173 | # and print each of them once, without duplicates. Input order is |
174 | 174 | # *not* preserved. |
185 | 185 | unique=`for i in $$list; do \ |
186 | 186 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
187 | 187 | done | $(am__uniquify_input)` |
188 | ETAGS = etags | |
189 | CTAGS = ctags | |
190 | CSCOPE = cscope | |
191 | 188 | DIST_SUBDIRS = libass test compare profile |
192 | 189 | am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ |
193 | $(srcdir)/libass.pc.in COPYING compile config.guess config.sub \ | |
194 | install-sh ltmain.sh missing | |
190 | $(srcdir)/libass.pc.in COPYING README.md compile config.guess \ | |
191 | config.sub install-sh ltmain.sh missing | |
195 | 192 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
196 | 193 | distdir = $(PACKAGE)-$(VERSION) |
197 | 194 | top_distdir = $(distdir) |
230 | 227 | DIST_ARCHIVES = $(distdir).tar.gz |
231 | 228 | GZIP_ENV = --best |
232 | 229 | DIST_TARGETS = dist-gzip |
230 | # Exists only to be overridden by the user if desired. | |
231 | AM_DISTCHECK_DVI_TARGET = dvi | |
233 | 232 | distuninstallcheck_listfiles = find . -type f -print |
234 | 233 | am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ |
235 | 234 | | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' |
249 | 248 | CFLAGS = @CFLAGS@ |
250 | 249 | CPP = @CPP@ |
251 | 250 | CPPFLAGS = @CPPFLAGS@ |
251 | CSCOPE = @CSCOPE@ | |
252 | CTAGS = @CTAGS@ | |
252 | 253 | CYGPATH_W = @CYGPATH_W@ |
253 | 254 | DEFS = @DEFS@ |
254 | 255 | DEPDIR = @DEPDIR@ |
259 | 260 | ECHO_N = @ECHO_N@ |
260 | 261 | ECHO_T = @ECHO_T@ |
261 | 262 | EGREP = @EGREP@ |
263 | ETAGS = @ETAGS@ | |
262 | 264 | EXEEXT = @EXEEXT@ |
263 | 265 | FGREP = @FGREP@ |
264 | 266 | FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ |
360 | 362 | prefix = @prefix@ |
361 | 363 | program_transform_name = @program_transform_name@ |
362 | 364 | psdir = @psdir@ |
365 | runstatedir = @runstatedir@ | |
363 | 366 | sbindir = @sbindir@ |
364 | 367 | sharedstatedir = @sharedstatedir@ |
365 | 368 | srcdir = @srcdir@ |
566 | 569 | distclean-tags: |
567 | 570 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
568 | 571 | -rm -f cscope.out cscope.in.out cscope.po.out cscope.files |
569 | ||
570 | 572 | distdir: $(BUILT_SOURCES) |
571 | 573 | $(MAKE) $(AM_MAKEFLAGS) distdir-am |
572 | 574 | |
650 | 652 | tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz |
651 | 653 | $(am__post_remove_distdir) |
652 | 654 | |
655 | dist-zstd: distdir | |
656 | tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst | |
657 | $(am__post_remove_distdir) | |
658 | ||
653 | 659 | dist-tarZ: distdir |
654 | 660 | @echo WARNING: "Support for distribution archives compressed with" \ |
655 | 661 | "legacy program 'compress' is deprecated." >&2 |
692 | 698 | eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ |
693 | 699 | *.zip*) \ |
694 | 700 | unzip $(distdir).zip ;;\ |
701 | *.tar.zst*) \ | |
702 | zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ | |
695 | 703 | esac |
696 | 704 | chmod -R a-w $(distdir) |
697 | 705 | chmod u+w $(distdir) |
707 | 715 | $(DISTCHECK_CONFIGURE_FLAGS) \ |
708 | 716 | --srcdir=../.. --prefix="$$dc_install_base" \ |
709 | 717 | && $(MAKE) $(AM_MAKEFLAGS) \ |
710 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ | |
718 | && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ | |
711 | 719 | && $(MAKE) $(AM_MAKEFLAGS) check \ |
712 | 720 | && $(MAKE) $(AM_MAKEFLAGS) install \ |
713 | 721 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ |
872 | 880 | am--refresh check check-am clean clean-cscope clean-generic \ |
873 | 881 | clean-libtool cscope cscopelist-am ctags ctags-am dist \ |
874 | 882 | dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ |
875 | dist-xz dist-zip distcheck distclean distclean-generic \ | |
876 | distclean-hdr distclean-libtool distclean-tags distcleancheck \ | |
877 | distdir distuninstallcheck dvi dvi-am html html-am info \ | |
878 | info-am install install-am install-data install-data-am \ | |
879 | install-dvi install-dvi-am install-exec install-exec-am \ | |
880 | install-html install-html-am install-info install-info-am \ | |
881 | install-man install-pdf install-pdf-am install-pkgconfigDATA \ | |
882 | install-ps install-ps-am install-strip installcheck \ | |
883 | installcheck-am installdirs installdirs-am maintainer-clean \ | |
884 | maintainer-clean-generic mostlyclean mostlyclean-generic \ | |
885 | mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ | |
886 | uninstall-am uninstall-pkgconfigDATA | |
883 | dist-xz dist-zip dist-zstd distcheck distclean \ | |
884 | distclean-generic distclean-hdr distclean-libtool \ | |
885 | distclean-tags distcleancheck distdir distuninstallcheck dvi \ | |
886 | dvi-am html html-am info info-am install install-am \ | |
887 | install-data install-data-am install-dvi install-dvi-am \ | |
888 | install-exec install-exec-am install-html install-html-am \ | |
889 | install-info install-info-am install-man install-pdf \ | |
890 | install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ | |
891 | install-strip installcheck installcheck-am installdirs \ | |
892 | installdirs-am maintainer-clean maintainer-clean-generic \ | |
893 | mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ | |
894 | ps ps-am tags tags-am uninstall uninstall-am \ | |
895 | uninstall-pkgconfigDATA | |
887 | 896 | |
888 | 897 | .PRECIOUS: Makefile |
889 | 898 |
0 | [![Build status](https://github.com/libass/libass/actions/workflows/ghci.yml/badge.svg?branch=master&event=push)](https://github.com/libass/libass/actions/workflows/ghci.yml?query=branch%3Amaster+event%3Apush) | |
1 | ||
2 | [![Coverity scan build status](https://scan.coverity.com/projects/3531/badge.svg)](https://scan.coverity.com/projects/3531) | |
3 | ||
4 | libass | |
5 | ====== | |
6 | libass is a portable subtitle renderer for the ASS/SSA (Advanced Substation Alpha/Substation Alpha) subtitle format. It is mostly compatible with VSFilter. | |
7 | ||
8 | Get it | |
9 | ====== | |
10 | See [GitHub releases](https://github.com/libass/libass/releases) for the latest release 0.15.1 (released 2021-05-01). This is a bug fix release. See the [changelog](https://github.com/libass/libass/blob/master/Changelog) for a detailed list of changes. | |
11 | ||
12 | Source code is available from our [GitHub repository](https://github.com/libass/libass). | |
13 | ||
14 | Contact | |
15 | ======= | |
16 | Please use the [issue tracker](https://github.com/libass/libass/issues?state=open) to report bugs or feature requests. We have an IRC channel, too. Talk to us on [irc.libera.chat/#libass](irc://irc.libera.chat/libass). | |
17 | ||
18 | Related Links | |
19 | ============= | |
20 | The following projects/companies use libass: | |
21 | ||
22 | - [MPlayer](http://www.mplayerhq.hu/) | |
23 | - [mplayer2](http://www.mplayer2.org/) | |
24 | - [mpv](http://mpv.io/) | |
25 | - [VLC](http://www.videolan.org/) | |
26 | - [GStreamer](http://gstreamer.freedesktop.org/) (assrender plugin) | |
27 | - [FFmpeg](http://ffmpeg.org/) | |
28 | - [Libav](http://libav.org/) (unmaintained) | |
29 | - [Aegisub](http://www.aegisub.org/) | |
30 | - [Kodi (XBMC)](http://kodi.tv/) | |
31 | - [avidemux](http://fixounet.free.fr/avidemux/) | |
32 | - [PunkGraphicsStream (BD subtitle encoder)](http://code.google.com/p/punkgraphicstream/) | |
33 | - [HandBrake](http://handbrake.fr/) | |
34 | - [MX Player](https://play.google.com/store/apps/details?id=com.mxtech.videoplayer.ad) | |
35 | - [QMPlay2](http://zaps166.sourceforge.net/?app=QMPlay2) | |
36 | - [SubtitlesOctopus](https://github.com/libass/JavascriptSubtitlesOctopus) (JavaScript ASS via wasm libass) | |
37 | - [Crunchyroll](http://www.crunchyroll.com/) uses SubtitlesOctopus | |
38 | - [AssRender for Avisynth(+)](http://avisynth.nl/index.php/AssRender) | |
39 | ||
40 | Information about the ASS format: | |
41 | ================================= | |
42 | - [ASS specification (incomplete)](http://moodub.free.fr/video/ass-specs.doc) | |
43 | - [ASS override tags (Aegisub manual)](http://docs.aegisub.org/latest/ASS_Tags/) | |
44 | - [VSFilter source code (Guliverkli2)](http://sourceforge.net/p/guliverkli2/code/HEAD/tree/src/subtitles/) | |
45 | ||
46 | Other ASS/SSA implementations: | |
47 | ============================== | |
48 | - VSFilter: | |
49 | - [xy-VSFilter/XySubFilter](https://github.com/Cyberbeing/xy-VSFilter/) | |
50 | - [pfmod](https://github.com/pinterf/xy-VSFilter/) | |
51 | - VSFilter in [MPC-HC](https://github.com/clsid2/mpc-hc/tree/develop/src/filters/transform/VSFilter/) | |
52 | - [VSFilterMod](https://code.google.com/archive/p/vsfiltermod/) (with custom format extensions) | |
53 | - [sorayuki fork](https://github.com/sorayuki/VSFilterMod/) with some bugfixes | |
54 | - [Threaded VSFilter](https://code.google.com/p/threaded-vsfilter/) (defunct) | |
55 | - VSFilter in [Guliverkli2](http://sourceforge.net/projects/guliverkli2/) (defunct, subsumed by all of the above) | |
56 | - VSFilter in [guliverkli](http://sourceforge.net/projects/guliverkli/) (defunct, forked as Guliverkli2) | |
57 | - [ffdshow](http://ffdshow-tryout.sourceforge.net/) (defunct) | |
58 | - [Perian](https://github.com/MaddTheSane/perian) (defunct) | |
59 | - [asa](http://git.spaceboyz.net/asa.git) (defunct) | |
60 | - [libjass](https://github.com/Arnavion/libjass) (defunct) | |
61 | - [ASS.js](https://github.com/weizhenye/ASS) |
0 | # generated automatically by aclocal 1.16.1 -*- Autoconf -*- | |
1 | ||
2 | # Copyright (C) 1996-2018 Free Software Foundation, Inc. | |
0 | # generated automatically by aclocal 1.16.4 -*- Autoconf -*- | |
1 | ||
2 | # Copyright (C) 1996-2021 Free Software Foundation, Inc. | |
3 | 3 | |
4 | 4 | # This file is free software; the Free Software Foundation |
5 | 5 | # gives unlimited permission to copy and/or distribute it, |
295 | 295 | AS_VAR_IF([$1], [""], [$5], [$4])dnl |
296 | 296 | ])dnl PKG_CHECK_VAR |
297 | 297 | |
298 | # Copyright (C) 2002-2018 Free Software Foundation, Inc. | |
298 | # Copyright (C) 2002-2021 Free Software Foundation, Inc. | |
299 | 299 | # |
300 | 300 | # This file is free software; the Free Software Foundation |
301 | 301 | # gives unlimited permission to copy and/or distribute it, |
310 | 310 | [am__api_version='1.16' |
311 | 311 | dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to |
312 | 312 | dnl require some minimum version. Point them to the right macro. |
313 | m4_if([$1], [1.16.1], [], | |
313 | m4_if([$1], [1.16.4], [], | |
314 | 314 | [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl |
315 | 315 | ]) |
316 | 316 | |
326 | 326 | # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. |
327 | 327 | # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. |
328 | 328 | AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], |
329 | [AM_AUTOMAKE_VERSION([1.16.1])dnl | |
329 | [AM_AUTOMAKE_VERSION([1.16.4])dnl | |
330 | 330 | m4_ifndef([AC_AUTOCONF_VERSION], |
331 | 331 | [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl |
332 | 332 | _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) |
333 | 333 | |
334 | 334 | # AM_AUX_DIR_EXPAND -*- Autoconf -*- |
335 | 335 | |
336 | # Copyright (C) 2001-2018 Free Software Foundation, Inc. | |
336 | # Copyright (C) 2001-2021 Free Software Foundation, Inc. | |
337 | 337 | # |
338 | 338 | # This file is free software; the Free Software Foundation |
339 | 339 | # gives unlimited permission to copy and/or distribute it, |
385 | 385 | |
386 | 386 | # AM_COND_IF -*- Autoconf -*- |
387 | 387 | |
388 | # Copyright (C) 2008-2018 Free Software Foundation, Inc. | |
388 | # Copyright (C) 2008-2021 Free Software Foundation, Inc. | |
389 | 389 | # |
390 | 390 | # This file is free software; the Free Software Foundation |
391 | 391 | # gives unlimited permission to copy and/or distribute it, |
422 | 422 | |
423 | 423 | # AM_CONDITIONAL -*- Autoconf -*- |
424 | 424 | |
425 | # Copyright (C) 1997-2018 Free Software Foundation, Inc. | |
425 | # Copyright (C) 1997-2021 Free Software Foundation, Inc. | |
426 | 426 | # |
427 | 427 | # This file is free software; the Free Software Foundation |
428 | 428 | # gives unlimited permission to copy and/or distribute it, |
453 | 453 | Usually this means the macro was only invoked conditionally.]]) |
454 | 454 | fi])]) |
455 | 455 | |
456 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. | |
456 | # Copyright (C) 1999-2021 Free Software Foundation, Inc. | |
457 | 457 | # |
458 | 458 | # This file is free software; the Free Software Foundation |
459 | 459 | # gives unlimited permission to copy and/or distribute it, |
644 | 644 | |
645 | 645 | # Generate code to set up dependency tracking. -*- Autoconf -*- |
646 | 646 | |
647 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. | |
647 | # Copyright (C) 1999-2021 Free Software Foundation, Inc. | |
648 | 648 | # |
649 | 649 | # This file is free software; the Free Software Foundation |
650 | 650 | # gives unlimited permission to copy and/or distribute it, |
683 | 683 | done |
684 | 684 | if test $am_rc -ne 0; then |
685 | 685 | AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments |
686 | for automatic dependency tracking. Try re-running configure with the | |
686 | for automatic dependency tracking. If GNU make was not used, consider | |
687 | re-running the configure script with MAKE="gmake" (or whatever is | |
688 | necessary). You can also try re-running configure with the | |
687 | 689 | '--disable-dependency-tracking' option to at least be able to build |
688 | 690 | the package (albeit without support for automatic dependency tracking).]) |
689 | 691 | fi |
710 | 712 | |
711 | 713 | # Do all the work for Automake. -*- Autoconf -*- |
712 | 714 | |
713 | # Copyright (C) 1996-2018 Free Software Foundation, Inc. | |
715 | # Copyright (C) 1996-2021 Free Software Foundation, Inc. | |
714 | 716 | # |
715 | 717 | # This file is free software; the Free Software Foundation |
716 | 718 | # gives unlimited permission to copy and/or distribute it, |
774 | 776 | [_AM_SET_OPTIONS([$1])dnl |
775 | 777 | dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. |
776 | 778 | m4_if( |
777 | m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), | |
779 | m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), | |
778 | 780 | [ok:ok],, |
779 | 781 | [m4_fatal([AC_INIT should be called with package and version arguments])])dnl |
780 | 782 | AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl |
826 | 828 | [m4_define([AC_PROG_OBJCXX], |
827 | 829 | m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl |
828 | 830 | ]) |
831 | # Variables for tags utilities; see am/tags.am | |
832 | if test -z "$CTAGS"; then | |
833 | CTAGS=ctags | |
834 | fi | |
835 | AC_SUBST([CTAGS]) | |
836 | if test -z "$ETAGS"; then | |
837 | ETAGS=etags | |
838 | fi | |
839 | AC_SUBST([ETAGS]) | |
840 | if test -z "$CSCOPE"; then | |
841 | CSCOPE=cscope | |
842 | fi | |
843 | AC_SUBST([CSCOPE]) | |
844 | ||
829 | 845 | AC_REQUIRE([AM_SILENT_RULES])dnl |
830 | 846 | dnl The testsuite driver may need to know about EXEEXT, so add the |
831 | 847 | dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This |
907 | 923 | done |
908 | 924 | echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) |
909 | 925 | |
910 | # Copyright (C) 2001-2018 Free Software Foundation, Inc. | |
926 | # Copyright (C) 2001-2021 Free Software Foundation, Inc. | |
911 | 927 | # |
912 | 928 | # This file is free software; the Free Software Foundation |
913 | 929 | # gives unlimited permission to copy and/or distribute it, |
928 | 944 | fi |
929 | 945 | AC_SUBST([install_sh])]) |
930 | 946 | |
931 | # Copyright (C) 2003-2018 Free Software Foundation, Inc. | |
947 | # Copyright (C) 2003-2021 Free Software Foundation, Inc. | |
932 | 948 | # |
933 | 949 | # This file is free software; the Free Software Foundation |
934 | 950 | # gives unlimited permission to copy and/or distribute it, |
949 | 965 | |
950 | 966 | # Check to see how 'make' treats includes. -*- Autoconf -*- |
951 | 967 | |
952 | # Copyright (C) 2001-2018 Free Software Foundation, Inc. | |
968 | # Copyright (C) 2001-2021 Free Software Foundation, Inc. | |
953 | 969 | # |
954 | 970 | # This file is free software; the Free Software Foundation |
955 | 971 | # gives unlimited permission to copy and/or distribute it, |
992 | 1008 | |
993 | 1009 | # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- |
994 | 1010 | |
995 | # Copyright (C) 1997-2018 Free Software Foundation, Inc. | |
1011 | # Copyright (C) 1997-2021 Free Software Foundation, Inc. | |
996 | 1012 | # |
997 | 1013 | # This file is free software; the Free Software Foundation |
998 | 1014 | # gives unlimited permission to copy and/or distribute it, |
1013 | 1029 | [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl |
1014 | 1030 | AC_REQUIRE_AUX_FILE([missing])dnl |
1015 | 1031 | if test x"${MISSING+set}" != xset; then |
1016 | case $am_aux_dir in | |
1017 | *\ * | *\ *) | |
1018 | MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; | |
1019 | *) | |
1020 | MISSING="\${SHELL} $am_aux_dir/missing" ;; | |
1021 | esac | |
1032 | MISSING="\${SHELL} '$am_aux_dir/missing'" | |
1022 | 1033 | fi |
1023 | 1034 | # Use eval to expand $SHELL |
1024 | 1035 | if eval "$MISSING --is-lightweight"; then |
1031 | 1042 | |
1032 | 1043 | # Helper functions for option handling. -*- Autoconf -*- |
1033 | 1044 | |
1034 | # Copyright (C) 2001-2018 Free Software Foundation, Inc. | |
1045 | # Copyright (C) 2001-2021 Free Software Foundation, Inc. | |
1035 | 1046 | # |
1036 | 1047 | # This file is free software; the Free Software Foundation |
1037 | 1048 | # gives unlimited permission to copy and/or distribute it, |
1060 | 1071 | AC_DEFUN([_AM_IF_OPTION], |
1061 | 1072 | [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) |
1062 | 1073 | |
1063 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. | |
1074 | # Copyright (C) 1999-2021 Free Software Foundation, Inc. | |
1064 | 1075 | # |
1065 | 1076 | # This file is free software; the Free Software Foundation |
1066 | 1077 | # gives unlimited permission to copy and/or distribute it, |
1107 | 1118 | # For backward compatibility. |
1108 | 1119 | AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) |
1109 | 1120 | |
1110 | # Copyright (C) 2001-2018 Free Software Foundation, Inc. | |
1121 | # Copyright (C) 2001-2021 Free Software Foundation, Inc. | |
1111 | 1122 | # |
1112 | 1123 | # This file is free software; the Free Software Foundation |
1113 | 1124 | # gives unlimited permission to copy and/or distribute it, |
1126 | 1137 | |
1127 | 1138 | # Check to make sure that the build environment is sane. -*- Autoconf -*- |
1128 | 1139 | |
1129 | # Copyright (C) 1996-2018 Free Software Foundation, Inc. | |
1140 | # Copyright (C) 1996-2021 Free Software Foundation, Inc. | |
1130 | 1141 | # |
1131 | 1142 | # This file is free software; the Free Software Foundation |
1132 | 1143 | # gives unlimited permission to copy and/or distribute it, |
1207 | 1218 | rm -f conftest.file |
1208 | 1219 | ]) |
1209 | 1220 | |
1210 | # Copyright (C) 2009-2018 Free Software Foundation, Inc. | |
1221 | # Copyright (C) 2009-2021 Free Software Foundation, Inc. | |
1211 | 1222 | # |
1212 | 1223 | # This file is free software; the Free Software Foundation |
1213 | 1224 | # gives unlimited permission to copy and/or distribute it, |
1267 | 1278 | _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl |
1268 | 1279 | ]) |
1269 | 1280 | |
1270 | # Copyright (C) 2001-2018 Free Software Foundation, Inc. | |
1281 | # Copyright (C) 2001-2021 Free Software Foundation, Inc. | |
1271 | 1282 | # |
1272 | 1283 | # This file is free software; the Free Software Foundation |
1273 | 1284 | # gives unlimited permission to copy and/or distribute it, |
1295 | 1306 | INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" |
1296 | 1307 | AC_SUBST([INSTALL_STRIP_PROGRAM])]) |
1297 | 1308 | |
1298 | # Copyright (C) 2006-2018 Free Software Foundation, Inc. | |
1309 | # Copyright (C) 2006-2021 Free Software Foundation, Inc. | |
1299 | 1310 | # |
1300 | 1311 | # This file is free software; the Free Software Foundation |
1301 | 1312 | # gives unlimited permission to copy and/or distribute it, |
1314 | 1325 | |
1315 | 1326 | # Check how to create a tarball. -*- Autoconf -*- |
1316 | 1327 | |
1317 | # Copyright (C) 2004-2018 Free Software Foundation, Inc. | |
1328 | # Copyright (C) 2004-2021 Free Software Foundation, Inc. | |
1318 | 1329 | # |
1319 | 1330 | # This file is free software; the Free Software Foundation |
1320 | 1331 | # gives unlimited permission to copy and/or distribute it, |
0 | # Makefile.in generated by automake 1.16.1 from Makefile.am. | |
0 | # Makefile.in generated by automake 1.16.4 from Makefile.am. | |
1 | 1 | # @configure_input@ |
2 | 2 | |
3 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. | |
3 | # Copyright (C) 1994-2021 Free Software Foundation, Inc. | |
4 | 4 | |
5 | 5 | # This Makefile.in is free software; the Free Software Foundation |
6 | 6 | # gives unlimited permission to copy and/or distribute it, |
172 | 172 | unique=`for i in $$list; do \ |
173 | 173 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
174 | 174 | done | $(am__uniquify_input)` |
175 | ETAGS = etags | |
176 | CTAGS = ctags | |
177 | am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp | |
175 | am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ | |
176 | README.md | |
178 | 177 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
179 | 178 | ACLOCAL = @ACLOCAL@ |
180 | 179 | AMTAR = @AMTAR@ |
191 | 190 | CFLAGS = @CFLAGS@ |
192 | 191 | CPP = @CPP@ |
193 | 192 | CPPFLAGS = @CPPFLAGS@ |
193 | CSCOPE = @CSCOPE@ | |
194 | CTAGS = @CTAGS@ | |
194 | 195 | CYGPATH_W = @CYGPATH_W@ |
195 | 196 | DEFS = @DEFS@ |
196 | 197 | DEPDIR = @DEPDIR@ |
201 | 202 | ECHO_N = @ECHO_N@ |
202 | 203 | ECHO_T = @ECHO_T@ |
203 | 204 | EGREP = @EGREP@ |
205 | ETAGS = @ETAGS@ | |
204 | 206 | EXEEXT = @EXEEXT@ |
205 | 207 | FGREP = @FGREP@ |
206 | 208 | FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ |
302 | 304 | prefix = @prefix@ |
303 | 305 | program_transform_name = @program_transform_name@ |
304 | 306 | psdir = @psdir@ |
307 | runstatedir = @runstatedir@ | |
305 | 308 | sbindir = @sbindir@ |
306 | 309 | sharedstatedir = @sharedstatedir@ |
307 | 310 | srcdir = @srcdir@ |
483 | 486 | |
484 | 487 | distclean-tags: |
485 | 488 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
486 | ||
487 | 489 | distdir: $(BUILT_SOURCES) |
488 | 490 | $(MAKE) $(AM_MAKEFLAGS) distdir-am |
489 | 491 |
0 | Regression Testing | |
1 | ================== | |
2 | ||
3 | To build a test utility configure libass with the `--enable-compare` flag. | |
4 | The utility works with `png` image files so there is external dependency of libpng. | |
5 | ||
6 | Test program command line: | |
7 | `compare ([-i] <input-dir>)+ [-o <output-dir>] [-s <scale:1-8>] [-p <pass-level:0-3>]` | |
8 | ||
9 | * `<input-dir>` is a test input directory, can be several of them; | |
10 | * `<output-dir>` if present sets directory to store the rendering results; | |
11 | * `<scale>` sets an oversampling factor (positive integer up to 8, default 1); | |
12 | * `<pass-level>` corresponds to the level of image differences required to pass test: | |
13 | - 0: only `SAME` level accepted, bitwise comparison mode; | |
14 | - 1: `GOOD` level or less required; | |
15 | - 2: `BAD` level or less required, default mode; | |
16 | - 3: `FAIL` level or less required, i. e. any difference accepted, error checking mode. | |
17 | ||
18 | An input directory consists of font files (`*.ttf`, `*.otf` and `*.pfb`), subtitle files (`*.ass`), and image files (`*.png`). | |
19 | All the fonts required for rendering should be present in the input directories as | |
20 | libass is configured to not use anything external outside of it (`ASS_FONTPROVIDER_NONE`). | |
21 | After loading all the fonts in the directories, the test program scans for subtitle files (`<sub_name>.ass`) | |
22 | and their corresponding image files in the form of `<sub_name>-NNNN.png`, | |
23 | where `NNNN` is an arbitrary number of decimal digits. | |
24 | The subtitle file then would be rendered at the time of `NNNN` milliseconds and compared with the loaded image file. | |
25 | For example, an input directory can have the following structure: | |
26 | ||
27 | ``` | |
28 | test/ | |
29 | font1.ttf | |
30 | font2.otf | |
31 | sub1.ass | |
32 | sub1-0500.png | |
33 | sub1-1500.png | |
34 | sub1-2500.png | |
35 | sub2.ass | |
36 | sub2-153000.png | |
37 | ``` | |
38 | ||
39 | More precisely, the test program (`compare`) would scan all input directories and do the following: | |
40 | 1) load all the fonts found (`*.ttf`, `*.otf`, `*.pfb`); | |
41 | 2) search for subtitle files (`*.ass`); | |
42 | 3) for every file found (`<sub_name>.ass`) scan for the files with names of `<sub_name>-NNNN.png`; | |
43 | 4) interpret `NNNN` as a time in milliseconds and render the subtitle file at that time with a transparent background; | |
44 | 5) fuzzy compare the rendering result with the corresponding png file; | |
45 | 6) save the rendering result in the output directory if requested. | |
46 | ||
47 | Target images should be transparent RGBA png files with 8 or 16 bits per channel. | |
48 | A subtitle rendering resolution is determined by the extents of the target image files multiplied by an optional scale factor (`-s` switch). | |
49 | In the case of nontrivial scale factor, the result would be downsampled using 16-bit precision before comparison. | |
50 | Downsampling is done assuming a linear color space which is physically incorrect but commonly used in computer rendering. | |
51 | ||
52 | It's possible to save rendering results by using `-o` switch. | |
53 | Saved files would have the same names as the target image files. | |
54 | That functionality can be used for an initial generation of target images | |
55 | by supplying arbitrary source images with correct names and extents. | |
56 | ||
57 | Test program output can look like the following: | |
58 | ``` | |
59 | Loading font 'font1.ttf'. | |
60 | Loading font 'font2.otf'. | |
61 | Processing 'sub1.ass': | |
62 | Time 0:00:00.500 - 2.464 BAD | |
63 | Time 0:00:01.500 - 1.412 OK | |
64 | Time 0:00:02.500 - 4.919 FAIL | |
65 | Processing 'sub2.ass': | |
66 | Time 0:02:33.000 - 0.728 OK | |
67 | Only 3 of 4 images have passed test | |
68 | ``` | |
69 | For each target image file the program reports a maximal ratio of the per pixel comparison difference to the baseline error scale. | |
70 | The baseline error scale tries to take account of neighboring pixels to estimate visibility of a difference in that specific pixel location. | |
71 | Zero difference is marked as `SAME` (level 0), nonzero value in the range of [0–2.0] is marked as `GOOD` (level 1), | |
72 | in the range of [2.0–4.0] as `BAD` (level 2) and more than 4.0 as `FAIL` (level 3). | |
73 | Any problem during processing of a specific image is treated as a level 4 difference. | |
74 | If all images have level of difference less or equal to pass level (`-p` switch, default 2) then the test is considered as passed | |
75 | and program returns 0. Otherwise program returns maximal level of difference throughout all images (4 in case of error). | |
76 | ||
77 | Note that almost any type of a rendering error can be greatly exaggerated by the specially tailored test cases. | |
78 | Therefore test cases should be chosen to represent generic real world scenarios only. |
21 | 21 | #include <sys/stat.h> |
22 | 22 | #include <dirent.h> |
23 | 23 | #include <string.h> |
24 | ||
25 | #if defined(_WIN32) && !defined(__CYGWIN__) | |
26 | #include <direct.h> | |
27 | #define mkdir(path, mode) _mkdir(path) | |
28 | #endif | |
24 | 29 | |
25 | 30 | |
26 | 31 | #define FFMAX(a,b) ((a) > (b) ? (a) : (b)) |
279 | 284 | const char *dir, const char *file) |
280 | 285 | { |
281 | 286 | char path[4096]; |
282 | snprintf(path, sizeof(path), "%s/%s.ass", dir, file); | |
287 | snprintf(path, sizeof(path), "%s/%s", dir, file); | |
283 | 288 | ASS_Track *track = ass_read_file(lib, path, NULL); |
284 | 289 | if (!track) { |
285 | printf("Cannot load subtitle file '%s.ass'!\n", file); | |
290 | printf("Cannot load subtitle file '%s'!\n", file); | |
286 | 291 | return NULL; |
287 | 292 | } |
288 | printf("Processing '%s.ass':\n", file); | |
293 | printf("Processing '%s':\n", file); | |
289 | 294 | return track; |
290 | 295 | } |
291 | 296 | |
295 | 300 | return false; |
296 | 301 | } |
297 | 302 | |
298 | static bool process_image(ASS_Renderer *renderer, ASS_Track *track, | |
299 | const char *input, const char *output, | |
300 | const char *file, int64_t time, int scale) | |
303 | typedef enum { | |
304 | R_SAME, R_GOOD, R_BAD, R_FAIL, R_ERROR | |
305 | } Result; | |
306 | ||
307 | static const char *result_text[R_ERROR] = { | |
308 | "SAME", "GOOD", "BAD", "FAIL" | |
309 | }; | |
310 | ||
311 | Result classify_result(double error) | |
312 | { | |
313 | if (error == 0) | |
314 | return R_SAME; | |
315 | else if (error < 2) | |
316 | return R_GOOD; | |
317 | else if (error < 4) | |
318 | return R_BAD; | |
319 | else | |
320 | return R_FAIL; | |
321 | } | |
322 | ||
323 | static Result process_image(ASS_Renderer *renderer, ASS_Track *track, | |
324 | const char *input, const char *output, | |
325 | const char *file, int64_t time, int scale) | |
301 | 326 | { |
302 | 327 | uint64_t tm = time; |
303 | 328 | unsigned msec = tm % 1000; tm /= 1000; |
311 | 336 | Image16 target; |
312 | 337 | if (!read_png(path, &target)) { |
313 | 338 | printf("PNG reading failed!\n"); |
314 | return false; | |
339 | return R_ERROR; | |
315 | 340 | } |
316 | 341 | |
317 | 342 | uint16_t *grad = malloc(2 * target.width * target.height); |
318 | 343 | if (!grad) { |
319 | 344 | free(target.buffer); |
320 | return out_of_memory(); | |
345 | out_of_memory(); | |
346 | return R_ERROR; | |
321 | 347 | } |
322 | 348 | calc_grad(&target, grad); |
323 | 349 | |
334 | 360 | int res = compare(&target, grad, img, out_file, &max_err, scale); |
335 | 361 | free(target.buffer); |
336 | 362 | free(grad); |
337 | if (!res) | |
338 | return out_of_memory(); | |
339 | bool flag = max_err < 4; | |
340 | printf("%.3f %s\n", max_err, flag ? (max_err < 2 ? "OK" : "BAD") : "FAIL"); | |
363 | if (!res) { | |
364 | out_of_memory(); | |
365 | return R_ERROR; | |
366 | } | |
367 | Result flag = classify_result(max_err); | |
368 | printf("%.3f %s\n", max_err, result_text[flag]); | |
341 | 369 | if (res < 0) |
342 | 370 | printf("Cannot write PNG to file '%s'!\n", path); |
343 | 371 | return flag; |
346 | 374 | |
347 | 375 | typedef struct { |
348 | 376 | char *name; |
377 | size_t prefix; | |
378 | const char *dir; | |
349 | 379 | int64_t time; |
350 | 380 | } Item; |
351 | 381 | |
354 | 384 | Item *items; |
355 | 385 | } ItemList; |
356 | 386 | |
357 | static bool init_items(ItemList *list) | |
358 | { | |
359 | int n = 256; | |
360 | list->n_items = list->max_items = 0; | |
361 | list->items = malloc(n * sizeof(Item)); | |
362 | if (!list->items) | |
363 | return out_of_memory(); | |
364 | list->max_items = n; | |
365 | return true; | |
366 | } | |
367 | ||
368 | 387 | static bool add_item(ItemList *list) |
369 | 388 | { |
370 | 389 | if (list->n_items < list->max_items) |
371 | 390 | return true; |
372 | 391 | |
373 | int n = 2 * list->max_items; | |
392 | size_t n = list->max_items ? 2 * list->max_items : 256; | |
374 | 393 | Item *next = realloc(list->items, n * sizeof(Item)); |
375 | 394 | if (!next) |
376 | 395 | return out_of_memory(); |
389 | 408 | static int item_compare(const void *ptr1, const void *ptr2) |
390 | 409 | { |
391 | 410 | const Item *e1 = ptr1, *e2 = ptr2; |
392 | int cmp = strcmp(e1->name, e2->name); | |
411 | ||
412 | int cmp_len = 0; | |
413 | size_t len = e1->prefix; | |
414 | if (len > e2->prefix) { | |
415 | cmp_len = +1; | |
416 | len = e2->prefix; | |
417 | } else if (len < e2->prefix) { | |
418 | cmp_len = -1; | |
419 | } | |
420 | int cmp = memcmp(e1->name, e2->name, len); | |
393 | 421 | if (cmp) |
394 | 422 | return cmp; |
423 | if (cmp_len) | |
424 | return cmp_len; | |
395 | 425 | if (e1->time > e2->time) |
396 | 426 | return +1; |
397 | 427 | if (e1->time < e2->time) |
400 | 430 | } |
401 | 431 | |
402 | 432 | |
403 | static bool add_sub_item(ItemList *list, const char *file, int len) | |
433 | static bool add_sub_item(ItemList *list, const char *dir, const char *file, size_t len) | |
404 | 434 | { |
405 | 435 | if (!add_item(list)) |
406 | 436 | return false; |
407 | 437 | |
408 | 438 | Item *item = &list->items[list->n_items]; |
409 | item->name = strndup(file, len); | |
439 | item->name = strdup(file); | |
410 | 440 | if (!item->name) |
411 | 441 | return out_of_memory(); |
442 | item->prefix = len; | |
443 | item->dir = dir; | |
412 | 444 | item->time = -1; |
413 | 445 | list->n_items++; |
414 | 446 | return true; |
415 | 447 | } |
416 | 448 | |
417 | static bool add_img_item(ItemList *list, const char *file, int len) | |
449 | static bool add_img_item(ItemList *list, const char *dir, const char *file, size_t len) | |
418 | 450 | { |
419 | 451 | // Parse image name: |
420 | 452 | // <subtitle_name>-<time_in_msec>.png |
421 | 453 | |
422 | int pos = len, first = len; | |
454 | size_t pos = len, first = len; | |
423 | 455 | while (true) { |
424 | 456 | if (!pos--) |
425 | 457 | return true; |
440 | 472 | item->name = strdup(file); |
441 | 473 | if (!item->name) |
442 | 474 | return out_of_memory(); |
443 | item->name[pos] = '\0'; | |
475 | item->prefix = pos; | |
476 | item->dir = dir; | |
444 | 477 | item->time = 0; |
445 | for (int i = first; i < len; i++) | |
478 | for (size_t i = first; i < len; i++) | |
446 | 479 | item->time = 10 * item->time + (file[i] - '0'); |
447 | 480 | list->n_items++; |
448 | 481 | return true; |
449 | 482 | } |
450 | 483 | |
451 | ||
452 | static int print_usage(const char *program) | |
453 | { | |
484 | static bool process_input(ItemList *list, const char *path, ASS_Library *lib) | |
485 | { | |
486 | DIR *dir = opendir(path); | |
487 | if (!dir) { | |
488 | printf("Cannot open input directory '%s'!\n", path); | |
489 | return false; | |
490 | } | |
491 | struct dirent *file; | |
492 | while ((file = readdir(dir))) { | |
493 | const char *name = file->d_name; | |
494 | if (name[0] == '.') | |
495 | continue; | |
496 | const char *ext = strrchr(name + 1, '.'); | |
497 | if (!ext) | |
498 | continue; | |
499 | ||
500 | char ext_lc[5]; | |
501 | size_t pos = 0; | |
502 | while (pos < sizeof(ext_lc) - 1) { | |
503 | char c = ext[pos + 1]; | |
504 | if (!c) | |
505 | break; | |
506 | if (c >= 'A' && c <= 'Z') | |
507 | c += 'a' - 'A'; | |
508 | ext_lc[pos] = c; | |
509 | pos++; | |
510 | } | |
511 | ext_lc[pos] = '\0'; | |
512 | ||
513 | if (!strcmp(ext_lc, "png")) { | |
514 | if (add_img_item(list, path, name, ext - name)) | |
515 | continue; | |
516 | } else if (!strcmp(ext_lc, "ass")) { | |
517 | if (add_sub_item(list, path, name, ext - name)) | |
518 | continue; | |
519 | } else if (!strcmp(ext_lc, "ttf") || | |
520 | !strcmp(ext_lc, "otf") || | |
521 | !strcmp(ext_lc, "pfb")) { | |
522 | if (load_font(lib, path, name)) | |
523 | continue; | |
524 | printf("Cannot load font '%s'!\n", name); | |
525 | } else { | |
526 | continue; | |
527 | } | |
528 | closedir(dir); | |
529 | return false; | |
530 | } | |
531 | closedir(dir); | |
532 | return true; | |
533 | } | |
534 | ||
535 | ||
536 | enum { | |
537 | OUTPUT, SCALE, LEVEL, INPUT | |
538 | }; | |
539 | ||
540 | static int *parse_cmdline(int argc, char *argv[]) | |
541 | { | |
542 | int *pos = calloc(INPUT + argc, sizeof(int)); | |
543 | if (!pos) { | |
544 | out_of_memory(); | |
545 | return NULL; | |
546 | } | |
547 | int input = INPUT; | |
548 | for (int i = 1; i < argc; i++) { | |
549 | if (argv[i][0] != '-') { | |
550 | pos[input++] = i; | |
551 | continue; | |
552 | } | |
553 | int index; | |
554 | switch (argv[i][1]) { | |
555 | case 'i': index = input++; break; | |
556 | case 'o': index = OUTPUT; break; | |
557 | case 's': index = SCALE; break; | |
558 | case 'p': index = LEVEL; break; | |
559 | default: goto fail; | |
560 | } | |
561 | if (argv[i][2] || ++i >= argc || pos[index]) | |
562 | goto fail; | |
563 | pos[index] = i; | |
564 | } | |
565 | if (pos[INPUT]) | |
566 | return pos; | |
567 | ||
568 | fail: | |
569 | free(pos); | |
454 | 570 | const char *fmt = |
455 | "Usage: %s [-i] <input-dir> [-o <output-dir>] [-s <scale:1-8>]\n"; | |
456 | printf(fmt, program); | |
457 | return 1; | |
571 | "Usage: %s ([-i] <input-dir>)+ [-o <output-dir>] [-s <scale:1-8>] [-p <pass-level:0-3>]\n"; | |
572 | printf(fmt, argv[0]); | |
573 | return NULL; | |
458 | 574 | } |
459 | 575 | |
460 | 576 | void msg_callback(int level, const char *fmt, va_list va, void *data) |
461 | 577 | { |
462 | 578 | if (level > 3) |
463 | 579 | return; |
464 | printf("libass: "); | |
465 | vprintf(fmt, va); | |
466 | printf("\n"); | |
580 | fprintf(stderr, "libass: "); | |
581 | vfprintf(stderr, fmt, va); | |
582 | fprintf(stderr, "\n"); | |
467 | 583 | } |
468 | 584 | |
469 | 585 | int main(int argc, char *argv[]) |
470 | 586 | { |
471 | enum { | |
472 | INPUT, OUTPUT, SCALE | |
473 | }; | |
474 | int pos[3] = {0}; | |
475 | for (int i = 1; i < argc; i++) { | |
476 | if (argv[i][0] != '-') { | |
477 | if (pos[INPUT]) | |
478 | return print_usage(argv[0]); | |
479 | pos[INPUT] = i; | |
480 | continue; | |
481 | } | |
482 | int index; | |
483 | switch (argv[i][1]) { | |
484 | case 'i': index = INPUT; break; | |
485 | case 'o': index = OUTPUT; break; | |
486 | case 's': index = SCALE; break; | |
487 | default: return print_usage(argv[0]); | |
488 | } | |
489 | if (argv[i][2] || ++i >= argc || pos[index]) | |
490 | return print_usage(argv[0]); | |
491 | pos[index] = i; | |
492 | } | |
493 | if (!pos[INPUT]) | |
494 | return print_usage(argv[0]); | |
587 | int *pos = parse_cmdline(argc, argv); | |
588 | if (!pos) | |
589 | return R_ERROR; | |
590 | ||
591 | ASS_Library *lib = NULL; | |
592 | ItemList list = {0}; | |
593 | int result = R_ERROR; | |
495 | 594 | |
496 | 595 | int scale = 1; |
497 | 596 | if (pos[SCALE]) { |
498 | 597 | const char *arg = argv[pos[SCALE]]; |
499 | 598 | if (arg[0] < '1' || arg[0] > '8' || arg[1]) { |
500 | 599 | printf("Invalid scale value, should be 1-8!\n"); |
501 | return 1; | |
600 | goto end; | |
502 | 601 | } |
503 | 602 | scale = arg[0] - '0'; |
504 | 603 | } |
505 | 604 | |
506 | const char *input = argv[pos[INPUT]]; | |
507 | DIR *dir = opendir(input); | |
508 | if (!dir) { | |
509 | printf("Cannot open input directory '%s'!\n", input); | |
510 | return 1; | |
605 | int level = R_BAD; | |
606 | if (pos[LEVEL]) { | |
607 | const char *arg = argv[pos[LEVEL]]; | |
608 | if (arg[0] < '0' || arg[0] > '3' || arg[1]) { | |
609 | printf("Invalid pass level value, should be 0-3!\n"); | |
610 | goto end; | |
611 | } | |
612 | level = arg[0] - '0'; | |
511 | 613 | } |
512 | 614 | |
513 | 615 | const char *output = NULL; |
517 | 619 | if (stat(output, &st)) { |
518 | 620 | if (mkdir(output, 0755)) { |
519 | 621 | printf("Cannot create output directory '%s'!\n", output); |
520 | closedir(dir); | |
521 | return 1; | |
622 | goto end; | |
522 | 623 | } |
523 | 624 | } else if (!(st.st_mode & S_IFDIR)) { |
524 | 625 | printf("Invalid output directory '%s'!\n", output); |
525 | closedir(dir); | |
526 | return 1; | |
527 | } | |
528 | } | |
529 | ||
530 | ASS_Library *lib = ass_library_init(); | |
626 | goto end; | |
627 | } | |
628 | } | |
629 | ||
630 | lib = ass_library_init(); | |
531 | 631 | if (!lib) { |
532 | 632 | printf("ass_library_init failed!\n"); |
533 | closedir(dir); | |
534 | return 1; | |
633 | goto end; | |
535 | 634 | } |
536 | 635 | ass_set_message_cb(lib, msg_callback, NULL); |
537 | 636 | ass_set_extract_fonts(lib, true); |
538 | 637 | |
539 | ItemList list; | |
540 | if (!init_items(&list)) { | |
541 | ass_library_done(lib); | |
542 | closedir(dir); | |
543 | return 1; | |
544 | } | |
545 | ||
546 | while (true) { | |
547 | struct dirent *file = readdir(dir); | |
548 | if (!file) | |
549 | break; | |
550 | const char *name = file->d_name; | |
551 | if (name[0] == '.') | |
552 | continue; | |
553 | const char *ext = strrchr(name + 1, '.'); | |
554 | if (!ext) | |
555 | continue; | |
556 | ||
557 | if (!strcmp(ext, ".png")) { | |
558 | if (add_img_item(&list, name, ext - name)) | |
559 | continue; | |
560 | } else if (!strcmp(ext, ".ass")) { | |
561 | if (add_sub_item(&list, name, ext - name)) | |
562 | continue; | |
563 | } else if (!strcmp(ext, ".ttf") || !strcmp(ext, ".otf") || !strcmp(ext, ".pfb")) { | |
564 | if (load_font(lib, input, name)) | |
565 | continue; | |
566 | printf("Cannot load font '%s'!\n", name); | |
567 | } else { | |
568 | continue; | |
569 | } | |
570 | delete_items(&list); | |
571 | ass_library_done(lib); | |
572 | closedir(dir); | |
573 | return 1; | |
574 | } | |
575 | closedir(dir); | |
638 | for (int *input = pos + INPUT; *input; input++) { | |
639 | if (!process_input(&list, argv[*input], lib)) | |
640 | goto end; | |
641 | } | |
576 | 642 | |
577 | 643 | ASS_Renderer *renderer = ass_renderer_init(lib); |
578 | 644 | if (!renderer) { |
579 | 645 | printf("ass_renderer_init failed!\n"); |
580 | delete_items(&list); | |
581 | ass_library_done(lib); | |
582 | return 1; | |
646 | goto end; | |
583 | 647 | } |
584 | 648 | ass_set_fonts(renderer, NULL, NULL, ASS_FONTPROVIDER_NONE, NULL, 0); |
585 | 649 | |
586 | int prefix; | |
650 | result = 0; | |
651 | size_t prefix = 0; | |
587 | 652 | const char *prev = ""; |
588 | 653 | ASS_Track *track = NULL; |
589 | 654 | unsigned total = 0, good = 0; |
590 | 655 | qsort(list.items, list.n_items, sizeof(Item), item_compare); |
591 | 656 | for (size_t i = 0; i < list.n_items; i++) { |
592 | if (strcmp(prev, list.items[i].name)) { | |
593 | if (track) | |
657 | char *name = list.items[i].name; | |
658 | size_t len = list.items[i].prefix; | |
659 | if (prefix != len || memcmp(prev, name, len)) { | |
660 | if (track) { | |
594 | 661 | ass_free_track(track); |
595 | prev = list.items[i].name; | |
596 | prefix = strlen(prev); | |
597 | if (list.items[i].time < 0) | |
598 | track = load_track(lib, input, prev); | |
599 | else { | |
600 | printf("Missing subtitle file '%s.ass'!\n", prev); | |
601 | 662 | track = NULL; |
663 | } | |
664 | prev = name; | |
665 | prefix = len; | |
666 | if (list.items[i].time >= 0) { | |
667 | printf("Missing subtitle file '%.*s.ass'!\n", (int) len, name); | |
602 | 668 | total++; |
603 | } | |
669 | } else if (i + 1 < list.n_items && list.items[i + 1].time >= 0) | |
670 | track = load_track(lib, list.items[i].dir, prev); | |
604 | 671 | continue; |
605 | 672 | } |
606 | ||
673 | if (list.items[i].time < 0) { | |
674 | printf("Multiple subtitle files '%.*s.ass'!\n", (int) len, name); | |
675 | continue; | |
676 | } | |
607 | 677 | total++; |
608 | 678 | if (!track) |
609 | 679 | continue; |
610 | char *name = list.items[i].name; | |
611 | name[prefix] = '-'; // restore initial filename | |
612 | if (process_image(renderer, track, input, output, | |
613 | name, list.items[i].time, scale)) | |
680 | Result res = process_image(renderer, track, list.items[i].dir, output, | |
681 | name, list.items[i].time, scale); | |
682 | result = FFMAX(result, res); | |
683 | if (res <= level) | |
614 | 684 | good++; |
615 | 685 | } |
616 | 686 | if (track) |
617 | 687 | ass_free_track(track); |
688 | ass_renderer_done(renderer); | |
689 | ||
690 | if (!total) { | |
691 | printf("No images found!\n"); | |
692 | result = R_ERROR; | |
693 | } else if (good < total) { | |
694 | printf("Only %u of %u images have passed test (%s or better)\n", | |
695 | good, total, result_text[level]); | |
696 | } else { | |
697 | printf("All %u images have passed test (%s or better)\n", | |
698 | total, result_text[level]); | |
699 | result = 0; | |
700 | } | |
701 | ||
702 | end: | |
618 | 703 | delete_items(&list); |
619 | ass_renderer_done(renderer); | |
620 | ass_library_done(lib); | |
621 | ||
622 | if (good < total) { | |
623 | printf("Only %u of %u images have passed test\n", good, total); | |
624 | return 1; | |
625 | } | |
626 | printf("All %u images have passed test\n", total); | |
627 | return 0; | |
628 | } | |
704 | if (lib) | |
705 | ass_library_done(lib); | |
706 | free(pos); | |
707 | return result; | |
708 | } |
2 | 2 | |
3 | 3 | scriptversion=2018-03-07.03; # UTC |
4 | 4 | |
5 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. | |
5 | # Copyright (C) 1999-2021 Free Software Foundation, Inc. | |
6 | 6 | # Written by Tom Tromey <tromey@cygnus.com>. |
7 | 7 | # |
8 | 8 | # This program is free software; you can redistribute it and/or modify |
52 | 52 | MINGW*) |
53 | 53 | file_conv=mingw |
54 | 54 | ;; |
55 | CYGWIN*) | |
55 | CYGWIN* | MSYS*) | |
56 | 56 | file_conv=cygwin |
57 | 57 | ;; |
58 | 58 | *) |
66 | 66 | mingw/*) |
67 | 67 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` |
68 | 68 | ;; |
69 | cygwin/*) | |
69 | cygwin/* | msys/*) | |
70 | 70 | file=`cygpath -m "$file" || echo "$file"` |
71 | 71 | ;; |
72 | 72 | wine/*) |
1 | 1 | # Attempt to guess a canonical system name. |
2 | 2 | # Copyright 1992-2018 Free Software Foundation, Inc. |
3 | 3 | |
4 | timestamp='2018-03-08' | |
4 | timestamp='2018-02-24' | |
5 | 5 | |
6 | 6 | # This file is free software; you can redistribute it and/or modify it |
7 | 7 | # under the terms of the GNU General Public License as published by |
1045 | 1045 | echo "$UNAME_MACHINE"-dec-linux-"$LIBC" |
1046 | 1046 | exit ;; |
1047 | 1047 | x86_64:Linux:*:*) |
1048 | echo "$UNAME_MACHINE"-pc-linux-"$LIBC" | |
1048 | if objdump -f /bin/sh | grep -q elf32-x86-64; then | |
1049 | echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 | |
1050 | else | |
1051 | echo "$UNAME_MACHINE"-pc-linux-"$LIBC" | |
1052 | fi | |
1049 | 1053 | exit ;; |
1050 | 1054 | xtensa*:Linux:*:*) |
1051 | 1055 | echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" |
1468 | 1472 | exit 1 |
1469 | 1473 | |
1470 | 1474 | # Local variables: |
1471 | # eval: (add-hook 'before-save-hook 'time-stamp) | |
1475 | # eval: (add-hook 'write-file-functions 'time-stamp) | |
1472 | 1476 | # time-stamp-start: "timestamp='" |
1473 | 1477 | # time-stamp-format: "%:y-%02m-%02d" |
1474 | 1478 | # time-stamp-end: "'" |
5 | 5 | /* found CoreText framework */ |
6 | 6 | #undef CONFIG_CORETEXT |
7 | 7 | |
8 | /* found DirectWrite */ | |
8 | /* found DirectWrite and GDI (Win32) */ | |
9 | 9 | #undef CONFIG_DIRECTWRITE |
10 | 10 | |
11 | 11 | /* found fontconfig via pkg-config */ |
1 | 1 | # Configuration validation subroutine script. |
2 | 2 | # Copyright 1992-2018 Free Software Foundation, Inc. |
3 | 3 | |
4 | timestamp='2018-03-08' | |
4 | timestamp='2018-02-22' | |
5 | 5 | |
6 | 6 | # This file is free software; you can redistribute it and/or modify it |
7 | 7 | # under the terms of the GNU General Public License as published by |
1375 | 1375 | | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ |
1376 | 1376 | | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ |
1377 | 1377 | | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ |
1378 | | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* | -hcos* \ | |
1378 | | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | |
1379 | 1379 | | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ |
1380 | 1380 | | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ |
1381 | 1381 | | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ |
1793 | 1793 | exit |
1794 | 1794 | |
1795 | 1795 | # Local variables: |
1796 | # eval: (add-hook 'before-save-hook 'time-stamp) | |
1796 | # eval: (add-hook 'write-file-functions 'time-stamp) | |
1797 | 1797 | # time-stamp-start: "timestamp='" |
1798 | 1798 | # time-stamp-format: "%:y-%02m-%02d" |
1799 | 1799 | # time-stamp-end: "'" |
725 | 725 | AM_DEFAULT_VERBOSITY |
726 | 726 | AM_DEFAULT_V |
727 | 727 | AM_V |
728 | CSCOPE | |
729 | ETAGS | |
730 | CTAGS | |
728 | 731 | am__untar |
729 | 732 | am__tar |
730 | 733 | AMTAR |
767 | 770 | docdir |
768 | 771 | oldincludedir |
769 | 772 | includedir |
773 | runstatedir | |
770 | 774 | localstatedir |
771 | 775 | sharedstatedir |
772 | 776 | sysconfdir |
871 | 875 | sysconfdir='${prefix}/etc' |
872 | 876 | sharedstatedir='${prefix}/com' |
873 | 877 | localstatedir='${prefix}/var' |
878 | runstatedir='${localstatedir}/run' | |
874 | 879 | includedir='${prefix}/include' |
875 | 880 | oldincludedir='/usr/include' |
876 | 881 | docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' |
1123 | 1128 | | -silent | --silent | --silen | --sile | --sil) |
1124 | 1129 | silent=yes ;; |
1125 | 1130 | |
1131 | -runstatedir | --runstatedir | --runstatedi | --runstated \ | |
1132 | | --runstate | --runstat | --runsta | --runst | --runs \ | |
1133 | | --run | --ru | --r) | |
1134 | ac_prev=runstatedir ;; | |
1135 | -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | |
1136 | | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | |
1137 | | --run=* | --ru=* | --r=*) | |
1138 | runstatedir=$ac_optarg ;; | |
1139 | ||
1126 | 1140 | -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) |
1127 | 1141 | ac_prev=sbindir ;; |
1128 | 1142 | -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ |
1260 | 1274 | for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ |
1261 | 1275 | datadir sysconfdir sharedstatedir localstatedir includedir \ |
1262 | 1276 | oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ |
1263 | libdir localedir mandir | |
1277 | libdir localedir mandir runstatedir | |
1264 | 1278 | do |
1265 | 1279 | eval ac_val=\$$ac_var |
1266 | 1280 | # Remove trailing slashes. |
1413 | 1427 | --sysconfdir=DIR read-only single-machine data [PREFIX/etc] |
1414 | 1428 | --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] |
1415 | 1429 | --localstatedir=DIR modifiable single-machine data [PREFIX/var] |
1430 | --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] | |
1416 | 1431 | --libdir=DIR object code libraries [EPREFIX/lib] |
1417 | 1432 | --includedir=DIR C header files [PREFIX/include] |
1418 | 1433 | --oldincludedir=DIR C header files for non-gcc [/usr/include] |
1467 | 1482 | [default=no] |
1468 | 1483 | --enable-profile enable profiling program [default=no] |
1469 | 1484 | --disable-fontconfig disable fontconfig support [default=enabled] |
1470 | --disable-directwrite disable DirectWrite support (win32 only) | |
1485 | --disable-directwrite disable DirectWrite support (Windows only) | |
1471 | 1486 | [default=check] |
1472 | 1487 | --disable-coretext disable CoreText support (OSX only) [default=check] |
1473 | 1488 | --disable-require-system-font-provider |
2424 | 2439 | am_aux_dir=`cd "$ac_aux_dir" && pwd` |
2425 | 2440 | |
2426 | 2441 | if test x"${MISSING+set}" != xset; then |
2427 | case $am_aux_dir in | |
2428 | *\ * | *\ *) | |
2429 | MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; | |
2430 | *) | |
2431 | MISSING="\${SHELL} $am_aux_dir/missing" ;; | |
2432 | esac | |
2442 | MISSING="\${SHELL} '$am_aux_dir/missing'" | |
2433 | 2443 | fi |
2434 | 2444 | # Use eval to expand $SHELL |
2435 | 2445 | if eval "$MISSING --is-lightweight"; then |
2782 | 2792 | |
2783 | 2793 | |
2784 | 2794 | |
2795 | ||
2796 | ||
2797 | # Variables for tags utilities; see am/tags.am | |
2798 | if test -z "$CTAGS"; then | |
2799 | CTAGS=ctags | |
2800 | fi | |
2801 | ||
2802 | if test -z "$ETAGS"; then | |
2803 | ETAGS=etags | |
2804 | fi | |
2805 | ||
2806 | if test -z "$CSCOPE"; then | |
2807 | CSCOPE=cscope | |
2808 | fi | |
2785 | 2809 | |
2786 | 2810 | |
2787 | 2811 | |
5178 | 5202 | lt_cv_deplibs_check_method=pass_all |
5179 | 5203 | ;; |
5180 | 5204 | |
5181 | netbsd*) | |
5205 | netbsd* | netbsdelf*-gnu) | |
5182 | 5206 | if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then |
5183 | 5207 | lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' |
5184 | 5208 | else |
5541 | 5565 | fi |
5542 | 5566 | |
5543 | 5567 | : ${AR=ar} |
5544 | : ${AR_FLAGS=cru} | |
5568 | : ${AR_FLAGS=cr} | |
5545 | 5569 | |
5546 | 5570 | |
5547 | 5571 | |
6042 | 6066 | test $ac_status = 0; }; then |
6043 | 6067 | # Now try to grab the symbols. |
6044 | 6068 | nlist=conftest.nm |
6045 | if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 | |
6046 | (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 | |
6047 | ac_status=$? | |
6048 | $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 | |
6049 | test $ac_status = 0; } && test -s "$nlist"; then | |
6069 | $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 | |
6070 | if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then | |
6050 | 6071 | # Try sorting and uniquifying the output. |
6051 | 6072 | if sort "$nlist" | uniq > "$nlist"T; then |
6052 | 6073 | mv -f "$nlist"T "$nlist" |
7265 | 7286 | _LT_EOF |
7266 | 7287 | echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 |
7267 | 7288 | $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 |
7268 | echo "$AR cru libconftest.a conftest.o" >&5 | |
7269 | $AR cru libconftest.a conftest.o 2>&5 | |
7289 | echo "$AR cr libconftest.a conftest.o" >&5 | |
7290 | $AR cr libconftest.a conftest.o 2>&5 | |
7270 | 7291 | echo "$RANLIB libconftest.a" >&5 |
7271 | 7292 | $RANLIB libconftest.a 2>&5 |
7272 | 7293 | cat > conftest.c << _LT_EOF |
7293 | 7314 | _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; |
7294 | 7315 | darwin1.*) |
7295 | 7316 | _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; |
7296 | darwin*) | |
7297 | case ${MACOSX_DEPLOYMENT_TARGET},$host in | |
7298 | 10.[012],*|,*powerpc*) | |
7317 | darwin*) # darwin 5.x on | |
7318 | # if running on 10.5 or later, the deployment target defaults | |
7319 | # to the OS version, if on x86, and 10.4, the deployment | |
7320 | # target defaults to 10.4. Don't you love it? | |
7321 | case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in | |
7322 | 10.0,*86*-darwin8*|10.0,*-darwin[912]*) | |
7323 | _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; | |
7324 | 10.[012][,.]*) | |
7299 | 7325 | _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; |
7300 | *) | |
7326 | 10.*|11.*) | |
7301 | 7327 | _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; |
7302 | 7328 | esac |
7303 | 7329 | ;; |
8388 | 8414 | ecc*) |
8389 | 8415 | lt_prog_compiler_wl='-Wl,' |
8390 | 8416 | lt_prog_compiler_pic='-KPIC' |
8417 | lt_prog_compiler_static='-static' | |
8418 | ;; | |
8419 | # flang / f18. f95 an alias for gfortran or flang on Debian | |
8420 | flang* | f18* | f95*) | |
8421 | lt_prog_compiler_wl='-Wl,' | |
8422 | lt_prog_compiler_pic='-fPIC' | |
8391 | 8423 | lt_prog_compiler_static='-static' |
8392 | 8424 | ;; |
8393 | 8425 | # icc used to be incompatible with GCC. |
8866 | 8898 | openbsd* | bitrig*) |
8867 | 8899 | with_gnu_ld=no |
8868 | 8900 | ;; |
8901 | linux* | k*bsd*-gnu | gnu*) | |
8902 | link_all_deplibs=no | |
8903 | ;; | |
8869 | 8904 | esac |
8870 | 8905 | |
8871 | 8906 | ld_shlibs=yes |
9120 | 9155 | fi |
9121 | 9156 | ;; |
9122 | 9157 | |
9123 | netbsd*) | |
9158 | netbsd* | netbsdelf*-gnu) | |
9124 | 9159 | if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then |
9125 | 9160 | archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' |
9126 | 9161 | wlarc= |
9790 | 9825 | if test yes = "$lt_cv_irix_exported_symbol"; then |
9791 | 9826 | 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' |
9792 | 9827 | fi |
9828 | link_all_deplibs=no | |
9793 | 9829 | else |
9794 | 9830 | 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' |
9795 | 9831 | 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' |
9811 | 9847 | esac |
9812 | 9848 | ;; |
9813 | 9849 | |
9814 | netbsd*) | |
9850 | netbsd* | netbsdelf*-gnu) | |
9815 | 9851 | if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then |
9816 | 9852 | archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out |
9817 | 9853 | else |
10926 | 10962 | dynamic_linker='GNU/Linux ld.so' |
10927 | 10963 | ;; |
10928 | 10964 | |
10965 | netbsdelf*-gnu) | |
10966 | version_type=linux | |
10967 | need_lib_prefix=no | |
10968 | need_version=no | |
10969 | library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' | |
10970 | soname_spec='${libname}${release}${shared_ext}$major' | |
10971 | shlibpath_var=LD_LIBRARY_PATH | |
10972 | shlibpath_overrides_runpath=no | |
10973 | hardcode_into_libs=yes | |
10974 | dynamic_linker='NetBSD ld.elf_so' | |
10975 | ;; | |
10976 | ||
10929 | 10977 | netbsd*) |
10930 | 10978 | version_type=sunos |
10931 | 10979 | need_lib_prefix=no |
13647 | 13695 | } |
13648 | 13696 | |
13649 | 13697 | _ACEOF |
13650 | if ac_fn_c_try_link "$LINENO"; then : | |
13651 | ||
13652 | ||
13653 | $as_echo "#define CONFIG_DIRECTWRITE 1" >>confdefs.h | |
13698 | if ac_fn_c_try_compile "$LINENO"; then : | |
13654 | 13699 | |
13655 | 13700 | directwrite=true |
13656 | 13701 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 |
13657 | 13702 | $as_echo "yes" >&6; } |
13703 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Win32 desktop APIs" >&5 | |
13704 | $as_echo_n "checking for Win32 desktop APIs... " >&6; } | |
13705 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
13706 | /* end confdefs.h. */ | |
13707 | ||
13708 | ||
13709 | #include <winapifamily.h> | |
13710 | #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) | |
13711 | #error Win32 desktop APIs are available | |
13712 | #endif | |
13713 | ||
13714 | int | |
13715 | main () | |
13716 | { | |
13717 | ; | |
13718 | ; | |
13719 | return 0; | |
13720 | } | |
13721 | ||
13722 | _ACEOF | |
13723 | if ac_fn_c_try_compile "$LINENO"; then : | |
13724 | ||
13725 | # WinRT/UWP/app build: GDI and LoadLibrary are | |
13726 | # unavailable, but DirectWrite is always present | |
13727 | LIBS="$LIBS -ldwrite" | |
13728 | ||
13729 | $as_echo "#define CONFIG_DIRECTWRITE 1" >>confdefs.h | |
13730 | ||
13731 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
13732 | $as_echo "no" >&6; } | |
13733 | ||
13734 | else | |
13735 | ||
13736 | # Win32/desktop build: GDI is always present; | |
13737 | # DirectWrite is optional but can be loaded via LoadLibrary | |
13738 | LIBS="$LIBS -lgdi32" | |
13739 | ||
13740 | $as_echo "#define CONFIG_DIRECTWRITE 1" >>confdefs.h | |
13741 | ||
13742 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
13743 | $as_echo "yes" >&6; } | |
13744 | ||
13745 | fi | |
13746 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
13658 | 13747 | |
13659 | 13748 | else |
13660 | 13749 | |
13663 | 13752 | $as_echo "no" >&6; } |
13664 | 13753 | |
13665 | 13754 | fi |
13666 | rm -f core conftest.err conftest.$ac_objext \ | |
13667 | conftest$ac_exeext conftest.$ac_ext | |
13755 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
13668 | 13756 | |
13669 | 13757 | fi |
13670 | 13758 | |
15822 | 15910 | { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 |
15823 | 15911 | $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} |
15824 | 15912 | as_fn_error $? "Something went wrong bootstrapping makefile fragments |
15825 | for automatic dependency tracking. Try re-running configure with the | |
15913 | for automatic dependency tracking. If GNU make was not used, consider | |
15914 | re-running the configure script with MAKE=\"gmake\" (or whatever is | |
15915 | necessary). You can also try re-running configure with the | |
15826 | 15916 | '--disable-dependency-tracking' option to at least be able to build |
15827 | 15917 | the package (albeit without support for automatic dependency tracking). |
15828 | 15918 | See \`config.log' for more details" "$LINENO" 5; } |
15849 | 15939 | cat <<_LT_EOF >> "$cfgfile" |
15850 | 15940 | #! $SHELL |
15851 | 15941 | # Generated automatically by $as_me ($PACKAGE) $VERSION |
15852 | # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: | |
15853 | 15942 | # NOTE: Changes made to this file will be lost: look at ltmain.sh. |
15854 | 15943 | |
15855 | 15944 | # Provide generalized library-building support services. |
27 | 27 | AC_ARG_ENABLE([fontconfig], AS_HELP_STRING([--disable-fontconfig], |
28 | 28 | [disable fontconfig support @<:@default=enabled@:>@])) |
29 | 29 | AC_ARG_ENABLE([directwrite], AS_HELP_STRING([--disable-directwrite], |
30 | [disable DirectWrite support (win32 only) @<:@default=check@:>@])) | |
30 | [disable DirectWrite support (Windows only) @<:@default=check@:>@])) | |
31 | 31 | AC_ARG_ENABLE([coretext], AS_HELP_STRING([--disable-coretext], |
32 | 32 | [disable CoreText support (OSX only) @<:@default=check@:>@])) |
33 | 33 | AC_ARG_ENABLE([require-system-font-provider], AS_HELP_STRING([--disable-require-system-font-provider], |
143 | 143 | AS_IF([test "x$enable_directwrite" != xno], [ |
144 | 144 | # Linking to DirectWrite directly only works from Windows |
145 | 145 | AC_MSG_CHECKING([for DIRECTWRITE]) |
146 | AC_LINK_IFELSE([ | |
146 | AC_COMPILE_IFELSE([ | |
147 | 147 | AC_LANG_PROGRAM([[#include <windows.h>]], [[;]]) |
148 | 148 | ], [ |
149 | AC_DEFINE(CONFIG_DIRECTWRITE, 1, [found DirectWrite]) | |
150 | 149 | directwrite=true |
151 | 150 | AC_MSG_RESULT([yes]) |
151 | AC_MSG_CHECKING([for Win32 desktop APIs]) | |
152 | AC_COMPILE_IFELSE([ | |
153 | AC_LANG_PROGRAM([[ | |
154 | #include <winapifamily.h> | |
155 | #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) | |
156 | #error Win32 desktop APIs are available | |
157 | #endif | |
158 | ]], [[;]]) | |
159 | ], [ | |
160 | # WinRT/UWP/app build: GDI and LoadLibrary are | |
161 | # unavailable, but DirectWrite is always present | |
162 | LIBS="$LIBS -ldwrite" | |
163 | AC_DEFINE(CONFIG_DIRECTWRITE, 1, [found DirectWrite (WinRT/UWP)]) | |
164 | AC_MSG_RESULT([no]) | |
165 | ], [ | |
166 | # Win32/desktop build: GDI is always present; | |
167 | # DirectWrite is optional but can be loaded via LoadLibrary | |
168 | LIBS="$LIBS -lgdi32" | |
169 | AC_DEFINE(CONFIG_DIRECTWRITE, 1, [found DirectWrite and GDI (Win32)]) | |
170 | AC_MSG_RESULT([yes]) | |
171 | ]) | |
152 | 172 | ], [ |
153 | 173 | directwrite=false |
154 | 174 | AC_MSG_RESULT([no]) |
0 | libass (1:0.15.1+git20210815.1.a8456e6-1) UNRELEASED; urgency=low | |
1 | ||
2 | * New upstream snapshot. | |
3 | ||
4 | -- Debian Janitor <janitor@jelmer.uk> Mon, 16 Aug 2021 17:13:08 -0000 | |
5 | ||
0 | 6 | libass (1:0.15.1-2) unstable; urgency=medium |
1 | 7 | |
2 | 8 | * Upload to unstable |
2 | 2 | |
3 | 3 | scriptversion=2018-03-07.03; # UTC |
4 | 4 | |
5 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. | |
5 | # Copyright (C) 1999-2021 Free Software Foundation, Inc. | |
6 | 6 | |
7 | 7 | # This program is free software; you can redistribute it and/or modify |
8 | 8 | # it under the terms of the GNU General Public License as published by |
0 | 0 | #!/bin/sh |
1 | 1 | # install - install a program, script, or datafile |
2 | 2 | |
3 | scriptversion=2018-03-11.20; # UTC | |
3 | scriptversion=2020-11-14.01; # UTC | |
4 | 4 | |
5 | 5 | # This originates from X11R5 (mit/util/scripts/install.sh), which was |
6 | 6 | # later released in X11R6 (xc/config/util/install.sh) with the |
68 | 68 | # Desired mode of installed file. |
69 | 69 | mode=0755 |
70 | 70 | |
71 | # Create dirs (including intermediate dirs) using mode 755. | |
72 | # This is like GNU 'install' as of coreutils 8.32 (2020). | |
73 | mkdir_umask=22 | |
74 | ||
75 | backupsuffix= | |
71 | 76 | chgrpcmd= |
72 | 77 | chmodcmd=$chmodprog |
73 | 78 | chowncmd= |
98 | 103 | --version display version info and exit. |
99 | 104 | |
100 | 105 | -c (ignored) |
101 | -C install only if different (preserve the last data modification time) | |
106 | -C install only if different (preserve data modification time) | |
102 | 107 | -d create directories instead of installing files. |
103 | 108 | -g GROUP $chgrpprog installed files to GROUP. |
104 | 109 | -m MODE $chmodprog installed files to MODE. |
105 | 110 | -o USER $chownprog installed files to USER. |
111 | -p pass -p to $cpprog. | |
106 | 112 | -s $stripprog installed files. |
113 | -S SUFFIX attempt to back up existing files, with suffix SUFFIX. | |
107 | 114 | -t DIRECTORY install into DIRECTORY. |
108 | 115 | -T report an error if DSTFILE is a directory. |
109 | 116 | |
110 | 117 | Environment variables override the default commands: |
111 | 118 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG |
112 | 119 | RMPROG STRIPPROG |
120 | ||
121 | By default, rm is invoked with -f; when overridden with RMPROG, | |
122 | it's up to you to specify -f if you want it. | |
123 | ||
124 | If -S is not specified, no backups are attempted. | |
125 | ||
126 | Email bug reports to bug-automake@gnu.org. | |
127 | Automake home page: https://www.gnu.org/software/automake/ | |
113 | 128 | " |
114 | 129 | |
115 | 130 | while test $# -ne 0; do |
136 | 151 | -o) chowncmd="$chownprog $2" |
137 | 152 | shift;; |
138 | 153 | |
154 | -p) cpprog="$cpprog -p";; | |
155 | ||
139 | 156 | -s) stripcmd=$stripprog;; |
157 | ||
158 | -S) backupsuffix="$2" | |
159 | shift;; | |
140 | 160 | |
141 | 161 | -t) |
142 | 162 | is_target_a_directory=always |
254 | 274 | dstdir=$dst |
255 | 275 | test -d "$dstdir" |
256 | 276 | dstdir_status=$? |
277 | # Don't chown directories that already exist. | |
278 | if test $dstdir_status = 0; then | |
279 | chowncmd="" | |
280 | fi | |
257 | 281 | else |
258 | 282 | |
259 | 283 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command |
300 | 324 | if test $dstdir_status != 0; then |
301 | 325 | case $posix_mkdir in |
302 | 326 | '') |
303 | # Create intermediate dirs using mode 755 as modified by the umask. | |
304 | # This is like FreeBSD 'install' as of 1997-10-28. | |
305 | umask=`umask` | |
306 | case $stripcmd.$umask in | |
307 | # Optimize common cases. | |
308 | *[2367][2367]) mkdir_umask=$umask;; | |
309 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; | |
310 | ||
311 | *[0-7]) | |
312 | mkdir_umask=`expr $umask + 22 \ | |
313 | - $umask % 100 % 40 + $umask % 20 \ | |
314 | - $umask % 10 % 4 + $umask % 2 | |
315 | `;; | |
316 | *) mkdir_umask=$umask,go-w;; | |
317 | esac | |
318 | ||
319 | 327 | # With -d, create the new directory with the user-specified mode. |
320 | 328 | # Otherwise, rely on $mkdir_umask. |
321 | 329 | if test -n "$dir_arg"; then |
325 | 333 | fi |
326 | 334 | |
327 | 335 | posix_mkdir=false |
328 | case $umask in | |
329 | *[123567][0-7][0-7]) | |
330 | # POSIX mkdir -p sets u+wx bits regardless of umask, which | |
331 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. | |
332 | ;; | |
333 | *) | |
334 | # Note that $RANDOM variable is not portable (e.g. dash); Use it | |
335 | # here however when possible just to lower collision chance. | |
336 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ | |
337 | ||
338 | trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 | |
339 | ||
340 | # Because "mkdir -p" follows existing symlinks and we likely work | |
341 | # directly in world-writeable /tmp, make sure that the '$tmpdir' | |
342 | # directory is successfully created first before we actually test | |
343 | # 'mkdir -p' feature. | |
344 | if (umask $mkdir_umask && | |
345 | $mkdirprog $mkdir_mode "$tmpdir" && | |
346 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 | |
347 | then | |
348 | if test -z "$dir_arg" || { | |
349 | # Check for POSIX incompatibilities with -m. | |
350 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or | |
351 | # other-writable bit of parent directory when it shouldn't. | |
352 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. | |
353 | test_tmpdir="$tmpdir/a" | |
354 | ls_ld_tmpdir=`ls -ld "$test_tmpdir"` | |
355 | case $ls_ld_tmpdir in | |
356 | d????-?r-*) different_mode=700;; | |
357 | d????-?--*) different_mode=755;; | |
358 | *) false;; | |
359 | esac && | |
360 | $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { | |
361 | ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` | |
362 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" | |
363 | } | |
364 | } | |
365 | then posix_mkdir=: | |
366 | fi | |
367 | rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" | |
368 | else | |
369 | # Remove any dirs left behind by ancient mkdir implementations. | |
370 | rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null | |
371 | fi | |
372 | trap '' 0;; | |
373 | esac;; | |
336 | # The $RANDOM variable is not portable (e.g., dash). Use it | |
337 | # here however when possible just to lower collision chance. | |
338 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ | |
339 | ||
340 | trap ' | |
341 | ret=$? | |
342 | rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null | |
343 | exit $ret | |
344 | ' 0 | |
345 | ||
346 | # Because "mkdir -p" follows existing symlinks and we likely work | |
347 | # directly in world-writeable /tmp, make sure that the '$tmpdir' | |
348 | # directory is successfully created first before we actually test | |
349 | # 'mkdir -p'. | |
350 | if (umask $mkdir_umask && | |
351 | $mkdirprog $mkdir_mode "$tmpdir" && | |
352 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 | |
353 | then | |
354 | if test -z "$dir_arg" || { | |
355 | # Check for POSIX incompatibilities with -m. | |
356 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or | |
357 | # other-writable bit of parent directory when it shouldn't. | |
358 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. | |
359 | test_tmpdir="$tmpdir/a" | |
360 | ls_ld_tmpdir=`ls -ld "$test_tmpdir"` | |
361 | case $ls_ld_tmpdir in | |
362 | d????-?r-*) different_mode=700;; | |
363 | d????-?--*) different_mode=755;; | |
364 | *) false;; | |
365 | esac && | |
366 | $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { | |
367 | ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` | |
368 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" | |
369 | } | |
370 | } | |
371 | then posix_mkdir=: | |
372 | fi | |
373 | rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" | |
374 | else | |
375 | # Remove any dirs left behind by ancient mkdir implementations. | |
376 | rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null | |
377 | fi | |
378 | trap '' 0;; | |
374 | 379 | esac |
375 | 380 | |
376 | 381 | if |
381 | 386 | then : |
382 | 387 | else |
383 | 388 | |
384 | # The umask is ridiculous, or mkdir does not conform to POSIX, | |
389 | # mkdir does not conform to POSIX, | |
385 | 390 | # or it failed possibly due to a race condition. Create the |
386 | 391 | # directory the slow way, step by step, checking for races as we go. |
387 | 392 | |
410 | 415 | prefixes= |
411 | 416 | else |
412 | 417 | if $posix_mkdir; then |
413 | (umask=$mkdir_umask && | |
418 | (umask $mkdir_umask && | |
414 | 419 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break |
415 | 420 | # Don't fail if two instances are running concurrently. |
416 | 421 | test -d "$prefix" || exit 1 |
450 | 455 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 |
451 | 456 | |
452 | 457 | # Copy the file name to the temp name. |
453 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && | |
458 | (umask $cp_umask && | |
459 | { test -z "$stripcmd" || { | |
460 | # Create $dsttmp read-write so that cp doesn't create it read-only, | |
461 | # which would cause strip to fail. | |
462 | if test -z "$doit"; then | |
463 | : >"$dsttmp" # No need to fork-exec 'touch'. | |
464 | else | |
465 | $doit touch "$dsttmp" | |
466 | fi | |
467 | } | |
468 | } && | |
469 | $doit_exec $cpprog "$src" "$dsttmp") && | |
454 | 470 | |
455 | 471 | # and set any options; do chmod last to preserve setuid bits. |
456 | 472 | # |
476 | 492 | then |
477 | 493 | rm -f "$dsttmp" |
478 | 494 | else |
495 | # If $backupsuffix is set, and the file being installed | |
496 | # already exists, attempt a backup. Don't worry if it fails, | |
497 | # e.g., if mv doesn't support -f. | |
498 | if test -n "$backupsuffix" && test -f "$dst"; then | |
499 | $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null | |
500 | fi | |
501 | ||
479 | 502 | # Rename the file to the real destination. |
480 | 503 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || |
481 | 504 | |
490 | 513 | # file should still install successfully. |
491 | 514 | { |
492 | 515 | test ! -f "$dst" || |
493 | $doit $rmcmd -f "$dst" 2>/dev/null || | |
516 | $doit $rmcmd "$dst" 2>/dev/null || | |
494 | 517 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && |
495 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } | |
518 | { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } | |
496 | 519 | } || |
497 | 520 | { echo "$0: cannot unlink or rename $dst" >&2 |
498 | 521 | (exit 1); exit 1 |
17 | 17 | x86/cpuid.h |
18 | 18 | |
19 | 19 | SRC_FONTCONFIG = ass_fontconfig.c ass_fontconfig.h |
20 | SRC_DIRECTWRITE = ass_directwrite.c ass_directwrite.h dwrite_c.h | |
20 | SRC_DIRECTWRITE = ass_directwrite.c ass_directwrite.h ass_directwrite_info_template.h dwrite_c.h | |
21 | 21 | SRC_CORETEXT = ass_coretext.c ass_coretext.h |
22 | 22 | |
23 | 23 | lib_LTLIBRARIES = libass.la |
0 | # Makefile.in generated by automake 1.16.1 from Makefile.am. | |
0 | # Makefile.in generated by automake 1.16.4 from Makefile.am. | |
1 | 1 | # @configure_input@ |
2 | 2 | |
3 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. | |
3 | # Copyright (C) 1994-2021 Free Software Foundation, Inc. | |
4 | 4 | |
5 | 5 | # This Makefile.in is free software; the Free Software Foundation |
6 | 6 | # gives unlimited permission to copy and/or distribute it, |
146 | 146 | ass_drawing.h ass_drawing.c ass_rasterizer.h ass_rasterizer.c \ |
147 | 147 | ass_rasterizer_c.c ass_bitmap.h ass_bitmap.c ass_blur.c \ |
148 | 148 | ass_func_template.h ass_fontconfig.c ass_fontconfig.h \ |
149 | ass_directwrite.c ass_directwrite.h dwrite_c.h ass_coretext.c \ | |
149 | ass_directwrite.c ass_directwrite.h \ | |
150 | ass_directwrite_info_template.h dwrite_c.h ass_coretext.c \ | |
150 | 151 | ass_coretext.h x86/rasterizer.asm x86/blend_bitmaps.asm \ |
151 | 152 | x86/be_blur.asm x86/blur.asm x86/cpuid.asm x86/cpuid.h |
152 | 153 | am__objects_1 = ass_fontconfig.lo |
243 | 244 | unique=`for i in $$list; do \ |
244 | 245 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
245 | 246 | done | $(am__uniquify_input)` |
246 | ETAGS = etags | |
247 | CTAGS = ctags | |
248 | 247 | am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp |
249 | 248 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
250 | 249 | ACLOCAL = @ACLOCAL@ |
262 | 261 | CFLAGS = @CFLAGS@ |
263 | 262 | CPP = @CPP@ |
264 | 263 | CPPFLAGS = @CPPFLAGS@ |
264 | CSCOPE = @CSCOPE@ | |
265 | CTAGS = @CTAGS@ | |
265 | 266 | CYGPATH_W = @CYGPATH_W@ |
266 | 267 | DEFS = @DEFS@ |
267 | 268 | DEPDIR = @DEPDIR@ |
272 | 273 | ECHO_N = @ECHO_N@ |
273 | 274 | ECHO_T = @ECHO_T@ |
274 | 275 | EGREP = @EGREP@ |
276 | ETAGS = @ETAGS@ | |
275 | 277 | EXEEXT = @EXEEXT@ |
276 | 278 | FGREP = @FGREP@ |
277 | 279 | FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ |
373 | 375 | prefix = @prefix@ |
374 | 376 | program_transform_name = @program_transform_name@ |
375 | 377 | psdir = @psdir@ |
378 | runstatedir = @runstatedir@ | |
376 | 379 | sbindir = @sbindir@ |
377 | 380 | sharedstatedir = @sharedstatedir@ |
378 | 381 | srcdir = @srcdir@ |
396 | 399 | x86/cpuid.h |
397 | 400 | |
398 | 401 | SRC_FONTCONFIG = ass_fontconfig.c ass_fontconfig.h |
399 | SRC_DIRECTWRITE = ass_directwrite.c ass_directwrite.h dwrite_c.h | |
402 | SRC_DIRECTWRITE = ass_directwrite.c ass_directwrite.h ass_directwrite_info_template.h dwrite_c.h | |
400 | 403 | SRC_CORETEXT = ass_coretext.c ass_coretext.h |
401 | 404 | lib_LTLIBRARIES = libass.la |
402 | 405 | libass_la_SOURCES = ass.h ass.c ass_types.h ass_utils.h ass_utils.c \ |
636 | 639 | |
637 | 640 | distclean-tags: |
638 | 641 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
639 | ||
640 | 642 | distdir: $(BUILT_SOURCES) |
641 | 643 | $(MAKE) $(AM_MAKEFLAGS) distdir-am |
642 | 644 |
125 | 125 | return ret; |
126 | 126 | } |
127 | 127 | |
128 | static bool fill_family_name(CTFontDescriptorRef fontd, | |
129 | ASS_FontProviderMetaData *info) | |
130 | { | |
131 | if (info->n_family) | |
132 | return true; | |
133 | ||
134 | char *family_name = get_name(fontd, kCTFontFamilyNameAttribute); | |
135 | if (!family_name) | |
136 | return false; | |
137 | ||
138 | info->families = malloc(sizeof(char *)); | |
139 | if (!info->families) { | |
140 | free(family_name); | |
141 | return false; | |
142 | } | |
143 | ||
144 | info->families[0] = family_name; | |
145 | info->n_family++; | |
146 | return true; | |
147 | } | |
148 | ||
149 | static bool get_font_info_ct(ASS_Library *lib, FT_Library ftlib, | |
150 | CTFontDescriptorRef fontd, | |
128 | static bool get_font_info_ct(CTFontDescriptorRef fontd, | |
151 | 129 | char **path_out, |
152 | 130 | ASS_FontProviderMetaData *info) |
153 | 131 | { |
159 | 137 | } |
160 | 138 | |
161 | 139 | char *ps_name = get_name(fontd, kCTFontNameAttribute); |
140 | info->postscript_name = ps_name; | |
162 | 141 | if (!ps_name) |
163 | 142 | return false; |
164 | 143 | |
165 | bool got_info = ass_get_font_info(lib, ftlib, path, ps_name, -1, false, info); | |
166 | free(ps_name); | |
167 | ||
168 | return got_info && fill_family_name(fontd, info); | |
169 | } | |
170 | ||
171 | static void process_descriptors(ASS_Library *lib, FT_Library ftlib, | |
172 | ASS_FontProvider *provider, CFArrayRef fontsd) | |
144 | char *family_name = get_name(fontd, kCTFontFamilyNameAttribute); | |
145 | info->extended_family = family_name; | |
146 | if (!family_name) | |
147 | return false; | |
148 | ||
149 | return true; | |
150 | } | |
151 | ||
152 | static void process_descriptors(ASS_FontProvider *provider, CFArrayRef fontsd) | |
173 | 153 | { |
174 | 154 | if (!fontsd) |
175 | 155 | return; |
180 | 160 | int index = -1; |
181 | 161 | |
182 | 162 | char *path = NULL; |
183 | if (get_font_info_ct(lib, ftlib, fontd, &path, &meta)) { | |
163 | if (get_font_info_ct(fontd, &path, &meta)) { | |
184 | 164 | CFRetain(fontd); |
185 | 165 | ass_font_provider_add_font(provider, &meta, path, index, (void*)fontd); |
186 | 166 | } |
187 | 167 | |
188 | for (int j = 0; j < meta.n_family; j++) | |
189 | free(meta.families[j]); | |
190 | ||
191 | for (int j = 0; j < meta.n_fullname; j++) | |
192 | free(meta.fullnames[j]); | |
193 | ||
194 | free(meta.families); | |
195 | free(meta.fullnames); | |
196 | ||
197 | 168 | free(meta.postscript_name); |
169 | free(meta.extended_family); | |
198 | 170 | |
199 | 171 | free(path); |
200 | 172 | } |
203 | 175 | static void match_fonts(void *priv, ASS_Library *lib, ASS_FontProvider *provider, |
204 | 176 | char *name) |
205 | 177 | { |
206 | FT_Library ftlib = priv; | |
207 | ||
208 | 178 | CFStringRef cfname = |
209 | 179 | CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8); |
210 | 180 | if (!cfname) |
241 | 211 | if (!descriptors) |
242 | 212 | goto cleanup; |
243 | 213 | |
244 | ctcoll = CTFontCollectionCreateWithFontDescriptors(descriptors, 0); | |
214 | const int nonzero = 1; | |
215 | CFNumberRef cfnonzero = CFNumberCreate(NULL, kCFNumberIntType, &nonzero); | |
216 | if (!cfnonzero) | |
217 | goto cleanup; | |
218 | CFDictionaryRef options = | |
219 | CFDictionaryCreate(NULL, | |
220 | (const void **)&kCTFontCollectionRemoveDuplicatesOption, | |
221 | (const void **)&cfnonzero, | |
222 | 1, NULL, NULL); | |
223 | CFRelease(cfnonzero); | |
224 | if (!options) | |
225 | goto cleanup; | |
226 | ||
227 | ctcoll = CTFontCollectionCreateWithFontDescriptors(descriptors, options); | |
228 | CFRelease(options); | |
245 | 229 | if (!ctcoll) |
246 | 230 | goto cleanup; |
247 | 231 | |
249 | 233 | if (!fontsd) |
250 | 234 | goto cleanup; |
251 | 235 | |
252 | process_descriptors(lib, ftlib, provider, fontsd); | |
236 | process_descriptors(provider, fontsd); | |
253 | 237 | |
254 | 238 | cleanup: |
255 | 239 | SAFE_CFRelease(fontsd); |
265 | 249 | static char *get_fallback(void *priv, ASS_Library *lib, |
266 | 250 | const char *family, uint32_t codepoint) |
267 | 251 | { |
268 | FT_Library ftlib = priv; | |
269 | ||
270 | 252 | CFStringRef name = CFStringCreateWithBytes( |
271 | 253 | 0, (UInt8 *)family, strlen(family), kCFStringEncodingUTF8, false); |
272 | 254 | if (!name) |
293 | 275 | if (!fb) |
294 | 276 | return NULL; |
295 | 277 | |
296 | CTFontDescriptorRef fontd = CTFontCopyFontDescriptor(fb); | |
278 | CFStringRef cffamily = CTFontCopyFamilyName(fb); | |
297 | 279 | CFRelease(fb); |
298 | if (!fontd) | |
299 | return NULL; | |
300 | ||
301 | char *res_name = NULL; | |
302 | char *path = NULL; | |
303 | ASS_FontProviderMetaData meta = {0}; | |
304 | if (get_font_info_ct(lib, ftlib, fontd, &path, &meta)) | |
305 | res_name = meta.families[0]; | |
306 | ||
307 | CFRelease(fontd); | |
308 | ||
309 | for (int i = 1 /* skip res_name */; i < meta.n_family; i++) | |
310 | free(meta.families[i]); | |
311 | ||
312 | for (int i = 0; i < meta.n_fullname; i++) | |
313 | free(meta.fullnames[i]); | |
314 | ||
315 | free(meta.families); | |
316 | free(meta.fullnames); | |
317 | ||
318 | free(meta.postscript_name); | |
319 | ||
320 | free(path); | |
321 | ||
322 | return res_name; | |
280 | if (!cffamily) | |
281 | return NULL; | |
282 | ||
283 | char *res_family = cfstr2buf(cffamily); | |
284 | CFRelease(cffamily); | |
285 | ||
286 | return res_family; | |
323 | 287 | } |
324 | 288 | |
325 | 289 | static void get_substitutions(void *priv, const char *name, |
342 | 306 | ass_coretext_add_provider(ASS_Library *lib, ASS_FontSelector *selector, |
343 | 307 | const char *config, FT_Library ftlib) |
344 | 308 | { |
345 | return ass_font_provider_new(selector, &coretext_callbacks, ftlib); | |
346 | } | |
309 | return ass_font_provider_new(selector, &coretext_callbacks, NULL); | |
310 | } |
20 | 20 | #include "ass_compat.h" |
21 | 21 | |
22 | 22 | #include <initguid.h> |
23 | #include <ole2.h> | |
24 | #include <shobjidl.h> | |
23 | #include <wchar.h> | |
25 | 24 | |
26 | 25 | #include "dwrite_c.h" |
27 | 26 | |
28 | 27 | #include "ass_directwrite.h" |
29 | 28 | #include "ass_utils.h" |
30 | 29 | |
31 | #define NAME_MAX_LENGTH 256 | |
32 | 30 | #define FALLBACK_DEFAULT_FONT L"Arial" |
33 | 31 | |
34 | 32 | static const ASS_FontMapping font_substitutions[] = { |
37 | 35 | {"monospace", "Courier New"} |
38 | 36 | }; |
39 | 37 | |
38 | typedef struct ASS_SharedHDC ASS_SharedHDC; | |
39 | ||
40 | #if ASS_WINAPI_DESKTOP | |
41 | ||
42 | struct ASS_SharedHDC { | |
43 | HDC hdc; | |
44 | unsigned ref_count; | |
45 | }; | |
46 | ||
47 | static ASS_SharedHDC *hdc_retain(ASS_SharedHDC *shared_hdc) | |
48 | { | |
49 | shared_hdc->ref_count++; | |
50 | return shared_hdc; | |
51 | } | |
52 | ||
53 | static void hdc_release(ASS_SharedHDC *shared_hdc) | |
54 | { | |
55 | if (!--shared_hdc->ref_count) { | |
56 | DeleteDC(shared_hdc->hdc); | |
57 | free(shared_hdc); | |
58 | } | |
59 | } | |
60 | ||
61 | #endif | |
62 | ||
40 | 63 | /* |
41 | 64 | * The private data stored for every font, detected by this backend. |
42 | 65 | */ |
43 | 66 | typedef struct { |
67 | #if ASS_WINAPI_DESKTOP | |
68 | ASS_SharedHDC *shared_hdc; | |
69 | #endif | |
44 | 70 | IDWriteFont *font; |
45 | 71 | IDWriteFontFace *face; |
46 | 72 | IDWriteFontFileStream *stream; |
47 | 73 | } FontPrivate; |
48 | 74 | |
49 | 75 | typedef struct { |
76 | #if ASS_WINAPI_DESKTOP | |
50 | 77 | HMODULE directwrite_lib; |
78 | #endif | |
51 | 79 | IDWriteFactory *factory; |
52 | 80 | IDWriteGdiInterop *gdi_interop; |
53 | 81 | } ProviderPrivate; |
376 | 404 | if (code == 0) |
377 | 405 | return true; |
378 | 406 | |
379 | hr = IDWriteFont_HasCharacter(priv->font, code, &exists); | |
380 | if (FAILED(hr)) | |
381 | return false; | |
407 | if (priv->font) { | |
408 | hr = IDWriteFont_HasCharacter(priv->font, code, &exists); | |
409 | if (FAILED(hr)) | |
410 | return false; | |
411 | } else { | |
412 | uint16_t glyph_index; | |
413 | hr = IDWriteFontFace_GetGlyphIndices(priv->face, &code, 1, &glyph_index); | |
414 | if (FAILED(hr)) | |
415 | return false; | |
416 | exists = !!glyph_index; | |
417 | } | |
382 | 418 | |
383 | 419 | return exists; |
384 | 420 | } |
391 | 427 | ProviderPrivate *provider_priv = (ProviderPrivate *)priv; |
392 | 428 | provider_priv->gdi_interop->lpVtbl->Release(provider_priv->gdi_interop); |
393 | 429 | provider_priv->factory->lpVtbl->Release(provider_priv->factory); |
430 | #if ASS_WINAPI_DESKTOP | |
394 | 431 | FreeLibrary(provider_priv->directwrite_lib); |
432 | #endif | |
395 | 433 | free(provider_priv); |
396 | 434 | } |
397 | 435 | |
404 | 442 | { |
405 | 443 | FontPrivate *priv = (FontPrivate *) data; |
406 | 444 | |
407 | IDWriteFont_Release(priv->font); | |
445 | if (priv->font != NULL) | |
446 | IDWriteFont_Release(priv->font); | |
408 | 447 | if (priv->face != NULL) |
409 | 448 | IDWriteFontFace_Release(priv->face); |
410 | 449 | if (priv->stream != NULL) |
411 | 450 | IDWriteFontFileStream_Release(priv->stream); |
451 | ||
452 | #if ASS_WINAPI_DESKTOP | |
453 | hdc_release(priv->shared_hdc); | |
454 | #endif | |
412 | 455 | |
413 | 456 | free(priv); |
414 | 457 | } |
423 | 466 | chars[1] = (codepoint & 0x3FF) + 0xDC00; |
424 | 467 | return 2; |
425 | 468 | } |
469 | } | |
470 | ||
471 | static char *get_utf8_name(IDWriteLocalizedStrings *names, int k) | |
472 | { | |
473 | wchar_t *temp_name = NULL; | |
474 | char *mbName = NULL; | |
475 | ||
476 | UINT32 length; | |
477 | HRESULT hr = IDWriteLocalizedStrings_GetStringLength(names, k, &length); | |
478 | if (FAILED(hr)) | |
479 | goto cleanup; | |
480 | ||
481 | if (length >= (UINT32) -1 || length + (size_t) 1 > SIZE_MAX / sizeof(wchar_t)) | |
482 | goto cleanup; | |
483 | ||
484 | temp_name = (wchar_t *) malloc((length + 1) * sizeof(wchar_t)); | |
485 | if (!temp_name) | |
486 | goto cleanup; | |
487 | ||
488 | hr = IDWriteLocalizedStrings_GetString(names, k, temp_name, length + 1); | |
489 | if (FAILED(hr)) | |
490 | goto cleanup; | |
491 | ||
492 | int size_needed = | |
493 | WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0, NULL, NULL); | |
494 | if (!size_needed) | |
495 | goto cleanup; | |
496 | ||
497 | mbName = (char *) malloc(size_needed); | |
498 | if (!mbName) | |
499 | goto cleanup; | |
500 | ||
501 | WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); | |
502 | ||
503 | cleanup: | |
504 | free(temp_name); | |
505 | return mbName; | |
426 | 506 | } |
427 | 507 | |
428 | 508 | static char *get_fallback(void *priv, ASS_Library *lib, |
471 | 551 | IDWriteTextLayout_Release(text_layout); |
472 | 552 | IDWriteTextFormat_Release(text_format); |
473 | 553 | |
554 | // DirectWrite may not have found a valid fallback, so check that | |
555 | // the selected font actually has the requested glyph. | |
556 | BOOL exists = FALSE; | |
557 | if (codepoint > 0) { | |
558 | hr = IDWriteFont_HasCharacter(font, codepoint, &exists); | |
559 | if (FAILED(hr) || !exists) { | |
560 | IDWriteFont_Release(font); | |
561 | return NULL; | |
562 | } | |
563 | } | |
564 | ||
474 | 565 | // Now, just extract the first family name |
475 | BOOL exists = FALSE; | |
476 | 566 | IDWriteLocalizedStrings *familyNames = NULL; |
477 | 567 | hr = IDWriteFont_GetInformationalStrings(font, |
478 | 568 | DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, |
482 | 572 | return NULL; |
483 | 573 | } |
484 | 574 | |
485 | wchar_t temp_name[NAME_MAX_LENGTH]; | |
486 | hr = IDWriteLocalizedStrings_GetString(familyNames, 0, temp_name, NAME_MAX_LENGTH); | |
487 | if (FAILED(hr)) { | |
488 | IDWriteLocalizedStrings_Release(familyNames); | |
489 | IDWriteFont_Release(font); | |
490 | return NULL; | |
491 | } | |
492 | temp_name[NAME_MAX_LENGTH-1] = 0; | |
493 | ||
494 | // DirectWrite may not have found a valid fallback, so check that | |
495 | // the selected font actually has the requested glyph. | |
496 | if (codepoint > 0) { | |
497 | hr = IDWriteFont_HasCharacter(font, codepoint, &exists); | |
498 | if (FAILED(hr) || !exists) { | |
499 | IDWriteLocalizedStrings_Release(familyNames); | |
500 | IDWriteFont_Release(font); | |
501 | return NULL; | |
502 | } | |
503 | } | |
504 | ||
505 | int size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0,NULL, NULL); | |
506 | char *family = (char *) malloc(size_needed); | |
507 | WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, family, size_needed, NULL, NULL); | |
575 | char *family = get_utf8_name(familyNames, 0); | |
508 | 576 | |
509 | 577 | IDWriteLocalizedStrings_Release(familyNames); |
510 | 578 | IDWriteFont_Release(font); |
528 | 596 | } |
529 | 597 | } |
530 | 598 | |
531 | static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily, | |
532 | ASS_FontProvider *provider) | |
533 | { | |
534 | HRESULT hr; | |
535 | BOOL exists; | |
536 | wchar_t temp_name[NAME_MAX_LENGTH]; | |
537 | int size_needed; | |
599 | #define FONT_TYPE IDWriteFontFace3 | |
600 | #include "ass_directwrite_info_template.h" | |
601 | #undef FONT_TYPE | |
602 | ||
603 | static void add_font_face(IDWriteFontFace *face, ASS_FontProvider *provider, | |
604 | ASS_SharedHDC *shared_hdc) | |
605 | { | |
538 | 606 | ASS_FontProviderMetaData meta = {0}; |
539 | 607 | |
540 | meta.weight = IDWriteFont_GetWeight(font); | |
541 | meta.width = map_width(IDWriteFont_GetStretch(font)); | |
542 | ||
543 | DWRITE_FONT_STYLE style = IDWriteFont_GetStyle(font); | |
544 | meta.slant = (style == DWRITE_FONT_STYLE_NORMAL) ? FONT_SLANT_NONE : | |
545 | (style == DWRITE_FONT_STYLE_OBLIQUE)? FONT_SLANT_OBLIQUE : | |
546 | (style == DWRITE_FONT_STYLE_ITALIC) ? FONT_SLANT_ITALIC : FONT_SLANT_NONE; | |
547 | ||
548 | IDWriteLocalizedStrings *psNames; | |
549 | hr = IDWriteFont_GetInformationalStrings(font, | |
550 | DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames, &exists); | |
551 | if (FAILED(hr)) | |
552 | goto cleanup; | |
553 | ||
554 | if (exists) { | |
555 | hr = IDWriteLocalizedStrings_GetString(psNames, 0, temp_name, NAME_MAX_LENGTH); | |
556 | if (FAILED(hr)) { | |
557 | IDWriteLocalizedStrings_Release(psNames); | |
608 | IDWriteFontFace3 *face3; | |
609 | HRESULT hr = IDWriteFontFace_QueryInterface(face, &IID_IDWriteFontFace3, | |
610 | (void **) &face3); | |
611 | if (SUCCEEDED(hr) && face3) { | |
612 | bool success = get_font_info_IDWriteFontFace3(face3, &meta); | |
613 | IDWriteFontFace3_Release(face3); | |
614 | if (!success) | |
558 | 615 | goto cleanup; |
559 | } | |
560 | ||
561 | temp_name[NAME_MAX_LENGTH-1] = 0; | |
562 | size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0, NULL, NULL); | |
563 | char *mbName = (char *) malloc(size_needed); | |
564 | if (!mbName) { | |
565 | IDWriteLocalizedStrings_Release(psNames); | |
566 | goto cleanup; | |
567 | } | |
568 | WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); | |
569 | meta.postscript_name = mbName; | |
570 | ||
571 | IDWriteLocalizedStrings_Release(psNames); | |
572 | } | |
573 | ||
574 | IDWriteLocalizedStrings *fontNames; | |
575 | hr = IDWriteFont_GetInformationalStrings(font, | |
576 | DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames, &exists); | |
577 | if (FAILED(hr)) | |
578 | goto cleanup; | |
579 | ||
580 | if (exists) { | |
581 | meta.n_fullname = IDWriteLocalizedStrings_GetCount(fontNames); | |
582 | meta.fullnames = (char **) calloc(meta.n_fullname, sizeof(char *)); | |
583 | if (!meta.fullnames) { | |
584 | IDWriteLocalizedStrings_Release(fontNames); | |
585 | goto cleanup; | |
586 | } | |
587 | for (int k = 0; k < meta.n_fullname; k++) { | |
588 | hr = IDWriteLocalizedStrings_GetString(fontNames, k, | |
589 | temp_name, | |
590 | NAME_MAX_LENGTH); | |
591 | if (FAILED(hr)) { | |
592 | IDWriteLocalizedStrings_Release(fontNames); | |
593 | goto cleanup; | |
594 | } | |
595 | ||
596 | temp_name[NAME_MAX_LENGTH-1] = 0; | |
597 | size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0, NULL, NULL); | |
598 | char *mbName = (char *) malloc(size_needed); | |
599 | if (!mbName) { | |
600 | IDWriteLocalizedStrings_Release(fontNames); | |
601 | goto cleanup; | |
602 | } | |
603 | WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); | |
604 | meta.fullnames[k] = mbName; | |
605 | } | |
606 | IDWriteLocalizedStrings_Release(fontNames); | |
607 | } | |
608 | ||
609 | IDWriteLocalizedStrings *familyNames; | |
610 | hr = IDWriteFont_GetInformationalStrings(font, | |
611 | DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists); | |
612 | if (FAILED(hr) || !exists) | |
613 | hr = IDWriteFontFamily_GetFamilyNames(fontFamily, &familyNames); | |
614 | if (FAILED(hr)) | |
615 | goto cleanup; | |
616 | ||
617 | meta.n_family = IDWriteLocalizedStrings_GetCount(familyNames); | |
618 | meta.families = (char **) calloc(meta.n_family, sizeof(char *)); | |
619 | if (!meta.families) { | |
620 | IDWriteLocalizedStrings_Release(familyNames); | |
621 | goto cleanup; | |
622 | } | |
623 | for (int k = 0; k < meta.n_family; k++) { | |
624 | hr = IDWriteLocalizedStrings_GetString(familyNames, k, | |
625 | temp_name, | |
626 | NAME_MAX_LENGTH); | |
627 | if (FAILED(hr)) { | |
628 | IDWriteLocalizedStrings_Release(familyNames); | |
629 | goto cleanup; | |
630 | } | |
631 | ||
632 | temp_name[NAME_MAX_LENGTH-1] = 0; | |
633 | size_needed = WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, NULL, 0, NULL, NULL); | |
634 | char *mbName = (char *) malloc(size_needed); | |
635 | if (!mbName) { | |
636 | IDWriteLocalizedStrings_Release(familyNames); | |
637 | goto cleanup; | |
638 | } | |
639 | WideCharToMultiByte(CP_UTF8, 0, temp_name, -1, mbName, size_needed, NULL, NULL); | |
640 | meta.families[k] = mbName; | |
641 | } | |
642 | IDWriteLocalizedStrings_Release(familyNames); | |
616 | } | |
643 | 617 | |
644 | 618 | FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); |
645 | 619 | if (!font_priv) |
646 | 620 | goto cleanup; |
647 | font_priv->font = font; | |
648 | font = NULL; | |
621 | ||
622 | font_priv->face = face; | |
623 | face = NULL; | |
624 | ||
625 | #if ASS_WINAPI_DESKTOP | |
626 | font_priv->shared_hdc = hdc_retain(shared_hdc); | |
627 | #endif | |
649 | 628 | |
650 | 629 | ass_font_provider_add_font(provider, &meta, NULL, 0, font_priv); |
651 | 630 | |
664 | 643 | |
665 | 644 | free(meta.postscript_name); |
666 | 645 | |
646 | if (face) | |
647 | IDWriteFontFace_Release(face); | |
648 | } | |
649 | ||
650 | #if ASS_WINAPI_DESKTOP | |
651 | ||
652 | struct font_enum_priv { | |
653 | ASS_FontProvider *provider; | |
654 | IDWriteGdiInterop *gdi_interop; | |
655 | ASS_SharedHDC *shared_hdc; | |
656 | }; | |
657 | ||
658 | /* | |
659 | * Windows has three similar functions: EnumFonts, EnumFontFamilies | |
660 | * and EnumFontFamiliesEx, which were introduced at different times. | |
661 | * Each takes a callback, and the declared callback type is the same | |
662 | * for all three. However, the actual arguments passed to the callback | |
663 | * have also changed over time. Some changes match the introduction | |
664 | * of new EnumFont... variants, and some don't. Documentation has | |
665 | * changed over the years, too, so it can be hard to figure out what | |
666 | * types, and when, are safe for the callback to take. | |
667 | * | |
668 | * In the header files, FONTENUMPROC is declared to take: | |
669 | * CONST LOGFONT *, CONST TEXTMETRIC * | |
670 | * These are the baseline structs dating back to 16-bit Windows EnumFont. | |
671 | * | |
672 | * As of 2021, current versions of Microsoft's docs | |
673 | * for the EnumFontFamiliesEx callback use the same: | |
674 | * const LOGFONT *, const TEXTMETRIC * | |
675 | * and for the EnumFontFamilies callback use: | |
676 | * ENUMLOGFONT *, NEWTEXTMETRIC * | |
677 | * and mention that the first "can be cast as" ENUMLOGFONTEX or ENUMLOGFONTEXDV | |
678 | * while the second "can be an ENUMTEXTMETRIC structure" but for | |
679 | * non-TrueType fonts "is a pointer to a TEXTMETRIC structure". | |
680 | * | |
681 | * Docs from the 2000s (which include Win95/98/Me/NT/2000/XP details) use | |
682 | * ENUMLOGFONTEX *, NEWTEXTMETRICEX * | |
683 | * in the EnumFontFamiliesEx callback's definition: | |
684 | * https://web.archive.org/web/20050907052149 | |
685 | * /http://msdn.microsoft.com/library/en-us/gdi/fontext_9rmr.asp | |
686 | * and highlight these two extended struct types as advantages over | |
687 | * the EnumFontFamilies callback, suggesting that the actual arguments | |
688 | * to the EnumFontFamiliesEx callback have always been these two extended | |
689 | * structs. This is also reflected in the callback's parameter names | |
690 | * (which have stayed unchanged in the current docs). | |
691 | * EnumFontFamiliesEx itself was added in Windows NT 4.0 and 95. | |
692 | * | |
693 | * Similarly, the EnumFontFamilies callback's parameter names support | |
694 | * the idea that they have always used ENUMLOGFONT and NEWTEXTMETRIC. | |
695 | * | |
696 | * It seems the extra fields in NEWTEXTMETRIC[EX] compared to TEXTMETRIC | |
697 | * are merely zero-filled when they are irrelevant, rather than nonexistent | |
698 | * or inaccessible. This is further supported by the fact the later-still | |
699 | * struct ENUMTEXTMETRIC extends NEWTEXTMETRICEX even though the former | |
700 | * is/was (upon introduction) relevant only to PostScript fonts | |
701 | * while the latter is (supposedly) relevant only to TrueType fonts. | |
702 | * | |
703 | * Docs from the 2000s for ENUMLOGFONTEXDV and ENUMTEXTMETRIC: | |
704 | * https://web.archive.org/web/20050306200105 | |
705 | * /http://msdn.microsoft.com/library/en-us/gdi/fontext_15gy.asp | |
706 | * seem to assert that the callback receives these two further-extended | |
707 | * structs *if and only if* running on Windows 2000 or newer. | |
708 | * We don't need them, but if we did, we'd have to check (or assume) | |
709 | * Windows version, because this extension does not seem to have | |
710 | * an associated feature check. Moreover, these structs are given | |
711 | * to the callbacks of all three EnumFont... function variants. | |
712 | * So even EnumFonts actually uses the extended structs in 21st-century | |
713 | * Windows, but the declared callback type can no longer be changed | |
714 | * without breaking existing C++ code due to its strongly-typed pointers. | |
715 | * When targeting modern Windows, though, it seems safe for consumer | |
716 | * code to take the newest structs and cast the function pointer | |
717 | * to the declared callback type. | |
718 | */ | |
719 | static int CALLBACK font_enum_proc(const ENUMLOGFONTW *lpelf, | |
720 | const NEWTEXTMETRICW *lpntm, | |
721 | DWORD FontType, LPARAM lParam) | |
722 | { | |
723 | struct font_enum_priv *priv = (struct font_enum_priv *) lParam; | |
724 | HFONT hFont = NULL; | |
725 | HRESULT hr; | |
726 | ||
727 | if (FontType & RASTER_FONTTYPE) | |
728 | goto cleanup; | |
729 | ||
730 | hFont = CreateFontIndirectW(&lpelf->elfLogFont); | |
731 | if (!hFont) | |
732 | goto cleanup; | |
733 | ||
734 | HDC hdc = priv->shared_hdc->hdc; | |
735 | if (!SelectObject(hdc, hFont)) | |
736 | goto cleanup; | |
737 | ||
738 | wchar_t selected_name[LF_FACESIZE]; | |
739 | if (!GetTextFaceW(hdc, LF_FACESIZE, selected_name)) | |
740 | goto cleanup; | |
741 | if (wcsncmp(selected_name, lpelf->elfLogFont.lfFaceName, LF_FACESIZE)) { | |
742 | // A different font was selected. This can happen if the requested | |
743 | // name is subject to charset-specific font substitution while | |
744 | // EnumFont... enumerates additional charsets contained in the font. | |
745 | // Alternatively, the font may have disappeared in the meantime. | |
746 | // Either way, there's no use looking at this font any further. | |
747 | goto cleanup; | |
748 | } | |
749 | ||
750 | // For single-font files, we could also use GetFontData, but for font | |
751 | // collection files, GDI does not expose the current font index. | |
752 | // CreateFontFaceFromHdc is able to find it out using a private API; | |
753 | // and it may also be more efficient if it doesn't copy the data. | |
754 | // The downside is that we must keep the HDC alive, at least on Windows 7, | |
755 | // to prevent the font from being deleted and breaking the IDWriteFontFace. | |
756 | IDWriteFontFace *face = NULL; | |
757 | hr = IDWriteGdiInterop_CreateFontFaceFromHdc(priv->gdi_interop, | |
758 | hdc, &face); | |
759 | if (FAILED(hr) || !face) | |
760 | goto cleanup; | |
761 | ||
762 | add_font_face(face, priv->provider, priv->shared_hdc); | |
763 | ||
764 | cleanup: | |
765 | if (hFont) | |
766 | DeleteObject(hFont); | |
767 | ||
768 | return 1 /* continue enumerating */; | |
769 | } | |
770 | ||
771 | #else | |
772 | ||
773 | static void add_font_set(IDWriteFontSet *fontSet, ASS_FontProvider *provider) | |
774 | { | |
775 | UINT32 n = IDWriteFontSet_GetFontCount(fontSet); | |
776 | for (UINT32 i = 0; i < n; i++) { | |
777 | HRESULT hr; | |
778 | ||
779 | IDWriteFontFaceReference *faceRef; | |
780 | hr = IDWriteFontSet_GetFontFaceReference(fontSet, i, &faceRef); | |
781 | if (FAILED(hr) || !faceRef) | |
782 | continue; | |
783 | ||
784 | if (IDWriteFontFaceReference_GetLocality(faceRef) != DWRITE_LOCALITY_LOCAL) | |
785 | goto cleanup; | |
786 | ||
787 | // Simulations for bold or oblique are sometimes synthesized by | |
788 | // DirectWrite. We are only interested in physical fonts. | |
789 | if (IDWriteFontFaceReference_GetSimulations(faceRef) != 0) | |
790 | goto cleanup; | |
791 | ||
792 | IDWriteFontFace3 *face; | |
793 | hr = IDWriteFontFaceReference_CreateFontFace(faceRef, &face); | |
794 | if (FAILED(hr) || !face) | |
795 | goto cleanup; | |
796 | ||
797 | add_font_face((IDWriteFontFace *) face, provider, NULL); | |
798 | ||
799 | cleanup: | |
800 | IDWriteFontFaceReference_Release(faceRef); | |
801 | } | |
802 | } | |
803 | ||
804 | #define FONT_TYPE IDWriteFont | |
805 | #define FAMILY_AS_ARG | |
806 | #include "ass_directwrite_info_template.h" | |
807 | #undef FONT_TYPE | |
808 | #undef FAMILY_AS_ARG | |
809 | ||
810 | static void add_font(IDWriteFont *font, IDWriteFontFamily *fontFamily, | |
811 | ASS_FontProvider *provider) | |
812 | { | |
813 | ASS_FontProviderMetaData meta = {0}; | |
814 | if (!get_font_info_IDWriteFont(font, fontFamily, &meta)) | |
815 | goto cleanup; | |
816 | ||
817 | FontPrivate *font_priv = (FontPrivate *) calloc(1, sizeof(*font_priv)); | |
818 | if (!font_priv) | |
819 | goto cleanup; | |
820 | font_priv->font = font; | |
821 | font = NULL; | |
822 | ||
823 | ass_font_provider_add_font(provider, &meta, NULL, 0, font_priv); | |
824 | ||
825 | cleanup: | |
826 | if (meta.families) { | |
827 | for (int k = 0; k < meta.n_family; k++) | |
828 | free(meta.families[k]); | |
829 | free(meta.families); | |
830 | } | |
831 | ||
832 | if (meta.fullnames) { | |
833 | for (int k = 0; k < meta.n_fullname; k++) | |
834 | free(meta.fullnames[k]); | |
835 | free(meta.fullnames); | |
836 | } | |
837 | ||
838 | free(meta.postscript_name); | |
839 | ||
667 | 840 | if (font) |
668 | 841 | IDWriteFont_Release(font); |
669 | 842 | } |
670 | 843 | |
844 | #endif | |
845 | ||
671 | 846 | /* |
672 | 847 | * When a new font name is requested, called to load that font from Windows |
673 | 848 | */ |
675 | 850 | ASS_FontProvider *provider, char *name) |
676 | 851 | { |
677 | 852 | ProviderPrivate *provider_priv = (ProviderPrivate *)priv; |
678 | IDWriteFont *font = NULL; | |
679 | IDWriteFontFamily *fontFamily = NULL; | |
680 | LOGFONTW lf; | |
681 | HRESULT hr = S_OK; | |
682 | ||
683 | memset(&lf, 0, sizeof(LOGFONTW)); | |
684 | lf.lfWeight = FW_DONTCARE; | |
685 | lf.lfCharSet = DEFAULT_CHARSET; | |
686 | lf.lfOutPrecision = OUT_TT_PRECIS; | |
687 | lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |
688 | lf.lfQuality = ANTIALIASED_QUALITY; | |
689 | lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; | |
853 | LOGFONTW lf = {0}; | |
690 | 854 | |
691 | 855 | // lfFaceName can hold up to LF_FACESIZE wchars; truncate longer names |
692 | 856 | MultiByteToWideChar(CP_UTF8, 0, name, -1, lf.lfFaceName, LF_FACESIZE-1); |
693 | 857 | |
694 | hr = IDWriteGdiInterop_CreateFontFromLOGFONT(provider_priv->gdi_interop, &lf, &font); | |
695 | if (FAILED(hr) || !font) | |
858 | #if ASS_WINAPI_DESKTOP | |
859 | struct font_enum_priv enum_priv; | |
860 | ||
861 | enum_priv.shared_hdc = calloc(1, sizeof(ASS_SharedHDC)); | |
862 | if (!enum_priv.shared_hdc) | |
696 | 863 | return; |
697 | 864 | |
698 | hr = IDWriteFont_GetFontFamily(font, &fontFamily); | |
699 | if (FAILED(hr) || !fontFamily) | |
700 | goto cleanup; | |
701 | ||
702 | add_font(font, fontFamily, provider); | |
703 | ||
704 | IDWriteFontFamily_Release(fontFamily); | |
705 | ||
706 | return; | |
707 | ||
708 | cleanup: | |
709 | if (font) | |
865 | // Keep this HDC alive to keep the fonts alive. This seems to be necessary | |
866 | // on Windows 7, where the fonts can't be deleted as long as the DC lives | |
867 | // and where the converted IDWriteFontFaces only work as long as the fonts | |
868 | // aren't deleted, although not on Windows 10, where fonts can be deleted | |
869 | // even if the DC still lives but IDWriteFontFaces keep working even if | |
870 | // the fonts are deleted. | |
871 | // | |
872 | // But beware of threading: docs say CreateCompatibleDC(NULL) creates a DC | |
873 | // that is bound to the current thread and is deleted when the thread dies. | |
874 | // It's not forbidden to call libass functions from multiple threads | |
875 | // over the lifetime of a font provider, so this doesn't work for us. | |
876 | // Practical tests suggest that the docs are wrong and the DC actually | |
877 | // persists after its creating thread dies, but let's not rely on that. | |
878 | // The workaround is to do a longer dance that is effectively equivalent to | |
879 | // CreateCompatibleDC(NULL) but isn't specifically CreateCompatibleDC(NULL). | |
880 | HDC screen_dc = GetDC(NULL); | |
881 | if (!screen_dc) { | |
882 | free(enum_priv.shared_hdc); | |
883 | return; | |
884 | } | |
885 | HDC hdc = CreateCompatibleDC(screen_dc); | |
886 | ReleaseDC(NULL, screen_dc); | |
887 | if (!hdc) { | |
888 | free(enum_priv.shared_hdc); | |
889 | return; | |
890 | } | |
891 | ||
892 | enum_priv.provider = provider; | |
893 | enum_priv.gdi_interop = provider_priv->gdi_interop; | |
894 | enum_priv.shared_hdc->hdc = hdc; | |
895 | enum_priv.shared_hdc->ref_count = 1; | |
896 | ||
897 | // EnumFontFamilies gives each font once, plus repeats for charset-specific | |
898 | // aliases. EnumFontFamiliesEx gives each charset of each font separately, | |
899 | // so it repeats each font as many times as it has charsets, regardless | |
900 | // of whether they have aliases. Other than this, the two functions are | |
901 | // equivalent. There's no reliable way to distinguish when two items | |
902 | // enumerated by either function refer to the same font (but different | |
903 | // aliases or charsets) or actually distinct fonts, so we add every item | |
904 | // as a separate font to our database and simply prefer the enumeration | |
905 | // function that tends to give fewer duplicates. Generally, many fonts | |
906 | // cover multiple charsets while very few have aliases, so we prefer | |
907 | // EnumFontFamilies. | |
908 | // | |
909 | // Furthermore, the requested name might be an empty string. In this case, | |
910 | // EnumFontFamilies will give us only fonts with empty names, whereas | |
911 | // EnumFontFamiliesEx would give us a list of all installed font families. | |
912 | EnumFontFamiliesW(hdc, lf.lfFaceName, | |
913 | (FONTENUMPROCW) font_enum_proc, (LPARAM) &enum_priv); | |
914 | ||
915 | hdc_release(enum_priv.shared_hdc); | |
916 | #else | |
917 | HRESULT hr; | |
918 | IDWriteFactory3 *factory3; | |
919 | hr = IDWriteFactory_QueryInterface(provider_priv->factory, | |
920 | &IID_IDWriteFactory3, (void **) &factory3); | |
921 | if (SUCCEEDED(hr) && factory3) { | |
922 | IDWriteFontSet *fontSet; | |
923 | hr = IDWriteFactory3_GetSystemFontSet(factory3, &fontSet); | |
924 | IDWriteFactory3_Release(factory3); | |
925 | if (FAILED(hr) || !fontSet) | |
926 | return; | |
927 | ||
928 | DWRITE_FONT_PROPERTY_ID property_ids[] = { | |
929 | DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME, | |
930 | DWRITE_FONT_PROPERTY_ID_FULL_NAME, | |
931 | DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME, | |
932 | }; | |
933 | for (int i = 0; i < sizeof property_ids / sizeof *property_ids; i++) { | |
934 | DWRITE_FONT_PROPERTY property = { | |
935 | property_ids[i], | |
936 | lf.lfFaceName, | |
937 | L"", | |
938 | }; | |
939 | ||
940 | IDWriteFontSet *filteredSet; | |
941 | hr = IDWriteFontSet_GetMatchingFonts(fontSet, &property, | |
942 | 1, &filteredSet); | |
943 | if (FAILED(hr) || !filteredSet) | |
944 | continue; | |
945 | ||
946 | add_font_set(filteredSet, provider); | |
947 | ||
948 | IDWriteFontSet_Release(filteredSet); | |
949 | } | |
950 | ||
951 | IDWriteFontSet_Release(fontSet); | |
952 | } else { | |
953 | // We must be in Windows 8 WinRT. IDWriteFontSet is not yet | |
954 | // supported, but GDI calls are forbidden. Our only options are | |
955 | // FindFamilyName, CreateFontFromLOGFONT, and eager preloading | |
956 | // of all fonts. The two lazy options are similar, with the | |
957 | // difference that FindFamilyName searches by WWS_FAMILY_NAME | |
958 | // whereas CreateFontFromLOGFONT searches by WIN32_FAMILY_NAME. | |
959 | // The latter is what GDI uses, so pick that. In at least some | |
960 | // versions of Windows, it also searches by FULL_NAME, which is | |
961 | // even better, but it's unclear whether this includes Windows 8. | |
962 | // It never searches by POSTSCRIPT_NAME. This means we won't | |
963 | // find CFF-outline fonts by their PostScript name and may not | |
964 | // find TrueType fonts by their full name; but we can't fix this | |
965 | // without loading the entire font list. | |
966 | lf.lfWeight = FW_DONTCARE; | |
967 | lf.lfCharSet = DEFAULT_CHARSET; | |
968 | lf.lfOutPrecision = OUT_TT_PRECIS; | |
969 | lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |
970 | lf.lfQuality = ANTIALIASED_QUALITY; | |
971 | lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; | |
972 | IDWriteFont *font = NULL; | |
973 | hr = IDWriteGdiInterop_CreateFontFromLOGFONT(provider_priv->gdi_interop, | |
974 | &lf, &font); | |
975 | if (FAILED(hr) || !font) | |
976 | return; | |
977 | ||
978 | IDWriteFontFamily *fontFamily = NULL; | |
979 | hr = IDWriteFont_GetFontFamily(font, &fontFamily); | |
710 | 980 | IDWriteFont_Release(font); |
711 | if (fontFamily) | |
981 | if (FAILED(hr) || !fontFamily) | |
982 | return; | |
983 | ||
984 | UINT32 n = IDWriteFontFamily_GetFontCount(fontFamily); | |
985 | for (UINT32 i = 0; i < n; i++) { | |
986 | hr = IDWriteFontFamily_GetFont(fontFamily, i, &font); | |
987 | if (FAILED(hr)) | |
988 | continue; | |
989 | ||
990 | // Simulations for bold or oblique are sometimes synthesized by | |
991 | // DirectWrite. We are only interested in physical fonts. | |
992 | if (IDWriteFont_GetSimulations(font) != 0) { | |
993 | IDWriteFont_Release(font); | |
994 | continue; | |
995 | } | |
996 | ||
997 | add_font(font, fontFamily, provider); | |
998 | } | |
999 | ||
712 | 1000 | IDWriteFontFamily_Release(fontFamily); |
1001 | } | |
1002 | #endif | |
713 | 1003 | } |
714 | 1004 | |
715 | 1005 | static void get_substitutions(void *priv, const char *name, |
735 | 1025 | .get_font_index = get_font_index, |
736 | 1026 | }; |
737 | 1027 | |
738 | typedef HRESULT (WINAPI *DWriteCreateFactoryFn)( | |
1028 | #if ASS_WINAPI_DESKTOP | |
1029 | typedef HRESULT (WINAPI *DWriteCreateFactoryFn) | |
1030 | #else | |
1031 | // LoadLibrary is forbidden in WinRT/UWP apps, so use DirectWrite directly. | |
1032 | // These apps cannot run on older Windows that lacks DirectWrite, | |
1033 | // so we lose nothing. | |
1034 | HRESULT WINAPI DWriteCreateFactory | |
1035 | #endif | |
1036 | ( | |
739 | 1037 | DWRITE_FACTORY_TYPE factoryType, |
740 | 1038 | REFIID iid, |
741 | 1039 | IUnknown **factory |
756 | 1054 | IDWriteFactory *dwFactory = NULL; |
757 | 1055 | IDWriteGdiInterop *dwGdiInterop = NULL; |
758 | 1056 | ASS_FontProvider *provider = NULL; |
759 | DWriteCreateFactoryFn DWriteCreateFactoryPtr = NULL; | |
760 | 1057 | ProviderPrivate *priv = NULL; |
761 | 1058 | |
1059 | #if ASS_WINAPI_DESKTOP | |
762 | 1060 | HMODULE directwrite_lib = LoadLibraryW(L"Dwrite.dll"); |
763 | 1061 | if (!directwrite_lib) |
764 | 1062 | goto cleanup; |
765 | 1063 | |
766 | DWriteCreateFactoryPtr = | |
1064 | DWriteCreateFactoryFn DWriteCreateFactory = | |
767 | 1065 | (DWriteCreateFactoryFn)(void *)GetProcAddress(directwrite_lib, |
768 | 1066 | "DWriteCreateFactory"); |
769 | if (!DWriteCreateFactoryPtr) | |
770 | goto cleanup; | |
771 | ||
772 | hr = DWriteCreateFactoryPtr(DWRITE_FACTORY_TYPE_SHARED, | |
773 | &IID_IDWriteFactory, | |
774 | (IUnknown **) (&dwFactory)); | |
1067 | if (!DWriteCreateFactory) | |
1068 | goto cleanup; | |
1069 | #endif | |
1070 | ||
1071 | hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, | |
1072 | &IID_IDWriteFactory, | |
1073 | (IUnknown **) (&dwFactory)); | |
775 | 1074 | if (FAILED(hr) || !dwFactory) { |
776 | 1075 | ass_msg(lib, MSGL_WARN, "Failed to initialize directwrite."); |
777 | 1076 | dwFactory = NULL; |
790 | 1089 | if (!priv) |
791 | 1090 | goto cleanup; |
792 | 1091 | |
1092 | #if ASS_WINAPI_DESKTOP | |
793 | 1093 | priv->directwrite_lib = directwrite_lib; |
1094 | #endif | |
794 | 1095 | priv->factory = dwFactory; |
795 | 1096 | priv->gdi_interop = dwGdiInterop; |
796 | 1097 | |
807 | 1108 | dwGdiInterop->lpVtbl->Release(dwGdiInterop); |
808 | 1109 | if (dwFactory) |
809 | 1110 | dwFactory->lpVtbl->Release(dwFactory); |
1111 | #if ASS_WINAPI_DESKTOP | |
810 | 1112 | if (directwrite_lib) |
811 | 1113 | FreeLibrary(directwrite_lib); |
1114 | #endif | |
812 | 1115 | |
813 | 1116 | return NULL; |
814 | 1117 | } |
21 | 21 | #ifndef ASS_DIRECTWRITE_H |
22 | 22 | #define ASS_DIRECTWRITE_H |
23 | 23 | |
24 | #ifdef WINAPI_FAMILY | |
25 | #include <winapifamily.h> | |
26 | #define ASS_WINAPI_DESKTOP WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) | |
27 | #else | |
28 | #define ASS_WINAPI_DESKTOP 1 | |
29 | #endif | |
30 | ||
24 | 31 | ASS_FontProvider * |
25 | 32 | ass_directwrite_add_provider(ASS_Library *lib, ASS_FontSelector *selector, |
26 | 33 | const char *config, FT_Library ftlib); |
0 | #define CONCAT(a, b) a ## b | |
1 | #define NAME(suffix) CONCAT(get_font_info_, suffix) | |
2 | static bool NAME(FONT_TYPE)(FONT_TYPE *font, | |
3 | #ifdef FAMILY_AS_ARG | |
4 | IDWriteFontFamily *fontFamily, | |
5 | #endif | |
6 | ASS_FontProviderMetaData *meta) | |
7 | #undef NAME | |
8 | #undef CONCAT | |
9 | { | |
10 | HRESULT hr; | |
11 | BOOL exists; | |
12 | ||
13 | meta->weight = font->lpVtbl->GetWeight(font); | |
14 | meta->width = map_width(font->lpVtbl->GetStretch(font)); | |
15 | ||
16 | DWRITE_FONT_STYLE style = font->lpVtbl->GetStyle(font); | |
17 | meta->slant = (style == DWRITE_FONT_STYLE_NORMAL) ? FONT_SLANT_NONE : | |
18 | (style == DWRITE_FONT_STYLE_OBLIQUE)? FONT_SLANT_OBLIQUE : | |
19 | (style == DWRITE_FONT_STYLE_ITALIC) ? FONT_SLANT_ITALIC : FONT_SLANT_NONE; | |
20 | ||
21 | IDWriteLocalizedStrings *psNames; | |
22 | hr = font->lpVtbl->GetInformationalStrings(font, | |
23 | DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &psNames, &exists); | |
24 | if (FAILED(hr)) | |
25 | return false; | |
26 | ||
27 | if (exists) { | |
28 | meta->postscript_name = get_utf8_name(psNames, 0); | |
29 | IDWriteLocalizedStrings_Release(psNames); | |
30 | if (!meta->postscript_name) | |
31 | return false; | |
32 | } | |
33 | ||
34 | IDWriteLocalizedStrings *fontNames; | |
35 | hr = font->lpVtbl->GetInformationalStrings(font, | |
36 | DWRITE_INFORMATIONAL_STRING_FULL_NAME, &fontNames, &exists); | |
37 | if (FAILED(hr)) | |
38 | return false; | |
39 | ||
40 | if (exists) { | |
41 | meta->n_fullname = IDWriteLocalizedStrings_GetCount(fontNames); | |
42 | meta->fullnames = (char **) calloc(meta->n_fullname, sizeof(char *)); | |
43 | if (!meta->fullnames) { | |
44 | IDWriteLocalizedStrings_Release(fontNames); | |
45 | return false; | |
46 | } | |
47 | for (int k = 0; k < meta->n_fullname; k++) { | |
48 | meta->fullnames[k] = get_utf8_name(fontNames, k); | |
49 | if (!meta->fullnames[k]) { | |
50 | IDWriteLocalizedStrings_Release(fontNames); | |
51 | return false; | |
52 | } | |
53 | } | |
54 | IDWriteLocalizedStrings_Release(fontNames); | |
55 | } | |
56 | ||
57 | IDWriteLocalizedStrings *familyNames; | |
58 | hr = font->lpVtbl->GetInformationalStrings(font, | |
59 | DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &familyNames, &exists); | |
60 | if (!FAILED(hr) && !exists) { | |
61 | #ifdef FAMILY_AS_ARG | |
62 | hr = IDWriteFontFamily_GetFamilyNames(fontFamily, &familyNames); | |
63 | #else | |
64 | hr = font->lpVtbl->GetFamilyNames(font, &familyNames); | |
65 | #endif | |
66 | } | |
67 | if (FAILED(hr)) | |
68 | return false; | |
69 | ||
70 | meta->n_family = IDWriteLocalizedStrings_GetCount(familyNames); | |
71 | meta->families = (char **) calloc(meta->n_family, sizeof(char *)); | |
72 | if (!meta->families) { | |
73 | IDWriteLocalizedStrings_Release(familyNames); | |
74 | return false; | |
75 | } | |
76 | for (int k = 0; k < meta->n_family; k++) { | |
77 | meta->families[k] = get_utf8_name(familyNames, k); | |
78 | if (!meta->families[k]) { | |
79 | IDWriteLocalizedStrings_Release(familyNames); | |
80 | return false; | |
81 | } | |
82 | } | |
83 | IDWriteLocalizedStrings_Release(familyNames); | |
84 | ||
85 | return true; | |
86 | } |
256 | 256 | |
257 | 257 | if (lib) |
258 | 258 | ass_msg(lib, MSGL_V, |
259 | "Parsed drawing with %d points and %d segments", | |
259 | "Parsed drawing with %zu points and %zu segments", | |
260 | 260 | outline->n_points, outline->n_segments); |
261 | 261 | |
262 | 262 | drawing_free_tokens(tokens); |
129 | 129 | } |
130 | 130 | } |
131 | 131 | |
132 | FT_Face ass_face_open(ASS_Library *lib, FT_Library ftlib, const char *path, | |
133 | const char *postscript_name, int index) | |
134 | { | |
135 | FT_Face face; | |
136 | int error = FT_New_Face(ftlib, path, index, &face); | |
137 | if (error) { | |
138 | ass_msg(lib, MSGL_WARN, "Error opening font: '%s', %d", path, index); | |
139 | return NULL; | |
140 | } | |
141 | ||
142 | if (postscript_name && index < 0 && face->num_faces > 0) { | |
143 | // The font provider gave us a postscript name and is not sure | |
144 | // about the face index.. so use the postscript name to find the | |
145 | // correct face_index in the collection! | |
146 | for (int i = 0; i < face->num_faces; i++) { | |
147 | FT_Done_Face(face); | |
148 | error = FT_New_Face(ftlib, path, i, &face); | |
149 | if (error) { | |
150 | ass_msg(lib, MSGL_WARN, "Error opening font: '%s', %d", path, i); | |
151 | return NULL; | |
152 | } | |
153 | ||
154 | const char *face_psname = FT_Get_Postscript_Name(face); | |
155 | if (face_psname != NULL && | |
156 | strcmp(face_psname, postscript_name) == 0) | |
157 | break; | |
158 | } | |
159 | } | |
160 | ||
161 | return face; | |
162 | } | |
163 | ||
132 | 164 | static unsigned long |
133 | 165 | read_stream_font(FT_Stream stream, unsigned long offset, unsigned char *buffer, |
134 | 166 | unsigned long count) |
146 | 178 | free(stream); |
147 | 179 | } |
148 | 180 | |
181 | FT_Face ass_face_stream(ASS_Library *lib, FT_Library ftlib, const char *name, | |
182 | const ASS_FontStream *stream, int index) | |
183 | { | |
184 | ASS_FontStream *fs = calloc(1, sizeof(ASS_FontStream)); | |
185 | if (!fs) | |
186 | return NULL; | |
187 | *fs = *stream; | |
188 | ||
189 | FT_Stream ftstream = calloc(1, sizeof(FT_StreamRec)); | |
190 | if (!ftstream) { | |
191 | free(fs); | |
192 | return NULL; | |
193 | } | |
194 | ftstream->size = stream->func(stream->priv, NULL, 0, 0); | |
195 | ftstream->read = read_stream_font; | |
196 | ftstream->close = close_stream_font; | |
197 | ftstream->descriptor.pointer = (void *)fs; | |
198 | ||
199 | FT_Open_Args args = { | |
200 | .flags = FT_OPEN_STREAM, | |
201 | .stream = ftstream, | |
202 | }; | |
203 | ||
204 | FT_Face face; | |
205 | int error = FT_Open_Face(ftlib, &args, index, &face); | |
206 | if (error) { | |
207 | if (name) { | |
208 | ass_msg(lib, MSGL_WARN, | |
209 | "Error opening memory font: '%s'", name); | |
210 | } else { | |
211 | ass_msg(lib, MSGL_WARN, | |
212 | "Error opening memory font"); | |
213 | } | |
214 | return NULL; | |
215 | } | |
216 | ||
217 | return face; | |
218 | } | |
219 | ||
149 | 220 | /** |
150 | 221 | * \brief Select a face with the given charcode and add it to ASS_Font |
151 | 222 | * \return index of the new face in font->faces, -1 if failed |
154 | 225 | { |
155 | 226 | char *path; |
156 | 227 | char *postscript_name = NULL; |
157 | int i, index, uid, error; | |
228 | int i, index, uid; | |
158 | 229 | ASS_FontStream stream = { NULL, NULL }; |
159 | 230 | FT_Face face; |
160 | 231 | |
161 | 232 | if (font->n_faces == ASS_FONT_MAX_FACES) |
162 | 233 | return -1; |
163 | 234 | |
164 | path = ass_font_select(fontsel, font->library, font , &index, | |
235 | path = ass_font_select(fontsel, font, &index, | |
165 | 236 | &postscript_name, &uid, &stream, ch); |
166 | 237 | |
167 | 238 | if (!path) |
176 | 247 | } |
177 | 248 | |
178 | 249 | if (stream.func) { |
179 | FT_Open_Args args; | |
180 | FT_Stream ftstream = calloc(1, sizeof(FT_StreamRec)); | |
181 | ASS_FontStream *fs = calloc(1, sizeof(ASS_FontStream)); | |
182 | ||
183 | *fs = stream; | |
184 | ftstream->size = stream.func(stream.priv, NULL, 0, 0); | |
185 | ftstream->read = read_stream_font; | |
186 | ftstream->close = close_stream_font; | |
187 | ftstream->descriptor.pointer = (void *)fs; | |
188 | ||
189 | memset(&args, 0, sizeof(FT_Open_Args)); | |
190 | args.flags = FT_OPEN_STREAM; | |
191 | args.stream = ftstream; | |
192 | ||
193 | error = FT_Open_Face(font->ftlibrary, &args, index, &face); | |
194 | ||
195 | if (error) { | |
196 | ass_msg(font->library, MSGL_WARN, | |
197 | "Error opening memory font: '%s'", path); | |
198 | return -1; | |
199 | } | |
200 | ||
250 | face = ass_face_stream(font->library, font->ftlibrary, path, | |
251 | &stream, index); | |
201 | 252 | } else { |
202 | error = FT_New_Face(font->ftlibrary, path, index, &face); | |
203 | if (error) { | |
204 | ass_msg(font->library, MSGL_WARN, | |
205 | "Error opening font: '%s', %d", path, index); | |
206 | return -1; | |
207 | } | |
208 | ||
209 | if (postscript_name && index < 0 && face->num_faces > 0) { | |
210 | // The font provider gave us a post_script name and is not sure | |
211 | // about the face index.. so use the postscript name to find the | |
212 | // correct face_index in the collection! | |
213 | for (int i = 0; i < face->num_faces; i++) { | |
214 | FT_Done_Face(face); | |
215 | error = FT_New_Face(font->ftlibrary, path, i, &face); | |
216 | if (error) { | |
217 | ass_msg(font->library, MSGL_WARN, | |
218 | "Error opening font: '%s', %d", path, i); | |
219 | return -1; | |
220 | } | |
221 | ||
222 | const char *face_psname = FT_Get_Postscript_Name(face); | |
223 | if (face_psname != NULL && | |
224 | strcmp(face_psname, postscript_name) == 0) | |
225 | break; | |
226 | } | |
227 | } | |
228 | } | |
253 | face = ass_face_open(font->library, font->ftlibrary, path, | |
254 | postscript_name, index); | |
255 | } | |
256 | ||
257 | if (!face) | |
258 | return -1; | |
229 | 259 | |
230 | 260 | charmap_magic(font->library, face); |
231 | 261 | set_font_metrics(face); |
473 | 503 | int face_idx; |
474 | 504 | ass_msg(font->library, MSGL_INFO, |
475 | 505 | "Glyph 0x%X not found, selecting one more " |
476 | "font for (%s, %d, %d)", symbol, font->desc.family, | |
506 | "font for (%.*s, %d, %d)", symbol, (int) font->desc.family.len, font->desc.family.str, | |
477 | 507 | font->desc.bold, font->desc.italic); |
478 | 508 | face_idx = *face_index = add_face(fontsel, font, symbol); |
479 | 509 | if (face_idx >= 0) { |
490 | 520 | } |
491 | 521 | if (index == 0) { |
492 | 522 | ass_msg(font->library, MSGL_ERR, |
493 | "Glyph 0x%X not found in font for (%s, %d, %d)", | |
494 | symbol, font->desc.family, font->desc.bold, | |
523 | "Glyph 0x%X not found in font for (%.*s, %d, %d)", | |
524 | symbol, (int) font->desc.family.len, font->desc.family.str, font->desc.bold, | |
495 | 525 | font->desc.italic); |
496 | 526 | } |
497 | 527 | } |
62 | 62 | ASS_Hinting hinting, int deco); |
63 | 63 | void ass_font_clear(ASS_Font *font); |
64 | 64 | |
65 | FT_Face ass_face_open(ASS_Library *lib, FT_Library ftlib, const char *path, | |
66 | const char *postscript_name, int index); | |
67 | FT_Face ass_face_stream(ASS_Library *lib, FT_Library ftlib, const char *name, | |
68 | const ASS_FontStream *stream, int index); | |
69 | ||
65 | 70 | #endif /* LIBASS_FONT_H */ |
86 | 86 | { |
87 | 87 | int i; |
88 | 88 | FcFontSet *fonts; |
89 | ASS_FontProviderMetaData meta; | |
89 | ASS_FontProviderMetaData meta = {0}; | |
90 | 90 | |
91 | 91 | // get list of fonts |
92 | 92 | fonts = FcConfigGetFonts(config, FcSetSystem); |
165 | 165 | |
166 | 166 | // read family names |
167 | 167 | meta.n_family = 0; |
168 | while (FcPatternGetString(pat, FC_FAMILY, meta.n_family, | |
169 | (FcChar8 **)&families[meta.n_family]) == FcResultMatch | |
170 | && meta.n_family < MAX_NAME) | |
168 | while (meta.n_family < MAX_NAME && | |
169 | FcPatternGetString(pat, FC_FAMILY, meta.n_family, | |
170 | (FcChar8 **)&families[meta.n_family]) == FcResultMatch) | |
171 | 171 | meta.n_family++; |
172 | 172 | meta.families = families; |
173 | 173 | |
174 | 174 | // read fullnames |
175 | 175 | meta.n_fullname = 0; |
176 | while (FcPatternGetString(pat, FC_FULLNAME, meta.n_fullname, | |
177 | (FcChar8 **)&fullnames[meta.n_fullname]) == FcResultMatch | |
178 | && meta.n_fullname < MAX_NAME) | |
176 | while (meta.n_fullname < MAX_NAME && | |
177 | FcPatternGetString(pat, FC_FULLNAME, meta.n_fullname, | |
178 | (FcChar8 **)&fullnames[meta.n_fullname]) == FcResultMatch) | |
179 | 179 | meta.n_fullname++; |
180 | 180 | meta.fullnames = fullnames; |
181 | 181 |
70 | 70 | char *postscript_name; // can be used as an alternative to index to |
71 | 71 | // identify a font inside a collection |
72 | 72 | |
73 | char *extended_family; | |
74 | ||
73 | 75 | // font source |
74 | 76 | ASS_FontProvider *provider; |
75 | 77 | |
78 | 80 | }; |
79 | 81 | |
80 | 82 | struct font_selector { |
83 | ASS_Library *library; | |
84 | FT_Library ftlibrary; | |
85 | ||
81 | 86 | // uid counter |
82 | 87 | int uid; |
83 | 88 | |
165 | 170 | DIR *d = opendir(dir); |
166 | 171 | if (!d) |
167 | 172 | return; |
173 | size_t dirlen = strlen(dir); | |
174 | size_t namemax = 0; | |
175 | char *namebuf = NULL; | |
168 | 176 | while (1) { |
169 | 177 | struct dirent *entry = readdir(d); |
170 | 178 | if (!entry) |
171 | 179 | break; |
172 | 180 | if (entry->d_name[0] == '.') |
173 | 181 | continue; |
174 | char fullname[4096]; | |
175 | snprintf(fullname, sizeof(fullname), "%s/%s", dir, entry->d_name); | |
182 | size_t namelen = dirlen + strlen(entry->d_name) + 2u; | |
183 | if (namelen < 2 || namelen - 2 < dirlen) | |
184 | continue; | |
185 | if (namelen > namemax) { | |
186 | size_t newlen = FFMAX(2048, namelen + FFMIN(256, SIZE_MAX - namelen)); | |
187 | if (ASS_REALLOC_ARRAY(namebuf, newlen)) | |
188 | namemax = newlen; | |
189 | else | |
190 | continue; | |
191 | } | |
192 | snprintf(namebuf, namemax, "%s/%s", dir, entry->d_name); | |
176 | 193 | size_t bufsize = 0; |
177 | ass_msg(library, MSGL_INFO, "Loading font file '%s'", fullname); | |
178 | void *data = read_file(library, fullname, &bufsize); | |
194 | ass_msg(library, MSGL_INFO, "Loading font file '%s'", namebuf); | |
195 | void *data = read_file(library, namebuf, &bufsize); | |
179 | 196 | if (data) { |
180 | 197 | ass_add_font(library, entry->d_name, data, bufsize); |
181 | 198 | free(data); |
182 | 199 | } |
183 | 200 | } |
201 | free(namebuf); | |
184 | 202 | closedir(d); |
185 | 203 | } |
186 | 204 | |
234 | 252 | if (info->postscript_name) |
235 | 253 | free(info->postscript_name); |
236 | 254 | |
255 | if (info->extended_family) | |
256 | free(info->extended_family); | |
257 | } | |
258 | ||
259 | /** | |
260 | * \brief Read basic metadata (names, weight, slant) from a FreeType face, | |
261 | * as required for the FontSelector for matching and sorting. | |
262 | * \param lib FreeType library | |
263 | * \param face FreeType face | |
264 | * \param fallback_family_name family name from outside source, used as last resort | |
265 | * \param info metadata, returned here | |
266 | * \return success | |
267 | */ | |
268 | static bool | |
269 | get_font_info(FT_Library lib, FT_Face face, const char *fallback_family_name, | |
270 | ASS_FontProviderMetaData *info) | |
271 | { | |
272 | int i; | |
273 | int num_fullname = 0; | |
274 | int num_family = 0; | |
275 | int num_names = FT_Get_Sfnt_Name_Count(face); | |
276 | int slant, weight; | |
277 | char *fullnames[MAX_FULLNAME]; | |
278 | char *families[MAX_FULLNAME]; | |
279 | ||
280 | // we're only interested in outlines | |
281 | if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) | |
282 | return false; | |
283 | ||
284 | for (i = 0; i < num_names; i++) { | |
285 | FT_SfntName name; | |
286 | ||
287 | if (FT_Get_Sfnt_Name(face, i, &name)) | |
288 | continue; | |
289 | ||
290 | if (name.platform_id == TT_PLATFORM_MICROSOFT && | |
291 | (name.name_id == TT_NAME_ID_FULL_NAME || | |
292 | name.name_id == TT_NAME_ID_FONT_FAMILY)) { | |
293 | char buf[1024]; | |
294 | ass_utf16be_to_utf8(buf, sizeof(buf), (uint8_t *)name.string, | |
295 | name.string_len); | |
296 | ||
297 | if (name.name_id == TT_NAME_ID_FULL_NAME && num_fullname < MAX_FULLNAME) { | |
298 | fullnames[num_fullname] = strdup(buf); | |
299 | if (fullnames[num_fullname] == NULL) | |
300 | goto error; | |
301 | num_fullname++; | |
302 | } | |
303 | ||
304 | if (name.name_id == TT_NAME_ID_FONT_FAMILY && num_family < MAX_FULLNAME) { | |
305 | families[num_family] = strdup(buf); | |
306 | if (families[num_family] == NULL) | |
307 | goto error; | |
308 | num_family++; | |
309 | } | |
310 | } | |
311 | ||
312 | } | |
313 | ||
314 | // check if we got a valid family - if not, use | |
315 | // whatever the font provider or FreeType gives us | |
316 | if (num_family == 0 && (fallback_family_name || face->family_name)) { | |
317 | families[0] = | |
318 | strdup(fallback_family_name ? fallback_family_name : face->family_name); | |
319 | if (families[0] == NULL) | |
320 | goto error; | |
321 | num_family++; | |
322 | } | |
323 | ||
324 | // we absolutely need a name | |
325 | if (num_family == 0) | |
326 | goto error; | |
327 | ||
328 | // calculate sensible slant and weight from style attributes | |
329 | slant = 110 * !!(face->style_flags & FT_STYLE_FLAG_ITALIC); | |
330 | weight = ass_face_get_weight(face); | |
331 | ||
332 | // fill our struct | |
333 | info->slant = slant; | |
334 | info->weight = weight; | |
335 | info->width = 100; // FIXME, should probably query the OS/2 table | |
336 | ||
337 | info->postscript_name = (char *)FT_Get_Postscript_Name(face); | |
338 | ||
339 | if (num_family) { | |
340 | info->families = calloc(sizeof(char *), num_family); | |
341 | if (info->families == NULL) | |
342 | goto error; | |
343 | memcpy(info->families, &families, sizeof(char *) * num_family); | |
344 | info->n_family = num_family; | |
345 | } | |
346 | ||
347 | if (num_fullname) { | |
348 | info->fullnames = calloc(sizeof(char *), num_fullname); | |
349 | if (info->fullnames == NULL) | |
350 | goto error; | |
351 | memcpy(info->fullnames, &fullnames, sizeof(char *) * num_fullname); | |
352 | info->n_fullname = num_fullname; | |
353 | } | |
354 | ||
355 | return true; | |
356 | ||
357 | error: | |
358 | for (i = 0; i < num_family; i++) | |
359 | free(families[i]); | |
360 | ||
361 | for (i = 0; i < num_fullname; i++) | |
362 | free(fullnames[i]); | |
363 | ||
364 | free(info->families); | |
365 | free(info->fullnames); | |
366 | ||
367 | info->families = info->fullnames = NULL; | |
368 | info->n_family = info->n_fullname = 0; | |
369 | ||
370 | return false; | |
371 | } | |
372 | ||
373 | /** | |
374 | * \brief Free the dynamically allocated fields of metadata | |
375 | * created by get_font_info. | |
376 | * \param meta metadata created by get_font_info | |
377 | */ | |
378 | static void free_font_info(ASS_FontProviderMetaData *meta) | |
379 | { | |
380 | if (meta->families) { | |
381 | for (int i = 0; i < meta->n_family; i++) | |
382 | free(meta->families[i]); | |
383 | free(meta->families); | |
384 | } | |
385 | ||
386 | if (meta->fullnames) { | |
387 | for (int i = 0; i < meta->n_fullname; i++) | |
388 | free(meta->fullnames[i]); | |
389 | free(meta->fullnames); | |
390 | } | |
237 | 391 | } |
238 | 392 | |
239 | 393 | /** |
253 | 407 | int i; |
254 | 408 | int weight, slant, width; |
255 | 409 | ASS_FontSelector *selector = provider->parent; |
256 | ASS_FontInfo *info; | |
410 | ASS_FontInfo *info = NULL; | |
411 | ASS_FontProviderMetaData implicit_meta = {0}; | |
412 | ||
413 | if (!meta->n_family) { | |
414 | FT_Face face; | |
415 | if (provider->funcs.get_font_index) | |
416 | index = provider->funcs.get_font_index(data); | |
417 | if (!path) { | |
418 | ASS_FontStream stream = { | |
419 | .func = provider->funcs.get_data, | |
420 | .priv = data, | |
421 | }; | |
422 | // This name is only used in an error message, so use | |
423 | // our best name but don't panic if we don't have any. | |
424 | // Prefer PostScript name because it is unique. | |
425 | const char *name = meta->postscript_name ? | |
426 | meta->postscript_name : meta->extended_family; | |
427 | face = ass_face_stream(selector->library, selector->ftlibrary, | |
428 | name, &stream, index); | |
429 | } else { | |
430 | face = ass_face_open(selector->library, selector->ftlibrary, | |
431 | path, meta->postscript_name, index); | |
432 | } | |
433 | if (!face) | |
434 | goto error; | |
435 | if (!get_font_info(selector->ftlibrary, face, meta->extended_family, | |
436 | &implicit_meta)) { | |
437 | FT_Done_Face(face); | |
438 | goto error; | |
439 | } | |
440 | if (implicit_meta.postscript_name) { | |
441 | implicit_meta.postscript_name = | |
442 | strdup(implicit_meta.postscript_name); | |
443 | if (!implicit_meta.postscript_name) { | |
444 | FT_Done_Face(face); | |
445 | goto error; | |
446 | } | |
447 | } | |
448 | FT_Done_Face(face); | |
449 | implicit_meta.extended_family = meta->extended_family; | |
450 | meta = &implicit_meta; | |
451 | } | |
257 | 452 | |
258 | 453 | #if 0 |
259 | 454 | int j; |
333 | 528 | goto error; |
334 | 529 | } |
335 | 530 | |
531 | if (meta->extended_family) { | |
532 | info->extended_family = strdup(meta->extended_family); | |
533 | if (info->extended_family == NULL) | |
534 | goto error; | |
535 | } | |
536 | ||
336 | 537 | if (path) { |
337 | 538 | info->path = strdup(path); |
338 | 539 | if (info->path == NULL) |
347 | 548 | return true; |
348 | 549 | |
349 | 550 | error: |
350 | ass_font_provider_free_fontinfo(info); | |
551 | if (info) | |
552 | ass_font_provider_free_fontinfo(info); | |
553 | ||
554 | free_font_info(&implicit_meta); | |
555 | free(implicit_meta.postscript_name); | |
351 | 556 | |
352 | 557 | if (provider->funcs.destroy_font) |
353 | 558 | provider->funcs.destroy_font(data); |
422 | 627 | /** |
423 | 628 | * \brief Return whether the given font is in the given family. |
424 | 629 | */ |
425 | static bool matches_family_name(ASS_FontInfo *f, const char *family) | |
630 | static bool matches_family_name(ASS_FontInfo *f, const char *family, | |
631 | bool match_extended_family) | |
426 | 632 | { |
427 | 633 | for (int i = 0; i < f->n_family; i++) { |
428 | 634 | if (ass_strcasecmp(f->families[i], family) == 0) |
635 | return true; | |
636 | } | |
637 | if (match_extended_family && f->extended_family) { | |
638 | if (ass_strcasecmp(f->extended_family, family) == 0) | |
429 | 639 | return true; |
430 | 640 | } |
431 | 641 | return false; |
515 | 725 | } |
516 | 726 | |
517 | 727 | static char * |
518 | find_font(ASS_FontSelector *priv, ASS_Library *library, | |
519 | ASS_FontProviderMetaData meta, unsigned bold, unsigned italic, | |
728 | find_font(ASS_FontSelector *priv, | |
729 | ASS_FontProviderMetaData meta, bool match_extended_family, | |
730 | unsigned bold, unsigned italic, | |
520 | 731 | int *index, char **postscript_name, int *uid, ASS_FontStream *stream, |
521 | 732 | uint32_t code, bool *name_match) |
522 | 733 | { |
541 | 752 | ASS_FontInfo *font = &priv->font_infos[x]; |
542 | 753 | unsigned score = UINT_MAX; |
543 | 754 | |
544 | if (matches_family_name(font, fullname)) { | |
755 | if (matches_family_name(font, fullname, match_extended_family)) { | |
545 | 756 | // If there's a family match, compare font attributes |
546 | 757 | // to determine best match in that particular family |
547 | 758 | score = font_attributes_similarity(font, &req); |
618 | 829 | return result; |
619 | 830 | } |
620 | 831 | |
621 | static char *select_font(ASS_FontSelector *priv, ASS_Library *library, | |
622 | const char *family, unsigned bold, unsigned italic, | |
832 | static char *select_font(ASS_FontSelector *priv, | |
833 | const char *family, bool match_extended_family, | |
834 | unsigned bold, unsigned italic, | |
623 | 835 | int *index, char **postscript_name, int *uid, |
624 | 836 | ASS_FontStream *stream, uint32_t code) |
625 | 837 | { |
646 | 858 | meta = default_meta; |
647 | 859 | } |
648 | 860 | |
649 | result = find_font(priv, library, meta, bold, italic, index, | |
650 | postscript_name, uid, stream, code, &name_match); | |
861 | result = find_font(priv, meta, match_extended_family, | |
862 | bold, italic, index, postscript_name, uid, | |
863 | stream, code, &name_match); | |
651 | 864 | |
652 | 865 | // If no matching font was found, it might not exist in the font list |
653 | 866 | // yet. Call the match_fonts callback to fill in the missing fonts |
658 | 871 | // implementations possible. |
659 | 872 | for (int i = 0; i < meta.n_fullname; i++) { |
660 | 873 | default_provider->funcs.match_fonts(default_provider->priv, |
661 | library, default_provider, | |
874 | priv->library, default_provider, | |
662 | 875 | meta.fullnames[i]); |
663 | 876 | } |
664 | result = find_font(priv, library, meta, bold, italic, index, | |
665 | postscript_name, uid, stream, code, &name_match); | |
877 | result = find_font(priv, meta, match_extended_family, | |
878 | bold, italic, index, postscript_name, uid, | |
879 | stream, code, &name_match); | |
666 | 880 | } |
667 | 881 | |
668 | 882 | // cleanup |
678 | 892 | |
679 | 893 | /** |
680 | 894 | * \brief Find a font. Use default family or path if necessary. |
681 | * \param library ASS library handle | |
682 | 895 | * \param family font family |
683 | 896 | * \param treat_family_as_pattern treat family as fontconfig pattern |
684 | 897 | * \param bold font weight value |
687 | 900 | * \param code: the character that should be present in the font, can be 0 |
688 | 901 | * \return font file path |
689 | 902 | */ |
690 | char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, | |
903 | char *ass_font_select(ASS_FontSelector *priv, | |
691 | 904 | ASS_Font *font, int *index, char **postscript_name, |
692 | 905 | int *uid, ASS_FontStream *data, uint32_t code) |
693 | 906 | { |
698 | 911 | ASS_FontProvider *default_provider = priv->default_provider; |
699 | 912 | |
700 | 913 | if (family && *family) |
701 | res = select_font(priv, library, family, bold, italic, index, | |
914 | res = select_font(priv, family, false, bold, italic, index, | |
702 | 915 | postscript_name, uid, data, code); |
703 | 916 | |
704 | 917 | if (!res && priv->family_default) { |
705 | res = select_font(priv, library, priv->family_default, bold, | |
918 | res = select_font(priv, priv->family_default, false, bold, | |
706 | 919 | italic, index, postscript_name, uid, data, code); |
707 | 920 | if (res) |
708 | ass_msg(library, MSGL_WARN, "fontselect: Using default " | |
921 | ass_msg(priv->library, MSGL_WARN, "fontselect: Using default " | |
709 | 922 | "font family: (%s, %d, %d) -> %s, %d, %s", |
710 | 923 | family, bold, italic, res, *index, |
711 | 924 | *postscript_name ? *postscript_name : "(none)"); |
716 | 929 | if (!search_family || !*search_family) |
717 | 930 | search_family = "Arial"; |
718 | 931 | char *fallback_family = default_provider->funcs.get_fallback( |
719 | default_provider->priv, library, search_family, code); | |
932 | default_provider->priv, priv->library, search_family, code); | |
720 | 933 | |
721 | 934 | if (fallback_family) { |
722 | res = select_font(priv, library, fallback_family, bold, italic, | |
935 | res = select_font(priv, fallback_family, true, bold, italic, | |
723 | 936 | index, postscript_name, uid, data, code); |
724 | 937 | free(fallback_family); |
725 | 938 | } |
728 | 941 | if (!res && priv->path_default) { |
729 | 942 | res = priv->path_default; |
730 | 943 | *index = priv->index_default; |
731 | ass_msg(library, MSGL_WARN, "fontselect: Using default font: " | |
944 | ass_msg(priv->library, MSGL_WARN, "fontselect: Using default font: " | |
732 | 945 | "(%s, %d, %d) -> %s, %d, %s", family, bold, italic, |
733 | 946 | priv->path_default, *index, |
734 | 947 | *postscript_name ? *postscript_name : "(none)"); |
735 | 948 | } |
736 | 949 | |
737 | 950 | if (res) |
738 | ass_msg(library, MSGL_INFO, | |
951 | ass_msg(priv->library, MSGL_INFO, | |
739 | 952 | "fontselect: (%s, %d, %d) -> %s, %d, %s", family, bold, |
740 | 953 | italic, res, *index, *postscript_name ? *postscript_name : "(none)"); |
741 | 954 | else |
742 | ass_msg(library, MSGL_WARN, "fontselect: failed to find any fallback for font: " | |
955 | ass_msg(priv->library, MSGL_WARN, | |
956 | "fontselect: failed to find any fallback for font: " | |
743 | 957 | "(%s, %d, %d)", family, bold, italic); |
744 | 958 | |
745 | 959 | return res; |
746 | 960 | } |
747 | 961 | |
748 | ||
749 | /** | |
750 | * \brief Read basic metadata (names, weight, slant) from a FreeType face, | |
751 | * as required for the FontSelector for matching and sorting. | |
752 | * \param lib FreeType library | |
753 | * \param face FreeType face | |
754 | * \param info metadata, returned here | |
755 | * \return success | |
756 | */ | |
757 | static bool | |
758 | get_font_info(FT_Library lib, FT_Face face, bool require_family_name, | |
759 | ASS_FontProviderMetaData *info) | |
760 | { | |
761 | int i; | |
762 | int num_fullname = 0; | |
763 | int num_family = 0; | |
764 | int num_names = FT_Get_Sfnt_Name_Count(face); | |
765 | int slant, weight; | |
766 | char *fullnames[MAX_FULLNAME]; | |
767 | char *families[MAX_FULLNAME]; | |
768 | ||
769 | // we're only interested in outlines | |
770 | if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) | |
771 | return false; | |
772 | ||
773 | for (i = 0; i < num_names; i++) { | |
774 | FT_SfntName name; | |
775 | ||
776 | if (FT_Get_Sfnt_Name(face, i, &name)) | |
777 | continue; | |
778 | ||
779 | if (name.platform_id == TT_PLATFORM_MICROSOFT && | |
780 | (name.name_id == TT_NAME_ID_FULL_NAME || | |
781 | name.name_id == TT_NAME_ID_FONT_FAMILY)) { | |
782 | char buf[1024]; | |
783 | ass_utf16be_to_utf8(buf, sizeof(buf), (uint8_t *)name.string, | |
784 | name.string_len); | |
785 | ||
786 | if (name.name_id == TT_NAME_ID_FULL_NAME && num_fullname < MAX_FULLNAME) { | |
787 | fullnames[num_fullname] = strdup(buf); | |
788 | if (fullnames[num_fullname] == NULL) | |
789 | goto error; | |
790 | num_fullname++; | |
791 | } | |
792 | ||
793 | if (name.name_id == TT_NAME_ID_FONT_FAMILY && num_family < MAX_FULLNAME) { | |
794 | families[num_family] = strdup(buf); | |
795 | if (families[num_family] == NULL) | |
796 | goto error; | |
797 | num_family++; | |
798 | } | |
799 | } | |
800 | ||
801 | } | |
802 | ||
803 | if (require_family_name) { | |
804 | // check if we got a valid family - if not use whatever FreeType gives us | |
805 | if (num_family == 0 && face->family_name) { | |
806 | families[0] = strdup(face->family_name); | |
807 | if (families[0] == NULL) | |
808 | goto error; | |
809 | num_family++; | |
810 | } | |
811 | ||
812 | // we absolutely need a name | |
813 | if (num_family == 0) | |
814 | goto error; | |
815 | } | |
816 | ||
817 | // calculate sensible slant and weight from style attributes | |
818 | slant = 110 * !!(face->style_flags & FT_STYLE_FLAG_ITALIC); | |
819 | weight = ass_face_get_weight(face); | |
820 | ||
821 | // fill our struct | |
822 | info->slant = slant; | |
823 | info->weight = weight; | |
824 | info->width = 100; // FIXME, should probably query the OS/2 table | |
825 | ||
826 | info->postscript_name = (char *)FT_Get_Postscript_Name(face); | |
827 | ||
828 | if (num_family) { | |
829 | info->families = calloc(sizeof(char *), num_family); | |
830 | if (info->families == NULL) | |
831 | goto error; | |
832 | memcpy(info->families, &families, sizeof(char *) * num_family); | |
833 | info->n_family = num_family; | |
834 | } | |
835 | ||
836 | if (num_fullname) { | |
837 | info->fullnames = calloc(sizeof(char *), num_fullname); | |
838 | if (info->fullnames == NULL) | |
839 | goto error; | |
840 | memcpy(info->fullnames, &fullnames, sizeof(char *) * num_fullname); | |
841 | info->n_fullname = num_fullname; | |
842 | } | |
843 | ||
844 | return true; | |
845 | ||
846 | error: | |
847 | for (i = 0; i < num_family; i++) | |
848 | free(families[i]); | |
849 | ||
850 | for (i = 0; i < num_fullname; i++) | |
851 | free(fullnames[i]); | |
852 | ||
853 | free(info->families); | |
854 | free(info->fullnames); | |
855 | ||
856 | info->families = info->fullnames = NULL; | |
857 | info->n_family = info->n_fullname = 0; | |
858 | ||
859 | return false; | |
860 | } | |
861 | ||
862 | bool ass_get_font_info(ASS_Library *lib, FT_Library ftlib, const char *path, | |
863 | const char *postscript_name, int index, | |
864 | bool require_family_name, | |
865 | ASS_FontProviderMetaData *info) | |
866 | { | |
867 | bool ret = false; | |
868 | FT_Face face = NULL; | |
869 | int error = FT_New_Face(ftlib, path, index, &face); | |
870 | if (error) { | |
871 | ass_msg(lib, MSGL_WARN, "Error opening font: '%s', %d", path, index); | |
872 | return false; | |
873 | } | |
874 | ||
875 | if (postscript_name && index < 0 && face->num_faces > 0) { | |
876 | // The font provider gave us a postscript name and is not sure | |
877 | // about the face index.. so use the postscript name to find the | |
878 | // correct face_index in the collection! | |
879 | for (int i = 0; i < face->num_faces; i++) { | |
880 | FT_Done_Face(face); | |
881 | error = FT_New_Face(ftlib, path, i, &face); | |
882 | if (error) { | |
883 | ass_msg(lib, MSGL_WARN, "Error opening font: '%s', %d", path, i); | |
884 | return false; | |
885 | } | |
886 | ||
887 | const char *face_psname = FT_Get_Postscript_Name(face); | |
888 | if (face_psname != NULL && | |
889 | strcmp(face_psname, postscript_name) == 0) | |
890 | break; | |
891 | } | |
892 | } | |
893 | ||
894 | if (face) { | |
895 | ret = get_font_info(ftlib, face, require_family_name, info); | |
896 | if (ret) | |
897 | info->postscript_name = strdup(info->postscript_name); | |
898 | FT_Done_Face(face); | |
899 | } | |
900 | ||
901 | return ret; | |
902 | } | |
903 | ||
904 | /** | |
905 | * \brief Free the dynamically allocated fields of metadata | |
906 | * created by get_font_info. | |
907 | * \param meta metadata created by get_font_info | |
908 | */ | |
909 | static void free_font_info(ASS_FontProviderMetaData *meta) | |
910 | { | |
911 | int i; | |
912 | ||
913 | for (i = 0; i < meta->n_family; i++) | |
914 | free(meta->families[i]); | |
915 | ||
916 | for (i = 0; i < meta->n_fullname; i++) | |
917 | free(meta->fullnames[i]); | |
918 | ||
919 | free(meta->families); | |
920 | free(meta->fullnames); | |
921 | } | |
922 | 962 | |
923 | 963 | /** |
924 | 964 | * \brief Process memory font. |
925 | 965 | * \param priv private data |
926 | * \param library library object | |
927 | * \param ftlibrary freetype library object | |
928 | * \param idx index of the processed font in library->fontdata | |
966 | * \param idx index of the processed font in priv->library->fontdata | |
929 | 967 | * |
930 | 968 | * Builds a FontInfo with FreeType and some table reading. |
931 | 969 | */ |
932 | static void process_fontdata(ASS_FontProvider *priv, ASS_Library *library, | |
933 | FT_Library ftlibrary, int idx) | |
934 | { | |
970 | static void process_fontdata(ASS_FontProvider *priv, int idx) | |
971 | { | |
972 | ASS_FontSelector *selector = priv->parent; | |
973 | ASS_Library *library = selector->library; | |
974 | ||
935 | 975 | int rc; |
936 | 976 | const char *name = library->fontdata[idx].name; |
937 | 977 | const char *data = library->fontdata[idx].data; |
944 | 984 | ASS_FontProviderMetaData info; |
945 | 985 | FontDataFT *ft; |
946 | 986 | |
947 | rc = FT_New_Memory_Face(ftlibrary, (unsigned char *) data, | |
987 | rc = FT_New_Memory_Face(selector->ftlibrary, (unsigned char *) data, | |
948 | 988 | data_size, face_index, &face); |
949 | 989 | if (rc) { |
950 | 990 | ass_msg(library, MSGL_WARN, "Error opening memory font '%s'", |
957 | 997 | charmap_magic(library, face); |
958 | 998 | |
959 | 999 | memset(&info, 0, sizeof(ASS_FontProviderMetaData)); |
960 | if (!get_font_info(ftlibrary, face, true, &info)) { | |
1000 | if (!get_font_info(selector->ftlibrary, face, NULL, &info)) { | |
961 | 1001 | ass_msg(library, MSGL_WARN, |
962 | 1002 | "Error getting metadata for embedded font '%s'", name); |
963 | 1003 | FT_Done_Face(face); |
989 | 1029 | /** |
990 | 1030 | * \brief Create font provider for embedded fonts. This parses the fonts known |
991 | 1031 | * to the current ASS_Library and adds them to the selector. |
992 | * \param lib library | |
993 | 1032 | * \param selector font selector |
994 | * \param ftlib FreeType library - used for querying fonts | |
995 | 1033 | * \return font provider |
996 | 1034 | */ |
997 | 1035 | static ASS_FontProvider * |
998 | ass_embedded_fonts_add_provider(ASS_Library *lib, ASS_FontSelector *selector, | |
999 | FT_Library ftlib, size_t *num_emfonts) | |
1036 | ass_embedded_fonts_add_provider(ASS_FontSelector *selector, size_t *num_emfonts) | |
1000 | 1037 | { |
1001 | 1038 | ASS_FontProvider *priv = ass_font_provider_new(selector, &ft_funcs, NULL); |
1002 | 1039 | if (priv == NULL) |
1003 | 1040 | return NULL; |
1004 | 1041 | |
1042 | ASS_Library *lib = selector->library; | |
1043 | ||
1005 | 1044 | if (lib->fonts_dir && lib->fonts_dir[0]) { |
1006 | 1045 | load_fonts_from_dir(lib, lib->fonts_dir); |
1007 | 1046 | } |
1008 | 1047 | |
1009 | 1048 | for (size_t i = 0; i < lib->num_fontdata; i++) |
1010 | process_fontdata(priv, lib, ftlib, i); | |
1049 | process_fontdata(priv, i); | |
1011 | 1050 | *num_emfonts = lib->num_fontdata; |
1012 | 1051 | |
1013 | 1052 | return priv; |
1025 | 1064 | { ASS_FONTPROVIDER_CORETEXT, &ass_coretext_add_provider, "coretext"}, |
1026 | 1065 | #endif |
1027 | 1066 | #ifdef CONFIG_DIRECTWRITE |
1028 | { ASS_FONTPROVIDER_DIRECTWRITE, &ass_directwrite_add_provider, "directwrite"}, | |
1067 | { ASS_FONTPROVIDER_DIRECTWRITE, &ass_directwrite_add_provider, "directwrite" | |
1068 | #if ASS_WINAPI_DESKTOP | |
1069 | " (with GDI)" | |
1070 | #else | |
1071 | " (without GDI)" | |
1072 | #endif | |
1073 | }, | |
1029 | 1074 | #endif |
1030 | 1075 | #ifdef CONFIG_FONTCONFIG |
1031 | 1076 | { ASS_FONTPROVIDER_FONTCONFIG, &ass_fontconfig_add_provider, "fontconfig"}, |
1050 | 1095 | if (priv == NULL) |
1051 | 1096 | return NULL; |
1052 | 1097 | |
1098 | priv->library = library; | |
1099 | priv->ftlibrary = ftlibrary; | |
1053 | 1100 | priv->uid = 1; |
1054 | 1101 | priv->family_default = family ? strdup(family) : NULL; |
1055 | 1102 | priv->path_default = path ? strdup(path) : NULL; |
1056 | 1103 | priv->index_default = 0; |
1057 | 1104 | |
1058 | priv->embedded_provider = ass_embedded_fonts_add_provider(library, priv, | |
1059 | ftlibrary, num_emfonts); | |
1105 | priv->embedded_provider = ass_embedded_fonts_add_provider(priv, num_emfonts); | |
1060 | 1106 | |
1061 | 1107 | if (priv->embedded_provider == NULL) { |
1062 | 1108 | ass_msg(library, MSGL_WARN, "failed to create embedded font provider"); |
1142 | 1188 | } |
1143 | 1189 | } |
1144 | 1190 | |
1145 | size_t ass_update_embedded_fonts(ASS_Library *lib, ASS_FontSelector *selector, | |
1146 | FT_Library ftlib, size_t num_loaded) | |
1191 | size_t ass_update_embedded_fonts(ASS_FontSelector *selector, size_t num_loaded) | |
1147 | 1192 | { |
1148 | 1193 | if (!selector->embedded_provider) |
1149 | 1194 | return num_loaded; |
1150 | 1195 | |
1151 | for (size_t i = num_loaded; i < lib->num_fontdata; i++) | |
1152 | process_fontdata(selector->embedded_provider, lib, ftlib, i); | |
1153 | return lib->num_fontdata; | |
1154 | } | |
1196 | size_t num_fontdata = selector->library->num_fontdata; | |
1197 | for (size_t i = num_loaded; i < num_fontdata; i++) | |
1198 | process_fontdata(selector->embedded_provider, i); | |
1199 | return num_fontdata; | |
1200 | } |
26 | 26 | typedef struct ass_shaper_font_data ASS_ShaperFontData; |
27 | 27 | typedef struct font_selector ASS_FontSelector; |
28 | 28 | typedef struct font_info ASS_FontInfo; |
29 | typedef struct ass_font_stream ASS_FontStream; | |
29 | 30 | |
30 | 31 | #include "ass_types.h" |
31 | 32 | #include "ass.h" |
131 | 132 | ASS_FontProviderMetaData *meta); |
132 | 133 | |
133 | 134 | /** |
134 | * Get an appropriate fallback font for a given codepoint. | |
135 | * Get an appropriate fallback extended font family for a given codepoint. | |
135 | 136 | * |
136 | 137 | * This is called by fontselect whenever a glyph is not found in the |
137 | 138 | * physical font list of a logical font. fontselect will try to add the |
146 | 147 | * \param lib ASS_Library instance |
147 | 148 | * \param family original font family name (try matching a similar font) (never NULL) |
148 | 149 | * \param codepoint Unicode codepoint (UTF-32) |
149 | * \return output font family, allocated with malloc(), must be freed | |
150 | * \return output extended font family, allocated with malloc(), must be freed | |
150 | 151 | * by caller. |
151 | 152 | */ |
152 | 153 | typedef char *(*GetFallbackFunc)(void *priv, |
169 | 170 | /* |
170 | 171 | * Basic font metadata. All strings must be encoded with UTF-8. |
171 | 172 | * At minimum one family is required. |
173 | * If no family names are present, ass_font_provider_add_font | |
174 | * will open the font file and read metadata from there, | |
175 | * replacing everything but extended_family. | |
172 | 176 | */ |
173 | 177 | struct ass_font_provider_meta_data { |
174 | 178 | /** |
175 | * List of localized font family names, e.g. "Arial". | |
179 | * List of localized font family names, | |
180 | * e.g. "Arial", "Arial Narrow" or "Arial Black". | |
176 | 181 | */ |
177 | 182 | char **families; |
178 | 183 | |
179 | 184 | /** |
180 | * List of localized full names, e.g. "Arial Bold". | |
185 | * List of localized full names, e.g. "Arial Bold", | |
186 | * "Arial Narrow Bold", "Arial Black" or "Arial Black Normal". | |
181 | 187 | * The English name should be listed first to speed up typical matching. |
182 | 188 | */ |
183 | 189 | char **fullnames; |
184 | 190 | |
185 | 191 | /** |
186 | * The PostScript name, e.g. "Arial-BoldMT". | |
192 | * The PostScript name, e.g. "Arial-BoldMT", | |
193 | * "ArialNarrow-Bold" or "Arial-Black". | |
187 | 194 | */ |
188 | 195 | char *postscript_name; |
196 | ||
197 | /** | |
198 | * Any name that identifies an extended font family, e.g. "Arial". | |
199 | * This could be the full designer-named typographic family or (perhaps | |
200 | * even better) a (sub)family limited to weight/width/slant variations. | |
201 | * Names returned by get_fallback are matched against this field. | |
202 | */ | |
203 | char *extended_family; | |
189 | 204 | |
190 | 205 | int n_family; // Number of localized family names |
191 | 206 | int n_fullname; // Number of localized full names |
197 | 212 | // See FONT_WIDTH_* |
198 | 213 | }; |
199 | 214 | |
200 | typedef struct ass_font_stream ASS_FontStream; | |
201 | ||
202 | 215 | struct ass_font_stream { |
203 | 216 | // GetDataFunc |
204 | 217 | size_t (*func)(void *font_priv, unsigned char *data, |
231 | 244 | ass_fontselect_init(ASS_Library *library, FT_Library ftlibrary, size_t *num_emfonts, |
232 | 245 | const char *family, const char *path, const char *config, |
233 | 246 | ASS_DefaultFontProvider dfp); |
234 | char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, | |
247 | char *ass_font_select(ASS_FontSelector *priv, | |
235 | 248 | ASS_Font *font, int *index, char **postscript_name, |
236 | 249 | int *uid, ASS_FontStream *data, uint32_t code); |
237 | 250 | void ass_fontselect_free(ASS_FontSelector *priv); |
269 | 282 | int index, void *data); |
270 | 283 | |
271 | 284 | /** |
272 | * \brief Read a font's parameters | |
273 | * \param lib a FT_Library to use (need not be the global one) | |
274 | * \param path the path to the font file to read | |
275 | * \param postscript_name the PS name of the specific face to read (set either this or index) | |
276 | * \param index the face index to read, or -1 if not applicable | |
277 | * \param require_family_name whether to try a fallback family name and fail if none found | |
278 | * \param info the struct to store results into | |
279 | * \return success | |
280 | * | |
281 | */ | |
282 | bool ass_get_font_info(ASS_Library *lib, FT_Library ftlib, const char *path, | |
283 | const char *postscript_name, int index, | |
284 | bool require_family_name, | |
285 | ASS_FontProviderMetaData *info); | |
286 | ||
287 | /** | |
288 | 285 | * \brief Free font provider and associated fonts. |
289 | 286 | * \param provider the font provider |
290 | 287 | * |
294 | 291 | /** |
295 | 292 | * \brief Update embedded and memory fonts |
296 | 293 | */ |
297 | size_t ass_update_embedded_fonts(ASS_Library *lib, ASS_FontSelector *selector, | |
298 | FT_Library ftlib, size_t num_loaded); | |
294 | size_t ass_update_embedded_fonts(ASS_FontSelector *selector, size_t num_loaded); | |
299 | 295 | |
300 | 296 | #endif /* LIBASS_FONTSELECT_H */ |
2877 | 2877 | |
2878 | 2878 | if (render_priv->library->num_fontdata != render_priv->num_emfonts) { |
2879 | 2879 | assert(render_priv->library->num_fontdata > render_priv->num_emfonts); |
2880 | render_priv->num_emfonts = ass_update_embedded_fonts(render_priv->library, | |
2881 | render_priv->fontselect, render_priv->ftlibrary, render_priv->num_emfonts); | |
2880 | render_priv->num_emfonts = ass_update_embedded_fonts( | |
2881 | render_priv->fontselect, render_priv->num_emfonts); | |
2882 | 2882 | } |
2883 | 2883 | |
2884 | 2884 | ass_shaper_set_kerning(render_priv->shaper, track->Kerning); |
103 | 103 | unsigned ass_utf8_get_char(char **str); |
104 | 104 | unsigned ass_utf8_put_char(char *dest, uint32_t ch); |
105 | 105 | void ass_utf16be_to_utf8(char *dst, size_t dst_size, uint8_t *src, size_t src_size); |
106 | #if defined(__MINGW32__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) | |
107 | __attribute__ ((format (gnu_printf, 3, 4))) | |
108 | #elif defined(__GNUC__) | |
109 | __attribute__ ((format (printf, 3, 4))) | |
110 | #endif | |
106 | 111 | void ass_msg(ASS_Library *priv, int lvl, const char *fmt, ...); |
107 | 112 | int lookup_style(ASS_Track *track, char *name); |
108 | 113 | ASS_Style *lookup_style_strict(ASS_Track *track, char *name, size_t len); |
14 | 14 | #include <unknwn.h> |
15 | 15 | |
16 | 16 | typedef struct IDWriteFactory IDWriteFactory; |
17 | typedef struct IDWriteFactory3 IDWriteFactory3; | |
17 | 18 | typedef struct IDWriteFont IDWriteFont; |
18 | 19 | typedef struct IDWriteFontCollection IDWriteFontCollection; |
19 | 20 | typedef struct IDWriteFontFace IDWriteFontFace; |
21 | typedef struct IDWriteFontFace3 IDWriteFontFace3; | |
22 | typedef struct IDWriteFontFaceReference IDWriteFontFaceReference; | |
20 | 23 | typedef struct IDWriteFontFamily IDWriteFontFamily; |
21 | 24 | typedef struct IDWriteFontList IDWriteFontList; |
22 | 25 | typedef struct IDWriteFontFile IDWriteFontFile; |
23 | 26 | typedef struct IDWriteFontFileLoader IDWriteFontFileLoader; |
24 | 27 | typedef struct IDWriteFontFileStream IDWriteFontFileStream; |
28 | typedef struct IDWriteFontSet IDWriteFontSet; | |
25 | 29 | typedef struct IDWriteInlineObject IDWriteInlineObject; |
26 | 30 | typedef struct IDWriteLocalizedStrings IDWriteLocalizedStrings; |
27 | 31 | typedef struct IDWritePixelSnapping IDWritePixelSnapping; |
70 | 74 | DWRITE_FONT_FACE_TYPE_RAW_CFF |
71 | 75 | } DWRITE_FONT_FACE_TYPE; |
72 | 76 | |
77 | typedef enum DWRITE_FONT_PROPERTY_ID { | |
78 | DWRITE_FONT_PROPERTY_ID_NONE = 0, | |
79 | DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME, | |
80 | DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FAMILY_NAME, | |
81 | DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FACE_NAME, | |
82 | DWRITE_FONT_PROPERTY_ID_FULL_NAME, | |
83 | DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME, | |
84 | DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME, | |
85 | DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG, | |
86 | DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG, | |
87 | DWRITE_FONT_PROPERTY_ID_SEMANTIC_TAG, | |
88 | DWRITE_FONT_PROPERTY_ID_WEIGHT, | |
89 | DWRITE_FONT_PROPERTY_ID_STRETCH, | |
90 | DWRITE_FONT_PROPERTY_ID_STYLE, | |
91 | DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME, | |
92 | /* rest dropped */ | |
93 | } DWRITE_FONT_PROPERTY_ID; | |
94 | ||
73 | 95 | typedef enum DWRITE_FONT_SIMULATIONS { |
74 | 96 | DWRITE_FONT_SIMULATIONS_NONE = 0x0000, |
75 | 97 | DWRITE_FONT_SIMULATIONS_BOLD = 0x0001, |
101 | 123 | /* rest dropped */ |
102 | 124 | } DWRITE_FONT_WEIGHT; |
103 | 125 | |
126 | typedef enum DWRITE_LOCALITY { | |
127 | DWRITE_LOCALITY_REMOTE = 0, | |
128 | DWRITE_LOCALITY_PARTIAL, | |
129 | DWRITE_LOCALITY_LOCAL | |
130 | } DWRITE_LOCALITY; | |
131 | ||
104 | 132 | typedef struct DWRITE_FONT_METRICS { |
105 | 133 | UINT16 designUnitsPerEm; |
106 | 134 | UINT16 ascent; |
114 | 142 | UINT16 strikethroughThickness; |
115 | 143 | } DWRITE_FONT_METRICS; |
116 | 144 | |
145 | typedef struct DWRITE_FONT_PROPERTY { | |
146 | DWRITE_FONT_PROPERTY_ID propertyId; | |
147 | const WCHAR *propertyValue; | |
148 | const WCHAR *localeName; | |
149 | } DWRITE_FONT_PROPERTY; | |
150 | ||
117 | 151 | typedef struct DWRITE_GLYPH_OFFSET DWRITE_GLYPH_OFFSET; |
118 | 152 | |
119 | 153 | typedef struct DWRITE_GLYPH_RUN { |
191 | 225 | IDWriteTextFormat **textFormat) PURE; |
192 | 226 | |
193 | 227 | STDMETHOD(dummy12)(THIS); |
228 | ||
194 | 229 | STDMETHOD(GetGdiInterop)(THIS_ |
195 | 230 | IDWriteGdiInterop **gdiInterop) PURE; |
196 | 231 | |
213 | 248 | #define IDWriteFactory_CreateTextFormat(This,fontFamilyName,fontCollection,fontWeight,fontStyle,fontStretch,fontSize,localeName,textFormat) (This)->lpVtbl->CreateTextFormat(This,fontFamilyName,fontCollection,fontWeight,fontStyle,fontStretch,fontSize,localeName,textFormat) |
214 | 249 | #define IDWriteFactory_CreateTextLayout(This,string,stringLength,textFormat,maxWidth,maxHeight,textLayout) (This)->lpVtbl->CreateTextLayout(This,string,stringLength,textFormat,maxWidth,maxHeight,textLayout) |
215 | 250 | #define IDWriteFactory_GetGdiInterop(This,gdiInterop) (This)->lpVtbl->GetGdiInterop(This,gdiInterop) |
251 | #endif /*COBJMACROS*/ | |
252 | ||
253 | #undef INTERFACE | |
254 | #define INTERFACE IDWriteFactory3 | |
255 | DECLARE_INTERFACE_(IDWriteFactory3,IDWriteFactory) | |
256 | { | |
257 | BEGIN_INTERFACE | |
258 | ||
259 | #ifndef __cplusplus | |
260 | /* IUnknown methods */ | |
261 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; | |
262 | STDMETHOD_(ULONG, AddRef)(THIS) PURE; | |
263 | STDMETHOD_(ULONG, Release)(THIS) PURE; | |
264 | ||
265 | /* IDWriteFactory methods */ | |
266 | STDMETHOD(GetSystemFontCollection)(THIS_ | |
267 | IDWriteFontCollection **fontCollection, | |
268 | BOOL checkForUpdates __MINGW_DEF_ARG_VAL(FALSE)) PURE; | |
269 | ||
270 | STDMETHOD(dummy1)(THIS); | |
271 | STDMETHOD(dummy2)(THIS); | |
272 | STDMETHOD(dummy3)(THIS); | |
273 | STDMETHOD(dummy4)(THIS); | |
274 | STDMETHOD(dummy5)(THIS); | |
275 | STDMETHOD(dummy6)(THIS); | |
276 | STDMETHOD(dummy7)(THIS); | |
277 | STDMETHOD(dummy8)(THIS); | |
278 | STDMETHOD(dummy9)(THIS); | |
279 | STDMETHOD(dummy10)(THIS); | |
280 | STDMETHOD(dummy11)(THIS); | |
281 | ||
282 | STDMETHOD(CreateTextFormat)(THIS_ | |
283 | WCHAR const *fontFamilyName, | |
284 | IDWriteFontCollection *fontCollection, | |
285 | DWRITE_FONT_WEIGHT fontWeight, | |
286 | DWRITE_FONT_STYLE fontStyle, | |
287 | DWRITE_FONT_STRETCH fontStretch, | |
288 | FLOAT fontSize, | |
289 | WCHAR const *localeName, | |
290 | IDWriteTextFormat **textFormat) PURE; | |
291 | ||
292 | STDMETHOD(dummy12)(THIS); | |
293 | ||
294 | STDMETHOD(GetGdiInterop)(THIS_ | |
295 | IDWriteGdiInterop **gdiInterop) PURE; | |
296 | ||
297 | STDMETHOD(CreateTextLayout)(THIS_ | |
298 | WCHAR const *string, | |
299 | UINT32 stringLength, | |
300 | IDWriteTextFormat *textFormat, | |
301 | FLOAT maxWidth, | |
302 | FLOAT maxHeight, | |
303 | IDWriteTextLayout **textLayout) PURE; | |
304 | #endif | |
305 | ||
306 | STDMETHOD(dummy13)(THIS); | |
307 | STDMETHOD(dummy14)(THIS); | |
308 | STDMETHOD(dummy15)(THIS); | |
309 | STDMETHOD(dummy16)(THIS); | |
310 | STDMETHOD(dummy17)(THIS); | |
311 | ||
312 | /* IDWriteFactory1 methods */ | |
313 | STDMETHOD(dummy18)(THIS); | |
314 | STDMETHOD(dummy19)(THIS); | |
315 | ||
316 | /* IDWriteFactory2 methods */ | |
317 | STDMETHOD(dummy20)(THIS); | |
318 | STDMETHOD(dummy21)(THIS); | |
319 | STDMETHOD(dummy22)(THIS); | |
320 | STDMETHOD(dummy23)(THIS); | |
321 | STDMETHOD(dummy24)(THIS); | |
322 | ||
323 | /* IDWriteFactory3 methods */ | |
324 | STDMETHOD(dummy25)(THIS); | |
325 | STDMETHOD(dummy26)(THIS); | |
326 | STDMETHOD(dummy27)(THIS); | |
327 | STDMETHOD(dummy28)(THIS); | |
328 | ||
329 | STDMETHOD(GetSystemFontSet)(THIS_ | |
330 | IDWriteFontSet **fontSet) PURE; | |
331 | ||
332 | /* rest dropped */ | |
333 | END_INTERFACE | |
334 | }; | |
335 | #ifdef COBJMACROS | |
336 | #define IDWriteFactory3_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) | |
337 | #define IDWriteFactory3_AddRef(This) (This)->lpVtbl->AddRef(This) | |
338 | #define IDWriteFactory3_Release(This) (This)->lpVtbl->Release(This) | |
339 | #define IDWriteFactory3_GetSystemFontCollection(This,fontCollection,checkForUpdates) (This)->lpVtbl->GetSystemFontCollection(This,fontCollection,checkForUpdates) | |
340 | #define IDWriteFactory3_CreateTextFormat(This,fontFamilyName,fontCollection,fontWeight,fontStyle,fontStretch,fontSize,localeName,textFormat) (This)->lpVtbl->CreateTextFormat(This,fontFamilyName,fontCollection,fontWeight,fontStyle,fontStretch,fontSize,localeName,textFormat) | |
341 | #define IDWriteFactory3_CreateTextLayout(This,string,stringLength,textFormat,maxWidth,maxHeight,textLayout) (This)->lpVtbl->CreateTextLayout(This,string,stringLength,textFormat,maxWidth,maxHeight,textLayout) | |
342 | #define IDWriteFactory3_GetGdiInterop(This,gdiInterop) (This)->lpVtbl->GetGdiInterop(This,gdiInterop) | |
343 | #define IDWriteFactory3_GetSystemFontSet(This,fontSet) (This)->lpVtbl->GetSystemFontSet(This,fontSet) | |
216 | 344 | #endif /*COBJMACROS*/ |
217 | 345 | |
218 | 346 | #undef INTERFACE |
339 | 467 | |
340 | 468 | STDMETHOD_(UINT32, GetIndex)(THIS) PURE; |
341 | 469 | |
470 | STDMETHOD(dummy1)(THIS); | |
471 | STDMETHOD(dummy2)(THIS); | |
472 | STDMETHOD(dummy3)(THIS); | |
473 | STDMETHOD(dummy4)(THIS); | |
474 | STDMETHOD(dummy5)(THIS); | |
475 | ||
476 | STDMETHOD(GetGlyphIndices)(THIS_ | |
477 | UINT32 const *codePoints, | |
478 | UINT32 codePointCount, | |
479 | UINT16 *glyphIndices) PURE; | |
480 | ||
342 | 481 | /* rest dropped */ |
343 | 482 | END_INTERFACE |
344 | 483 | }; |
345 | 484 | #ifdef COBJMACROS |
485 | #define IDWriteFontFace_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) | |
486 | #define IDWriteFontFace_AddRef(This) (This)->lpVtbl->AddRef(This) | |
346 | 487 | #define IDWriteFontFace_Release(This) (This)->lpVtbl->Release(This) |
347 | 488 | #define IDWriteFontFace_GetType(This) (This)->lpVtbl->GetType(This) |
348 | #define IDWriteFontFace_GetFiles(This,fontFiles,b) (This)->lpVtbl->GetFiles(This,fontFiles,b) | |
489 | #define IDWriteFontFace_GetFiles(This,numberOfFiles,fontFiles) (This)->lpVtbl->GetFiles(This,numberOfFiles,fontFiles) | |
349 | 490 | #define IDWriteFontFace_GetIndex(This) (This)->lpVtbl->GetIndex(This) |
491 | #define IDWriteFontFace_GetGlyphIndices(This,codePoints,codePointCount,glyphIndices) (This)->lpVtbl->GetGlyphIndices(This,codePoints,codePointCount,glyphIndices) | |
492 | #endif /*COBJMACROS*/ | |
493 | ||
494 | #undef INTERFACE | |
495 | #define INTERFACE IDWriteFontFace3 | |
496 | DECLARE_INTERFACE_(IDWriteFontFace3,IDWriteFontFace) | |
497 | { | |
498 | BEGIN_INTERFACE | |
499 | ||
500 | #ifndef __cplusplus | |
501 | /* IUnknown methods */ | |
502 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; | |
503 | STDMETHOD_(ULONG, AddRef)(THIS) PURE; | |
504 | STDMETHOD_(ULONG, Release)(THIS) PURE; | |
505 | ||
506 | /* IDWriteFontFace methods */ | |
507 | STDMETHOD_(DWRITE_FONT_FACE_TYPE, GetType)(THIS) PURE; | |
508 | ||
509 | STDMETHOD(GetFiles)(THIS_ | |
510 | UINT32 *numberOfFiles, | |
511 | IDWriteFontFile **fontFiles) PURE; | |
512 | ||
513 | STDMETHOD_(UINT32, GetIndex)(THIS) PURE; | |
514 | ||
515 | STDMETHOD(dummy1)(THIS); | |
516 | STDMETHOD(dummy2)(THIS); | |
517 | STDMETHOD(dummy3)(THIS); | |
518 | STDMETHOD(dummy4)(THIS); | |
519 | STDMETHOD(dummy5)(THIS); | |
520 | ||
521 | STDMETHOD(GetGlyphIndices)(THIS_ | |
522 | UINT32 const *codePoints, | |
523 | UINT32 codePointCount, | |
524 | UINT16 *glyphIndices) PURE; | |
525 | ||
526 | STDMETHOD(dummy6)(THIS); | |
527 | STDMETHOD(dummy7)(THIS); | |
528 | STDMETHOD(dummy8)(THIS); | |
529 | STDMETHOD(dummy9)(THIS); | |
530 | STDMETHOD(dummy10)(THIS); | |
531 | STDMETHOD(dummy11)(THIS); | |
532 | #endif | |
533 | ||
534 | /* IDWriteFontFace1 methods */ | |
535 | STDMETHOD(dummy12)(THIS); | |
536 | STDMETHOD(dummy13)(THIS); | |
537 | STDMETHOD(dummy14)(THIS); | |
538 | STDMETHOD(dummy15)(THIS); | |
539 | STDMETHOD(dummy16)(THIS); | |
540 | STDMETHOD(dummy17)(THIS); | |
541 | STDMETHOD(dummy18)(THIS); | |
542 | STDMETHOD(dummy19)(THIS); | |
543 | STDMETHOD(dummy20)(THIS); | |
544 | STDMETHOD(dummy21)(THIS); | |
545 | STDMETHOD(dummy22)(THIS); | |
546 | STDMETHOD(dummy23)(THIS); | |
547 | ||
548 | /* IDWriteFontFace2 methods */ | |
549 | STDMETHOD(dummy24)(THIS); | |
550 | STDMETHOD(dummy25)(THIS); | |
551 | STDMETHOD(dummy26)(THIS); | |
552 | STDMETHOD(dummy27)(THIS); | |
553 | STDMETHOD(dummy28)(THIS); | |
554 | ||
555 | /* IDWriteFontFace3 methods */ | |
556 | STDMETHOD(dummy29)(THIS); | |
557 | STDMETHOD(dummy30)(THIS); | |
558 | ||
559 | STDMETHOD_(DWRITE_FONT_WEIGHT, GetWeight)(THIS) PURE; | |
560 | STDMETHOD_(DWRITE_FONT_STRETCH, GetStretch)(THIS) PURE; | |
561 | STDMETHOD_(DWRITE_FONT_STYLE, GetStyle)(THIS) PURE; | |
562 | ||
563 | STDMETHOD(GetFamilyNames)(THIS_ | |
564 | IDWriteLocalizedStrings **names) PURE; | |
565 | ||
566 | STDMETHOD(dummy31)(THIS); | |
567 | ||
568 | STDMETHOD(GetInformationalStrings)(THIS_ | |
569 | DWRITE_INFORMATIONAL_STRING_ID informationalStringID, | |
570 | IDWriteLocalizedStrings **informationalStrings, | |
571 | BOOL *exists) PURE; | |
572 | ||
573 | /* rest dropped */ | |
574 | END_INTERFACE | |
575 | }; | |
576 | #ifdef COBJMACROS | |
577 | #define IDWriteFontFace3_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) | |
578 | #define IDWriteFontFace3_AddRef(This) (This)->lpVtbl->AddRef(This) | |
579 | #define IDWriteFontFace3_Release(This) (This)->lpVtbl->Release(This) | |
580 | #define IDWriteFontFace3_GetType(This) (This)->lpVtbl->GetType(This) | |
581 | #define IDWriteFontFace3_GetFiles(This,numberOfFiles,fontFiles) (This)->lpVtbl->GetFiles(This,numberOfFiles,fontFiles) | |
582 | #define IDWriteFontFace3_GetIndex(This) (This)->lpVtbl->GetIndex(This) | |
583 | #define IDWriteFontFace3_GetGlyphIndices(This,codePoints,codePointCount,glyphIndices) (This)->lpVtbl->GetGlyphIndices(This,codePoints,codePointCount,glyphIndices) | |
584 | #define IDWriteFontFace3_GetWeight(This) (This)->lpVtbl->GetWeight(This) | |
585 | #define IDWriteFontFace3_GetStretch(This) (This)->lpVtbl->GetStretch(This) | |
586 | #define IDWriteFontFace3_GetStyle(This) (This)->lpVtbl->GetStyle(This) | |
587 | #define IDWriteFontFace3_GetFamilyNames(This,names) (This)->lpVtbl->GetFamilyNames(This,names) | |
588 | #define IDWriteFontFace3_GetInformationalStrings(This,informationalStringID,informationalStrings,exists) (This)->lpVtbl->GetInformationalStrings(This,informationalStringID,informationalStrings,exists) | |
589 | #endif /*COBJMACROS*/ | |
590 | ||
591 | #undef INTERFACE | |
592 | #define INTERFACE IDWriteFontFaceReference | |
593 | DECLARE_INTERFACE_(IDWriteFontFaceReference,IUnknown) | |
594 | { | |
595 | BEGIN_INTERFACE | |
596 | ||
597 | #ifndef __cplusplus | |
598 | /* IUnknown methods */ | |
599 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; | |
600 | STDMETHOD_(ULONG, AddRef)(THIS) PURE; | |
601 | STDMETHOD_(ULONG, Release)(THIS) PURE; | |
602 | #endif | |
603 | ||
604 | STDMETHOD(CreateFontFace)(THIS_ | |
605 | IDWriteFontFace3 **fontFace) PURE; | |
606 | ||
607 | STDMETHOD(dummy1)(THIS); | |
608 | STDMETHOD(dummy2)(THIS); | |
609 | STDMETHOD(dummy3)(THIS); | |
610 | ||
611 | STDMETHOD_(DWRITE_FONT_SIMULATIONS, GetSimulations)(THIS) PURE; | |
612 | ||
613 | STDMETHOD(dummy4)(THIS); | |
614 | STDMETHOD(dummy5)(THIS); | |
615 | STDMETHOD(dummy6)(THIS); | |
616 | STDMETHOD(dummy7)(THIS); | |
617 | ||
618 | STDMETHOD_(DWRITE_LOCALITY, GetLocality)(THIS) PURE; | |
619 | ||
620 | /* rest dropped */ | |
621 | END_INTERFACE | |
622 | }; | |
623 | #ifdef COBJMACROS | |
624 | #define IDWriteFontFaceReference_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) | |
625 | #define IDWriteFontFaceReference_AddRef(This) (This)->lpVtbl->AddRef(This) | |
626 | #define IDWriteFontFaceReference_Release(This) (This)->lpVtbl->Release(This) | |
627 | #define IDWriteFontFaceReference_CreateFontFace(This,fontFace) (This)->lpVtbl->CreateFontFace(This,fontFace) | |
628 | #define IDWriteFontFaceReference_GetSimulations(This) (This)->lpVtbl->GetSimulations(This) | |
629 | #define IDWriteFontFaceReference_GetLocality(This) (This)->lpVtbl->GetLocality(This) | |
350 | 630 | #endif /*COBJMACROS*/ |
351 | 631 | |
352 | 632 | #undef INTERFACE |
487 | 767 | #endif /*COBJMACROS*/ |
488 | 768 | |
489 | 769 | #undef INTERFACE |
490 | #define INTERFACE IDWriteLocalizedStrings | |
491 | DECLARE_INTERFACE_(IDWriteLocalizedStrings,IUnknown) | |
492 | { | |
493 | BEGIN_INTERFACE | |
494 | ||
495 | #ifndef __cplusplus | |
496 | /* IUnknown methods */ | |
497 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; | |
498 | STDMETHOD_(ULONG, AddRef)(THIS) PURE; | |
499 | STDMETHOD_(ULONG, Release)(THIS) PURE; | |
500 | #endif | |
501 | ||
502 | /* IDWriteLocalizedStrings methods */ | |
503 | STDMETHOD_(UINT32, GetCount)(THIS) PURE; | |
770 | #define INTERFACE IDWriteFontSet | |
771 | DECLARE_INTERFACE_(IDWriteFontSet,IUnknown) | |
772 | { | |
773 | BEGIN_INTERFACE | |
774 | ||
775 | #ifndef __cplusplus | |
776 | /* IUnknown methods */ | |
777 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; | |
778 | STDMETHOD_(ULONG, AddRef)(THIS) PURE; | |
779 | STDMETHOD_(ULONG, Release)(THIS) PURE; | |
780 | #endif | |
781 | ||
782 | /* IDWriteFontSet methods */ | |
783 | STDMETHOD_(UINT32, GetFontCount)(THIS) PURE; | |
784 | ||
785 | STDMETHOD(GetFontFaceReference)(THIS_ | |
786 | UINT32 listIndex, | |
787 | IDWriteFontFaceReference **fontFaceReference) PURE; | |
504 | 788 | |
505 | 789 | STDMETHOD(dummy1)(THIS); |
506 | 790 | STDMETHOD(dummy2)(THIS); |
507 | 791 | STDMETHOD(dummy3)(THIS); |
508 | 792 | STDMETHOD(dummy4)(THIS); |
509 | ||
793 | STDMETHOD(dummy5)(THIS); | |
794 | STDMETHOD(dummy6)(THIS); | |
795 | STDMETHOD(dummy7)(THIS); | |
796 | ||
797 | STDMETHOD(GetMatchingFonts)(THIS_ | |
798 | DWRITE_FONT_PROPERTY const *properties, | |
799 | UINT32 propertyCount, | |
800 | IDWriteFontSet **filteredSet) PURE; | |
801 | ||
802 | /* rest dropped */ | |
803 | END_INTERFACE | |
804 | }; | |
805 | #ifdef COBJMACROS | |
806 | #define IDWriteFontSet_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) | |
807 | #define IDWriteFontSet_AddRef(This) (This)->lpVtbl->AddRef(This) | |
808 | #define IDWriteFontSet_Release(This) (This)->lpVtbl->Release(This) | |
809 | #define IDWriteFontSet_GetFontCount(This) (This)->lpVtbl->GetFontCount(This) | |
810 | #define IDWriteFontSet_GetFontFaceReference(This,listIndex,fontFaceReference) (This)->lpVtbl->GetFontFaceReference(This,listIndex,fontFaceReference) | |
811 | #define IDWriteFontSet_GetMatchingFonts(This,properties,propertyCount,filteredSet) (This)->lpVtbl->GetMatchingFonts(This,properties,propertyCount,filteredSet) | |
812 | #endif /*COBJMACROS*/ | |
813 | ||
814 | #undef INTERFACE | |
815 | #define INTERFACE IDWriteLocalizedStrings | |
816 | DECLARE_INTERFACE_(IDWriteLocalizedStrings,IUnknown) | |
817 | { | |
818 | BEGIN_INTERFACE | |
819 | ||
820 | #ifndef __cplusplus | |
821 | /* IUnknown methods */ | |
822 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppvObject) PURE; | |
823 | STDMETHOD_(ULONG, AddRef)(THIS) PURE; | |
824 | STDMETHOD_(ULONG, Release)(THIS) PURE; | |
825 | #endif | |
826 | ||
827 | /* IDWriteLocalizedStrings methods */ | |
828 | STDMETHOD_(UINT32, GetCount)(THIS) PURE; | |
829 | ||
830 | STDMETHOD(dummy1)(THIS); | |
831 | STDMETHOD(dummy2)(THIS); | |
832 | STDMETHOD(dummy3)(THIS); | |
833 | ||
834 | STDMETHOD(GetStringLength)(THIS_ | |
835 | UINT32 index, | |
836 | UINT32 *length) PURE; | |
510 | 837 | STDMETHOD(GetString)(THIS_ |
511 | 838 | UINT32 index, |
512 | 839 | WCHAR *stringBuffer, |
517 | 844 | #ifdef COBJMACROS |
518 | 845 | #define IDWriteLocalizedStrings_Release(This) (This)->lpVtbl->Release(This) |
519 | 846 | #define IDWriteLocalizedStrings_GetCount(This) (This)->lpVtbl->GetCount(This) |
847 | #define IDWriteLocalizedStrings_GetStringLength(This,index,length) (This)->lpVtbl->GetStringLength(This,index,length) | |
520 | 848 | #define IDWriteLocalizedStrings_GetString(This,index,stringBuffer,size) (This)->lpVtbl->GetString(This,index,stringBuffer,size) |
521 | 849 | #endif /*COBJMACROS*/ |
522 | 850 | |
698 | 1026 | STDMETHOD(CreateFontFromLOGFONT)(THIS_ |
699 | 1027 | LOGFONTW const *logFont, |
700 | 1028 | IDWriteFont **font) PURE; |
1029 | ||
1030 | STDMETHOD(dummy1)(THIS); | |
1031 | STDMETHOD(dummy2)(THIS); | |
1032 | ||
1033 | STDMETHOD(CreateFontFaceFromHdc)(THIS_ | |
1034 | HDC hdc, | |
1035 | IDWriteFontFace **fontFace) PURE; | |
701 | 1036 | /* rest dropped */ |
702 | 1037 | END_INTERFACE |
703 | 1038 | }; |
706 | 1041 | #define IDWriteGdiInterop_AddRef(This) (This)->lpVtbl->AddRef(This) |
707 | 1042 | #define IDWriteGdiInterop_Release(This) (This)->lpVtbl->Release(This) |
708 | 1043 | #define IDWriteGdiInterop_CreateFontFromLOGFONT(This,logFont,font) (This)->lpVtbl->CreateFontFromLOGFONT(This,logFont,font) |
1044 | #define IDWriteGdiInterop_CreateFontFaceFromHdc(This,hdc,fontFace) (This)->lpVtbl->CreateFontFaceFromHdc(This,hdc,fontFace) | |
709 | 1045 | #endif /*COBJMACROS*/ |
710 | 1046 | |
711 | 1047 | DEFINE_GUID(IID_IDWriteFactory, 0xb859ee5a,0xd838,0x4b5b,0xa2,0xe8,0x1a,0xdc,0x7d,0x93,0xdb,0x48); |
1048 | DEFINE_GUID(IID_IDWriteFactory3, 0x9a1b41c3,0xd3bb,0x466a,0x87,0xfc,0xfe,0x67,0x55,0x6a,0x3b,0x65); | |
1049 | DEFINE_GUID(IID_IDWriteFontFace3, 0xd37d7598,0x09be,0x4222,0xa2,0x36,0x20,0x81,0x34,0x1c,0xc1,0xf2); | |
712 | 1050 | DEFINE_GUID(IID_IDWritePixelSnapping, 0xeaf3a2da,0xecf4,0x4d24,0xb6,0x44,0xb3,0x4f,0x68,0x42,0x02,0x4b); |
713 | 1051 | DEFINE_GUID(IID_IDWriteTextRenderer, 0xef8a8135,0x5cc6,0x45fe,0x88,0x25,0xc5,0xa0,0x72,0x4e,0xb8,0x19); |
714 | DEFINE_GUID(IID_IDWriteGdiInterop, 0x1edd9491,0x9853,0x4299,0x89,0x8f,0x64,0x32,0x98,0x3b,0x6f,0x3a); | |
715 | 1052 | |
716 | 1053 | #endif /* __INC_DWRITE__ */ |
30 | 30 | |
31 | 31 | PROGRAM=libtool |
32 | 32 | PACKAGE=libtool |
33 | VERSION=2.4.6 | |
33 | VERSION="2.4.6 Debian-2.4.6-15" | |
34 | 34 | package_revision=2.4.6 |
35 | 35 | |
36 | 36 | |
386 | 386 | # putting '$debug_cmd' at the start of all your functions, you can get |
387 | 387 | # bash to show function call trace with: |
388 | 388 | # |
389 | # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name | |
389 | # debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name | |
390 | 390 | debug_cmd=${debug_cmd-":"} |
391 | 391 | exit_cmd=: |
392 | 392 | |
1369 | 1369 | #! /bin/sh |
1370 | 1370 | |
1371 | 1371 | # Set a version string for this script. |
1372 | scriptversion=2014-01-07.03; # UTC | |
1372 | scriptversion=2015-10-07.11; # UTC | |
1373 | 1373 | |
1374 | 1374 | # A portable, pluggable option parser for Bourne shell. |
1375 | 1375 | # Written by Gary V. Vaughan, 2010 |
1529 | 1529 | { |
1530 | 1530 | $debug_cmd |
1531 | 1531 | |
1532 | _G_rc_run_hooks=false | |
1533 | ||
1532 | 1534 | case " $hookable_fns " in |
1533 | 1535 | *" $1 "*) ;; |
1534 | 1536 | *) func_fatal_error "'$1' does not support hook funcions.n" ;; |
1537 | 1539 | eval _G_hook_fns=\$$1_hooks; shift |
1538 | 1540 | |
1539 | 1541 | for _G_hook in $_G_hook_fns; do |
1540 | eval $_G_hook '"$@"' | |
1541 | ||
1542 | # store returned options list back into positional | |
1543 | # parameters for next 'cmd' execution. | |
1544 | eval _G_hook_result=\$${_G_hook}_result | |
1545 | eval set dummy "$_G_hook_result"; shift | |
1542 | if eval $_G_hook '"$@"'; then | |
1543 | # store returned options list back into positional | |
1544 | # parameters for next 'cmd' execution. | |
1545 | eval _G_hook_result=\$${_G_hook}_result | |
1546 | eval set dummy "$_G_hook_result"; shift | |
1547 | _G_rc_run_hooks=: | |
1548 | fi | |
1546 | 1549 | done |
1547 | 1550 | |
1548 | func_quote_for_eval ${1+"$@"} | |
1549 | func_run_hooks_result=$func_quote_for_eval_result | |
1551 | $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result | |
1550 | 1552 | } |
1551 | 1553 | |
1552 | 1554 | |
1556 | 1558 | ## --------------- ## |
1557 | 1559 | |
1558 | 1560 | # In order to add your own option parsing hooks, you must accept the |
1559 | # full positional parameter list in your hook function, remove any | |
1560 | # options that you action, and then pass back the remaining unprocessed | |
1561 | # full positional parameter list in your hook function, you may remove/edit | |
1562 | # any options that you action, and then pass back the remaining unprocessed | |
1561 | 1563 | # options in '<hooked_function_name>_result', escaped suitably for |
1562 | # 'eval'. Like this: | |
1564 | # 'eval'. In this case you also must return $EXIT_SUCCESS to let the | |
1565 | # hook's caller know that it should pay attention to | |
1566 | # '<hooked_function_name>_result'. Returning $EXIT_FAILURE signalizes that | |
1567 | # arguments are left untouched by the hook and therefore caller will ignore the | |
1568 | # result variable. | |
1569 | # | |
1570 | # Like this: | |
1563 | 1571 | # |
1564 | 1572 | # my_options_prep () |
1565 | 1573 | # { |
1569 | 1577 | # usage_message=$usage_message' |
1570 | 1578 | # -s, --silent don'\''t print informational messages |
1571 | 1579 | # ' |
1572 | # | |
1573 | # func_quote_for_eval ${1+"$@"} | |
1574 | # my_options_prep_result=$func_quote_for_eval_result | |
1580 | # # No change in '$@' (ignored completely by this hook). There is | |
1581 | # # no need to do the equivalent (but slower) action: | |
1582 | # # func_quote_for_eval ${1+"$@"} | |
1583 | # # my_options_prep_result=$func_quote_for_eval_result | |
1584 | # false | |
1575 | 1585 | # } |
1576 | 1586 | # func_add_hook func_options_prep my_options_prep |
1577 | 1587 | # |
1580 | 1590 | # { |
1581 | 1591 | # $debug_cmd |
1582 | 1592 | # |
1593 | # args_changed=false | |
1594 | # | |
1583 | 1595 | # # Note that for efficiency, we parse as many options as we can |
1584 | 1596 | # # recognise in a loop before passing the remainder back to the |
1585 | 1597 | # # caller on the first unrecognised argument we encounter. |
1586 | 1598 | # while test $# -gt 0; do |
1587 | 1599 | # opt=$1; shift |
1588 | 1600 | # case $opt in |
1589 | # --silent|-s) opt_silent=: ;; | |
1601 | # --silent|-s) opt_silent=: | |
1602 | # args_changed=: | |
1603 | # ;; | |
1590 | 1604 | # # Separate non-argument short options: |
1591 | 1605 | # -s*) func_split_short_opt "$_G_opt" |
1592 | 1606 | # set dummy "$func_split_short_opt_name" \ |
1593 | 1607 | # "-$func_split_short_opt_arg" ${1+"$@"} |
1594 | 1608 | # shift |
1609 | # args_changed=: | |
1595 | 1610 | # ;; |
1596 | # *) set dummy "$_G_opt" "$*"; shift; break ;; | |
1611 | # *) # Make sure the first unrecognised option "$_G_opt" | |
1612 | # # is added back to "$@", we could need that later | |
1613 | # # if $args_changed is true. | |
1614 | # set dummy "$_G_opt" ${1+"$@"}; shift; break ;; | |
1597 | 1615 | # esac |
1598 | 1616 | # done |
1599 | 1617 | # |
1600 | # func_quote_for_eval ${1+"$@"} | |
1601 | # my_silent_option_result=$func_quote_for_eval_result | |
1618 | # if $args_changed; then | |
1619 | # func_quote_for_eval ${1+"$@"} | |
1620 | # my_silent_option_result=$func_quote_for_eval_result | |
1621 | # fi | |
1622 | # | |
1623 | # $args_changed | |
1602 | 1624 | # } |
1603 | 1625 | # func_add_hook func_parse_options my_silent_option |
1604 | 1626 | # |
1610 | 1632 | # $opt_silent && $opt_verbose && func_fatal_help "\ |
1611 | 1633 | # '--silent' and '--verbose' options are mutually exclusive." |
1612 | 1634 | # |
1613 | # func_quote_for_eval ${1+"$@"} | |
1614 | # my_option_validation_result=$func_quote_for_eval_result | |
1635 | # false | |
1615 | 1636 | # } |
1616 | 1637 | # func_add_hook func_validate_options my_option_validation |
1617 | 1638 | # |
1618 | # You'll alse need to manually amend $usage_message to reflect the extra | |
1639 | # You'll also need to manually amend $usage_message to reflect the extra | |
1619 | 1640 | # options you parse. It's preferable to append if you can, so that |
1620 | 1641 | # multiple option parsing hooks can be added safely. |
1642 | ||
1643 | ||
1644 | # func_options_finish [ARG]... | |
1645 | # ---------------------------- | |
1646 | # Finishing the option parse loop (call 'func_options' hooks ATM). | |
1647 | func_options_finish () | |
1648 | { | |
1649 | $debug_cmd | |
1650 | ||
1651 | _G_func_options_finish_exit=false | |
1652 | if func_run_hooks func_options ${1+"$@"}; then | |
1653 | func_options_finish_result=$func_run_hooks_result | |
1654 | _G_func_options_finish_exit=: | |
1655 | fi | |
1656 | ||
1657 | $_G_func_options_finish_exit | |
1658 | } | |
1621 | 1659 | |
1622 | 1660 | |
1623 | 1661 | # func_options [ARG]... |
1629 | 1667 | { |
1630 | 1668 | $debug_cmd |
1631 | 1669 | |
1632 | func_options_prep ${1+"$@"} | |
1633 | eval func_parse_options \ | |
1634 | ${func_options_prep_result+"$func_options_prep_result"} | |
1635 | eval func_validate_options \ | |
1636 | ${func_parse_options_result+"$func_parse_options_result"} | |
1637 | ||
1638 | eval func_run_hooks func_options \ | |
1639 | ${func_validate_options_result+"$func_validate_options_result"} | |
1640 | ||
1641 | # save modified positional parameters for caller | |
1642 | func_options_result=$func_run_hooks_result | |
1670 | _G_rc_options=false | |
1671 | ||
1672 | for my_func in options_prep parse_options validate_options options_finish | |
1673 | do | |
1674 | if eval func_$my_func '${1+"$@"}'; then | |
1675 | eval _G_res_var='$'"func_${my_func}_result" | |
1676 | eval set dummy "$_G_res_var" ; shift | |
1677 | _G_rc_options=: | |
1678 | fi | |
1679 | done | |
1680 | ||
1681 | # Save modified positional parameters for caller. As a top-level | |
1682 | # options-parser function we always need to set the 'func_options_result' | |
1683 | # variable (regardless the $_G_rc_options value). | |
1684 | if $_G_rc_options; then | |
1685 | func_options_result=$_G_res_var | |
1686 | else | |
1687 | func_quote_for_eval ${1+"$@"} | |
1688 | func_options_result=$func_quote_for_eval_result | |
1689 | fi | |
1690 | ||
1691 | $_G_rc_options | |
1643 | 1692 | } |
1644 | 1693 | |
1645 | 1694 | |
1648 | 1697 | # All initialisations required before starting the option parse loop. |
1649 | 1698 | # Note that when calling hook functions, we pass through the list of |
1650 | 1699 | # positional parameters. If a hook function modifies that list, and |
1651 | # needs to propogate that back to rest of this script, then the complete | |
1700 | # needs to propagate that back to rest of this script, then the complete | |
1652 | 1701 | # modified list must be put in 'func_run_hooks_result' before |
1653 | # returning. | |
1702 | # returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). | |
1654 | 1703 | func_hookable func_options_prep |
1655 | 1704 | func_options_prep () |
1656 | 1705 | { |
1660 | 1709 | opt_verbose=false |
1661 | 1710 | opt_warning_types= |
1662 | 1711 | |
1663 | func_run_hooks func_options_prep ${1+"$@"} | |
1664 | ||
1665 | # save modified positional parameters for caller | |
1666 | func_options_prep_result=$func_run_hooks_result | |
1712 | _G_rc_options_prep=false | |
1713 | if func_run_hooks func_options_prep ${1+"$@"}; then | |
1714 | _G_rc_options_prep=: | |
1715 | # save modified positional parameters for caller | |
1716 | func_options_prep_result=$func_run_hooks_result | |
1717 | fi | |
1718 | ||
1719 | $_G_rc_options_prep | |
1667 | 1720 | } |
1668 | 1721 | |
1669 | 1722 | |
1677 | 1730 | |
1678 | 1731 | func_parse_options_result= |
1679 | 1732 | |
1733 | _G_rc_parse_options=false | |
1680 | 1734 | # this just eases exit handling |
1681 | 1735 | while test $# -gt 0; do |
1682 | 1736 | # Defer to hook functions for initial option parsing, so they |
1683 | 1737 | # get priority in the event of reusing an option name. |
1684 | func_run_hooks func_parse_options ${1+"$@"} | |
1685 | ||
1686 | # Adjust func_parse_options positional parameters to match | |
1687 | eval set dummy "$func_run_hooks_result"; shift | |
1738 | if func_run_hooks func_parse_options ${1+"$@"}; then | |
1739 | eval set dummy "$func_run_hooks_result"; shift | |
1740 | _G_rc_parse_options=: | |
1741 | fi | |
1688 | 1742 | |
1689 | 1743 | # Break out of the loop if we already parsed every option. |
1690 | 1744 | test $# -gt 0 || break |
1691 | 1745 | |
1746 | _G_match_parse_options=: | |
1692 | 1747 | _G_opt=$1 |
1693 | 1748 | shift |
1694 | 1749 | case $_G_opt in |
1703 | 1758 | ;; |
1704 | 1759 | |
1705 | 1760 | --warnings|--warning|-W) |
1706 | test $# = 0 && func_missing_arg $_G_opt && break | |
1761 | if test $# = 0 && func_missing_arg $_G_opt; then | |
1762 | _G_rc_parse_options=: | |
1763 | break | |
1764 | fi | |
1707 | 1765 | case " $warning_categories $1" in |
1708 | 1766 | *" $1 "*) |
1709 | 1767 | # trailing space prevents matching last $1 above |
1756 | 1814 | shift |
1757 | 1815 | ;; |
1758 | 1816 | |
1759 | --) break ;; | |
1817 | --) _G_rc_parse_options=: ; break ;; | |
1760 | 1818 | -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; |
1761 | *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; | |
1819 | *) set dummy "$_G_opt" ${1+"$@"}; shift | |
1820 | _G_match_parse_options=false | |
1821 | break | |
1822 | ;; | |
1762 | 1823 | esac |
1824 | ||
1825 | $_G_match_parse_options && _G_rc_parse_options=: | |
1763 | 1826 | done |
1764 | 1827 | |
1765 | # save modified positional parameters for caller | |
1766 | func_quote_for_eval ${1+"$@"} | |
1767 | func_parse_options_result=$func_quote_for_eval_result | |
1828 | ||
1829 | if $_G_rc_parse_options; then | |
1830 | # save modified positional parameters for caller | |
1831 | func_quote_for_eval ${1+"$@"} | |
1832 | func_parse_options_result=$func_quote_for_eval_result | |
1833 | fi | |
1834 | ||
1835 | $_G_rc_parse_options | |
1768 | 1836 | } |
1769 | 1837 | |
1770 | 1838 | |
1777 | 1845 | { |
1778 | 1846 | $debug_cmd |
1779 | 1847 | |
1848 | _G_rc_validate_options=false | |
1849 | ||
1780 | 1850 | # Display all warnings if -W was not given. |
1781 | 1851 | test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" |
1782 | 1852 | |
1783 | func_run_hooks func_validate_options ${1+"$@"} | |
1853 | if func_run_hooks func_validate_options ${1+"$@"}; then | |
1854 | # save modified positional parameters for caller | |
1855 | func_validate_options_result=$func_run_hooks_result | |
1856 | _G_rc_validate_options=: | |
1857 | fi | |
1784 | 1858 | |
1785 | 1859 | # Bail if the options were screwed! |
1786 | 1860 | $exit_cmd $EXIT_FAILURE |
1787 | 1861 | |
1788 | # save modified positional parameters for caller | |
1789 | func_validate_options_result=$func_run_hooks_result | |
1862 | $_G_rc_validate_options | |
1790 | 1863 | } |
1791 | 1864 | |
1792 | 1865 | |
2067 | 2140 | compiler: $LTCC |
2068 | 2141 | compiler flags: $LTCFLAGS |
2069 | 2142 | linker: $LD (gnu? $with_gnu_ld) |
2070 | version: $progname (GNU libtool) 2.4.6 | |
2143 | version: $progname $scriptversion Debian-2.4.6-15 | |
2071 | 2144 | automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` |
2072 | 2145 | autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` |
2073 | 2146 | |
2074 | 2147 | Report bugs to <bug-libtool@gnu.org>. |
2075 | GNU libtool home page: <http://www.gnu.org/software/libtool/>. | |
2148 | GNU libtool home page: <http://www.gnu.org/s/libtool/>. | |
2076 | 2149 | General help using GNU software: <http://www.gnu.org/gethelp/>." |
2077 | 2150 | exit 0 |
2078 | 2151 | } |
2269 | 2342 | nonopt= |
2270 | 2343 | preserve_args= |
2271 | 2344 | |
2345 | _G_rc_lt_options_prep=: | |
2346 | ||
2272 | 2347 | # Shorthand for --mode=foo, only valid as the first argument |
2273 | 2348 | case $1 in |
2274 | 2349 | clean|clea|cle|cl) |
2292 | 2367 | uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) |
2293 | 2368 | shift; set dummy --mode uninstall ${1+"$@"}; shift |
2294 | 2369 | ;; |
2370 | *) | |
2371 | _G_rc_lt_options_prep=false | |
2372 | ;; | |
2295 | 2373 | esac |
2296 | 2374 | |
2297 | # Pass back the list of options. | |
2298 | func_quote_for_eval ${1+"$@"} | |
2299 | libtool_options_prep_result=$func_quote_for_eval_result | |
2375 | if $_G_rc_lt_options_prep; then | |
2376 | # Pass back the list of options. | |
2377 | func_quote_for_eval ${1+"$@"} | |
2378 | libtool_options_prep_result=$func_quote_for_eval_result | |
2379 | fi | |
2380 | ||
2381 | $_G_rc_lt_options_prep | |
2300 | 2382 | } |
2301 | 2383 | func_add_hook func_options_prep libtool_options_prep |
2302 | 2384 | |
2308 | 2390 | { |
2309 | 2391 | $debug_cmd |
2310 | 2392 | |
2393 | _G_rc_lt_parse_options=false | |
2394 | ||
2311 | 2395 | # Perform our own loop to consume as many options as possible in |
2312 | 2396 | # each iteration. |
2313 | 2397 | while test $# -gt 0; do |
2398 | _G_match_lt_parse_options=: | |
2314 | 2399 | _G_opt=$1 |
2315 | 2400 | shift |
2316 | 2401 | case $_G_opt in |
2385 | 2470 | func_append preserve_args " $_G_opt" |
2386 | 2471 | ;; |
2387 | 2472 | |
2388 | # An option not handled by this hook function: | |
2389 | *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; | |
2473 | # An option not handled by this hook function: | |
2474 | *) set dummy "$_G_opt" ${1+"$@"} ; shift | |
2475 | _G_match_lt_parse_options=false | |
2476 | break | |
2477 | ;; | |
2390 | 2478 | esac |
2479 | $_G_match_lt_parse_options && _G_rc_lt_parse_options=: | |
2391 | 2480 | done |
2392 | 2481 | |
2393 | ||
2394 | # save modified positional parameters for caller | |
2395 | func_quote_for_eval ${1+"$@"} | |
2396 | libtool_parse_options_result=$func_quote_for_eval_result | |
2482 | if $_G_rc_lt_parse_options; then | |
2483 | # save modified positional parameters for caller | |
2484 | func_quote_for_eval ${1+"$@"} | |
2485 | libtool_parse_options_result=$func_quote_for_eval_result | |
2486 | fi | |
2487 | ||
2488 | $_G_rc_lt_parse_options | |
2397 | 2489 | } |
2398 | 2490 | func_add_hook func_parse_options libtool_parse_options |
2399 | 2491 | |
7271 | 7363 | # -tp=* Portland pgcc target processor selection |
7272 | 7364 | # --sysroot=* for sysroot support |
7273 | 7365 | # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization |
7366 | # -specs=* GCC specs files | |
7274 | 7367 | # -stdlib=* select c++ std lib with clang |
7368 | # -fsanitize=* Clang/GCC memory and address sanitizer | |
7369 | # -fuse-ld=* Linker select flags for GCC | |
7370 | # -static-* direct GCC to link specific libraries statically | |
7371 | # -fcilkplus Cilk Plus language extension features for C/C++ | |
7275 | 7372 | -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ |
7276 | 7373 | -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ |
7277 | -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) | |
7374 | -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ | |
7375 | -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) | |
7278 | 7376 | func_quote_for_eval "$arg" |
7279 | 7377 | arg=$func_quote_for_eval_result |
7280 | 7378 | func_append compile_command " $arg" |
7567 | 7665 | case $pass in |
7568 | 7666 | dlopen) libs=$dlfiles ;; |
7569 | 7667 | dlpreopen) libs=$dlprefiles ;; |
7570 | link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; | |
7668 | link) | |
7669 | libs="$deplibs %DEPLIBS%" | |
7670 | test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" | |
7671 | ;; | |
7571 | 7672 | esac |
7572 | 7673 | fi |
7573 | 7674 | if test lib,dlpreopen = "$linkmode,$pass"; then |
7886 | 7987 | # It is a libtool convenience library, so add in its objects. |
7887 | 7988 | func_append convenience " $ladir/$objdir/$old_library" |
7888 | 7989 | func_append old_convenience " $ladir/$objdir/$old_library" |
7990 | tmp_libs= | |
7991 | for deplib in $dependency_libs; do | |
7992 | deplibs="$deplib $deplibs" | |
7993 | if $opt_preserve_dup_deps; then | |
7994 | case "$tmp_libs " in | |
7995 | *" $deplib "*) func_append specialdeplibs " $deplib" ;; | |
7996 | esac | |
7997 | fi | |
7998 | func_append tmp_libs " $deplib" | |
7999 | done | |
7889 | 8000 | elif test prog != "$linkmode" && test lib != "$linkmode"; then |
7890 | 8001 | func_fatal_error "'$lib' is not a convenience library" |
7891 | 8002 | fi |
7892 | tmp_libs= | |
7893 | for deplib in $dependency_libs; do | |
7894 | deplibs="$deplib $deplibs" | |
7895 | if $opt_preserve_dup_deps; then | |
7896 | case "$tmp_libs " in | |
7897 | *" $deplib "*) func_append specialdeplibs " $deplib" ;; | |
7898 | esac | |
7899 | fi | |
7900 | func_append tmp_libs " $deplib" | |
7901 | done | |
7902 | 8003 | continue |
7903 | 8004 | fi # $pass = conv |
7904 | 8005 | |
8821 | 8922 | age=$number_minor |
8822 | 8923 | revision=$number_minor |
8823 | 8924 | lt_irix_increment=no |
8925 | ;; | |
8926 | *) | |
8927 | func_fatal_configuration "$modename: unknown library version type '$version_type'" | |
8824 | 8928 | ;; |
8825 | 8929 | esac |
8826 | 8930 | ;; |
727 | 727 | cat <<_LT_EOF >> "$cfgfile" |
728 | 728 | #! $SHELL |
729 | 729 | # Generated automatically by $as_me ($PACKAGE) $VERSION |
730 | # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: | |
731 | 730 | # NOTE: Changes made to this file will be lost: look at ltmain.sh. |
732 | 731 | |
733 | 732 | # Provide generalized library-building support services. |
1041 | 1040 | _LT_EOF |
1042 | 1041 | echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD |
1043 | 1042 | $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD |
1044 | echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD | |
1045 | $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD | |
1043 | echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD | |
1044 | $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD | |
1046 | 1045 | echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD |
1047 | 1046 | $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD |
1048 | 1047 | cat > conftest.c << _LT_EOF |
1066 | 1065 | _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; |
1067 | 1066 | darwin1.*) |
1068 | 1067 | _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; |
1069 | darwin*) | |
1070 | case ${MACOSX_DEPLOYMENT_TARGET},$host in | |
1071 | 10.[[012]],*|,*powerpc*) | |
1068 | darwin*) # darwin 5.x on | |
1069 | # if running on 10.5 or later, the deployment target defaults | |
1070 | # to the OS version, if on x86, and 10.4, the deployment | |
1071 | # target defaults to 10.4. Don't you love it? | |
1072 | case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in | |
1073 | 10.0,*86*-darwin8*|10.0,*-darwin[[912]]*) | |
1074 | _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; | |
1075 | 10.[[012]][[,.]]*) | |
1072 | 1076 | _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; |
1073 | *) | |
1077 | 10.*|11.*) | |
1074 | 1078 | _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; |
1075 | 1079 | esac |
1076 | 1080 | ;; |
1487 | 1491 | m4_defun([_LT_PROG_AR], |
1488 | 1492 | [AC_CHECK_TOOLS(AR, [ar], false) |
1489 | 1493 | : ${AR=ar} |
1490 | : ${AR_FLAGS=cru} | |
1494 | : ${AR_FLAGS=cr} | |
1491 | 1495 | _LT_DECL([], [AR], [1], [The archiver]) |
1492 | 1496 | _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) |
1493 | 1497 | |
2881 | 2885 | dynamic_linker='GNU/Linux ld.so' |
2882 | 2886 | ;; |
2883 | 2887 | |
2888 | netbsdelf*-gnu) | |
2889 | version_type=linux | |
2890 | need_lib_prefix=no | |
2891 | need_version=no | |
2892 | library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' | |
2893 | soname_spec='${libname}${release}${shared_ext}$major' | |
2894 | shlibpath_var=LD_LIBRARY_PATH | |
2895 | shlibpath_overrides_runpath=no | |
2896 | hardcode_into_libs=yes | |
2897 | dynamic_linker='NetBSD ld.elf_so' | |
2898 | ;; | |
2899 | ||
2884 | 2900 | netbsd*) |
2885 | 2901 | version_type=sunos |
2886 | 2902 | need_lib_prefix=no |
3540 | 3556 | lt_cv_deplibs_check_method=pass_all |
3541 | 3557 | ;; |
3542 | 3558 | |
3543 | netbsd*) | |
3559 | netbsd* | netbsdelf*-gnu) | |
3544 | 3560 | if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then |
3545 | 3561 | lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' |
3546 | 3562 | else |
4046 | 4062 | if AC_TRY_EVAL(ac_compile); then |
4047 | 4063 | # Now try to grab the symbols. |
4048 | 4064 | nlist=conftest.nm |
4049 | if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then | |
4065 | $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD | |
4066 | if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then | |
4050 | 4067 | # Try sorting and uniquifying the output. |
4051 | 4068 | if sort "$nlist" | uniq > "$nlist"T; then |
4052 | 4069 | mv -f "$nlist"T "$nlist" |
4418 | 4435 | ;; |
4419 | 4436 | esac |
4420 | 4437 | ;; |
4421 | netbsd*) | |
4438 | netbsd* | netbsdelf*-gnu) | |
4422 | 4439 | ;; |
4423 | 4440 | *qnx* | *nto*) |
4424 | 4441 | # QNX uses GNU C++, but need to define -shared option too, otherwise |
4686 | 4703 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' |
4687 | 4704 | _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' |
4688 | 4705 | ;; |
4706 | # flang / f18. f95 an alias for gfortran or flang on Debian | |
4707 | flang* | f18* | f95*) | |
4708 | _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' | |
4709 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' | |
4710 | _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' | |
4711 | ;; | |
4689 | 4712 | # icc used to be incompatible with GCC. |
4690 | 4713 | # ICC 10 doesn't accept -KPIC any more. |
4691 | 4714 | icc* | ifort*) |
4930 | 4953 | ;; |
4931 | 4954 | esac |
4932 | 4955 | ;; |
4956 | linux* | k*bsd*-gnu | gnu*) | |
4957 | _LT_TAGVAR(link_all_deplibs, $1)=no | |
4958 | ;; | |
4933 | 4959 | *) |
4934 | 4960 | _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' |
4935 | 4961 | ;; |
4991 | 5017 | ;; |
4992 | 5018 | openbsd* | bitrig*) |
4993 | 5019 | with_gnu_ld=no |
5020 | ;; | |
5021 | linux* | k*bsd*-gnu | gnu*) | |
5022 | _LT_TAGVAR(link_all_deplibs, $1)=no | |
4994 | 5023 | ;; |
4995 | 5024 | esac |
4996 | 5025 | |
5246 | 5275 | fi |
5247 | 5276 | ;; |
5248 | 5277 | |
5249 | netbsd*) | |
5278 | netbsd* | netbsdelf*-gnu) | |
5250 | 5279 | if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then |
5251 | 5280 | _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' |
5252 | 5281 | wlarc= |
5767 | 5796 | if test yes = "$lt_cv_irix_exported_symbol"; then |
5768 | 5797 | _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' |
5769 | 5798 | fi |
5799 | _LT_TAGVAR(link_all_deplibs, $1)=no | |
5770 | 5800 | else |
5771 | 5801 | _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' |
5772 | 5802 | _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' |
5788 | 5818 | esac |
5789 | 5819 | ;; |
5790 | 5820 | |
5791 | netbsd*) | |
5821 | netbsd* | netbsdelf*-gnu) | |
5792 | 5822 | if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then |
5793 | 5823 | _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out |
5794 | 5824 | else |
6414 | 6444 | # Commands to make compiler produce verbose output that lists |
6415 | 6445 | # what "hidden" libraries, object files and flags are used when |
6416 | 6446 | # linking a shared library. |
6417 | output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' | |
6447 | output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' | |
6418 | 6448 | |
6419 | 6449 | else |
6420 | 6450 | GXX=no |
6789 | 6819 | # explicitly linking system object files so we need to strip them |
6790 | 6820 | # from the output so that they don't get included in the library |
6791 | 6821 | # dependencies. |
6792 | output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' | |
6822 | output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' | |
6793 | 6823 | ;; |
6794 | 6824 | *) |
6795 | 6825 | if test yes = "$GXX"; then |
6854 | 6884 | # explicitly linking system object files so we need to strip them |
6855 | 6885 | # from the output so that they don't get included in the library |
6856 | 6886 | # dependencies. |
6857 | output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' | |
6887 | output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' | |
6858 | 6888 | ;; |
6859 | 6889 | *) |
6860 | 6890 | if test yes = "$GXX"; then |
7193 | 7223 | # Commands to make compiler produce verbose output that lists |
7194 | 7224 | # what "hidden" libraries, object files and flags are used when |
7195 | 7225 | # linking a shared library. |
7196 | output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' | |
7226 | output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' | |
7197 | 7227 | |
7198 | 7228 | else |
7199 | 7229 | # FIXME: insert proper C++ library support |
7277 | 7307 | # Commands to make compiler produce verbose output that lists |
7278 | 7308 | # what "hidden" libraries, object files and flags are used when |
7279 | 7309 | # linking a shared library. |
7280 | output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' | |
7310 | output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' | |
7281 | 7311 | else |
7282 | 7312 | # g++ 2.7 appears to require '-G' NOT '-shared' on this |
7283 | 7313 | # platform. |
7288 | 7318 | # Commands to make compiler produce verbose output that lists |
7289 | 7319 | # what "hidden" libraries, object files and flags are used when |
7290 | 7320 | # linking a shared library. |
7291 | output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' | |
7321 | output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' | |
7292 | 7322 | fi |
7293 | 7323 | |
7294 | 7324 | _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' |
2 | 2 | |
3 | 3 | scriptversion=2018-03-07.03; # UTC |
4 | 4 | |
5 | # Copyright (C) 1996-2018 Free Software Foundation, Inc. | |
5 | # Copyright (C) 1996-2021 Free Software Foundation, Inc. | |
6 | 6 | # Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. |
7 | 7 | |
8 | 8 | # This program is free software; you can redistribute it and/or modify |
0 | # Makefile.in generated by automake 1.16.1 from Makefile.am. | |
0 | # Makefile.in generated by automake 1.16.4 from Makefile.am. | |
1 | 1 | # @configure_input@ |
2 | 2 | |
3 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. | |
3 | # Copyright (C) 1994-2021 Free Software Foundation, Inc. | |
4 | 4 | |
5 | 5 | # This Makefile.in is free software; the Free Software Foundation |
6 | 6 | # gives unlimited permission to copy and/or distribute it, |
171 | 171 | unique=`for i in $$list; do \ |
172 | 172 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
173 | 173 | done | $(am__uniquify_input)` |
174 | ETAGS = etags | |
175 | CTAGS = ctags | |
176 | 174 | am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp |
177 | 175 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
178 | 176 | ACLOCAL = @ACLOCAL@ |
190 | 188 | CFLAGS = @CFLAGS@ |
191 | 189 | CPP = @CPP@ |
192 | 190 | CPPFLAGS = @CPPFLAGS@ |
191 | CSCOPE = @CSCOPE@ | |
192 | CTAGS = @CTAGS@ | |
193 | 193 | CYGPATH_W = @CYGPATH_W@ |
194 | 194 | DEFS = @DEFS@ |
195 | 195 | DEPDIR = @DEPDIR@ |
200 | 200 | ECHO_N = @ECHO_N@ |
201 | 201 | ECHO_T = @ECHO_T@ |
202 | 202 | EGREP = @EGREP@ |
203 | ETAGS = @ETAGS@ | |
203 | 204 | EXEEXT = @EXEEXT@ |
204 | 205 | FGREP = @FGREP@ |
205 | 206 | FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ |
301 | 302 | prefix = @prefix@ |
302 | 303 | program_transform_name = @program_transform_name@ |
303 | 304 | psdir = @psdir@ |
305 | runstatedir = @runstatedir@ | |
304 | 306 | sbindir = @sbindir@ |
305 | 307 | sharedstatedir = @sharedstatedir@ |
306 | 308 | srcdir = @srcdir@ |
467 | 469 | |
468 | 470 | distclean-tags: |
469 | 471 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
470 | ||
471 | 472 | distdir: $(BUILT_SOURCES) |
472 | 473 | $(MAKE) $(AM_MAKEFLAGS) distdir-am |
473 | 474 |
0 | # Makefile.in generated by automake 1.16.1 from Makefile.am. | |
0 | # Makefile.in generated by automake 1.16.4 from Makefile.am. | |
1 | 1 | # @configure_input@ |
2 | 2 | |
3 | # Copyright (C) 1994-2018 Free Software Foundation, Inc. | |
3 | # Copyright (C) 1994-2021 Free Software Foundation, Inc. | |
4 | 4 | |
5 | 5 | # This Makefile.in is free software; the Free Software Foundation |
6 | 6 | # gives unlimited permission to copy and/or distribute it, |
171 | 171 | unique=`for i in $$list; do \ |
172 | 172 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
173 | 173 | done | $(am__uniquify_input)` |
174 | ETAGS = etags | |
175 | CTAGS = ctags | |
176 | 174 | am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp |
177 | 175 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
178 | 176 | ACLOCAL = @ACLOCAL@ |
190 | 188 | CFLAGS = @CFLAGS@ |
191 | 189 | CPP = @CPP@ |
192 | 190 | CPPFLAGS = @CPPFLAGS@ |
191 | CSCOPE = @CSCOPE@ | |
192 | CTAGS = @CTAGS@ | |
193 | 193 | CYGPATH_W = @CYGPATH_W@ |
194 | 194 | DEFS = @DEFS@ |
195 | 195 | DEPDIR = @DEPDIR@ |
200 | 200 | ECHO_N = @ECHO_N@ |
201 | 201 | ECHO_T = @ECHO_T@ |
202 | 202 | EGREP = @EGREP@ |
203 | ETAGS = @ETAGS@ | |
203 | 204 | EXEEXT = @EXEEXT@ |
204 | 205 | FGREP = @FGREP@ |
205 | 206 | FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ |
301 | 302 | prefix = @prefix@ |
302 | 303 | program_transform_name = @program_transform_name@ |
303 | 304 | psdir = @psdir@ |
305 | runstatedir = @runstatedir@ | |
304 | 306 | sbindir = @sbindir@ |
305 | 307 | sharedstatedir = @sharedstatedir@ |
306 | 308 | srcdir = @srcdir@ |
467 | 469 | |
468 | 470 | distclean-tags: |
469 | 471 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
470 | ||
471 | 472 | distdir: $(BUILT_SOURCES) |
472 | 473 | $(MAKE) $(AM_MAKEFLAGS) distdir-am |
473 | 474 |