diff --git a/.admin/run_admin.sh b/.admin/run_admin.sh new file mode 100644 index 0000000000..1a7a823e20 --- /dev/null +++ b/.admin/run_admin.sh @@ -0,0 +1,86 @@ +#/bin/bash + +ARCH=x86_64-w64-mingw32 + +WORKDIR="$(cd "$(dirname "$0")" && pwd)" + +BINUTILS_VERSION=2.41 +BUSYBOX_VERSION=FRP-5236-g7dff7f376 +CPPCHECK_VERSION=2.10 +CTAGS_VERSION=6.0.0 +EXPAT_VERSION=2.5.0 +GCC_VERSION=13.2.0 +GDB_VERSION=13.1 +GMP_VERSION=6.3.0 +LIBICONV_VERSION=1.17 +MAKE_VERSION=4.4.1 +MINGW_VERSION=11.0.1 +MPC_VERSION=1.3.1 +MPFR_VERSION=4.2.1 +NASM_VERSION=2.15.05 +PDCURSES_VERSION=3.9 +VERSION=1.21.0 +VIM_VERSION=9.0 + +cd $WORKDIR + +apt update && \ + apt upgrade -y && \ + apt install -y autotools-dev binutils binutils-x86-64-linux-gnu cmake-data cpp cpp-12 fakeroot \ + fontconfig-config fonts-dejavu-core g++-12 gcc-12 libalgorithm-diff-perl libalgorithm-diff-xs-perl \ + libalgorithm-merge-perl libaom3 libarchive13 libasan8 libatomic1 libbinutils libbrotli1 libc-dev-bin \ + libc-devtools libc6-dev libcc1-0 libcrypt-dev libctf-nobfd0 libctf0 libcurl4 libde265-0 libdeflate0 \ + libdpkg-perl libexpat1 libfakeroot libfile-fcntllock-perl libfl2 libfontconfig1 libfreetype6 \ + libgcc-12-dev libgd3 libgmpxx4ldbl libgomp1 libheif1 libitm1 libjbig0 libjsoncpp25 liblsan0 \ + libnghttp2-14 libnsl-dev libnsl2 libnuma1 libpng16-16 libpsl5 libquadmath0 librhash0 librtmp1 \ + libssh2-1 libstdc++-12-dev libtirpc-dev libtsan2 libubsan1 libuv1 libwebp7 libx11-6 libx11-data \ + libx265-199 libxau6 libxcb1 libxdmcp6 libxml2 libxpm4 libyuv0 linux-libc-dev manpages-dev patch \ + publicsuffix rpcsvc-proto unzip autoconf automake bison build-essential cmake curl dpkg-dev flex \ + g++ gcc libfl-dev libgmp-dev libmpc-dev libmpfr-dev m4 make wget zip texinfo pkg-config python3 \ + python3-pip python3-venv file mingw-w64-x86-64-dev mingw-w64-i686-dev mingw-w64-tools + +wget --trust-server-names \ + http://ftp.vim.org/pub/vim/unix/vim-$VIM_VERSION.tar.bz2 \ + http://ftp.vim.org/pub/vim/unix/vim-$VIM_VERSION.tar.bz2 + +wget --trust-server-names \ + https://downloads.sourceforge.net/project/mingw-w64/mingw-w64/mingw-w64-release/mingw-w64-v$MINGW_VERSION.tar.bz2 \ + https://downloads.sourceforge.net/project/pdcurses/pdcurses/$PDCURSES_VERSION/PDCurses-$PDCURSES_VERSION.tar.gz + +wget --trust-server-names https://fossies.org/linux/www/expat-$EXPAT_VERSION.tar.xz + +wget --trust-server-names https://frippery.org/files/busybox/busybox-w32-$BUSYBOX_VERSION.tgz + +wget --trust-server-names \ + https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VERSION.tar.xz \ + https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.xz \ + https://ftp.gnu.org/gnu/gdb/gdb-$GDB_VERSION.tar.xz \ + https://ftp.gnu.org/gnu/gmp/gmp-$GMP_VERSION.tar.xz \ + https://ftp.gnu.org/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz \ + https://ftp.gnu.org/gnu/make/make-$MAKE_VERSION.tar.gz \ + https://ftp.gnu.org/gnu/mpc/mpc-$MPC_VERSION.tar.gz \ + https://ftp.gnu.org/gnu/mpc/mpc-$MPC_VERSION.tar.gz \ + https://ftp.gnu.org/gnu/mpfr/mpfr-$MPFR_VERSION.tar.xz + +wget -O cppcheck-$CPPCHECK_VERSION.tar.gz https://codeload.github.com/danmar/cppcheck/tar.gz/refs/tags/$CPPCHECK_VERSION + +wget -O ctags-$CTAGS_VERSION.tar.gz https://codeload.github.com/universal-ctags/ctags/tar.gz/refs/tags/v$CTAGS_VERSION + +wget --trust-server-names https://www.nasm.us/pub/nasm/releasebuilds/$NASM_VERSION/nasm-$NASM_VERSION.tar.xz + +tar xJf binutils-$BINUTILS_VERSION.tar.xz \ + && tar xzf busybox-w32-$BUSYBOX_VERSION.tgz \ + && tar xzf ctags-$CTAGS_VERSION.tar.gz \ + && tar xJf gcc-$GCC_VERSION.tar.xz \ + && tar xJf gdb-$GDB_VERSION.tar.xz \ + && tar xJf expat-$EXPAT_VERSION.tar.xz \ + && tar xzf libiconv-$LIBICONV_VERSION.tar.gz \ + && tar xJf gmp-$GMP_VERSION.tar.xz \ + && tar xzf mpc-$MPC_VERSION.tar.gz \ + && tar xJf mpfr-$MPFR_VERSION.tar.xz \ + && tar xzf make-$MAKE_VERSION.tar.gz \ + && tar xjf mingw-w64-v$MINGW_VERSION.tar.bz2 \ + && tar xzf PDCurses-$PDCURSES_VERSION.tar.gz \ + && tar xJf nasm-$NASM_VERSION.tar.xz \ + && tar xjf vim-$VIM_VERSION.tar.bz2 \ + && tar xzf cppcheck-$CPPCHECK_VERSION.tar.gz diff --git a/.cpan/CPAN/MyConfig.pm b/.cpan/CPAN/MyConfig.pm new file mode 100644 index 0000000000..c12dda7399 --- /dev/null +++ b/.cpan/CPAN/MyConfig.pm @@ -0,0 +1,74 @@ + +$CPAN::Config = { + 'allow_installing_module_downgrades' => q[ask/no], + 'allow_installing_outdated_dists' => q[ask/no], + 'applypatch' => q[], + 'auto_commit' => q[0], + 'build_cache' => q[100], + 'build_dir' => q[/root/.cpan/build], + 'build_dir_reuse' => q[0], + 'build_requires_install_policy' => q[yes], + 'bzip2' => q[/usr/bin/bzip2], + 'cache_metadata' => q[1], + 'check_sigs' => q[0], + 'cleanup_after_install' => q[0], + 'colorize_output' => q[0], + 'commandnumber_in_prompt' => q[1], + 'connect_to_internet_ok' => q[1], + 'cpan_home' => q[/root/.cpan], + 'ftp_passive' => q[1], + 'ftp_proxy' => q[], + 'getcwd' => q[cwd], + 'gpg' => q[/usr/bin/gpg], + 'gzip' => q[/usr/bin/gzip], + 'halt_on_failure' => q[0], + 'histfile' => q[/root/.cpan/histfile], + 'histsize' => q[100], + 'http_proxy' => q[], + 'inactivity_timeout' => q[0], + 'index_expire' => q[1], + 'inhibit_startup_message' => q[0], + 'keep_source_where' => q[/root/.cpan/sources], + 'load_module_verbosity' => q[none], + 'make' => q[/usr/bin/make], + 'make_arg' => q[], + 'make_install_arg' => q[], + 'make_install_make_command' => q[/usr/bin/make], + 'makepl_arg' => q[INSTALLDIRS=site], + 'mbuild_arg' => q[], + 'mbuild_install_arg' => q[], + 'mbuild_install_build_command' => q[./Build], + 'mbuildpl_arg' => q[--installdirs site], + 'no_proxy' => q[], + 'pager' => q[/usr/bin/more], + 'patch' => q[/usr/bin/patch], + 'perl5lib_verbosity' => q[none], + 'prefer_external_tar' => q[1], + 'prefer_installer' => q[MB], + 'prefs_dir' => q[/root/.cpan/prefs], + 'prerequisites_policy' => q[follow], + 'pushy_https' => q[1], + 'recommends_policy' => q[1], + 'scan_cache' => q[atstart], + 'shell' => undef, + 'show_unparsable_versions' => q[0], + 'show_upload_date' => q[0], + 'show_zero_versions' => q[0], + 'suggests_policy' => q[0], + 'tar' => q[/usr/bin/tar], + 'tar_verbosity' => q[none], + 'term_is_latin' => q[1], + 'term_ornaments' => q[1], + 'test_report' => q[0], + 'trust_test_report_history' => q[0], + 'unzip' => q[/usr/bin/unzip], + 'urllist' => [q[https://cpan.org/]], + 'use_prompt_default' => q[0], + 'use_sqlite' => q[0], + 'version_timeout' => q[15], + 'wget' => q[/usr/bin/wget], + 'yaml_load_code' => q[0], + 'yaml_module' => q[YAML], +}; +1; +__END__ diff --git a/.cpan/CPAN/MyConfig.pm~ b/.cpan/CPAN/MyConfig.pm~ new file mode 100644 index 0000000000..0afc6045cf --- /dev/null +++ b/.cpan/CPAN/MyConfig.pm~ @@ -0,0 +1 @@ +1; diff --git a/.cpan/Metadata b/.cpan/Metadata new file mode 100644 index 0000000000..03a8fe67e1 Binary files /dev/null and b/.cpan/Metadata differ diff --git a/.cpan/build/Font-TTF-1.06-0/CONTRIBUTORS b/.cpan/build/Font-TTF-1.06-0/CONTRIBUTORS new file mode 100644 index 0000000000..fb5b49edaa --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/CONTRIBUTORS @@ -0,0 +1,7 @@ +Bob Hallissy +Alan Ward +David Raymond +Jon Coblentz +Jonathan Kew +NIIBE Yutaka +Nicolas Spalinger \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/Changes b/.cpan/build/Font-TTF-1.06-0/Changes new file mode 100644 index 0000000000..cd3826f506 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/Changes @@ -0,0 +1,91 @@ +1.06 2016-08-17 + +* Source repo moved from Subversion to Github +* OpenType script and lang tags updated from ISO/IEC 14496-22:2015, draft amendment 2 +* Various POD improvements +* Add deepcopy mode to Dumper::ttfdump() +* Bug fixes +* Wasn't installing on Windows Perl 5.22 and up +* Reading mark-to-ligature lookups would crash if anchors were omitted +* Incorrect extension lookup structure +* Multiple fixes in Silf table processing +* rt.cpan.org #106562 Uninitialized value warnings +* rt.cpan.org #106816 spelling errors in manpage + +1.05 2015-01-26 r1069 + +* Add support for GSUB Type 8 Reverse-chaining substitution +* OpenType script/lang/feature tags now based on ISO/IEC 14496-22 +* Remove deprecated GDL_old.pm +* +* Bug fixes: +* Fix rt.cpan.org 92150, 93597 +* Force 0xFFFF sentry to be in a segment by itself in format 4 cmap subtables +* Less aggressive cmap format 4 optimization to eliminate USV holes +* Fix various issues reading WOFF-compressed font tables +* Fix reading DSIG + +1.04 2014-01-09 r994 + +* Bug fixes: +* Fix rt.cpan.org 80671, 80672; simplify fix for #42553 per OP +* Shared tables in TTC weren't working +* Quiet a cleanup warning in TTC processing +* Update licensing info for test fonts to OFL + +1.03 2013-11-10 r969 + +* Add $t->minsize() to all tables for assisting with font subsetting +* Add deduping to Name table writing +* Add OS/2 table method to guess at Unicode and Codepage range bits. +* Add support for cmap format 13 subtables +* Expunge notion of 'dflt' language tag from Ttopen.pm +* Bug fixes + +1.02 2012-08-30 r862 + +* Fix typo in Useall to get case right + +1.01 2012-08-30 r859 + +* Add IO::String prerequisite to make BSD and other testing environments happy + +1.00 2012-08-28 r857 + +* Major change to glyph creation/editing -- now utilizes ' isDirty' flag +* Add support for: +* V4 OS/2 table +* Reading WOFF fonts +* MarkFilterSets in GDEF +* Feature parameters (for cvxx, ssxx and size features) +* Additional Graphite tables (Silf, Glac, and Gloc) +* Updated MS Lang IDs to Dec 2011 +* Finish implementation of coverage table sorting +* Copyright and licensing updated to CPAN requirements +* Bug fixes + +0.48 2010-12-14 r692 + +* Ensure coverage tables are properly sorted +* Additional OT tags (from OpenType 1.6) +* Bug fixes + +0.47 2009-08-10 r649 + +* Add support for Graphite Sill table +* Handle kerning tables version > 0 +* Bug fixes + +0.46 2009-01-26 r577 + +* Bug fixes +* Change Copyright to Artistic License 2.0 + +0.45 2008-06-11 r527 + +* Introduce changelog +* tidy up 0.44 package, fix README to be more accurate +* tests failing on perl 5.8.2 and before due to no use Exporter qw(import); + Fix OTTags accordingly. + +Some previous changes documented in lib/Font/TTF/Changes_old.txt diff --git a/.cpan/build/Font-TTF-1.06-0/LICENSE b/.cpan/build/Font-TTF-1.06-0/LICENSE new file mode 100644 index 0000000000..cbda892f6b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/LICENSE @@ -0,0 +1,76 @@ + +Artistic License 2.0 + +Copyright (c) 2000-2006, The Perl Foundation. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. +Preamble + +This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. + +You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. +Definitions + +"Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. + +"Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. + +"You" and "your" means any person who would like to copy, distribute, or modify the Package. + +"Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. + +"Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. + +"Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. + +"Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. + +"Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. + +"Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. + +"Source" form means the source code, documentation source, and configuration files for the Package. + +"Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. +Permission for Use and Modification Without Distribution + +(1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. +Permissions for Redistribution of the Standard Version + +(2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. + +(3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. +Distribution of Modified Versions of the Package as Source + +(4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: + +(a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. +(b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. +(c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under +(i) the Original License or +(ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. +Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source + +(5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. + +(6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. +Aggregating or Linking the Package + +(7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. + +(8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. +Items That are Not Considered Part of a Modified Version + +(9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. +General Provisions + +(10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. + +(11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. + +(12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. + +(13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. + +(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/.cpan/build/Font-TTF-1.06-0/MANIFEST b/.cpan/build/Font-TTF-1.06-0/MANIFEST new file mode 100644 index 0000000000..6fffffd80a --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/MANIFEST @@ -0,0 +1,96 @@ +buildutils/convert_tags.pl +buildutils/convert_tags_from_html.pl +Changes +CONTRIBUTORS +lib/Font/TTF.pm +lib/Font/TTF/AATKern.pm +lib/Font/TTF/AATutils.pm +lib/Font/TTF/Anchor.pm +lib/Font/TTF/Bsln.pm +lib/Font/TTF/Changes_old.txt +lib/Font/TTF/Cmap.pm +lib/Font/TTF/Coverage.pm +lib/Font/TTF/Cvt_.pm +lib/Font/TTF/Delta.pm +lib/Font/TTF/DSIG.pm +lib/Font/TTF/Dumper.pm +lib/Font/TTF/EBDT.pm +lib/Font/TTF/EBLC.pm +lib/Font/TTF/Fdsc.pm +lib/Font/TTF/Feat.pm +lib/Font/TTF/Features/Cvar.pm +lib/Font/TTF/Features/Size.pm +lib/Font/TTF/Features/Sset.pm +lib/Font/TTF/Fmtx.pm +lib/Font/TTF/Font.pm +lib/Font/TTF/Fpgm.pm +lib/Font/TTF/GDEF.pm +lib/Font/TTF/Glat.pm +lib/Font/TTF/Gloc.pm +lib/Font/TTF/Glyf.pm +lib/Font/TTF/Glyph.pm +lib/Font/TTF/GPOS.pm +lib/Font/TTF/GrFeat.pm +lib/Font/TTF/GSUB.pm +lib/Font/TTF/Hdmx.pm +lib/Font/TTF/Head.pm +lib/Font/TTF/Hhea.pm +lib/Font/TTF/Hmtx.pm +lib/Font/TTF/Kern.pm +lib/Font/TTF/Kern/ClassArray.pm +lib/Font/TTF/Kern/CompactClassArray.pm +lib/Font/TTF/Kern/OrderedList.pm +lib/Font/TTF/Kern/StateTable.pm +lib/Font/TTF/Kern/Subtable.pm +lib/Font/TTF/Loca.pm +lib/Font/TTF/LTSH.pm +lib/Font/TTF/Manual.pod +lib/Font/TTF/Maxp.pm +lib/Font/TTF/Mort.pm +lib/Font/TTF/Mort/Chain.pm +lib/Font/TTF/Mort/Contextual.pm +lib/Font/TTF/Mort/Insertion.pm +lib/Font/TTF/Mort/Ligature.pm +lib/Font/TTF/Mort/Noncontextual.pm +lib/Font/TTF/Mort/Rearrangement.pm +lib/Font/TTF/Mort/Subtable.pm +lib/Font/TTF/Name.pm +lib/Font/TTF/OldCmap.pm +lib/Font/TTF/OldMort.pm +lib/Font/TTF/OS_2.pm +lib/Font/TTF/OTTags.pm +lib/Font/TTF/PCLT.pm +lib/Font/TTF/Post.pm +lib/Font/TTF/Prep.pm +lib/Font/TTF/Prop.pm +lib/Font/TTF/PSNames.pm +lib/Font/TTF/Segarr.pm +lib/Font/TTF/Silf.pm +lib/Font/TTF/Sill.pm +lib/Font/TTF/Table.pm +lib/Font/TTF/Ttc.pm +lib/Font/TTF/Ttopen.pm +lib/Font/TTF/Useall.pm +lib/Font/TTF/Utils.pm +lib/Font/TTF/Vhea.pm +lib/Font/TTF/Vmtx.pm +lib/Font/TTF/Win32.pm +lib/Font/TTF/Woff.pm +lib/Font/TTF/Woff/MetaData.pm +lib/Font/TTF/Woff/PrivateData.pm +lib/Font/TTF/XMLparse.pm +lib/ttfmod.pl +LICENSE +Makefile.PL +MANIFEST This list of files +MANIFEST.SKIP +README.TXT +t/changes.t +t/OFL.txt +t/tags.t +t/testfont.ttf +t/testfont.woff +t/ttfcopy.t +TODO +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/.cpan/build/Font-TTF-1.06-0/MANIFEST.SKIP b/.cpan/build/Font-TTF-1.06-0/MANIFEST.SKIP new file mode 100644 index 0000000000..f4fa04c7c5 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/MANIFEST.SKIP @@ -0,0 +1,35 @@ +blib/ +\.\$\$\$ +\.tmp +\.temp +\.bak +\.patch +CVS/ +\.tar +\.tgz +\.old +misc/ +Build/ +exes/ +\.cvsignore +^# +(^|/)\.git +\.svn/ +Makefile$ +\.par$ +-stamp$ +debian/ +pm_to_blib +\~$ +dev/ +build/ +^build(?!utils) +dists/ +dest-deb/ +^libfont- +description-pak +^doc +^doc-pak +\.swp +^\.hg/ +^MYMETA\..*$ diff --git a/.cpan/build/Font-TTF-1.06-0/META.json b/.cpan/build/Font-TTF-1.06-0/META.json new file mode 100644 index 0000000000..ca1645e118 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/META.json @@ -0,0 +1,31 @@ +{ + "abstract" : "TTF font support for Perl", + "author" : [ + "martin_hosken@sil.org" + ], + "dynamic_config" : 1, + "generated_by" : "ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921", + "license" : [ + "artistic_2" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Font-TTF", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "release_status" : "stable", + "resources" : { + "repository" : { + "type" : "git", + "url" : "https://github.com/silnrsi/font-ttf.git", + "web" : "https://github.com/silnrsi/font-ttf" + } + }, + "version" : "1.06" +} diff --git a/.cpan/build/Font-TTF-1.06-0/META.yml b/.cpan/build/Font-TTF-1.06-0/META.yml new file mode 100644 index 0000000000..22025b774b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/META.yml @@ -0,0 +1,19 @@ +--- +abstract: 'TTF font support for Perl' +author: + - martin_hosken@sil.org +build_requires: {} +dynamic_config: 1 +generated_by: 'ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921' +license: artistic_2 +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: Font-TTF +no_index: + directory: + - t + - inc +resources: + repository: https://github.com/silnrsi/font-ttf.git +version: 1.06 diff --git a/.cpan/build/Font-TTF-1.06-0/MYMETA.json b/.cpan/build/Font-TTF-1.06-0/MYMETA.json new file mode 100644 index 0000000000..1bfd26f4b6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/MYMETA.json @@ -0,0 +1,49 @@ +{ + "abstract" : "TTF font support for Perl", + "author" : [ + "martin_hosken@sil.org" + ], + "dynamic_config" : 0, + "generated_by" : "ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921, CPAN::Meta::Converter version 2.150010", + "license" : [ + "artistic_2" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : 2 + }, + "name" : "Font-TTF", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "requires" : { + "IO::String" : "0" + } + } + }, + "release_status" : "stable", + "resources" : { + "repository" : { + "type" : "git", + "url" : "https://github.com/silnrsi/font-ttf.git", + "web" : "https://github.com/silnrsi/font-ttf" + } + }, + "version" : "1.06", + "x_serialization_backend" : "JSON::PP version 4.07" +} diff --git a/.cpan/build/Font-TTF-1.06-0/MYMETA.yml b/.cpan/build/Font-TTF-1.06-0/MYMETA.yml new file mode 100644 index 0000000000..d1417e6213 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/MYMETA.yml @@ -0,0 +1,25 @@ +--- +abstract: 'TTF font support for Perl' +author: + - martin_hosken@sil.org +build_requires: + ExtUtils::MakeMaker: '0' +configure_requires: + ExtUtils::MakeMaker: '0' +dynamic_config: 0 +generated_by: 'ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921, CPAN::Meta::Converter version 2.150010' +license: artistic_2 +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Font-TTF +no_index: + directory: + - t + - inc +requires: + IO::String: '0' +resources: + repository: https://github.com/silnrsi/font-ttf.git +version: '1.06' +x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff --git a/.cpan/build/Font-TTF-1.06-0/Makefile.PL b/.cpan/build/Font-TTF-1.06-0/Makefile.PL new file mode 100644 index 0000000000..ef783a4337 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/Makefile.PL @@ -0,0 +1,113 @@ +use strict; +use ExtUtils::MakeMaker; +use Getopt::Std; + +our ($opt_d, $opt_r, $opt_v); +getopts('d:rv:'); + +my %pbuilderopts = ( + 'gutsy' => '--bindmounts /media/hosk_1' + ); + +$opt_v ||= 1; + +if ($^O eq 'linux' && !defined $opt_d) +{ + $opt_d = `lsb_release -c`; + $opt_d =~ s/^.*?(\w+)\s*$/$1/o; +} + +my (@extras, @theselibs); + +@theselibs = (grep {-f } glob("lib/Font/TTF/*"), "lib/Font/TTF.pm"); + +# incantation to enable MY::pm_to_blib later on +if ($^O eq 'MSWin32') +{ + @extras = ('dist' => { 'TO_UNIX' => 'perl -Mtounix -e "tounix(\"$(DISTVNAME)\")"' }); +} + +if ($^O eq 'linux') +{ + + *MY::postamble = sub + { + my ($self) = @_; + my ($res); + my ($package) = lc($self->{'NAME'}); + my ($pversion) = $self->{'VERSION'}; + my ($svn) = `svnversion`; + my ($sign) = '--auto-debsign' if ($opt_r); + my ($fpackage); + + $svn =~ s/\s+$//o; + if ($svn and $svn ne "exported") + { + $svn =~ s/[0-9]*://og; + } + else + { + $svn = `hg identify -n`; + $svn =~ s/\+?\s+$//o; + } + $package =~ s/::/-/g; + $package = "lib${package}-perl"; + $pversion .= "+$svn" unless ($opt_r); + $fpackage = "$package-$pversion"; + + $res = <<"EOT"; +debsrc: dist + rm -fr $self->{'DISTVNAME'} + rm -fr $package + rm -fr $fpackage + tar xvzf $self->{'DISTVNAME'}.tar.gz + cp -r $self->{'DISTVNAME'} $package + tar cvzf ${package}_${pversion}.orig.tar.gz $package + cp -r $package $fpackage + cp -a debian $fpackage + cd $fpackage && dch -v $pversion "interim dev release" && dpkg-buildpackage -S + +# make deb builds an interim deb from svn source for release +deb: deb-base +EOT + + foreach my $d (split(' ', $opt_d)) + { + $res .= <<"EOT"; + mkdir -p dists/$d + dch -D $d -v $pversion-$opt_v -m -b -c $fpackage/debian/changelog "Auto build from perl for $d" + cd $fpackage && pdebuild --buildresult ../dists/$d -- --basetgz /var/cache/pbuilder/base-$d.tgz $pbuilderopts{$d} +EOT + } + + return $res; + }; + +} + +my %makeinfo = ( + NAME => 'Font::TTF', + VERSION_FROM => 'lib/Font/TTF.pm', +# HTMLLIBPODS => {map {my $t = $_; $t=~s/\..*?$/.html/o; $t='blib/Html/'.$t; $_ => $t;} @theselibs}, +# HTMLSCRIPTPODS => {map {my $t=$_; $t=~s/\..*?$/.html/o; $t='blib/Html/'.$t; $_ => $t;} @scripts}, + AUTHOR => "martin_hosken\@sil.org", + ABSTRACT => "TTF font support for Perl", + LICENSE => "artistic_2", + PREREQ_PM => { + 'IO::String' => 0 + }, + META_MERGE => { + 'meta-spec' => { version => 2 }, + resources => { + repository => { + type => 'git', + url => 'https://github.com/silnrsi/font-ttf.git', + web => 'https://github.com/silnrsi/font-ttf', + } + } + }, + @extras + ); + +WriteMakefile(%makeinfo); + diff --git a/.cpan/build/Font-TTF-1.06-0/README.TXT b/.cpan/build/Font-TTF-1.06-0/README.TXT new file mode 100644 index 0000000000..961e702a89 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/README.TXT @@ -0,0 +1,97 @@ +=head1 INTRODUCTION + +Perl module for TrueType/OpenType font hacking. Supports reading, processing and +writing of the following tables: GDEF, GPOS, GSUB, LTSH, OS/2, PCLT, +bsln, cmap, cvt, fdsc, feat, fpgm, glyf, hdmx, head, hhea, hmtx, kern, +loca, maxp, mort, name, post, prep, prop, vhea, vmtx and the reading and +writing of all other table types. + +In short, you can do almost anything with a standard TrueType font with +this module. Be Brave! + +Any suggestions, improvements, additions, subclasses, etc. would be gratefully +received and probably included in a future release. Please send them to me. + +This module has been tested on Win32, Unix and Mac. + +Applications that were associated with this module have been moved to +Font::TTF::Scripts where great things can be done. + +=head1 SYNOPSIS + +Here is the regression test (you provide your own font). Run it once and then +again on the output of the first run. There should be no differences between +the outputs of the two runs. + + use Font::TTF::Font; + + $f = Font::TTF::Font->open($ARGV[0]); + + # force a read of all the tables + $f->tables_do(sub { $_[0]->read; }); + + # force read of all glyphs (use read_dat to use lots of memory!) + # $f->{'loca'}->glyphs_do(sub { $_[0]->read; }); + $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; }); + # NB. no need to $g->update since $_[0]->{'glyf'}->out will do it for us + + $f->out($ARGV[1]); + $f->DESTROY; # forces close of $in and maybe memory reclaim! + +=head1 INSTALLATION + +If you have received this package as part of an Activestate PPM style .zip file +then type + + ppm install Font-TTF.ppd + +Otherwise. + +To configure this module, cd to the directory that contains this README file +and type the following. + + perl Makefile.PL + +Alternatively, if you plan to install Font::TTF somewhere other than +your system's perl library directory. You can type something like this: + + perl Makefile.PL PREFIX=/home/me/perl INSTALLDIRS=perl + +Then to build you run make. + + make + +If you have write access to the perl library directories, you may then +install by typing: + + make install + +To tidy up, type: + + make realclean + +Windows users should use dmake instead of make. + +=head1 CHANGES + +See Changes for an overview of recent changes. + +=head2 Future Changes + +I do not anticipate any more restructuring changes (but reserve the right to do so). + +=head1 AUTHOR + +Martin Hosken L. +(see CONTRIBUTORS for other authors). + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +The fonts in the test suite are released under the SIL Open Font License 1.1, see t/OFL.txt. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/TODO b/.cpan/build/Font-TTF-1.06-0/TODO new file mode 100644 index 0000000000..472a58c7f0 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/TODO @@ -0,0 +1,6 @@ +* Currently no support for format 1 Name tables + +* update() is a mess. What is needed is a mark sweep clean algorithm where the + dirty is used only for tables that have changed. Thus if a table is updated + it could well become dirty! Also need to be able to pass a force parameter + to force a table to update and all the tables in its dependency tree. diff --git a/.cpan/build/Font-TTF-1.06-0/blib/arch/.exists b/.cpan/build/Font-TTF-1.06-0/blib/arch/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/arch/auto/Font/TTF/.exists b/.cpan/build/Font-TTF-1.06-0/blib/arch/auto/Font/TTF/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/bin/.exists b/.cpan/build/Font-TTF-1.06-0/blib/bin/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/.exists b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF.pm new file mode 100644 index 0000000000..5613ed77f4 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF.pm @@ -0,0 +1,59 @@ +package Font::TTF; + +$VERSION = '1.06'; # RMH 02-Aug-2016 Bug fixes; updated OT tags; +# $VERSION = '1.05'; # MJPH 19-Jan-2015 Bug fixes; updated OT tags; GSUB Lookup Type 8 support +# $VERSION = '1.04'; # MJPH 8-Jan-2014 License, POD, and perl -w tidying; bug fixes +# $VERSION = '1.03'; # MJPH 5-Sep-2013 Add $t->minsize() +# $VERSION = '1.02'; # MJPH 30-Aug-2012 Fix case typo in Useall +# $VERSION = '1.01'; # MJPH 30-Aug-2012 add IO::String prerequisite +# $VERSION = '1.00'; # MJPH 21-Aug-2012 OS/2, OT & Graphite improvements; bug fixes +# $VERSION = '0.48'; # MJPH 15-DEC-2010 Bug fixes +# $VERSION = '0.47'; # MJPH 7-AUG-2009 Minor bug fix in Name.pm +# $VERSION = '0.46'; # MJPH 26-JAN-2009 Various bug fixes, add Sill table +# $VERSION = '0.45'; # MJPH 11-JUN-2008 Packaging tidying +# $VERSION = '0.44'; # MJPH 9-JUN-2008 Various bug fixes +# $VERSION = '0.43'; # MJPH 20-NOV-2007 Add a test! +# $VERSION = '0.42'; # MJPH 11-OCT-2007 Add Volt2ttf support +# $VERSION = '0.41'; # MJPH 27-MAR-2007 Remove warnings from font copy +# Bug fixes in Ttopen, GDEF +# Remove redundant head and maxp ->reads +# $VERSION = '0.40'; # MJPH 31-JUL-2006 Add EBDT, EBLC tables +# $VERSION = 0.39; + +1; + +=head1 NAME + +Font::TTF - Perl module for TrueType Font hacking + +=head1 DESCRIPTION + +This module allows you to do almost anything to a TrueType/OpenType Font +including modify and inspect nearly all tables. + +=head1 AUTHOR + +Martin Hosken L. +(see CONTRIBUTORS for other authors). + +Repository available at L + +=head1 HISTORY + +See F file for a change log. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +The fonts in the test suite are released under the Open Font License 1.1, see F. + + +=head1 SEE ALSO + +L + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/AATKern.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/AATKern.pm new file mode 100644 index 0000000000..f75e81c63d --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/AATKern.pm @@ -0,0 +1,150 @@ +package Font::TTF::AATKern; + +=head1 NAME + +Font::TTF::AATKern - AAT Kern table + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Kern::Subtable; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + + $self->SUPER::read or return $self; + + my ($dat, $fh, $numSubtables); + $fh = $self->{' INFILE'}; + + $fh->read($dat, 8); + ($self->{'version'}, $numSubtables) = TTF_Unpack("vL", $dat); + + my $subtables = []; + foreach (1 .. $numSubtables) { + my $subtableStart = $fh->tell(); + + $fh->read($dat, 8); + my ($length, $coverage, $tupleIndex) = TTF_Unpack("LSS", $dat); + my $type = $coverage & 0x00ff; + + my $subtable = Font::TTF::Kern::Subtable->create($type, $coverage, $length); + $subtable->read($fh); + + $subtable->{'tupleIndex'} = $tupleIndex if $subtable->{'variation'}; + $subtable->{' PARENT'} = $self; + push @$subtables, $subtable; + } + + $self->{'subtables'} = $subtables; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $subtables = $self->{'subtables'}; + $fh->print(TTF_Pack("vL", $self->{'version'}, scalar @$subtables)); + + foreach (@$subtables) { + $_->out($fh); + } +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read unless $self->{' read'}; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\n", $self->{'version'}); + + my $subtables = $self->{'subtables'}; + foreach (@$subtables) { + $_->print($fh); + } +} + +sub dumpXML +{ + my ($self, $fh) = @_; + $self->read unless $self->{' read'}; + + my $post = $self->{' PARENT'}->{'post'}; + $post->read; + + $fh = 'STDOUT' unless defined $fh; + $fh->printf("\n", $self->{'version'}); + + my $subtables = $self->{'subtables'}; + foreach (@$subtables) { + $fh->printf("<%s", $_->type); + $fh->printf(" vertical=\"1\"") if $_->{'vertical'}; + $fh->printf(" crossStream=\"1\"") if $_->{'crossStream'}; + $fh->printf(" variation=\"1\"") if $_->{'variation'}; + $fh->printf(" tupleIndex=\"%s\"", $_->{'tupleIndex'}) if exists $_->{'tupleIndex'}; + $fh->printf(">\n"); + + $_->dumpXML($fh); + + $fh->printf("\n", $_->type); + } + + $fh->printf("\n"); +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/AATutils.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/AATutils.pm new file mode 100644 index 0000000000..544dc93af6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/AATutils.pm @@ -0,0 +1,712 @@ +package Font::TTF::AATutils; + +=head1 NAME + +Font::TTF::AATutils - Utility functions for AAT tables + +=cut + +use strict; +use vars qw(@ISA @EXPORT); +require Exporter; + +use Font::TTF::Utils; +use Font::TTF::Segarr; +use IO::File; + +@ISA = qw(Exporter); +@EXPORT = qw( + AAT_read_lookup + AAT_pack_lookup + AAT_write_lookup + AAT_pack_classes + AAT_write_classes + AAT_pack_states + AAT_write_states + AAT_read_state_table + AAT_read_subtable + xmldump +); + +sub xmldump +{ + my ($var, $links, $depth, $processedVars, $type) = @_; + + $processedVars = {} unless (defined $processedVars); + print("\n") if $depth == 0; # not necessarily true encoding for all text! + + my $indent = "\t" x $depth; + + my ($objType, $addr) = ($var =~ m/^.+=(.+)\((.+)\)$/); + unless (defined $type) { + if (defined $addr) { + if (defined $processedVars->{$addr}) { + if ($links) { + printf("%s%s\n", $indent, "$objType"); + } + else { + printf("%s%s\n", $indent, "$objType"); + } + return; + } + $processedVars->{$addr} = 1; + } + } + + $type = ref $var unless defined $type; + + if ($type eq 'REF') { + printf("%s\n", $indent, $$var); + } + elsif ($type eq 'SCALAR') { + printf("%s%s\n", $indent, $var); + } + elsif ($type eq 'ARRAY') { + # printf("%s\n", $indent); + foreach (0 .. $#$var) { + if (ref($var->[$_])) { + printf("%s\n", $indent, $_); + xmldump($var->[$_], $links, $depth + 1, $processedVars); + printf("%s\n", $indent); + } + else { + printf("%s%s\n", $indent, $_, $var->[$_]); + } + } + # printf("%s\n", $indent); + } + elsif ($type eq 'HASH') { + # printf("%s\n", $indent); + foreach (sort keys %$var) { + if (ref($var->{$_})) { + printf("%s\n", $indent, $_); + xmldump($var->{$_}, $links, $depth + 1, $processedVars); + printf("%s\n", $indent); + } + else { + printf("%s%s\n", $indent, $_, $var->{$_}); + } + } + # printf("%s\n", $indent); + } + elsif ($type eq 'CODE') { + printf("%s\n", $indent, $var); + } + elsif ($type eq 'GLOB') { + printf("%s\n", $indent, $var); + } + elsif ($type eq '') { + printf("%s%s\n", $indent, $var); + } + else { + if ($links) { + printf("%s\n", $indent, $type, $addr); + } + else { + printf("%s\n", $indent, $type); + } + xmldump($var, $links, $depth + 1, $processedVars, $objType); + printf("%s\n", $indent); + } +} + +=head2 ($classes, $states) = AAT_read_subtable($fh, $baseOffset, $subtableStart, $limits) + +=cut + +sub AAT_read_subtable +{ + my ($fh, $baseOffset, $subtableStart, $limits) = @_; + + my $limit = 0xffffffff; + foreach (@$limits) { + $limit = $_ if ($_ > $subtableStart and $_ < $limit); + } + die if $limit == 0xffffffff; + + my $dat; + $fh->seek($baseOffset + $subtableStart, IO::File::SEEK_SET); + $fh->read($dat, $limit - $subtableStart); + + $dat; +} + +=head2 $length = AAT_write_state_table($fh, $classes, $states, $numExtraTables, $packEntry) + +$packEntry is a subroutine for packing an entry into binary form, called as + +$dat = $packEntry($entry, $entryTable, $numEntries) + +where the entry is a comma-separated list of nextStateOffset, flags, actions + +=cut + +sub AAT_pack_state_table +{ + my ($classes, $states, $numExtraTables, $packEntry) = @_; + + my ($dat) = pack("n*", (0) x (4 + $numExtraTables)); # placeholders for stateSize, classTable, stateArray, entryTable + + my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0); + my (@classTable, $i); + foreach $i (0 .. $#$classes) { + my $class = $classes->[$i]; + foreach (@$class) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + $classTable[$_] = $i; + } + } + + my $classTable = length($dat); + $dat .= pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1, + map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph)); + $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0; # pad if odd number of glyphs + + my $stateArray = length($dat); + my (@entries, %entries); + my $state = $states->[0]; + my $stateSize = @$state; + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $actions = $_->{'actions'}; + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions); + if (not defined $entries{$entry}) { + push @entries, $entry; + $entries{$entry} = $#entries; + die "too many different state array entries" if $#entries == 256; + } + $dat .= pack("C", $entries{$entry}); + } + } + $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + my $entryTable = length($dat); + $dat .= map { &$packEntry($_, $entryTable, $#entries + 1) } @entries; + + my ($dat1) = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +sub AAT_write_state_table +{ + my ($fh, $classes, $states, $numExtraTables, $packEntry) = @_; + + my $stateTableStart = $fh->tell(); + + $fh->print(pack("n*", (0) x (4 + $numExtraTables))); # placeholders for stateSize, classTable, stateArray, entryTable + + my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0); + my (@classTable, $i); + foreach $i (0 .. $#$classes) { + my $class = $classes->[$i]; + foreach (@$class) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + $classTable[$_] = $i; + } + } + + my $classTable = $fh->tell() - $stateTableStart; + $fh->print(pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1, + map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph))); + $fh->print(pack("C", 0)) if (($lastGlyph - $firstGlyph) & 1) == 0; # pad if odd number of glyphs + + my $stateArray = $fh->tell() - $stateTableStart; + my (@entries, %entries); + my $state = $states->[0]; + my $stateSize = @$state; + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $actions = $_->{'actions'}; + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions); + if (not defined $entries{$entry}) { + push @entries, $entry; + $entries{$entry} = $#entries; + die "too many different state array entries" if $#entries == 256; + } + $fh->print(pack("C", $entries{$entry})); + } + } + $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + my $entryTable = $fh->tell() - $stateTableStart; + $fh->print(map { &$packEntry($_, $entryTable, $#entries + 1) } @entries); + + my $length = $fh->tell() - $stateTableStart; + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->print(pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable)); + + $fh->seek($stateTableStart + $length, IO::File::SEEK_SET); + $length; +} + +sub AAT_pack_classes +{ + my ($classes) = @_; + + my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0); + my (@classTable, $i); + foreach $i (0 .. $#$classes) { + my $class = $classes->[$i]; + foreach (@$class) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + $classTable[$_] = $i; + } + } + + my ($dat) = pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1, + map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph)); + $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0; # pad if odd number of glyphs + + return $dat; +} + +sub AAT_write_classes +{ + my ($fh, $classes) = @_; + + $fh->print(AAT_pack_classes($fh, $classes)); +} + +sub AAT_pack_states +{ + my ($classes, $stateArray, $states, $buildEntryProc) = @_; + + my ($entries, %entryHash); + my $state = $states->[0]; + my $stateSize = @$state; + + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + my ($dat); + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_)); + if (not defined $entryHash{$entry}) { + push @$entries, $entry; + $entryHash{$entry} = $#$entries; + die "too many different state array entries" if $#$entries == 256; + } + $dat .= pack("C", $entryHash{$entry}); + } + } + $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + ($dat, $stateSize, $entries); +} + +sub AAT_write_states +{ + my ($fh, $classes, $stateArray, $states, $buildEntryProc) = @_; + + my ($entries, %entryHash); + my $state = $states->[0]; + my $stateSize = @$state; + + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_)); + if (not defined $entryHash{$entry}) { + push @$entries, $entry; + $entryHash{$entry} = $#$entries; + die "too many different state array entries" if $#$entries == 256; + } + $fh->print(pack("C", $entryHash{$entry})); + } + } + $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + ($stateSize, $entries); +} + +=head2 ($classes, $states, $entries) = AAT_read_state_table($fh, $numActionWords) + +=cut + +sub AAT_read_state_table +{ + my ($fh, $numActionWords) = @_; + + my $stateTableStart = $fh->tell(); + my $dat; + $fh->read($dat, 8); + my ($stateSize, $classTable, $stateArray, $entryTable) = unpack("nnnn", $dat); + + my $classes; # array of lists of glyphs + + $fh->seek($stateTableStart + $classTable, IO::File::SEEK_SET); + $fh->read($dat, 4); + my ($firstGlyph, $nGlyphs) = unpack("nn", $dat); + $fh->read($dat, $nGlyphs); + foreach (unpack("C*", $dat)) { + if ($_ != 1) { + my $class = $classes->[$_]; + push(@$class, $firstGlyph); + $classes->[$_] = $class unless defined $classes->[$_]; + } + $firstGlyph++; + } + + $fh->seek($stateTableStart + $stateArray, IO::File::SEEK_SET); + my $states; # array of arrays of hashes{nextState, flags, actions} + + my $entrySize = 4 + ($numActionWords * 2); + my $lastState = 1; + my $entries; + while ($#$states < $lastState) { + $fh->read($dat, $stateSize); + my @stateEntries = unpack("C*", $dat); + my $state; + foreach (@stateEntries) { + if (not defined $entries->[$_]) { + my $loc = $fh->tell(); + $fh->seek($stateTableStart + $entryTable + ($_ * $entrySize), IO::File::SEEK_SET); + $fh->read($dat, $entrySize); + my ($nextState, $flags, $actions); + ($nextState, $flags, @$actions) = unpack("n*", $dat); + $nextState -= $stateArray; + $nextState /= $stateSize; + $entries->[$_] = { 'nextState' => $nextState, 'flags' => $flags }; + $entries->[$_]->{'actions'} = $actions if $numActionWords > 0; + $lastState = $nextState if ($nextState > $lastState); + $fh->seek($loc, IO::File::SEEK_SET); + } + push(@$state, $entries->[$_]); + } + push(@$states, $state); + } + + ($classes, $states, $entries); +} + +=head2 ($format, $lookup) = AAT_read_lookup($fh, $valueSize, $length, $default) + +=cut + +sub AAT_read_lookup +{ + my ($fh, $valueSize, $length, $default) = @_; + + my $lookupStart = $fh->tell(); + my ($dat, $unpackChar); + if ($valueSize == 1) { + $unpackChar = "C"; + } + elsif ($valueSize == 2) { + $unpackChar = "n"; + } + elsif ($valueSize == 4) { + $unpackChar = "N"; + } + else { + die "unsupported value size"; + } + + $fh->read($dat, 2); + my $format = unpack("n", $dat); + my $lookup; + + if ($format == 0) { + $fh->read($dat, $length - 2); + my $i = -1; + $lookup = { map { $i++; ($_ != $default) ? ($i, $_) : () } unpack($unpackChar . "*", $dat) }; + } + + elsif ($format == 2) { + $fh->read($dat, 10); + my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat); + die if $unitSize != 4 + $valueSize; + foreach (1 .. $nUnits) { + $fh->read($dat, $unitSize); + my ($lastGlyph, $firstGlyph, $value) = unpack("nn" . $unpackChar, $dat); + if ($firstGlyph != 0xffff and $value != $default) { + foreach ($firstGlyph .. $lastGlyph) { + $lookup->{$_} = $value; + } + } + } + } + + elsif ($format == 4) { + $fh->read($dat, 10); + my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat); + die if $unitSize != 6; + foreach (1 .. $nUnits) { + $fh->read($dat, $unitSize); + my ($lastGlyph, $firstGlyph, $offset) = unpack("nnn", $dat); + if ($firstGlyph != 0xffff) { + my $loc = $fh->tell(); + $fh->seek($lookupStart + $offset, IO::File::SEEK_SET); + $fh->read($dat, ($lastGlyph - $firstGlyph + 1) * $valueSize); + my @values = unpack($unpackChar . "*", $dat); + foreach (0 .. $lastGlyph - $firstGlyph) { + $lookup->{$firstGlyph + $_} = $values[$_] if $values[$_] != $default; + } + $fh->seek($loc, IO::File::SEEK_SET); + } + } + } + + elsif ($format == 6) { + $fh->read($dat, 10); + my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat); + die if $unitSize != 2 + $valueSize; + foreach (1 .. $nUnits) { + $fh->read($dat, $unitSize); + my ($glyph, $value) = unpack("n" . $unpackChar, $dat); + $lookup->{$glyph} = $value if $glyph != 0xffff and $value != $default; + } + } + + elsif ($format == 8) { + $fh->read($dat, 4); + my ($firstGlyph, $glyphCount) = unpack("nn", $dat); + $fh->read($dat, $glyphCount * $valueSize); + $firstGlyph--; + $lookup = { map { $firstGlyph++; $_ != $default ? ($firstGlyph, $_) : () } unpack($unpackChar . "*", $dat) }; + } + + else { + die "unknown lookup format"; + } + + $fh->seek($lookupStart + $length, IO::File::SEEK_SET); + + ($format, $lookup); +} + +=head2 AAT_write_lookup($fh, $format, $lookup, $valueSize, $default) + +=cut + +sub AAT_pack_lookup +{ + my ($format, $lookup, $valueSize, $default) = @_; + + my $packChar; + if ($valueSize == 1) { + $packChar = "C"; + } + elsif ($valueSize == 2) { + $packChar = "n"; + } + elsif ($valueSize == 4) { + $packChar = "N"; + } + else { + die "unsupported value size"; + } + + my ($dat) = pack("n", $format); + + my ($firstGlyph, $lastGlyph) = (0xffff, 0); + foreach (keys %$lookup) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + } + my $glyphCount = $lastGlyph - $firstGlyph + 1; + + if ($format == 0) { + $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph)); + } + + elsif ($format == 2) { + my $prev = $default; + my $segStart = $firstGlyph; + my $dat1; + foreach ($firstGlyph .. $lastGlyph + 1) { + my $val = $lookup->{$_}; + $val = $default unless defined $val; + if ($val != $prev) { + $dat1 .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default; + $prev = $val; + $segStart = $_; + } + } + $dat1 .= pack("nn" . $packChar, 0xffff, 0xffff, 0); + my $unitSize = 4 + $valueSize; + $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize)); + $dat .= $dat1; + } + + elsif ($format == 4) { + my $segArray = new Font::TTF::Segarr($valueSize); + $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph)); + my ($start, $end, $offset); + $offset = 12 + @$segArray * 6 + 6; # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment + my $dat1; + foreach (@$segArray) { + $start = $_->{'START'}; + $end = $start + $_->{'LEN'} - 1; + $dat1 .= pack("nnn", $end, $start, $offset); + $offset += $_->{'LEN'} * 2; + } + $dat1 .= pack("nnn", 0xffff, 0xffff, 0); + $dat .= pack("nnnnn", 6, TTF_bininfo(length($dat1) / 6, 6)); + $dat .= $dat1; + foreach (@$segArray) { + $dat1 = $_->{'VAL'}; + $dat .= pack($packChar . "*", @$dat1); + } + } + + elsif ($format == 6) { + die "unsupported" if $valueSize != 2; + my $dat1 = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup); + my $unitSize = 2 + $valueSize; + $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize)); + $dat .= $dat1; + } + + elsif ($format == 8) { + $dat .= pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1); + $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph)); + } + + else { + die "unknown lookup format"; + } + + my $padBytes = (4 - (length($dat) & 3)) & 3; + $dat .= pack("C*", (0) x $padBytes); + + return $dat; +} + +sub AAT_write_lookup +{ + my ($fh, $format, $lookup, $valueSize, $default) = @_; + + my $lookupStart = $fh->tell(); + my $packChar; + if ($valueSize == 1) { + $packChar = "C"; + } + elsif ($valueSize == 2) { + $packChar = "n"; + } + elsif ($valueSize == 4) { + $packChar = "N"; + } + else { + die "unsupported value size"; + } + + $fh->print(pack("n", $format)); + + my ($firstGlyph, $lastGlyph) = (0xffff, 0); + foreach (keys %$lookup) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + } + my $glyphCount = $lastGlyph - $firstGlyph + 1; + + if ($format == 0) { + $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph))); + } + + elsif ($format == 2) { + my $prev = $default; + my $segStart = $firstGlyph; + my $dat; + foreach ($firstGlyph .. $lastGlyph + 1) { + my $val = $lookup->{$_}; + $val = $default unless defined $val; + if ($val != $prev) { + $dat .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default; + $prev = $val; + $segStart = $_; + } + } + $dat .= pack("nn" . $packChar, 0xffff, 0xffff, 0); + my $unitSize = 4 + $valueSize; + $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize))); + $fh->print($dat); + } + + elsif ($format == 4) { + my $segArray = new Font::TTF::Segarr($valueSize); + $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph)); + my ($start, $end, $offset); + $offset = 12 + @$segArray * 6 + 6; # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment + my $dat; + foreach (@$segArray) { + $start = $_->{'START'}; + $end = $start + $_->{'LEN'} - 1; + $dat .= pack("nnn", $end, $start, $offset); + $offset += $_->{'LEN'} * 2; + } + $dat .= pack("nnn", 0xffff, 0xffff, 0); + $fh->print(pack("nnnnn", 6, TTF_bininfo(length($dat) / 6, 6))); + $fh->print($dat); + foreach (@$segArray) { + $dat = $_->{'VAL'}; + $fh->print(pack($packChar . "*", @$dat)); + } + } + + elsif ($format == 6) { + die "unsupported" if $valueSize != 2; + my $dat = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup); + my $unitSize = 2 + $valueSize; + $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize))); + $fh->print($dat); + } + + elsif ($format == 8) { + $fh->print(pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1)); + $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph))); + } + + else { + die "unknown lookup format"; + } + + my $length = $fh->tell() - $lookupStart; + my $padBytes = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + + $length; +} + +1; + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Anchor.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Anchor.pm new file mode 100644 index 0000000000..fdacb9c881 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Anchor.pm @@ -0,0 +1,224 @@ +package Font::TTF::Anchor; + +=head1 NAME + +Font::TTF::Anchor - Anchor points for GPOS tables + +=head1 DESCRIPTION + +The Anchor defines an anchor point on a glyph providing various information +depending on how much is available, including such information as the co-ordinates, +a curve point and even device specific modifiers. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item x + +XCoordinate of the anchor point + +=item y + +YCoordinate of the anchor point + +=item p + +Curve point on the glyph to use as the anchor point + +=item xdev + +Device table (delta) for the xcoordinate + +=item ydev + +Device table (delta) for the ycoordinate + +=item xid + +XIdAnchor for multiple master horizontal metric id + +=item yid + +YIdAnchor for multiple master vertical metric id + +=back + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; + + +=head2 new + +Creates a new Anchor + +=cut + +sub new +{ + my ($class) = shift; + my ($self) = {@_}; + + bless $self, $class; +} + + +=head2 read($fh) + +Reads the anchor from the given file handle at that point. The file handle is left +at an arbitrary read point, usually the end of something! + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat, $loc, $fmt, $p, $xoff, $yoff); + + $fh->read($dat, 6); + $fmt = unpack('n', $dat); + if ($fmt == 4) + { ($self->{'xid'}, $self->{'yid'}) = TTF_Unpack('S2', substr($dat,2)); } + else + { ($self->{'x'}, $self->{'y'}) = TTF_Unpack('s2', substr($dat,2)); } + + if ($fmt == 2) + { + $fh->read($dat, 2); + $self->{'p'} = unpack('n', $dat); + } elsif ($fmt == 3) + { + $fh->read($dat, 4); + ($xoff, $yoff) = unpack('n2', $dat); + $loc = $fh->tell() - 10; + if ($xoff) + { + $fh->seek($loc + $xoff, 0); + $self->{'xdev'} = Font::TTF::Delta->new->read($fh); + } + if ($yoff) + { + $fh->seek($loc + $yoff, 0); + $self->{'ydev'} = Font::TTF::Delta->new->read($fh); + } + } + $self; +} + + +=head2 out($fh, $style) + +Outputs the Anchor to the given file handle at this point also addressing issues +of deltas. If $style is set, then no output is sent to the file handle. The return +value is the output string. + +=cut + +sub out +{ + my ($self, $fh, $style) = @_; + my ($xoff, $yoff, $fmt, $out); + + if (defined $self->{'xid'} || defined $self->{'yid'}) + { $out = TTF_Pack('SSS', 4, $self->{'xid'}, $self->{'yid'}); } + elsif (defined $self->{'p'}) + { $out = TTF_Pack('Ssss', 2, @{$self}{'x', 'y', 'p'}); } + elsif (defined $self->{'xdev'} || defined $self->{'ydev'}) + { + $out = TTF_Pack('Sss', 3, @{$self}{'x', 'y'}); + if (defined $self->{'xdev'}) + { + $out .= pack('n2', 10, 0); + $out .= $self->{'xdev'}->out($fh, 1); + $yoff = length($out) - 10; + } + else + { $out .= pack('n2', 0, 0); } + if (defined $self->{'ydev'}) + { + $yoff = 10 unless $yoff; + substr($out, 8, 2) = pack('n', $yoff); + $out .= $self->{'ydev'}->out($fh, 1); + } + } else + { $out = TTF_Pack('Sss', 1, @{$self}{'x', 'y'}); } + $fh->print($out) unless $style; + $out; +} + + +sub signature +{ + my ($self) = @_; + return join (",", map {"${_}=$self->{$_}"} qw(x y p xdev ydev xid yid)); +} + + +=head2 $a->out_xml($context) + +Outputs the anchor in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($end); + + $fh->print("$depthprint(" p='$self->{'p'}'") if defined ($self->{'p'}); + $end = (defined $self->{'xdev'} || defined $self->{'ydev'} || defined $self->{'xid'} || defined $self->{'yid'}); + unless ($end) + { + $fh->print("/>\n"); + return $self; + } + + if (defined $self->{'xdev'}) + { + $fh->print("$depth$context->{'indent'}\n"); + $self->{'xdev'}->out_xml($context, $depth . ($context->{'indent'} x 2)); + $fh->print("$depth$context->{'indent'}\n"); + } + + if (defined $self->{'ydev'}) + { + $fh->print("$depth$context->{'indent'}\n"); + $self->{'ydev'}->out_xml($context, $depth . ($context->{'indent'} x 2)); + $fh->print("$depth$context->{'indent'}\n"); + } + + if (defined $self->{'xid'} || defined $self->{'yid'}) + { + $fh->print("$depth$context->{'indent'}print(" xid='$self->{'xid'}'") if defined ($self->{'xid'}); + $fh->print(" yid='$self->{'yid'}'") if defined ($self->{'yid'}); + $fh->print("/>\n"); + } + $fh->print("$depth\n"); + $self; +} + +1; + + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Bsln.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Bsln.pm new file mode 100644 index 0000000000..30c42b74a0 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Bsln.pm @@ -0,0 +1,176 @@ +package Font::TTF::Bsln; + +=head1 NAME + +Font::TTF::Bsln - Baseline table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +=item xformat + +=item defaultBaseline + +=item deltas + +=item stdGlyph + +=item ctlPoints + +=item lookupFormat + +=item lookup + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +use Font::TTF::AATutils; +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + $fh->read($dat, 8); + my ($version, $format, $defaultBaseline) = TTF_Unpack("vSS", $dat); + + if ($format == 0 or $format == 1) { + $fh->read($dat, 64); + $self->{'deltas'} = [TTF_Unpack("s*", $dat)]; + } + elsif ($format == 2 or $format == 3) { + $fh->read($dat, 2); + $self->{'stdGlyph'} = unpack("n", $dat); + $fh->read($dat, 64); + $self->{'ctlPoints'} = unpack("n*", $dat); + } + else { + die "unknown table format"; + } + + if ($format == 1 or $format == 3) { + my $len = $self->{' LENGTH'} - ($fh->tell() - $self->{' OFFSET'}); + my ($lookupFormat, $lookup) = AAT_read_lookup($fh, 2, $len, $defaultBaseline); + $self->{'lookupFormat'} = $lookupFormat; + $self->{'lookup'} = $lookup; + } + + $self->{'version'} = $version; + $self->{'format'} = $format; + $self->{'defaultBaseline'} = $defaultBaseline; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $format = $self->{'format'}; + my $defaultBaseline = $self->{'defaultBaseline'}; + $fh->print(TTF_Pack("vSS", $self->{'version'}, $format, $defaultBaseline)); + + AAT_write_lookup($fh, $self->{'lookupFormat'}, $self->{'lookup'}, 2, $defaultBaseline) if ($format == 1 or $format == 3); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read; + + $fh = 'STDOUT' unless defined $fh; + + my $format = $self->{'format'}; + $fh->printf("version %f\nformat %d\ndefaultBaseline %d\n", $self->{'version'}, $format, $self->{'defaultBaseline'}); + if ($format == 0 or $format == 1) { + $fh->printf("\tdeltas:\n"); + my $deltas = $self->{'deltas'}; + foreach (0 .. 31) { + $fh->printf("\t\t%d: %d%s\n", $_, $deltas->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : ""); + } + } + if ($format == 2 or $format == 3) { + $fh->printf("\tstdGlyph = %d\n", $self->{'stdGlyph'}); + my $ctlPoints = $self->{'ctlPoints'}; + foreach (0 .. 31) { + $fh->printf("\t\t%d: %d%s\n", $_, $ctlPoints->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : ""); + } + } + if ($format == 1 or $format == 3) { + $fh->printf("lookupFormat %d\n", $self->{'lookupFormat'}); + my $lookup = $self->{'lookup'}; + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\tglyph %d: %d%s\n", $_, $lookup->{$_}, defined baselineName_($_) ? "\t# " . baselineName_($_) : ""); + } + } +} + +sub baselineName_ +{ + my ($b) = @_; + my @baselines = ( 'Roman', 'Ideographic centered', 'Ideographic low', 'Hanging', 'Math' ); + $baselines[$b]; +} + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Changes_old.txt b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Changes_old.txt new file mode 100644 index 0000000000..7c939f498f --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Changes_old.txt @@ -0,0 +1,108 @@ +Note. The version number implies a release point. Thus changes that go into a +version occur above the version number, not after it. + +* 0.05 +** cmap + debug reverse() + provide scripts as .pl instead of .bat to placate Unix world + rename makefile.pl to Makefile.PL to keep Unix happy + Add ttfremap script + +* 0.06 .. 0.08 + Fixes to get this stuff working in Unix + +* 0.09 + Never released + +* 0.10 +** cmap + Make reverse return the lowest codepoint that matches rather than + the highest +** font + Use IO::File everywhere to allow passing in of psuedo-file objects + rather than file names +** Utils + Debug FDot2.14 conversion + +* 0.11 +** cmap + Don't store empty entries in the cmap + +* 0.12 +Various changes to reduce warnings + +** glyph + Add update_bbox + Do full glyph writes if loca read rather than glyf read + Get glyph update working usefully. Clarify glyf->read + +* 0.13 + +** glyph + Debug update_bbox for compound glyphs + Add empty() to clear to unread state (allows apps to save memory) + +** OS/2 + update update() to account for new cmap structure + +** Post + Correct mu to pi in Postscript name list. The list now follows the + MS convention for good or ill. + +** Table + Add empty() to clear a table to its unread state + +** Scripts +*** psfix + Added. Creates Post table based on cmap information + +*** eurofix + Added bullet hacking and generally backwards, forwards, all + ways mapping. + +*** ttfenc + Now supports the difference between MS post name list and TeXs + +* 0.14 + + Sort out mix up over CVS mess + +* 0.15 + +** Table + read_dat no longer marks table as read + +** Cvt_ + Mark table as read when read + +** Fpgm + Mark table as read when read + +** Prep + Mark table as read when read + +** Font + Add support for Mac sfnt version code ('true') + Be stricter on out @fontlist, only output tables that exist + +* 0.16 + +** Install + add pmake support + +** glyph + tidy up pod + +** kern + tidy up pod + +** name + add utf8 support + +* 0.17 + +** Utils + Debug TTF_bininfo >>= seems to have stopped working! + +* 0.18 + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Cmap.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Cmap.pm new file mode 100644 index 0000000000..3d8c3cf553 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Cmap.pm @@ -0,0 +1,746 @@ +package Font::TTF::Cmap; + +=head1 NAME + +Font::TTF::Cmap - Character map table + +=head1 DESCRIPTION + +Looks after the character map. For ease of use, the actual cmap is held in +a hash against codepoint. Thus for a given table: + + $gid = $font->{'cmap'}{'Tables'}[0]{'val'}{$code}; + +Note that C<$code> should be a true value (0x1234) rather than a string representation. + +=head1 INSTANCE VARIABLES + +The instance variables listed here are not preceded by a space due to their +emulating structural information in the font. + +=over 4 + +=item Num + +Number of subtables in this table + +=item Tables + +An array of subtables ([0..Num-1]) + +Each subtable also has its own instance variables which are, again, not +preceded by a space. + +=over 4 + +=item Platform + +The platform number for this subtable + +=item Encoding + +The encoding number for this subtable + +=item Format + +Gives the stored format of this subtable + +=item Ver + +Gives the version (or language) information for this subtable + +=item val + +A hash keyed by the codepoint value (not a string) storing the glyph id + +=back + +=back + +The following cmap options are controlled by instance variables that start with a space: + +=over 4 + +=item allowholes + +By default, when generating format 4 cmap subtables character codes that point to glyph zero +(normally called .notdef) are not included in the subtable. In some cases including some of these +character codes can result in a smaller format 4 subtable. To enable this behavior, set allowholes +to non-zero. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the cmap into memory. Format 4 subtables read the whole subtable and +fill in the segmented array accordingly. + +=cut + +sub read +{ + my ($self, $keepzeros) = @_; + $self->SUPER::read or return $self; + + my ($dat, $i, $j, $k, $id, @ids, $s); + my ($start, $end, $range, $delta, $form, $len, $num, $ver, $sg); + my ($fh) = $self->{' INFILE'}; + + $fh->read($dat, 4); + $self->{'Num'} = unpack("x2n", $dat); + $self->{'Tables'} = []; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = {}; + $fh->read($dat, 8); + ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat)); + $s->{'LOC'} += $self->{' OFFSET'}; + push(@{$self->{'Tables'}}, $s); + } + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + $fh->seek($s->{'LOC'}, 0); + $fh->read($dat, 2); + $form = unpack("n", $dat); + + $s->{'Format'} = $form; + if ($form == 0) + { + my $j = 0; + + $fh->read($dat, 4); + ($len, $s->{'Ver'}) = unpack('n2', $dat); + $fh->read($dat, 256); + $s->{'val'} = {map {$j++; ($_ ? ($j - 1, $_) : ())} unpack("C*", $dat)}; + } elsif ($form == 6) + { + my ($start, $ecount); + + $fh->read($dat, 8); + ($len, $s->{'Ver'}, $start, $ecount) = unpack('n4', $dat); + $fh->read($dat, $ecount << 1); + $s->{'val'} = {map {$start++; ($_ ? ($start - 1, $_) : ())} unpack("n*", $dat)}; + } elsif ($form == 2) # Contributed by Huw Rogers + { + $fh->read($dat, 4); + ($len, $s->{'Ver'}) = unpack('n2', $dat); + $fh->read($dat, 512); + my ($j, $k, $l, $m, $n, @subHeaderKeys, @subHeaders, $subHeader); + $n = 1; + for ($j = 0; $j < 256; $j++) { + my $k = unpack('@'.($j<<1).'n', $dat)>>3; + $n = $k + 1 if $k >= $n; + $subHeaders[$subHeaderKeys[$j] = $k] ||= [ ]; + } + $fh->read($dat, $n<<3); # read subHeaders[] + for ($k = 0; $k < $n; $k++) { + $subHeader = $subHeaders[$k]; + $l = $k<<3; + @$subHeader = unpack('@'.$l.'n4', $dat); + $subHeader->[2] = unpack('s', pack('S', $subHeader->[2])) + if $subHeader->[2] & 0x8000; # idDelta + $subHeader->[3] = + ($subHeader->[3] - (($n - $k)<<3) + 6)>>1; # idRangeOffset + } + $fh->read($dat, $len - ($n<<3) - 518); # glyphIndexArray[] + for ($j = 0; $j < 256; $j++) { + $k = $subHeaderKeys[$j]; + $subHeader = $subHeaders[$k]; + unless ($k) { + $l = $j - $subHeader->[0]; + if ($l >= 0 && $l < $subHeader->[1]) { + $m = unpack('@'.(($l + $subHeader->[3])<<1).'n', $dat); + $m += $subHeader->[2] if $m; + $s->{'val'}{$j} = $m; + } + } else { + for ($l = 0; $l < $subHeader->[1]; $l++) { + $m = unpack('@'.(($l + $subHeader->[3])<<1).'n', $dat); + $m += $subHeader->[2] if $m; + $s->{'val'}{($j<<8) + $l + $subHeader->[0]} = $m; + } + } + } + } elsif ($form == 4) + { + $fh->read($dat, 12); + ($len, $s->{'Ver'}, $num) = unpack('n3', $dat); + $num >>= 1; + $fh->read($dat, $len - 14); + for ($j = 0; $j < $num; $j++) + { + $end = unpack("n", substr($dat, $j << 1, 2)); + $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2)); + $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2)); + $delta -= 65536 if $delta > 32767; + $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2)); + for ($k = $start; $k <= $end; $k++) + { + if ($range == 0 || $range == 65535) # support the buggy FOG with its range=65535 for final segment + { $id = $k + $delta; } + else + { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 + + 2 + ($k - $start) * 2 + $range, 2)) + $delta; } + $id -= 65536 if $id >= 65536; + $s->{'val'}{$k} = $id if ($id || $keepzeros); + } + } + } elsif ($form == 8 || $form == 12 || $form == 13) + { + $fh->read($dat, 10); + ($len, $s->{'Ver'}) = unpack('x2N2', $dat); + if ($form == 8) + { + $fh->read($dat, 8196); + $num = unpack("N", substr($dat, 8192, 4)); # don't need the map + } else + { + $fh->read($dat, 4); + $num = unpack("N", $dat); + } + $fh->read($dat, 12 * $num); + for ($j = 0; $j < $num; $j++) + { + ($start, $end, $sg) = unpack("N3", substr($dat, $j * 12, 12)); + for ($k = $start; $k <= $end; $k++) + { $s->{'val'}{$k} = $form == 13 ? $sg : $sg++; } + } + } elsif ($form == 10) + { + $fh->read($dat, 18); + ($len, $s->{'Ver'}, $start, $num) = unpack('x2N4', $dat); + $fh->read($dat, $num << 1); + for ($j = 0; $j < $num; $j++) + { $s->{'val'}{$start + $j} = unpack("n", substr($dat, $j << 1, 2)); } + } + } + $self; +} + + +=head2 $t->ms_lookup($uni) + +Finds a Unicode table, giving preference to the MS one, and looks up the given +Unicode codepoint in it to find the glyph id. + +=cut + +sub ms_lookup +{ + my ($self, $uni) = @_; + + $self->find_ms || return undef unless (defined $self->{' mstable'}); + return $self->{' mstable'}{'val'}{$uni}; +} + + +=head2 $t->find_ms + +Finds the a Unicode table, giving preference to the Microsoft one, and sets the C instance variable +to it if found. Returns the table it finds. + +=cut + +sub find_ms +{ + my ($self) = @_; + my ($i, $s, $alt, $found); + + return $self->{' mstable'} if defined $self->{' mstable'}; + $self->read; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + if ($s->{'Platform'} == 3) + { + $self->{' mstable'} = $s; + return $s if ($s->{'Encoding'} == 10); + $found = 1 if ($s->{'Encoding'} == 1); + } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1)) + { $alt = $s; } + } + $self->{' mstable'} = $alt if ($alt && !$found); + $self->{' mstable'}; +} + + +=head2 $t->ms_enc + +Returns the encoding of the microsoft table (0 => symbol, etc.). Returns undef if there is +no Microsoft cmap. + +=cut + +sub ms_enc +{ + my ($self) = @_; + my ($s); + + return $self->{' mstable'}{'Encoding'} + if (defined $self->{' mstable'} && $self->{' mstable'}{'Platform'} == 3); + + foreach $s (@{$self->{'Tables'}}) + { + return $s->{'Encoding'} if ($s->{'Platform'} == 3); + } + return undef; +} + + +=head2 $t->out($fh) + +Writes out a cmap table to a filehandle. If it has not been read, then +just copies from input file to output + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($loc, $s, $i, $base_loc, $j, @keys); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + + $self->{'Tables'} = [sort {$a->{'Platform'} <=> $b->{'Platform'} + || $a->{'Encoding'} <=> $b->{'Encoding'} + || $a->{'Ver'} <=> $b->{'Ver'}} @{$self->{'Tables'}}]; + $self->{'Num'} = scalar @{$self->{'Tables'}}; + + $base_loc = $fh->tell(); + $fh->print(pack("n2", 0, $self->{'Num'})); + + for ($i = 0; $i < $self->{'Num'}; $i++) + { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); } + + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + if ($s->{'Format'} < 8) + { @keys = sort {$a <=> $b} grep { $_ <= 0xFFFF} keys %{$s->{'val'}}; } + else + { @keys = sort {$a <=> $b} keys %{$s->{'val'}}; } + $s->{' outloc'} = $fh->tell(); + if ($s->{'Format'} < 8) + { $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'})); } # come back for length + else + { $fh->print(pack("n2N2", $s->{'Format'}, 0, 0, $s->{'Ver'})); } + + if ($s->{'Format'} == 0) + { + $fh->print(pack("C256", map {defined $_ ? $_ : 0} @{$s->{'val'}}{0 .. 255})); + } elsif ($s->{'Format'} == 6) + { + $fh->print(pack("n2", $keys[0], $keys[-1] - $keys[0] + 1)); + $fh->print(pack("n*", map {defined $_ ? $_ : 0} @{$s->{'val'}}{$keys[0] .. $keys[-1]})); + } elsif ($s->{'Format'} == 2) # Contributed by Huw Rogers + { + my ($g, $k, $h, $l, $m, $n); + my (@subHeaderKeys, @subHeaders, $subHeader, @glyphIndexArray); + $n = 0; + @subHeaderKeys = (-1) x 256; + for $j (@keys) { + next unless defined($g = $s->{'val'}{$j}); + $h = int($j>>8); + $l = ($j & 0xff); + if (($k = $subHeaderKeys[$h]) < 0) { + $subHeader = [ $l, 1, 0, 0, [ $g ] ]; + $subHeaders[$k = $n++] = $subHeader; + $subHeaderKeys[$h] = $k; + } else { + $subHeader = $subHeaders[$k]; + $m = ($l - $subHeader->[0] + 1) - $subHeader->[1]; + $subHeader->[1] += $m; + push @{$subHeader->[4]}, (0) x ($m - 1), $g - $subHeader->[2]; + } + } + @subHeaderKeys = map { $_ < 0 ? 0 : $_ } @subHeaderKeys; + $subHeader = $subHeaders[0]; + $subHeader->[3] = 0; + push @glyphIndexArray, @{$subHeader->[4]}; + splice(@$subHeader, 4); + { + my @subHeaders_ = sort {@{$a->[4]} <=> @{$b->[4]}} @subHeaders[1..$#subHeaders]; + my ($f, $d, $r, $subHeader_); + for ($k = 0; $k < @subHeaders_; $k++) { + $subHeader = $subHeaders_[$k]; + $f = $r = shift @{$subHeader->[4]}; + $subHeader->[5] = join(':', + map { + $d = $_ - $r; + $r = $_; + $d < 0 ? + sprintf('-%04x', -$d) : + sprintf('+%04x', $d) + } @{$subHeader->[4]}); + unshift @{$subHeader->[4]}, $f; + } + for ($k = 0; $k < @subHeaders_; $k++) { + $subHeader = $subHeaders_[$k]; + next unless $subHeader->[4]; + $subHeader->[3] = @glyphIndexArray; + push @glyphIndexArray, @{$subHeader->[4]}; + for ($l = $k + 1; $l < @subHeaders_; $l++) { + $subHeader_ = $subHeaders_[$l]; + next unless $subHeader_->[4]; + $d = $subHeader_->[5]; + if ($subHeader->[5] =~ /\Q$d\E/) { + my $o = length($`)/6; #` + $subHeader_->[2] += + $subHeader_->[4]->[$o] - $subHeader->[4]->[0]; + $subHeader_->[3] = $subHeader->[3] + $o; + splice(@$subHeader_, 4); + } + } + splice(@$subHeader, 4); + } + } + $fh->print(pack('n*', map { $_<<3 } @subHeaderKeys)); + for ($j = 0; $j < 256; $j++) { + $k = $subHeaderKeys[$j]; + $subHeader = $subHeaders[$k]; + } + for ($k = 0; $k < $n; $k++) { + $subHeader = $subHeaders[$k]; + $fh->print(pack('n4', + $subHeader->[0], + $subHeader->[1], + $subHeader->[2] < 0 ? + unpack('S', pack('s', $subHeader->[2])) : + $subHeader->[2], + ($subHeader->[3]<<1) + (($n - $k)<<3) - 6 + )); + } + $fh->print(pack('n*', @glyphIndexArray)); + } elsif ($s->{'Format'} == 4) + { + my (@starts, @ends, @deltas, @range); + + # There appears to be a bug in Windows that requires the final 0xFFFF (sentry) + # to be in a segment by itself -- otherwise Windows 7 and 8 (at least) won't install + # or preview the font, complaining that it doesn't appear to be a valid font. + # Therefore we can't just add 0XFFFF to the USV list as we used to do: + # push(@keys, 0xFFFF) unless ($keys[-1] == 0xFFFF); + # Instead, for now *remove* 0xFFFF from the USV list, and add a segement + # for it after all the other segments are computed. + pop @keys if $keys[-1] == 0xFFFF; + + # Step 1: divide into maximal length idDelta runs + + my ($prevUSV, $prevgid); + for ($j = 0; $j <= $#keys; $j++) + { + my $u = $keys[$j]; + my $g = $s->{'val'}{$u}; + if ($j == 0 || $u != $prevUSV+1 || $g != $prevgid+1) + { + push @ends, $prevUSV unless $j == 0; + push @starts, $u; + push @range, 0; + } + $prevUSV = $u; + $prevgid = $g; + } + push @ends, $prevUSV; + + # Step 2: find each macro-range + + my ($start, $end); # Start and end of macro-range + for ($start = 0; $start < $#starts; $start++) + { + next if $ends[$start] - $starts[$start] > 7; # if count > 8, we always treat this as a run unto itself + for ($end = $start+1; $end <= $#starts; $end++) + { + last if $starts[$end] - $ends[$end-1] > ($self->{' allowholes'} ? 5 : 1) + || $ends[$end] - $starts[$end] > 7; # gap > 4 or count > 8 so $end is beyond end of macro-range + } + $end--; #Ending index of this macro-range + + # Step 3: optimize this macro-range (from $start through $end) + L1: for ($j = $start; $j < $end; ) + { + my $size1 = ($range[$j] ? 8 + 2 * ($ends[$j] - $starts[$j] + 1) : 8); # size of first range (which may now be idRange type) + for (my $k = $j+1; $k <= $end; $k++) + { + if (8 + 2 * ($ends[$k] - $starts[$j] + 1) <= $size1 + 8 * ($k - $j)) + { + # Need to coalesce $j..$k into $j: + $ends[$j] = $ends[$k]; + $range[$j] = 1; # for now use boolean to indicate this is an idRange segment + splice @starts, $j+1, $k-$j; + splice @ends, $j+1, $k-$j; + splice @range, $j+1, $k-$j; + $end -= ($k-$j); + next L1; # Note that $j isn't incremented so this is a redo + } + } + # Nothing coalesced + $j++; + } + + # Finished with this macro-range + $start = $end; + } + + # Ok, add the final segment containing the sentry value + push(@keys, 0xFFFF); + push @starts, 0xFFFF; + push @ends, 0xFFFF; + push @range, 0; + + # What is left is a collection of segments that will represent the cmap in mimimum-sized format 4 subtable + + my ($num, $count, $sRange, $eSel, $eShift); + + $num = scalar(@starts); + $count = 0; + for ($j = 0; $j < $num; $j++) + { + if ($range[$j]) + { + $range[$j] = ($count + $num - $j) << 1; + $count += $ends[$j] - $starts[$j] + 1; + push @deltas, 0; + } + else + { + push @deltas, ($s->{'val'}{$starts[$j]} || 0) - $starts[$j]; + } + } + + ($num, $sRange, $eSel, $eShift) = Font::TTF::Utils::TTF_bininfo($num, 2); + $fh->print(pack("n4", $num * 2, $sRange, $eSel, $eShift)); + $fh->print(pack("n*", @ends)); + $fh->print(pack("n", 0)); + $fh->print(pack("n*", @starts)); + $fh->print(pack("n*", @deltas)); + $fh->print(pack("n*", @range)); + + for ($j = 0; $j < $num; $j++) + { + next if ($range[$j] == 0); + $fh->print(pack("n*", map {$_ || 0} @{$s->{'val'}}{$starts[$j] .. $ends[$j]})); + } + } elsif ($s->{'Format'} == 8 || $s->{'Format'} == 12 || $s->{'Format'} == 13) + { + my (@jobs, $start, $current, $curr_glyf, $map); + + $current = 0; $curr_glyf = 0; + $map = "\000" x 8192; + foreach $j (@keys) + { + if ($j > 0xFFFF && $s->{'Format'} == 8) + { + if (defined $s->{'val'}{$j >> 16}) + { $s->{'Format'} = 12; } + vec($map, $j >> 16, 1) = 1; + } + if ($j != $current + 1 || $s->{'val'}{$j} != ($s->{'Format'} == 13 ? $curr_glyf : $curr_glyf + 1)) + { + push (@jobs, [$start, $current, $s->{'Format'} == 13 ? $curr_glyf : $curr_glyf - ($current - $start)]) if (defined $start); + $start = $j; $current = $j; $curr_glyf = $s->{'val'}{$j}; + } + $current = $j; + $curr_glyf = $s->{'val'}{$j}; + } + push (@jobs, [$start, $current, $s->{'Format'} == 13 ? $curr_glyf : $curr_glyf - ($current - $start)]) if (defined $start); + $fh->print($map) if ($s->{'Format'} == 8); + $fh->print(pack('N', $#jobs + 1)); + foreach $j (@jobs) + { $fh->print(pack('N3', @{$j})); } + } elsif ($s->{'Format'} == 10) + { + $fh->print(pack('N2', $keys[0], $keys[-1] - $keys[0] + 1)); + $fh->print(pack('n*', $s->{'val'}{$keys[0] .. $keys[-1]})); + } + + $loc = $fh->tell(); + if ($s->{'Format'} < 8) + { + $fh->seek($s->{' outloc'} + 2, 0); + $fh->print(pack("n", $loc - $s->{' outloc'})); + } else + { + $fh->seek($s->{' outloc'} + 4, 0); + $fh->print(pack("N", $loc - $s->{' outloc'})); + } + $fh->seek($base_loc + 8 + ($i << 3), 0); + $fh->print(pack("N", $s->{' outloc'} - $base_loc)); + $fh->seek($loc, 0); + } + $self; +} + + +=head2 $t->XML_element($context, $depth, $name, $val) + +Outputs the elements of the cmap in XML. We only need to process val here + +=cut + +sub XML_element +{ + my ($self, $context, $depth, $k, $val) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self if ($k eq 'LOC'); + return $self->SUPER::XML_element($context, $depth, $k, $val) unless ($k eq 'val'); + + $fh->print("$depth\n"); + foreach $i (sort {$a <=> $b} keys %{$val}) + { $fh->printf("%s\n", $depth . $context->{'indent'}, $i, $val->{$i}); } + $fh->print("$depth\n"); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be in bytes. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + + +=head2 $t->update + +Tidies the cmap table. + +Removes MS Fmt12 cmap if it is no longer needed. + +Removes from all cmaps any codepoint that map to GID=0. Note that such entries will +be re-introduced as necessary depending on the cmap format. + +=cut + +sub update +{ + my ($self) = @_; + my ($max, $code, $gid, @keep); + + return undef unless ($self->SUPER::update); + + foreach my $s (@{$self->{'Tables'}}) + { + $max = 0; + while (($code, $gid) = each %{$s->{'val'}}) + { + if ($gid) + { + # remember max USV + $max = $code if $max < $code; + } + else + { + # Remove unneeded key + delete $s->{'val'}{$code}; # nb: this is a safe delete according to perldoc perlfunc. + } + } + push @keep, $s unless $s->{'Platform'} == 3 && $s->{'Encoding'} == 10 && $s->{'Format'} == 12 && $max <= 0xFFFF; + } + + $self->{'Tables'} = [ @keep ]; + + delete $self->{' mstable'}; # Force rediscovery of this. + + $self; +} + +=head2 @map = $t->reverse(%opt) + +Returns a reverse map of the Unicode cmap. I.e. given a glyph gives the Unicode value for it. Options are: + +=over 4 + +=item tnum + +Table number to use rather than the default Unicode table + +=item array + +Returns each element of reverse as an array since a glyph may be mapped by more +than one Unicode value. The arrays are unsorted. Otherwise store any one unicode value for a glyph. + +=back + +=cut + +sub reverse +{ + my ($self, %opt) = @_; + my ($table) = defined $opt{'tnum'} ? $self->{'Tables'}[$opt{'tnum'}] : $self->find_ms; + my (@res, $code, $gid); + + while (($code, $gid) = each(%{$table->{'val'}})) + { + if ($opt{'array'}) + { push (@{$res[$gid]}, $code); } + else + { $res[$gid] = $code unless (defined $res[$gid] && $res[$gid] > 0 && $res[$gid] < $code); } + } + @res; +} + + +=head2 is_unicode($index) + +Returns whether the table of a given index is known to be a unicode table +(as specified in the specifications) + +=cut + +sub is_unicode +{ + my ($self, $index) = @_; + my ($pid, $eid) = ($self->{'Tables'}[$index]{'Platform'}, $self->{'Tables'}[$index]{'Encoding'}); + + return ($pid == 3 || $pid == 0 || ($pid == 2 && $eid == 1)); +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +Format 14 (Unicode Variation Sequences) cmaps are not supported. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Coverage.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Coverage.pm new file mode 100644 index 0000000000..db5ab26bcb --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Coverage.pm @@ -0,0 +1,351 @@ +package Font::TTF::Coverage; + +=head1 NAME + +Font::TTF::Coverage - Opentype coverage and class definition objects + +=head1 DESCRIPTION + +Coverage tables and class definition objects are virtually identical concepts +in OpenType. Their difference comes purely in their storage. Therefore we can +say that a coverage table is a class definition in which the class definition +for each glyph is the corresponding index in the coverage table. The resulting +data structure is that a Coverage table has the following fields: + +=over + +=item cover + +A boolean to indicate whether this table is a coverage table (TRUE) or a +class definition (FALSE) + +=item val + +A hash of glyph ids against values (either coverage index or class value) + +=item fmt + +The storage format used is given here, but is recalculated when the table +is written out. + +=item count + +A count of the elements in a coverage table for use with add. Each subsequent +addition is added with the current count and increments the count. + +=item max + +Maximum class value in a class table. + +=back + +=head1 METHODS + +=cut + +=head2 new($isCover [, vals]) + +Creates a new coverage table or class definition table, depending upon the +value of $isCover. if $isCover then vals may be a list of glyphs to include in order. +If no $isCover, then vals is a hash of glyphs against class values. + +=cut + +our $dontsort; + +sub new +{ + my ($class) = shift; + my ($isCover) = shift; + my ($self) = {}; + + $self->{'cover'} = $isCover; + if ($isCover) + { + $self->{'count'} = 0; + my ($v); + foreach $v (@_) + { $self->{'val'}{$v} = $self->{'count'}++; } + } + else + { + $self->{'max'} = 0; + $self->{'val'} = {@_}; + foreach (values %{$self->{'val'}}) {$self->{'max'} = $_ if $_ > $self->{'max'}} + } + bless $self, $class; +} + + +=head2 read($fh) + +Reads the coverage/class table from the given file handle + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat, $fmt, $num, $i, $c); + + $fh->read($dat, 4); + ($fmt, $num) = unpack("n2", $dat); + $self->{'fmt'} = $fmt; + + if ($self->{'cover'}) + { + if ($fmt == 1) + { + $fh->read($dat, $num << 1); + map {$self->{'val'}{$_} = $i++} unpack("n*", $dat); + $self->{'count'} = $num; + } elsif ($fmt == 2) + { + $fh->read($dat, $num * 6); + for ($i = 0; $i < $num; $i++) + { + ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6)); + map {$self->{'val'}{$_} = $c++} ($first .. $last); + } + $self->{'count'} = $c; + } + } elsif ($fmt == 1) + { + $fh->read($dat, 2); + $first = $num; + ($num) = unpack("n", $dat); + $fh->read($dat, $num << 1); + map {$self->{'val'}{$first++} = $_; $self->{'max'} = $_ if ($_ > $self->{'max'})} unpack("n*", $dat); + } elsif ($fmt == 2) + { + $fh->read($dat, $num * 6); + for ($i = 0; $i < $num; $i++) + { + ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6)); + map {$self->{'val'}{$_} = $c} ($first .. $last); + $self->{'max'} = $c if ($c > $self->{'max'}); + } + } + $self; +} + + +=head2 out($fh, $state) + +Writes the coverage/class table to the given file handle. If $state is 1 then +the output string is returned rather than being output to a filehandle. + +=cut + +sub out +{ + my ($self, $fh, $state) = @_; + my ($g, $eff, $grp, $out); + my ($shipout) = ($state ? sub {$out .= $_[0];} : sub {$fh->print($_[0]);}); + my (@gids) = sort {$a <=> $b} keys %{$self->{'val'}}; + + if ($self->{'cover'}) + { $self->sort() unless ($self->{'dontsort'} or $dontsort); } + else + { @gids = grep {$self->{'val'}{$_} > 0} @gids;} # class value=0 is not explicitly coded in class table + + $fmt = 1; $grp = 1; $eff = 0; + for ($i = 1; $i <= $#gids; $i++) + { + if ($self->{'val'}{$gids[$i]} < $self->{'val'}{$gids[$i-1]} && $self->{'cover'}) + { + $fmt = 2; + last; + } elsif ($gids[$i] == $gids[$i-1] + 1 && ($self->{'cover'} || $self->{'val'}{$gids[$i]} == $self->{'val'}{$gids[$i-1]})) + { $eff++; } + else + { + $grp++; + $eff += $gids[$i] - $gids[$i-1] if (!$self->{'cover'}); + } + } +# if ($self->{'cover'}) + { $fmt = 2 if ($eff / $grp > 3 || scalar (@gids) == 0); } +# else +# { $fmt = 2 if ($grp > 1); } + + if ($fmt == 1 && $self->{'cover'}) + { + my ($last) = 0; + &$shipout(pack('n2', 1, scalar @gids)); + &$shipout(pack('n*', @gids)); + } elsif ($fmt == 1) + { + my ($last) = $gids[0]; + &$shipout(pack("n3", 1, $last, $gids[-1] - $last + 1)); + foreach $g (@gids) + { + if ($g > $last + 1) + { &$shipout(pack('n*', (0) x ($g - $last - 1))); } + &$shipout(pack('n', $self->{'val'}{$g})); + $last = $g; + } + } else + { + my ($start, $end, $ind, $numloc, $endloc, $num); + &$shipout(pack("n2", 2, 0)); + $numloc = $fh->tell() - 2 unless $state; + + $start = 0; $end = 0; $num = 0; + while ($end < $#gids) + { + if ($gids[$end + 1] == $gids[$end] + 1 + && $self->{'val'}{$gids[$end + 1]} + == $self->{'val'}{$gids[$end]} + + ($self->{'cover'} ? 1 : 0)) + { + $end++; + next; + } + + &$shipout(pack("n3", $gids[$start], $gids[$end], + $self->{'val'}{$gids[$start]})); + $start = $end + 1; + $end++; + $num++; + } + if (scalar(@gids)) + { + &$shipout(pack("n3", $gids[$start], $gids[$end], + $self->{'val'}{$gids[$start]})); + $num++; + } + if ($state) + { substr($out, 2, 2) = pack('n', $num); } + else + { + $endloc = $fh->tell(); + $fh->seek($numloc, 0); + $fh->print(pack("n", $num)); + $fh->seek($endloc, 0); + } + } + return ($state ? $out : $self); +} + + +=head2 $c->add($glyphid[, $class]) + +Adds a glyph id to the coverage or class table. +Returns the index or class number of the glyphid added. + +=cut + +sub add +{ + my ($self, $gid, $class) = @_; + + return $self->{'val'}{$gid} if (defined $self->{'val'}{$gid}); + if ($self->{'cover'}) + { + $self->{'val'}{$gid} = $self->{'count'}; + return $self->{'count'}++; + } + else + { + $self->{'val'}{$gid} = $class || '0'; + $self->{'max'} = $class if ($class > $self->{'max'}); + return $class; + } +} + + +=head2 $c->signature + +Returns a vector of all the glyph ids covered by this coverage table or class + +=cut + +sub signature +{ + my ($self) = @_; + my ($vec, $range, $size); + +if (0) +{ + if ($self->{'cover'}) + { $range = 1; $size = 1; } + else + { + $range = $self->{'max'}; + $size = 1; + while ($range > 1) + { + $size = $size << 1; + $range = $range >> 1; + } + $range = $self->{'max'} + 1; + } + foreach (keys %{$self->{'val'}}) + { vec($vec, $_, $size) = $self->{'val'}{$_} > $range ? $range : $self->{'val'}{$_}; } + length($vec) . ":" . $vec; +} + $vec = join(";", map{"$_,$self->{'val'}{$_}"} sort { $a <=> $b} keys %{$self->{'val'}}); +} + +=head2 @map=$c->sort + +Sorts the coverage table so that indexes are in ascending order of glyphid. +Returns a map such that $map[$new_index]=$old_index. + +=cut + +sub sort +{ + my ($self) = @_; + my (@res, $i); + + foreach (sort {$a <=> $b} keys %{$self->{'val'}}) + { + push(@res, $self->{'val'}{$_}); + $self->{'val'}{$_} = $i++; + } + @res; +} + +=head2 $c->out_xml($context) + +Outputs this coverage/class in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + + $fh->print("$depth<" . ($self->{'cover'} ? 'coverage' : 'class') . ">\n"); + foreach $gid (sort {$a <=> $b} keys %{$self->{'val'}}) + { + $fh->printf("$depth$context->{'indent'}\n", $gid, $self->{'val'}{$gid}); + } + $fh->print("$depth{'cover'} ? 'coverage' : 'class') . ">\n"); + $self; +} + +sub release +{ } + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Cvt_.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Cvt_.pm new file mode 100644 index 0000000000..d7695ac216 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Cvt_.pm @@ -0,0 +1,90 @@ +package Font::TTF::Cvt_; + +=head1 NAME + +Font::TTF::Cvt_ - Control Value Table in a TrueType font + +=head1 DESCRIPTION + +This is a minimal class adding nothing beyond a table, but is a repository +for cvt type information for those processes brave enough to address hinting. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item val + +This is an array of CVT values. Thus access to the CVT is via: + + $f->{'cvt_'}{'val'}[$num]; + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA $VERSION); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +$VERSION = 0.0001; + +=head2 $t->read + +Reads the CVT table into both the tables C<' dat'> variable and the C +array. + +=cut + +sub read +{ + my ($self) = @_; + + $self->read_dat || return undef; + $self->{' read'} = 1; + $self->{'val'} = [TTF_Unpack("s*", $self->{' dat'})]; + $self; +} + + +=head2 $t->update + +Updates the RAM file copy C<' dat'> to be the same as the array. + +=cut + +sub update +{ + my ($self) = @_; + + return undef unless ($self->{' read'} && $#{$self->{'val'}} >= 0); + $self->{' dat'} = TTF_Pack("s*", @{$self->{'val'}}); + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/DSIG.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/DSIG.pm new file mode 100644 index 0000000000..af9a24dc97 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/DSIG.pm @@ -0,0 +1,88 @@ +package Font::TTF::DSIG; + +use strict; +use vars qw(@ISA); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +sub create +{ + my ($class) = @_; + my ($self) = { 'version' => 1, 'numtables' => 0, 'perms' => 0 }; + bless $self, ref $class || $class; + return $self; +} + +sub read +{ + my ($self) = @_; + my ($dat, $i, @records, $r); + + $self->SUPER::read || return $self; + $self->{' INFILE'}->read($dat, 8); + ($self->{'version'}, $self->{'numtables'}, $self->{'perms'}) = unpack("Nnn", $dat); + for ($i = 0; $i < $self->{'numtables'}; $i++) + { + $self->{' INFILE'}->read($dat, 12); + push (@records, [unpack("N3", $dat)]); + } + foreach $r (@records) + { + if ($r->[0] == 1) + { + $self->{' INFILE'}->seek($self->{' OFFSET'} + $r->[2],0); + $self->{' INFILE'}->read($dat, $r->[1]); + push @{$self->{'records'}}, substr($dat, 8); + } + } + $self; +} + +sub isempty +{ + my ($self) = @_; + return $self->read->{'numtables'} == 0; +} + +sub out +{ + my ($self, $fh) = @_; + my ($i, $curlen); + + return $self->SUPER::out($fh) unless $self->{' read'}; # this is never true + $fh->print(pack("Nnn", $self->{'version'}, $self->{'numtables'}, $self->{'perms'})); + $curlen = 0; + for ($i = 0; $i < $self->{'numtables'}; $i++) + { + $fh->print(pack("N3", 1, length($self->{'records'}[$i]) + 8, $curlen + $self->{'numtables'} * 12 + 8)); + $curlen += length($self->{'records'}[$i]) + 8; + } + for ($i = 0; $i < $self->{'numtables'}; $i++) + { + $fh->print(pack("nnN", 0, 0, length($self->{'records'}[$i]))); + $fh->print($self->{'records'}[$i]); + } + $self; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Delta.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Delta.pm new file mode 100644 index 0000000000..718d49383e --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Delta.pm @@ -0,0 +1,186 @@ +package Font::TTF::Delta; + +=head1 NAME + +Font::TTF::Delta - Opentype Device tables + +=head1 DESCRIPTION + +Each device table corresponds to a set of deltas for a particular point over +a range of ppem values. + +=over + +=item first + +The first ppem value in the range + +=item last + +The last ppem value in the range + +=item val + +This is an array of deltas corresponding to each ppem in the range between +first and last inclusive. + +=item fmt + +This is the fmt used (log2 of number bits per value) when the device table was +read. It is recalculated on output. + +=back + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; + +=head2 new + +Creates a new device table + +=cut + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + bless $self, $class; +} + + +=head2 read + +Reads a device table from the given IO object at the current location + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat, $fmt, $num, $i, $j, $mask); + + $fh->read($dat, 6); + ($self->{'first'}, $self->{'last'}, $fmt) = TTF_Unpack("S3", $dat); + $self->{'fmt'} = $fmt; + + $fmt = 1 << $fmt; + $num = ((($self->{'last'} - $self->{'first'} + 1) * $fmt) + 15) >> 8; + $fh->read($dat, $num); + + $mask = (0xffff << (16 - $fmt)) & 0xffff; + $j = 0; + for ($i = $self->{'first'}; $i <= $self->{'last'}; $i++) + { + if ($j == 0) + { + $num = TTF_Unpack("S", substr($dat, 0, 2)); + substr($dat, 0, 2) = ''; + } + push (@{$self->{'val'}}, ($num & $mask) >> (16 - $fmt)); + $num <<= $fmt; + $j += $fmt; + $j = 0 if ($j >= 16); + } + $self; +} + + +=head2 out($fh, $style) + +Outputs a device table to the given IO object at the current location, or just +returns the data to be output if $style != 0 + +=cut + +sub out +{ + my ($self, $fh, $style) = @_; + my ($dat, $fmt, $num, $mask, $j, $f, $out); + + foreach $f (@{$self->{'val'}}) + { + my ($tfmt) = $f > 0 ? $f + 1 : -$f; + $fmt = $tfmt if $tfmt > $fmt; + } + + if ($fmt > 8) + { $fmt = 3; } + elsif ($fmt > 2) + { $fmt = 2; } + else + { $fmt = 1; } + + $out = TTF_Pack("S3", $self->{'first'}, $self->{'last'}, $fmt); + + $fmt = 1 << $fmt; + $mask = 0xffff >> (16 - $fmt); + $j = 0; $dat = 0; + foreach $f (@{$self->{'val'}}) + { + $dat |= ($f & $mask) << (16 - $fmt - $j); + $j += $fmt; + if ($j >= 16) + { + $j = 0; + $out .= TTF_Pack("S", $dat); + $dat = 0; + } + } + $out .= pack('n', $dat) if ($j > 0); + $fh->print($out) unless $style; + $out; +} + +=head2 $d->signature() + +Returns a content based identifying string for this delta for +compression purposes + +=cut + +sub signature +{ + my ($self) = @_; + return join (",", $self->{'first'}, $self->{'last'}, @{$self->{'val'}}); +} + + +=head2 $d->out_xml($context) + +Outputs a delta in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + + $fh->printf("%s\n", $depth, $self->{'first'}, $self->{'last'}); + $fh->print("$depth$context->{'indent'}" . join (' ', @{$self->{'val'}}) . "\n") if defined ($self->{'val'}); + $fh->print("$depth\n"); +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Dumper.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Dumper.pm new file mode 100644 index 0000000000..ffb8e17203 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Dumper.pm @@ -0,0 +1,97 @@ +package Font::TTF::Dumper; + +=head1 NAME + +Font::TTF::Dumper - Debug dump of a font datastructure, avoiding recursion on ' PARENT' + +=head1 SYNOPSIS + + use Font::TTF::Dumper; + + # Print a table from the font structure: + print ttfdump($font->{$tag}); + + # Print font table with name + print ttfdump($font->{'head'}, 'head'); + + # Print font table with name and other options + print ttfdump($font->{'head'}, 'head', %opts); + + # Print one glyph's data: + print ttfdump($font->{'loca'}->read->{'glyphs'}[$gid], "glyph_$gid"); + +=head1 DESCRIPTION + +Font::TTF data structures are trees created from hashes and arrays. When trying to figure +out how the structures work, sometimes it is helpful to use Data::Dumper on them. However, +many of the object structures have ' PARENT' links that refer back to the object's parent, +which means that Data::Dumper ends up dumping the whole font no matter what. + +The main purpose of this module is to invoke Data::Dumper with a +filter that skips over the ' PARENT' element of any hash. + +To reduce output further, this module also skips over ' CACHE' elements and any +hash element whose value is a Font::TTF::Glyph or Font::TTF::Font object. +(Really should make this configurable.) + +If $opts{'d'}, then set Deepcopy mode to minimize use of crossreferencing. + +=cut + +use strict; +use Data::Dumper; + +use vars qw(@EXPORT @ISA); +require Exporter; +@ISA = qw( Exporter ); +@EXPORT = qw( ttfdump ); + +my %skip = ( Font => 1, Glyph => 1 ); + +sub ttfdump +{ + my ($var, $name, %opts) = @_; + my $res; + + my $d = Data::Dumper->new([$var]); + $d->Names([$name]) if defined $name; + $d->Sortkeys(\&myfilter); # This is the trick to keep from dumping the whole font + $d->Deepcopy($opts{'d'}); # Caller controls whether to use crossreferencing + $d->Indent(3); # I want array indicies + $d->Useqq(1); # Perlquote -- slower but there might be binary data. + $res = $d->Dump; + $d->DESTROY; + $res; +} + +sub myfilter +{ + my ($hash) = @_; + my @a = grep { + ($_ eq ' PARENT' || $_ eq ' CACHE') ? 0 : + ref($hash->{$_}) =~ m/^Font::TTF::(.*)$/ ? !$skip{$1} : + 1 + } (keys %{$hash}) ; + # Sort numerically if that is reasonable: + return [ sort {$a =~ /\D/ || $b =~ /\D/ ? $a cmp $b : $a <=> $b} @a ]; +} + +1; + + +=head1 AUTHOR + +Bob Hallissy L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/EBDT.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/EBDT.pm new file mode 100644 index 0000000000..6ba07a550d --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/EBDT.pm @@ -0,0 +1,311 @@ +package Font::TTF::EBDT; + +=head1 NAME + +Font::TTF::EBDT - Embeeded Bitmap Data Table + +=head1 DESCRIPTION + +Contains the metrics and bitmap image data. + +=head1 INSTANCE VARIABLES + +Only has 'bitmap' instance variable. It is an array of assosiative +array keyed by glyph-id. The element is an object which consists +of metric information and image data. + +=over 4 + +=item bitmap object + +=over 8 + +=item format + +Only 7 is supported. + +=item height + +=item width + +=item horiBearingX + +=item horiBearingY + +=item horiAdvance + +=item vertBearingX + +=item vertBearingY + +=item vertAdvance + +=item imageData + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the embedded bitmap data from the TTF file into memory. +This routine should be called _after_ {'EBLC'}->read. + +=cut + +sub read +{ + my ($self) = shift; + my ($fh); + my ($i, $dat); + my ($eblc) = $self->{' PARENT'}->{'EBLC'}; + my ($bst_array); + + $eblc->read; + $self->SUPER::read || return $self; + $fh = $self->{' INFILE'}; + + # ebdtHeader + $fh->read($dat, 4); # version + + $bst_array = $eblc->{'bitmapSizeTable'}; + + for ($i = 0; $i < $eblc->{'Num'}; $i++) + { + my ($bst) = $bst_array->[$i]; + my ($format) = $bst->{'imageFormat'}; + my ($offset) = $bst->{'imageDataOffset'}; + my ($j); + my ($ist_array) = $eblc->{'indexSubTableArray'}[$i]; + my ($bitmap) = {}; + + die "Only EBDT format 7 is implemented." unless ($format == 7); + + $self->{'bitmap'}[$i] = $bitmap; + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + my ($ista) = $ist_array->[$j]; + my ($offsetArray) = $eblc->{'indexSubTable'}[$i][$j]; + my ($p, $o0, $c); + +# if ($fh->tell != $self->{' OFFSET'} + $offset) { +# $fh->seek($self->{' OFFSET'} + $offset, 0); +# } + + $p = 0; + $o0 = $offsetArray->[$p++]; + for ($c = $ista->{'firstGlyphIndex'}; $c <= $ista->{'lastGlyphIndex'}; $c++) + { + my ($b) = {}; + my ($o1) = $offsetArray->[$p++]; + my ($len) = $o1 - $o0 - 8; + +# if ($fh->tell != $self->{' OFFSET'} + $offset + $o0) { +# $fh->seek($self->{' OFFSET'} + $offset + $o0, 0); +# } + + $fh->read($dat, 8); + ($b->{'height'}, + $b->{'width'}, + $b->{'horiBearingX'}, + $b->{'horiBearingY'}, + $b->{'horiAdvance'}, + $b->{'vertBearingX'}, + $b->{'vertBearingY'}, + $b->{'vertAdvance'}) + = unpack("cccccccc", $dat); + + $fh->read($dat, $len); + $b->{'imageData'} = $dat; + $b->{'format'} = 7; # bitmap and bigMetrics + + $bitmap->{$c} = $b; + $o0 = $o1; + } + + $offset += $o0; + } + } + + $self; +} + + +=head2 $t->update + +Update EBLC information using EBDT data. + +=cut + +sub get_regions +{ + my (@l) = @_; + my (@r) = (); + my ($e); + my ($first); + my ($last); + + $first = $l[0]; + $last = $first - 1; + foreach $e (@l) { + if ($last + 1 != $e) { # not contiguous + $r[++$#r] = [$first, $last]; + $first = $e; + } + + $last = $e; + } + + $r[++$#r] = [$first, $last]; + @r; +} + +sub update +{ + my ($self) = @_; + my ($eblc) = $self->{' PARENT'}->{'EBLC'}; + my ($bst_array) = []; + my ($offset) = 4; + my ($i); + my ($bitmap_array) = $self->{'bitmap'}; + my ($istao) = 8 + 48 * $eblc->{'Num'}; + + $eblc->{'bitmapSizeTable'} = $bst_array; + + for ($i = 0; $i < $eblc->{'Num'}; $i++) { + my ($bst) = {}; + my ($ist_array) = []; + my ($j); + my ($bitmap) = $bitmap_array->[$i]; + my (@regions) = get_regions(sort {$a <=> $b} keys (%$bitmap)); + my ($aotis) = 8 * (1+$#regions); + + $bst->{'indexFormat'} = 1; + $bst->{'imageFormat'} = 7; + $bst->{'imageDataOffset'} = $offset; + $bst->{'numberOfIndexSubTables'} = 1+$#regions; + $bst->{'indexSubTableArrayOffset'} = $istao; + $bst->{'colorRef'} = 0; + + $bst->{'startGlyphIndex'} = $regions[0][0]; + $bst->{'endGlyphIndex'} = $regions[-1][1]; + $bst->{'bitDepth'} = 1; + $bst->{'flags'} = 1; # Horizontal + $bst_array->[$i] = $bst; + + $eblc->{'indexSubTableArray'}[$i] = $ist_array; + for ($j = 0; $j <= $#regions; $j++) { + my ($ista) = {}; + my ($offsetArray) = []; + my ($p, $o0, $c); + $ist_array->[$j] = $ista; + + $ista->{'firstGlyphIndex'} = $regions[$j][0]; + $ista->{'lastGlyphIndex'} = $regions[$j][1]; + $ista->{'additionalOffsetToIndexSubtable'} = $aotis; + $eblc->{'indexSubTable'}[$i][$j] = $offsetArray; + $p = 0; + $o0 = 0; + for ($c = $regions[$j][0]; $c <= $regions[$j][1]; $c++) { + my ($b) = $bitmap->{$c}; + + $offsetArray->[$p++] = $o0; + $o0 += 8 + length($b->{'imageData'}); + } + + $offsetArray->[$p++] = $o0; + + $aotis += ($regions[$j][1] - $regions[$j][0] + 1 + 1)*4; + $offset += $o0; + + # Do we need the element of 0x10007 and absolute offset here, + # at the end of offsetArray? +# if ($j + 1 <= $#regions) { +# $offsetArray->[$p++] = 0x10007; +# $offsetArray->[$p++] = $offset; +# $aotis += 8; +# } + } + + $istao += $aotis + 8; + $bst->{'indexTablesSize'} = $aotis + 8; + } +} + +=head2 $t->out($fh) + +Outputs the bitmap data of embedded bitmap for this font. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my ($eblc) = $self->{' PARENT'}->{'EBLC'}; + my ($i); + my ($bitmap_array) = $self->{'bitmap'}; + + $fh->print(pack("N", 0x00020000)); + + for ($i = 0; $i < $eblc->{'Num'}; $i++) { + my ($j); + my ($bitmap) = $bitmap_array->[$i]; + my (@regions) = get_regions(sort {$a <=> $b} keys (%$bitmap)); + + for ($j = 0; $j <= $#regions; $j++) { + my ($c); + + for ($c = $regions[$j][0]; $c <= $regions[$j][1]; $c++) { + my ($b) = $bitmap->{$c}; + + $fh->print(pack("cccccccc", + $b->{'height'}, $b->{'width'}, + $b->{'horiBearingX'}, $b->{'horiBearingY'}, + $b->{'horiAdvance'}, $b->{'vertBearingX'}, + $b->{'vertBearingY'}, $b->{'vertAdvance'})); + $fh->print($b->{'imageData'}); + } + } + } +} + +1; + +=head1 BUGS + +Only Format 7 is implemented. XML output is not supported (yet). + +=head1 AUTHOR + +NIIBE Yutaka L. +This was written at the CodeFest Akihabara 2006 hosted by FSIJ. + +?? patch sent with licensing requirements or not? + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/EBLC.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/EBLC.pm new file mode 100644 index 0000000000..2eca08cbcc --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/EBLC.pm @@ -0,0 +1,259 @@ +package Font::TTF::EBLC; + +=head1 NAME + +Font::TTF::EBLC - Embeeded Bitmap Location Table + +=head1 DESCRIPTION + +Contains the sizes and glyph ranges of bitmaps, and the offsets to +glyph bitmap data in indexSubTables for EBDT. + +Possibly contains glyph metrics information. + +=head1 INSTANCE VARIABLES + +The information specified 'B<(R)>ead only' is read only, those +are calculated from EBDT, when it is 'update'-ed. + +=over 4 + +=item bitmapSizeTable + +An array of tables of following information + +=over 8 + +=item indexSubTableArrayOffset (R) + +=item indexTablesSize (R) + +=item numberOfIndexSubTables (R) + +=item colorRef + +=item hori + +=item vert + +=item startGlyphIndex (R) + +=item endGlyphIndex (R) + +=item ppemX + +=item ppemY + +=item bitDepth + +=item flags + +=back + +=item indexSubTableArray (R) + +An array which contains range information. + +=item indexSubTable (R) + +An array which contains offsets of EBDT table. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the location information of embedded bitmap from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($i, $dat); + my ($indexSubTableArrayOffset, + $indexTablesSize, + $numberOfIndexSubTables, + $colorRef); + my ($startGlyphIndex, + $endGlyphIndex, + $ppemX, $ppemY, + $bitDepth, $flags); + my (@hori, @vert); + my ($bst, $ista, $ist); + my ($j); + + + # eblcHeader + $fh->read($dat, 4); + $self->{'version'} = unpack("N",$dat); + + $fh->read($dat, 4); + $self->{'Num'} = unpack("N",$dat); + + # bitmapSizeTable + for ($i = 0; $i < $self->{'Num'}; $i++) { + $fh->read($dat, 16); + ($indexSubTableArrayOffset, $indexTablesSize, + $numberOfIndexSubTables, $colorRef) = unpack("NNNN", $dat); + $fh->read($dat, 12); @hori = unpack("cccccccccccc", $dat); + $fh->read($dat, 12); @vert = unpack("cccccccccccc", $dat); + + $fh->read($dat, 8); + ($startGlyphIndex, $endGlyphIndex, + $ppemX, $ppemY, $bitDepth, $flags) = unpack("nnCCCC", $dat); + + $self->{'bitmapSizeTable'}[$i] = { + 'indexSubTableArrayOffset' => $indexSubTableArrayOffset, + 'indexTablesSize' => $indexTablesSize, + 'numberOfIndexSubTables' => $numberOfIndexSubTables, + 'colorRef' => $colorRef, + 'hori' => [@hori], + 'vert' => [@vert], + 'startGlyphIndex' => $startGlyphIndex, + 'endGlyphIndex' => $endGlyphIndex, + 'ppemX' => $ppemX, + 'ppemY' => $ppemY, + 'bitDepth' => $bitDepth, + 'flags' => $flags + }; + } + + for ($i = 0; $i < $self->{'Num'}; $i++) { + my ($count, $x); + + $bst = $self->{'bitmapSizeTable'}[$i]; + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + $ista = {}; + + # indexSubTableArray + $self->{'indexSubTableArray'}[$i][$j] = $ista; + $fh->read($dat, 8); + ($ista->{'firstGlyphIndex'}, + $ista->{'lastGlyphIndex'}, + $ista->{'additionalOffsetToIndexSubtable'}) + = unpack("nnN", $dat); + } + + # indexSubTable + # indexSubHeader + $fh->read($dat, 8); + ($bst->{'indexFormat'}, + $bst->{'imageFormat'}, + $bst->{'imageDataOffset'}) = unpack("nnN", $dat); + + die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1); + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + $ista = $self->{'indexSubTableArray'}[$i][$j]; + $count = $ista->{'lastGlyphIndex'} - $ista->{'firstGlyphIndex'} + 1 + 1; + $fh->seek($self->{' OFFSET'} + $bst->{'indexSubTableArrayOffset'} + + $ista->{'additionalOffsetToIndexSubtable'} + 8, 0); + +# $count += 2 if $j < $bst->{'numberOfIndexSubTables'} - 1; + + $fh->read($dat, 4*$count); + + $self->{'indexSubTable'}[$i][$j] = [unpack("N*", $dat)]; + } + } + + $self; +} + +=head2 $t->out($fh) + +Outputs the location information of embedded bitmap for this font. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my ($bst_array) = $self->{'bitmapSizeTable'}; + + $fh->print(pack("N", 0x00020000)); + $fh->print(pack("N", $self->{'Num'})); + + for ($i = 0; $i < $self->{'Num'}; $i++) { + my ($bst) = $bst_array->[$i]; + + $fh->print(pack("NNNN", + $bst->{'indexSubTableArrayOffset'}, + $bst->{'indexTablesSize'}, + $bst->{'numberOfIndexSubTables'}, + $bst->{'colorRef'})); + $fh->print(pack("cccccccccccc", @{$bst->{'hori'}})); + $fh->print(pack("cccccccccccc", @{$bst->{'vert'}})); + $fh->print(pack("nnCCCC", $bst->{'startGlyphIndex'}, + $bst->{'endGlyphIndex'}, $bst->{'ppemX'}, + $bst->{'ppemY'}, $bst->{'bitDepth'}, $bst->{'flags'})); + } + + for ($i = 0; $i < $self->{'Num'}; $i++) { + my ($bst) = $bst_array->[$i]; + my ($j); + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + my ($ista) = $self->{'indexSubTableArray'}[$i][$j]; + + $fh->print("nnN", + $ista->{'firstGlyphIndex'}, + $ista->{'lastGlyphIndex'}, + $ista->{'additionalOffsetToIndexSubtable'}); + } + + $fh->print(pack("nnN", $bst->{'indexFormat'}, $bst->{'imageFormat'}, + $bst->{'imageDataOffset'})); + + die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1); + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + $fh->print(pack("N*", $self->{'indexSubTable'}[$i][$j])); + } + } +} + +1; + +=head1 BUGS + +Only indexFormat ==1 is implemented. XML output is not supported (yet). + +=head1 AUTHOR + +NIIBE Yutaka L. +This was written at the CodeFest Akihabara 2006 hosted by FSIJ. + +Patch sent with licensing requirements?? + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fdsc.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fdsc.pm new file mode 100644 index 0000000000..d919caeb9b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fdsc.pm @@ -0,0 +1,138 @@ +package Font::TTF::Fdsc; + +=head1 NAME + +Font::TTF::Fdsc - Font Descriptors table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +=item descriptors + +Hash keyed by descriptor tags + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh, $numDescs, $tag, $descs); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + $fh->read($dat, 4); + $self->{'version'} = TTF_Unpack("v", $dat); + + $fh->read($dat, 4); + + foreach (1 .. unpack("N", $dat)) { + $fh->read($tag, 4); + $fh->read($dat, 4); + $descs->{$tag} = ($tag eq 'nalf') ? unpack("N", $dat) : TTF_Unpack("f", $dat); + } + + $self->{'descriptors'} = $descs; + + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($descs); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $fh->print(TTF_Pack("v", $self->{'version'})); + + $descs = $self->{'descriptors'} || {}; + + $fh->print(pack("N", scalar keys %$descs)); + foreach (sort keys %$descs) { + $fh->print($_); + $fh->print(($_ eq 'nalf') ? pack("N", $descs->{$_}) : TTF_Pack("f", $descs->{$_})); + } + + $self; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($descs, $k); + + $self->read; + + $fh = 'STDOUT' unless defined $fh; + + $descs = $self->{'descriptors'}; + foreach $k (sort keys %$descs) { + if ($k eq 'nalf') { + $fh->printf("Descriptor '%s' = %d\n", $k, $descs->{$k}); + } + else { + $fh->printf("Descriptor '%s' = %f\n", $k, $descs->{$k}); + } + } + + $self; +} + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Feat.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Feat.pm new file mode 100644 index 0000000000..90f8d58f13 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Feat.pm @@ -0,0 +1,215 @@ +package Font::TTF::Feat; + +=head1 NAME + +Font::TTF::Feat - Font Features + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over 4 + +=item version + +=item features + +An array of hashes of the following form + +=over 8 + +=item feature + +feature id number + +=item name + +name index in name table + +=item exclusive + +exclusive flag + +=item settings + +hash of setting number against name string index + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +use Font::TTF::Utils; + +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the features from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($featureCount, $features); + + $self->SUPER::read_dat or return $self; + + ($self->{'version'}, $featureCount) = TTF_Unpack("vS", $self->{' dat'}); + + $features = []; + foreach (1 .. $featureCount) { + my ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex) + = TTF_Unpack("SSLSS", substr($self->{' dat'}, $_ * 12, 12)); + push @$features, + { + 'feature' => $feature, + 'name' => $nameIndex, + 'exclusive' => (($featureFlags & 0x8000) != 0), + 'settings' => { TTF_Unpack("S*", substr($self->{' dat'}, $settingTable, $nSettings * 4)) } + }; + } + $self->{'features'} = $features; + + delete $self->{' dat'}; # no longer needed, and may become obsolete + + $self; +} + +=head2 $t->out($fh) + +Writes the features to a TTF file + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($features, $numFeatures, $settings, $featuresData, $settingsData); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $features = $self->{'features'}; + $numFeatures = @$features; + + foreach (@$features) { + $settings = $_->{'settings'}; + $featuresData .= TTF_Pack("SSLSS", + $_->{'feature'}, + scalar keys %$settings, + 12 + 12 * $numFeatures + length $settingsData, + ($_->{'exclusive'} ? 0x8000 : 0x0000), + $_->{'name'}); + foreach (sort {$a <=> $b} keys %$settings) { + $settingsData .= TTF_Pack("SS", $_, $settings->{$_}); + } + } + + $fh->print(TTF_Pack("vSSL", $self->{'version'}, $numFeatures, 0, 0)); + $fh->print($featuresData); + $fh->print($settingsData); + + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($names, $features, $settings); + + $self->read; + + $names = $self->{' PARENT'}->{'name'}; + $names->read; + + $fh = 'STDOUT' unless defined $fh; + + $features = $self->{'features'}; + foreach (@$features) { + $fh->printf("Feature %d, %s, name %d # '%s'\n", + $_->{'feature'}, + ($_->{'exclusive'} ? "exclusive" : "additive"), + $_->{'name'}, + $names->{'strings'}[$_->{'name'}][1][0]{0}); + $settings = $_->{'settings'}; + foreach (sort { $a <=> $b } keys %$settings) { + $fh->printf("\tSetting %d, name %d # '%s'\n", + $_, $settings->{$_}, $names->{'strings'}[$settings->{$_}][1][0]{0}); + } + } + + $self; +} + +sub settingName +{ + my ($self, $feature, $setting) = @_; + + $self->read; + + my $names = $self->{' PARENT'}->{'name'}; + $names->read; + + my $features = $self->{'features'}; + my ($featureEntry) = grep { $_->{'feature'} == $feature } @$features; + my $featureName = $names->{'strings'}[$featureEntry->{'name'}][1][0]{0}; + my $settingName = $featureEntry->{'exclusive'} + ? $names->{'strings'}[$featureEntry->{'settings'}->{$setting}][1][0]{0} + : $names->{'strings'}[$featureEntry->{'settings'}->{$setting & ~1}][1][0]{0} + . (($setting & 1) == 0 ? " On" : " Off"); + + ($featureName, $settingName); +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Cvar.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Cvar.pm new file mode 100644 index 0000000000..3b8f9c183c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Cvar.pm @@ -0,0 +1,165 @@ +package Font::TTF::Features::Cvar; + +=head1 NAME + +Font::TTF::Features::Size - Class for Character Variants Feature Parameters + +=head1 DESCRIPTION + +Handles the Feature Parameters valus forCharacter Variants features + +=head1 INSTANCE VARIABLES + +=over 4 + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item Format + +Table format - set to 0 + +=item UINameID + +The 'name' table name ID that specifies a string (or strings, for multiple +languages) for a user-interface label for this feature + +=item TooltipNameID + +The 'name' table name ID for tooltip text for the feature + +=item SampleTextNameID + +The 'name' table name ID for sample text to illustrate the feature + +=item NumNamedParms + +The number of named parameters + +=item FirstNamedParmID + +The 'name' table name ID for the first named parameter + +=item Characters + +An array holding the unicode values of the characters for which the feature +provides glyph variants + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Utils; +use strict; + +=head2 $t->read + +Reads the Feature Params + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($off) = $self->{' OFFSET'}; + my ($dat, $i, $charcount); + $fh->seek($off, 0); + $fh->read($dat, 14); + ( $self->{'Format'} + ,$self->{'UINameID'} + ,$self->{'TooltipNameID'} + ,$self->{'SampleTextNameID'} + ,$self->{'NumNamedParm'} + ,$self->{'FirstNamedParmID'} + ,$charcount ) = TTF_Unpack("S*", $dat); + +# Now read the list of characters. Since these are 24bit insigned integers, need to +# read add a zero value byte to the front then treat as a 32bit integer + + foreach $i (0 .. $charcount-1) + { + $fh->read($dat,3); + $dat = pack("C","0") . $dat; + $self->{'Characters'}->[$i] = TTF_Unpack("L",$dat); + } + + return $self; +} + +=head2 $t->out($fh) + +Writes the FeatureParams table to the output + +=cut + + + +sub out +{ + my ($self, $fh) = @_; + my $chars = $self->{'Characters'}; + my $charcount = 0; + if ($chars) { $charcount = scalar @{$chars} } + my ($dat, $i); + + $fh->print(TTF_Pack("S*" + ,$self->{'Format'} + ,$self->{'UINameID'} + ,$self->{'TooltipNameID'} + ,$self->{'SampleTextNameID'} + ,$self->{'NumNamedParms'} + ,$self->{'FirstNamedParmID'} + ,$charcount )); + + foreach $i ( 0 .. $charcount-1) + { + $dat = substr ( TTF_Pack("L",$chars->[$i]) ,1,3); # Pack as long then remove first byte to get UINT22 + $fh->print($dat); + } + + $self; +} + +=head2 Font::TTF::Features::Sset->new() + +Creates a new FeatureParams object. +Values for INFILE and OFFSET canbe passed as parameters + +=cut + +sub new +{ + my ($class,%parms) = @_; + my ($self) = {}; + my ($p); + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +sub out_xml +{ +} + +1; + +=head1 AUTHOR + +David Raymond L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Size.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Size.pm new file mode 100644 index 0000000000..74c1ce5fb4 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Size.pm @@ -0,0 +1,131 @@ +package Font::TTF::Features::Size; + +=head1 NAME + +Font::TTF::Features::Size - Class for Size Feature Parameters + +=head1 DESCRIPTION + +Handles the Feature Parameters valus for Size features + +=head1 INSTANCE VARIABLES + +=over 4 + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item DesignSize + +Design Size in decipoints + +=item SubFID + +Identifier for the fonts in a subfamily + +=item SubFNameID + +The 'name' table name ID for the subfamily name + +=item MinSize + +Bottom end of recomended usage size range + +=item MaxSize + +Top end of recomended usage size range + + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Utils; +use strict; + +=head2 $t->read + +Reads the Feature Params + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($off) = $self->{' OFFSET'}; + my $dat; + $fh->seek($off, 0); + $fh->read($dat, 10); + + ( $self->{'DesignSize'} + ,$self->{'SubFID'} + ,$self->{'SubFNameID'} + ,$self->{'MinSize'} + ,$self->{'MaxSize'} ) = TTF_Unpack("S*", $dat); + + return $self; +} + +=head2 $t->out($fh) + +Writes the FeatureParams table to the output + +=cut + +sub out +{ + my ($self, $fh) = @_; + + $fh->print(TTF_Pack("S*" + ,$self->{'DesignSize'} + ,$self->{'SubFID'} + ,$self->{'SubFNameID'} + ,$self->{'MinSize'} + ,$self->{'MaxSize'} )); + $self; +} + +=head2 Font::TTF::Features::Sset->new() + +Creates a new FeatureParams object. Table instance variables are passed in +at this point as an associative array. + +=cut + +sub new +{ + my ($class,%parms) = @_; + my ($self) = {}; + my ($p); + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +sub out_xml +{ +} + +1; + +=head1 AUTHOR + +David Raymond L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Sset.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Sset.pm new file mode 100644 index 0000000000..78d4fe69c5 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Features/Sset.pm @@ -0,0 +1,108 @@ +package Font::TTF::Features::Sset; + +=head1 NAME + +Font::TTF::Features::Sset - Class for Stylistic Set Feature Parameters + +=head1 DESCRIPTION + +Handles the Feature Parameters valus for Stylistic Sets + +=head1 INSTANCE VARIABLES + +=over 4 + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item Version + +The minor version number, currently always 0 + +=item UINameID + +The 'name' table name ID that specifies a string (or strings, for multiple +languages) for a user-interface label for this feature + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Utils; +use strict; + +=head2 $t->read + +Reads the Feature Params + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($off) = $self->{' OFFSET'}; + my $dat; + $fh->seek($off, 0); + $fh->read($dat, 4); + ($self->{'Version'}, $self->{'UINameID'}) = TTF_Unpack("SS", $dat); + + return $self; +} + +=head2 $t->out($fh) + +Writes the FeatureParams table to the output + +=cut + +sub out +{ + my ($self, $fh) = @_; + $fh->print(TTF_Pack("S", $self->{'Version'})); + $fh->print(TTF_Pack("S", $self->{'UINameID'})); + $self; +} + +=head2 Font::TTF::Features::Sset->new() + +Creates a new FeatureParams object. +Values for INFILE and OFFSET canbe passed as parameters + +=cut + +sub new +{ + my ($class,%parms) = @_; + my ($self) = {}; + my ($p); + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +sub out_xml +{ +} + +1; + +=head1 AUTHOR + +David Raymond L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fmtx.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fmtx.pm new file mode 100644 index 0000000000..f7640a7456 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fmtx.pm @@ -0,0 +1,118 @@ +package Font::TTF::Fmtx; + +=head1 NAME + +Font::TTF::Fmtx - Font Metrics table + +=head1 DESCRIPTION + +This is a simple table with just standards specified instance variables + +=head1 INSTANCE VARIABLES + + version + glyphIndex + horizontalBefore + horizontalAfter + horizontalCaretHead + horizontalCaretBase + verticalBefore + verticalAfter + verticalCaretHead + verticalCaretBase + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'glyphIndex' => 'L', + 'horizontalBefore' => 'c', + 'horizontalAfter' => 'c', + 'horizontalCaretHead' => 'c', + 'horizontalCaretBase' => 'c', + 'verticalBefore' => 'c', + 'verticalAfter' => 'c', + 'verticalCaretHead' => 'c', + 'verticalCaretBase' => 'c'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory as instance variables + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + init unless defined $fields{'glyphIndex'}; + $self->{' INFILE'}->read($dat, 16); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $fh->print(TTF_Out_Fields($self, \%fields, 16)); + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Font.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Font.pm new file mode 100644 index 0000000000..2dd5f22355 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Font.pm @@ -0,0 +1,927 @@ +package Font::TTF::Font; + +=head1 NAME + +Font::TTF::Font - Memory representation of a font + +=head1 SYNOPSIS + +Here is the regression test (you provide your own font). Run it once and then +again on the output of the first run. There should be no differences between +the outputs of the two runs. + + $f = Font::TTF::Font->open($ARGV[0]); + + # force a read of all the tables + $f->tables_do(sub { $_[0]->read; }); + + # force read of all glyphs (use read_dat to use lots of memory!) + # $f->{'loca'}->glyphs_do(sub { $_[0]->read; }); + $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; }); + # NB. no need to $g->update since $f->{'glyf'}->out will do it for us + + $f->out($ARGV[1]); + $f->release; # clear up memory forcefully! + +=head1 DESCRIPTION + +A Truetype font consists of a header containing a directory of tables which +constitute the rest of the file. This class holds that header and directory and +also creates objects of the appropriate type for each table within the font. +Note that it does not read each table into memory, but creates a short reference +which can be read using the form: + + $f->{$tablename}->read; + +Classes are included that support many of the different TrueType tables. For +those for which no special code exists, the table type C is used, which +defaults to L. The current tables which are supported are: + + table Font::TTF::Table - for unknown tables + EBDT Font::TTF::EBDT + EBLC Font::TTF::EBLC + Feat Font::TTF::GrFeat + GDEF Font::TTF::GDEF + GPOS Font::TTF::GPOS + GSUB Font::TTF::GSUB + Glat Font::TTF::Glat + Gloc Font::TTF::Gloc + LTSH Font::TTF::LTSH + OS/2 Font::TTF::OS_2 + PCLT Font::TTF::PCLT + Sill Font::TTF::Sill + Silf Font::TTF::Silf + bsln Font::TTF::Bsln + cmap Font::TTF::Cmap - see also Font::TTF::OldCmap + cvt Font::TTF::Cvt_ + fdsc Font::TTF::Fdsc + feat Font::TTF::Feat + fmtx Font::TTF::Fmtx + fpgm Font::TTF::Fpgm + glyf Font::TTF::Glyf - see also Font::TTF::Glyph + hdmx Font::TTF::Hdmx + head Font::TTF::Head + hhea Font::TTF::Hhea + hmtx Font::TTF::Hmtx + kern Font::TTF::Kern - see alternative Font::TTF::AATKern + loca Font::TTF::Loca + maxp Font::TTF::Maxp + mort Font::TTF::Mort - see also Font::TTF::OldMort + name Font::TTF::Name + post Font::TTF::Post + prep Font::TTF::Prep + prop Font::TTF::Prop + vhea Font::TTF::Vhea + vmtx Font::TTF::Vmtx + DSIG FONT::TTF::DSIG + +Links are: + +L +L L L +L L L L L L +L L L L L L L +L L L L L +L L L L L +L L L L L +L L L L L +L L L +L + + +=head1 INSTANCE VARIABLES + +Instance variables begin with a space (and have lengths greater than the 4 +characters which make up table names). + +=over + +=item nocsum + +This is used during output to disable the creation of the file checksum in the +head table. For example, during DSIG table creation, this flag will be set to +ensure that the file checksum is left at zero. + +=item noharmony + +If set, do not harmonize the script and lang trees of GPOS and GSUB tables. See L for more info. + +=item nocompress + +Is the default value controlling WOFF output table compression. If undef, all tables will be compressed if there is +a size benefit in doing so. +It may be set to an array of tagnames naming tables that should not be compressed, or to a scalar integer specifying a +table size threshold below which tables will not be compressed. +Note that individual L objects may override this default. See L for more info. + +=item fname (R) + +Contains the filename of the font which this object was read from. + +=item INFILE (P) + +The file handle which reflects the source file for this font. + +=item OFFSET (P) + +Contains the offset from the beginning of the read file of this particular +font directory, thus providing support for TrueType Collections. + +=item WOFF + +Contains a reference to a C object. + +=back + +=head1 METHODS + +=cut + +use IO::File; + +use strict; +use vars qw(%tables $VERSION $dumper); +use Symbol(); + +require 5.004; + +my $havezlib = eval {require Compress::Zlib}; + +$VERSION = 0.39; # MJPH 2-FEB-2008 Add DSIG table +# $VERSION = 0.38; # MJPH 2-FEB-2008 Add Sill table +# $VERSION = 0.37; # MJPH 7-OCT-2005 Force hhea update if dirty, give more OS/2 stuff in update +# $VERSION = 0.36; # MJPH 19-AUG-2005 Change cmap::reverse api to be opts based +# $VERSION = 0.35; # MJPH 4-MAY-2004 Various fixes to OpenType stuff, separate off scripts +# $VERSION = 0.34; # MJPH 22-MAY-2003 Update PSNames to latest AGL +# $VERSION = 0.33; # MJPH 9-OCT-2002 Support CFF OpenType (just by version=='OTTO'?!) +# $VERSION = 0.32; # MJPH 2-OCT-2002 Bug fixes to TTFBuilder, new methods and some +# extension table support in Ttopen and Coverage +# $VERSION = 0.31; # MJPH 1-JUL-2002 fix read format 12 cmap (bart@cs.pdx.edu) +# improve surrogate support in ttfremap +# fix return warn to return warn,undef +# ensure correct indexToLocFormat +# $VERSION = 0.30; # MJPH 28-MAY-2002 add updated release +# $VERSION = 0.29; # MJPH 9-APR-2002 update ttfbuilder, sort out surrogates +# $VERSION = 0.28; # MJPH 13-MAR-2002 update ttfbuilder, add Font::TTF::Cmap::ms_enc() +# $VERSION = 0.27; # MJPH 6-FEB-2002 update ttfbuilder, support no fpgm, no more __DATA__ +# $VERSION = 0.26; # MJPH 19-SEP-2001 Update ttfbuilder +# $VERSION = 0.25; # MJPH 18-SEP-2001 problems in update of head +# $VERSION = 0.24; # MJPH 1-AUG-2001 Sort out update +# $VERSION = 0.23; # GST 30-MAY-2001 Memory leak fixed +# $VERSION = 0.22; # MJPH 09-APR-2001 Ensure all of AAT stuff included +# $VERSION = 0.21; # MJPH 23-MAR-2001 Improve Opentype support +# $VERSION = 0.20; # MJPH 13-JAN-2001 Add XML output and some of XML input, AAT & OT tables +# $VERSION = 0.19; # MJPH 29-SEP-2000 Add cmap::is_unicode, debug makefile.pl +# $VERSION = 0.18; # MJPH 21-JUL-2000 Debug Utils::TTF_bininfo +# $VERSION = 0.17; # MJPH 16-JUN-2000 Add utf8 support to names +# $VERSION = 0.16; # MJPH 26-APR-2000 Mark read tables as read, tidy up POD +# $VERSION = 0.15; # MJPH 5-FEB-2000 Ensure right versions released +# $VERSION = 0.14; # MJPH 11-SEP-1999 Sort out Unixisms, agian! +# $VERSION = 0.13; # MJPH 9-SEP-1999 Add empty, debug update_bbox +# $VERSION = 0.12; # MJPH 22-JUL-1999 Add update_bbox +# $VERSION = 0.11; # MJPH 7-JUL-1999 Don't store empties in cmaps +# $VERSION = 0.10; # MJPH 21-JUN-1999 Use IO::File +# $VERSION = 0.09; # MJPH 9-JUN-1999 Add 5.004 require, minor tweeks in cmap +# $VERSION = 0.08; # MJPH 19-MAY-1999 Sort out line endings for Unix +# $VERSION = 0.07; # MJPH 28-APR-1999 Get the regression tests to work +# $VERSION = 0.06; # MJPH 26-APR-1999 Start to add to CVS, correct MANIFEST.SKIP +# $VERSION = 0.05; # MJPH 13-APR-1999 See changes for 0.05 +# $VERSION = 0.04; # MJPH 13-MAR-1999 Tidy up Tarball +# $VERSION = 0.03; # MJPH 9-MAR-1999 Move to Font::TTF for CPAN +# $VERSION = 0.02; # MJPH 12-FEB-1999 Add support for ' nocsum' for DSIGS +# $VERSION = 0.0001; + +%tables = ( + 'table' => 'Font::TTF::Table', + 'DSIG' => 'Font::TTF::DSIG', + 'EBDT' => 'Font::TTF::EBDT', + 'EBLC' => 'Font::TTF::EBLC', + 'Feat' => 'Font::TTF::GrFeat', + 'GDEF' => 'Font::TTF::GDEF', + 'Glat' => 'Font::TTF::Glat', + 'Gloc' => 'Font::TTF::Gloc', + 'GPOS' => 'Font::TTF::GPOS', + 'GSUB' => 'Font::TTF::GSUB', + 'Glat' => 'Font::TTF::Glat', + 'Gloc' => 'Font::TTF::Gloc', + 'LTSH' => 'Font::TTF::LTSH', + 'OS/2' => 'Font::TTF::OS_2', + 'PCLT' => 'Font::TTF::PCLT', + 'Sill' => 'Font::TTF::Sill', + 'Silf' => 'Font::TTF::Silf', + 'bsln' => 'Font::TTF::Bsln', + 'cmap' => 'Font::TTF::Cmap', + 'cvt ' => 'Font::TTF::Cvt_', + 'fdsc' => 'Font::TTF::Fdsc', + 'feat' => 'Font::TTF::Feat', + 'fmtx' => 'Font::TTF::Fmtx', + 'fpgm' => 'Font::TTF::Fpgm', + 'glyf' => 'Font::TTF::Glyf', + 'hdmx' => 'Font::TTF::Hdmx', + 'head' => 'Font::TTF::Head', + 'hhea' => 'Font::TTF::Hhea', + 'hmtx' => 'Font::TTF::Hmtx', + 'kern' => 'Font::TTF::Kern', + 'loca' => 'Font::TTF::Loca', + 'maxp' => 'Font::TTF::Maxp', + 'mort' => 'Font::TTF::Mort', + 'name' => 'Font::TTF::Name', + 'post' => 'Font::TTF::Post', + 'prep' => 'Font::TTF::Prep', + 'prop' => 'Font::TTF::Prop', + 'vhea' => 'Font::TTF::Vhea', + 'vmtx' => 'Font::TTF::Vmtx', + ); + +# This is special code because I am fed up of every time I x a table in the debugger +# I get the whole font printed. Thus substitutes my 3 line change to dumpvar into +# the debugger. Clunky, but nice. You are welcome to a copy if you want one. + +BEGIN { + my ($p); + + foreach $p (@INC) + { + if (-f "$p/mydumpvar.pl") + { + $dumper = 'mydumpvar.pl'; + last; + } + } + $dumper ||= 'dumpvar.pl'; +} + +sub main::dumpValue +{ do $dumper; &main::dumpValue; } + + +=head2 Font::TTF::Font->AddTable($tablename, $class) + +Adds the given class to be used when representing the given table name. It also +'requires' the class for you. + +=cut + +sub AddTable +{ + my ($class, $table, $useclass) = @_; + + $tables{$table} = $useclass; +# $useclass =~ s|::|/|oig; +# require "$useclass.pm"; +} + + +=head2 Font::TTF::Font->Init + +For those people who like making fonts without reading them. This subroutine +will require all the table code for the various table types for you. Not +needed if using Font::TTF::Font::read before using a table. + +=cut + +sub Init +{ + my ($class) = @_; + my ($t); + + foreach $t (values %tables) + { + $t =~ s|::|/|oig; + require "$t.pm"; + } +} + +=head2 Font::TTF::Font->new(%props) + +Creates a new font object and initialises with the given properties. This is +primarily for use when a TTF is embedded somewhere. Notice that the properties +are automatically preceded by a space when inserted into the object. This is in +order that fields do not clash with tables. + +=cut + +sub new +{ + my ($class, %props) = @_; + my ($self) = {}; + + bless $self, $class; + + foreach (keys %props) + { $self->{" $_"} = $props{$_}; } + $self; +} + + +=head2 Font::TTF::Font->open($fname) + +Reads the header and directory for the given font file and creates appropriate +objects for each table in the font. + +=cut + +sub open +{ + my ($class, $fname) = @_; + my ($fh); + my ($self) = {}; + + unless (ref($fname)) + { + $fh = IO::File->new($fname) or return undef; + binmode $fh; + } else + { $fh = $fname; } + + $self->{' INFILE'} = $fh; + $self->{' fname'} = $fname; + $self->{' OFFSET'} = 0; + bless $self, $class; + + $self->read; +} + +=head2 $f->read + +Reads a Truetype font directory starting from location C<$self->{' OFFSET'}> in the file. +This has been separated from the C function to allow support for embedded +TTFs for example in TTCs. Also reads the C and C tables immediately. + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($dat, $i, $ver, $dir_num, $type, $name, $check, $off, $len, $t); + my ($iswoff, $woffLength, $sfntSize, $zlen); # needed for WOFF files + + $fh->seek($self->{' OFFSET'}, 0); + $fh->read($dat, 4); + $ver = unpack("N", $dat); + $iswoff = ($ver == unpack('N', 'wOFF')); + if ($iswoff) + { + require Font::TTF::Woff; + my $woff = Font::TTF::Woff->new(PARENT => $self); + $fh->read($dat, 32); + ($ver, $woffLength, $dir_num, undef, $sfntSize, $woff->{'majorVersion'}, $woff->{'minorVersion'}, + $off, $zlen, $len) = unpack('NNnnNnnNNN', $dat); + # TODO: According to WOFF spec we should verify $woffLength and $sfntSize, and fail if the values are wrong. + if ($off) + { + # Font has metadata + if ($off + $zlen > $woffLength) + { + warn "invalid WOFF header in $self->{' fname'}: meta data beyond end."; + return undef; + } + require Font::TTF::Woff::MetaData; + $woff->{'metaData'} = Font::TTF::Woff::MetaData->new( + PARENT => $woff, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len, + ZLENGTH => $zlen); + } + + $fh->read($dat, 8); + ($off, $len) = unpack('NN', $dat); + if ($off) + { + # Font has private data + if ($off + $len > $woffLength) + { + warn "invalid WOFF header in $self->{' fname'}: private data beyond end."; + return undef; + } + require Font::TTF::Woff::PrivateData; + $woff->{'privateData'} = Font::TTF::Woff::PrivateData->new( + PARENT => $woff, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len); + } + + $self->{' WOFF'} = $woff; + } + else + { + $fh->read($dat, 8); + $dir_num = unpack("n", $dat); + } + + $ver == 1 << 16 # TrueType outlines + || $ver == unpack('N', 'OTTO') # 0x4F54544F CFF outlines + || $ver == unpack('N', 'true') # 0x74727565 Mac sfnts + or return undef; # else unrecognized type + + + for ($i = 0; $i < $dir_num; $i++) + { + $fh->read($dat, $iswoff ? 20 : 16) || die "Reading table entry"; + if ($iswoff) + { + ($name, $off, $zlen, $len, $check) = unpack("a4NNNN", $dat); + if ($off + $zlen > $woffLength || $zlen > $len) + { + my $err; + $err = "Offset + compressed length > total length. " if $off + $zlen > $woffLength; + $err = "Compressed length > uncompressed length. " if $zlen > $len; + warn "invalid WOFF '$name' table in $self->{' fname'}: $err\n"; + return undef; + } + } + else + { + ($name, $check, $off, $len) = unpack("a4NNN", $dat); + $zlen = $len; + } + $self->{$name} = $self->{' PARENT'}->find($self, $name, $check, $off, $len) and next + if (defined $self->{' PARENT'}); + $type = $tables{$name} || 'Font::TTF::Table'; + $t = $type; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $self->{$name} = $type->new(PARENT => $self, + NAME => $name, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len, + ZLENGTH => $zlen, + CSUM => $check); + } + + foreach $t ('head', 'maxp') + { $self->{$t}->read if defined $self->{$t}; } + + $self; +} + + +=head2 $f->out($fname [, @tablelist]) + +Writes a TTF file consisting of the tables in tablelist. The list is checked to +ensure that only tables that exist are output. (This means that you cannot have +non table information stored in the font object with key length of exactly 4) + +In many cases the user simply wants to output all the tables in alphabetical order. +This can be done by not including a @tablelist, in which case the subroutine will +output all the defined tables in the font in alphabetical order. + +Returns $f on success and undef on failure, including warnings. + +All output files must include the C table. + +=cut + +sub out +{ + my ($self, $fname, @tlist) = @_; + my ($fh); + my ($dat, $numTables, $sRange, $eSel); + my (%dir, $k, $mloc, $count); + my ($csum, $lsum, $msum, $loc, $oldloc, $len, $shift); + + my ($iswoff); # , $woffLength, $sfntSize, $zlen); # needed for WOFF files + + unless (ref($fname)) + { + $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname for writing"), undef; + binmode $fh; + } else + { $fh = $fname; } + + $self->{' oname'} = $fname; + $self->{' outfile'} = $fh; + + if ($self->{' wantsig'}) + { + $self->{' nocsum'} = 1; +# $self->{'head'}{'checkSumAdjustment'} = 0; + $self->{' tempDSIG'} = $self->{'DSIG'}; + $self->{' tempcsum'} = $self->{'head'}{' CSUM'}; + delete $self->{'DSIG'}; + @tlist = sort {$self->{$a}{' OFFSET'} <=> $self->{$b}{' OFFSET'}} + grep (length($_) == 4 && defined $self->{$_}, keys %$self) if ($#tlist < 0); + } + elsif ($#tlist < 0) + { @tlist = sort keys %$self; } + + @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist); + $numTables = $#tlist + 1; + $numTables++ if ($self->{' wantsig'}); + + if ($iswoff) + { + } + else + { + ($numTables, $sRange, $eSel, $shift) = Font::TTF::Utils::TTF_bininfo($numTables, 16); + $dat = pack("Nnnnn", 1 << 16, $numTables, $sRange, $eSel, $shift); + $fh->print($dat); + $msum = unpack("%32N*", $dat); + } + +# reserve place holders for each directory entry + foreach $k (@tlist) + { + $dir{$k} = pack("A4NNN", $k, 0, 0, 0); + $fh->print($dir{$k}); + } + + $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'}); + + $loc = $fh->tell(); + if ($loc & 3) + { + $fh->print(substr("\000" x 4, $loc & 3)); + $loc += 4 - ($loc & 3); + } + + foreach $k (@tlist) + { + $oldloc = $loc; + if ($iswoff && $havezlib && + # output font is WOFF -- should we try to compress this table? + exists ($self->{$k}->{' nocompress'}) ? $self->{$k}->{' nocompress'} != -1 : + ref($self->{' nocompress'}) eq 'ARRAY' ? !exists($self->{' nocompress'}{$k}) : + ref($self->{' nocompress'}) eq 'SCALAR' && $self->{' nocompress'} != -1) + { + # Yes -- we may want to compress this table. + # Create string file handle to hold uncompressed table + my $dat; + my $fh2 = IO::String->new($dat); + binmode $fh2; + $self->{$k}->out($fh2); + $len = $fh2->tell(); + close $fh2; + + # Is table long enough to try compression? + unless ( + exists ($self->{$k}->{' nocompress'}) && $len <= $self->{$k}->{' nocompress'} || + ref($self->{' nocompress'}) eq 'SCALAR' && $len <= $self->{' nocompress'}) + { + # Yes -- so compress and check lengths: + my $zdat = Compress::Zlib::compress($dat); + my $zlen = bytes::length($zdat); + if ($zlen < $len) + { + # write the compressed $zdat + + } + else + { + # write the uncompressed $dat + } + } + else + { + # write uncompressed $dat + } + + + } + else + { + # Output table normally + $self->{$k}->out($fh); + $loc = $fh->tell(); + $len = $loc - $oldloc; + } + if ($loc & 3) + { + $fh->print(substr("\000" x 4, $loc & 3)); + $loc += 4 - ($loc & 3); + } + $fh->seek($oldloc, 0); + $csum = 0; $mloc = $loc; + while ($mloc > $oldloc) + { + $count = ($mloc - $oldloc > 4096) ? 4096 : $mloc - $oldloc; + $fh->read($dat, $count); + $csum += unpack("%32N*", $dat); +# this line ensures $csum stays within 32 bit bounds, clipping as necessary + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + $mloc -= $count; + } + $dir{$k} = pack("A4NNN", $k, $csum, $oldloc, $len); + $msum += $csum + unpack("%32N*", $dir{$k}); + while ($msum > 0xffffffff) { $msum -= 0xffffffff; $msum--; } + $fh->seek($loc, 0); + } + + unless ($self->{' nocsum'}) # assuming we want a file checksum + { +# Now we need to sort out the head table's checksum + if (!defined $dir{'head'}) + { # you have to have a head table + $fh->close(); + return warn("No 'head' table to output in $fname"), undef; + } + ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'}); + $fh->seek($loc + 8, 0); + $fh->read($dat, 4); + $lsum = unpack("N", $dat); + if ($lsum != 0) + { + $csum -= $lsum; + if ($csum < 0) { $csum += 0xffffffff; $csum++; } + $msum -= $lsum * 2; # twice (in head and in csum) + while ($msum < 0) { $msum += 0xffffffff; $msum++; } + } + $lsum = 0xB1B0AFBA - $msum; + $fh->seek($loc + 8, 0); + $fh->print(pack("N", $lsum)); + $dir{'head'} = pack("A4NNN", 'head', $csum, $loc, $len); + } elsif ($self->{' wantsig'}) + { + if (!defined $dir{'head'}) + { # you have to have a head table + $fh->close(); + return warn("No 'head' table to output in $fname"), undef; + } + ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'}); + $fh->seek($loc + 8, 0); + $fh->print(pack("N", 0)); +# $dir{'head'} = pack("A4NNN", 'head', $self->{' tempcsum'}, $loc, $len); + } + +# Now we can output the directory again + if ($self->{' wantsig'}) + { @tlist = sort @tlist; } + $fh->seek(12, 0); + foreach $k (@tlist) + { $fh->print($dir{$k}); } + $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'}); + $fh->close(); + $self; +} + + +=head2 $f->out_xml($filename [, @tables]) + +Outputs the font in XML format + +=cut + +sub out_xml +{ + my ($self, $fname, @tlist) = @_; + my ($fh, $context, $numTables, $k); + + $context->{'indent'} = ' ' x 4; + + unless (ref($fname)) + { + $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname"), undef; + binmode $fh; + } else + { $fh = $fname; } + + unless (scalar @tlist > 0) + { + @tlist = sort keys %$self; + @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist); + } + $numTables = $#tlist + 1; + + $context->{'fh'} = $fh; + $fh->print("\n"); + $fh->print("\n\n"); + + foreach $k (@tlist) + { + $fh->print("
\n"); + $self->{$k}->out_xml($context, $context->{'indent'}); + $fh->print("
\n"); + } + + $fh->print("\n"); + $fh->close; + $self; +} + + +=head2 $f->XML_start($context, $tag, %attrs) + +Handles start messages from the XML parser. Of particular interest to us are and +. + +=cut + +sub XML_start +{ + my ($self, $context, $tag, %attrs) = @_; + my ($name, $type, $t); + + if ($tag eq 'font') + { $context->{'tree'}[-1] = $self; } + elsif ($tag eq 'table') + { + $name = $attrs{'name'}; + unless (defined $self->{$name}) + { + $type = $tables{$name} || 'Font::TTF::Table'; + $t = $type; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $self->{$name} = $type->new('PARENT' => $self, 'NAME' => $name, 'read' => 1); + } + $context->{'receiver'} = ($context->{'tree'}[-1] = $self->{$name}); + } + $context; +} + + +sub XML_end +{ + my ($self) = @_; + my ($context, $tag, %attrs) = @_; + my ($i); + + return undef unless ($tag eq 'table' && $attrs{'name'} eq 'loca'); + if (defined $context->{'glyphs'} && $context->{'glyphs'} ne $self->{'loca'}{'glyphs'}) + { + for ($i = 0; $i <= $#{$context->{'glyphs'}}; $i++) + { $self->{'loca'}{'glyphs'}[$i] = $context->{'glyphs'}[$i] if defined $context->{'glyphs'}[$i]; } + $context->{'glyphs'} = $self->{'loca'}{'glyphs'}; + } + return undef; +} + +=head2 $f->update + +Sends update to all the tables in the font and then resets all the isDirty +flags on each table. The data structure in now consistent as a font (we hope). + +=cut + +sub update +{ + my ($self) = @_; + + $self->tables_do(sub { $_[0]->update; }); + + $self; +} + +=head2 $f->dirty + +Dirties all the tables in the font + +=cut + +sub dirty +{ $_[0]->tables_do(sub { $_[0]->dirty; }); $_[0]; } + +=head2 $f->tables_do(&func [, tables]) + +Calls &func for each table in the font. Calls the table in alphabetical sort +order as per the order in the directory: + + &func($table, $name); + +May optionally take a list of table names in which case func is called +for each of them in the given order. + +=cut + +sub tables_do +{ + my ($self, $func, @tables) = @_; + my ($t); + + foreach $t (@tables ? @tables : sort grep {length($_) == 4} keys %$self) + { &$func($self->{$t}, $t); } + $self; +} + + +=head2 $f->release + +Releases ALL of the memory used by the TTF font and all of its component +objects. After calling this method, do B expect to have anything left in +the C object. + +B, that it is important that you call this method on any +C object when you wish to destruct it and free up its memory. +Internally, we track things in a structure that can result in circular +references, and without calling 'C' these will not properly get +cleaned up by Perl. Once you've called this method, though, don't expect to be +able to do anything else with the C object; it'll have B +internal state whatsoever. + +B As part of the brute-force cleanup done here, this method +will throw a warning message whenever unexpected key values are found within +the C object. This is done to help ensure that any unexpected +and unfreed values are brought to your attention so that you can bug us to keep +the module updated properly; otherwise the potential for memory leaks due to +dangling circular references will exist. + +=cut + +sub release +{ + my ($self) = @_; + +# delete stuff that we know we can, here + + my @tofree = map { delete $self->{$_} } keys %{$self}; + + while (my $item = shift @tofree) + { + my $ref = ref($item); + if (UNIVERSAL::can($item, 'release')) + { $item->release(); } + elsif ($ref eq 'ARRAY') + { push( @tofree, @{$item} ); } + elsif (UNIVERSAL::isa($ref, 'HASH')) + { release($item); } + } + +# check that everything has gone - it better had! + foreach my $key (keys %{$self}) + { warn ref($self) . " still has '$key' key left after release.\n"; } +} + +1; + +=head1 BUGS + +Bugs abound aplenty I am sure. There is a lot of code here and plenty of scope. +The parts of the code which haven't been implemented yet are: + +=over 4 + +=item Post + +Version 4 format types are not supported yet. + +=item Cmap + +Format type 2 (MBCS) has not been implemented yet and therefore may cause +somewhat spurious results for this table type. + +=item Kern + +Only type 0 & type 2 tables are supported (type 1 & type 3 yet to come). + +=item TTC and WOFF + +The current Font::TTF::Font::out method does not support the writing of TrueType +Collections or WOFF files. + +=item DSIG + +Haven't figured out how to correctly calculate and output digital signature (DSIG) table + +=back + +In addition there are weaknesses or features of this module library + +=over 4 + +=item * + +There is very little (or no) error reporting. This means that if you have +garbled data or garbled data structures, then you are liable to generate duff +fonts. + +=item * + +The exposing of the internal data structures everywhere means that doing +radical re-structuring is almost impossible. But it stop the code from becoming +ridiculously large. + +=back + +Apart from these, I try to keep the code in a state of "no known bugs", which +given the amount of testing this code has had, is not a guarantee of high +quality, yet. + +For more details see the appropriate class files. + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fpgm.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fpgm.pm new file mode 100644 index 0000000000..b51adb1bf2 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Fpgm.pm @@ -0,0 +1,97 @@ +package Font::TTF::Fpgm; + +=head1 NAME + +Font::TTF::Fpgm - Font program in a TrueType font. Called when a font is loaded + +=head1 DESCRIPTION + +This is a minimal class adding nothing beyond a table, but is a repository +for fpgm type information for those processes brave enough to address hinting. + +=cut + +use strict; +use vars qw(@ISA $VERSION); + +@ISA = qw(Font::TTF::Table); + +$VERSION = 0.0001; + +=head2 $t->read + +Reading this table is simply a process of reading all the data into the RAM +copy. Nothing more is done with it. + +=cut + +sub read +{ + $_[0]->read_dat; + $_[0]->{' read'} = 1; +} + +=head2 $t->out_xml($context, $depth) + +Outputs Fpgm program as XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($dat); + + $self->read; + $dat = Font::TTF::Utils::XML_binhint($self->{' dat'}); + $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg; + $fh->print("$depth\n"); + $fh->print("$depth$context->{'indent'}$dat"); + $fh->print("$depth\n"); + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Parse all that hinting code + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'code') + { + $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'}); + return $context; + } else + { return $self->SUPER::XML_end(@_); } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GDEF.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GDEF.pm new file mode 100644 index 0000000000..12005d43f5 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GDEF.pm @@ -0,0 +1,476 @@ +package Font::TTF::GDEF; + +=head1 NAME + +Font::TTF::GDEF - Opentype GDEF table support + +=head1 DESCRIPTION + +The GDEF table contains various global lists of information which are apparantly +used in other places in an OpenType renderer. But precisely where is open to +speculation... + +=head1 INSTANCE VARIABLES + +There are up to 5 tables in the GDEF table, each with their own structure: + +=over 4 + +=item GLYPH + +This is an L Class Definition table containing information +as to what type each glyph is. + +=item ATTACH + +The attach table consists of a coverage table and then attachment points for +each glyph in the coverage table: + +=over 8 + +=item COVERAGE + +This is a coverage table + +=item POINTS + +This is an array of point elements. Each element is an array of curve points +corresponding to the attachment points on that glyph. The order of the curve points +in the array corresponds to the attachment point number specified in the MARKS +coverage table (see below). + +=back + +=item LIG + +This contains the ligature caret positioning information for ligature glyphs + +=over 8 + +=item COVERAGE + +A coverage table to say which glyphs are ligatures + +=item LIGS + +An array of elements for each ligature. Each element is an array of information +for each caret position in the ligature (there being number of components - 1 of +these, generally) + +=over 12 + +=item FMT + +This is the format of the information and is important to provide the semantics +for the value. This value must be set correctly before output + +=item VAL + +The value which has meaning according to FMT + +=item DEVICE + +For FMT = 3, a device table is also referenced which is stored here + +=back + +=back + +=item MARKS + +This class definition table defines the classes of mark glyphs that can be selected +for processing using the MarkAttachmentType field of lookup FLAG words. + +=item MARKSETS + +Contains an array of coverage tables indexed by the FILTER value of a lookup. + +=back + + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Table; +use Font::TTF::Utils; +use Font::TTF::Ttopen; +use vars qw(@ISA $new_gdef); + +@ISA = qw(Font::TTF::Table); +$new_gdef = 1; # Prior to 2012-07, this config variable did more than it does today. + # Currently all it does is force the GDEF to include a field in the + # header for the MARKS class definition. That is, it makes sure the + # font is compatible with at least the OT 1.2 specification. + +=head2 $t->read + +Reads the table into the data structure + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($boff) = $self->{' OFFSET'}; + my ($dat, $goff, $aoff, $loff, $macoff, $mgsoff, $r, $s, $bloc); + + $bloc = $fh->tell(); + $fh->read($dat, 10); + ($self->{'Version'}, $goff, $aoff, $loff) = TTF_Unpack('LS3', $dat); + + # GDEF is the ONLY table that uses a ULONG for version rather than a Fixed or USHORT, + # and this seems to clearly be a hack. + # OpenType 1.2 introduced MarkAttachClassDef but left the table version at 0x00010000 + # Up through OpenType 1.5, the Version field was typed as Fixed. + # OpenType 1.6 introduced MarkGlyphSetsDef and bumped table version to 0x00010002 (sic) + # and changed it to ULONG. + + + # Thus some trickery here to read the table correctly! + + if ($self->{'Version'} > 0x00010000) + { + # Ok, header guaranteed to have both MarAttachClassDef MarkGlyphSetsDef + $fh->read($dat, 4); + ($macoff, $mgsoff) = TTF_Unpack('S2', $dat); + } + else + { + # What I've seen in other code (examples: + # http://skia.googlecode.com/svn/trunk/third_party/harfbuzz/src/harfbuzz-gdef.c and + # http://doxygen.reactos.org/d0/d55/otvalid_8h_a0487daffceceb98ba425bbf2806fbaff.html + # ) is to read GPOS and GDEF and see if any lookups have a + # MarkAttachType in the upper byte of their flag word and if so then assume that the + # MarkAttachClassDef field is in the header. While this is probably the most + # reliable way to do it, it would require us to read GSUB and GPOS. + # Prior to 2012-07 what we did is depend on our $new_gdef class variable to tell us + # whether to assume a MarkAttachClassDef. + # What we do now is see if the header actually has room for the MarkAttachClassDef field. + + my $minOffset = $self->{' LENGTH'}; + foreach ($goff, $aoff, $loff) + { + $minOffset = $_ if $_ > 0 && $_ < $minOffset; + } + if ($minOffset >= 12) + { + # There is room for the field, so read it: + $fh->read($dat, 2); + ($macoff) = TTF_Unpack('S', $dat); + # Sanity check: + $macoff = 0 if $macoff >= $self->{' LENGTH'}; + } + } + + if ($goff > 0) + { + $fh->seek($goff + $boff, 0); + $self->{'GLYPH'} = Font::TTF::Coverage->new(0)->read($fh); + } + + if ($aoff > 0) + { + my ($off, $gcount, $pcount); + + $fh->seek($aoff + $boff, 0); + $fh->read($dat, 4); + ($off, $gcount) = TTF_Unpack('SS', $dat); + $fh->read($dat, $gcount << 1); + + $fh->seek($aoff + $boff + $off, 0); + $self->{'ATTACH'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh); + + foreach $r (TTF_Unpack('S*', $dat)) + { + unless ($r) + { + push (@{$self->{'ATTACH'}{'POINTS'}}, []); + next; + } + $fh->seek($aoff + $boff + $r, 0); + $fh->read($dat, 2); + $pcount = TTF_Unpack('S', $dat); + $fh->read($dat, $pcount << 1); + push (@{$self->{'ATTACH'}{'POINTS'}}, [TTF_Unpack('S*', $dat)]); + } + } + + if ($loff > 0) + { + my ($lcount, $off, $ccount, $srec, $comp); + + $fh->seek($loff + $boff, 0); + $fh->read($dat, 4); + ($off, $lcount) = TTF_Unpack('SS', $dat); + $fh->read($dat, $lcount << 1); + + $fh->seek($off + $loff + $boff, 0); + $self->{'LIG'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh); + + foreach $r (TTF_Unpack('S*', $dat)) + { + $fh->seek($r + $loff + $boff, 0); + $fh->read($dat, 2); + $ccount = TTF_Unpack('S', $dat); + $fh->read($dat, $ccount << 1); + + $srec = []; + foreach $s (TTF_Unpack('S*', $dat)) + { + $comp = {}; + $fh->seek($s + $r + $loff + $boff, 0); + $fh->read($dat, 4); + ($comp->{'FMT'}, $comp->{'VAL'}) = TTF_Unpack('S*', $dat); + if ($comp->{'FMT'} == 3) + { + $fh->read($dat, 2); + $off = TTF_Unpack('S', $dat); + if (defined $self->{' CACHE'}{$off + $s + $r + $loff}) + { $comp->{'DEVICE'} = $self->{' CACHE'}{$off + $s + $r + $loff}; } + else + { + $fh->seek($off + $s + $r + $loff + $boff, 0); + $comp->{'DEVICE'} = Font::TTF::Delta->new->read($fh); + $self->{' CACHE'}{$off + $s + $r + $loff} = $comp->{'DEVICE'}; + } + } + push (@$srec, $comp); + } + push (@{$self->{'LIG'}{'LIGS'}}, $srec); + } + } + + if ($macoff > 0) + { + $fh->seek($macoff + $boff, 0); + $self->{'MARKS'} = Font::TTF::Coverage->new(0)->read($fh); + } + + if ($mgsoff > 0) + { + my ($fmt, $count, $off); + $fh->seek($mgsoff + $boff, 0); + $fh->read($dat, 4); + ($fmt, $count) = TTF_Unpack('SS', $dat); + # Sanity check opportunity: Could verify $fmt == 1, but I don't. + $self->{'MARKSETS'} = []; + $fh->read($dat, $count << 2); # NB: These offets are ULONGs! + foreach $off (TTF_Unpack('L*', $dat)) + { + unless (defined $self->{' CACHE'}{$off + $mgsoff}) + { + $fh->seek($off + $mgsoff + $boff, 0); + $self->{' CACHE'}{$off + $mgsoff} = Font::TTF::Coverage->new(1)->read($fh); + } + push @{$self->{'MARKSETS'}}, $self->{' CACHE'}{$off + $mgsoff}; + } + } + + $self; +} + + +=head2 $t->out($fh) + +Writes out this table. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($goff, $aoff, $loff, $macoff, $mgsoff, @offs, $loc1, $coff, $loc); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $loc = $fh->tell(); + if (defined $self->{'MARKSETS'} && @{$self->{'MARKSETS'}} > 0) + { + $self->{'Version'} = 0x00010002 if ($self->{'Version'} < 0x00010002); + $fh->print(TTF_Pack('LSSSSS', $self->{'Version'}, 0, 0, 0, 0, 0)); + } + else + { + $self->{'Version'} = 0x00010000; + if ($new_gdef || defined $self->{'MARKS'}) + { $fh->print(TTF_Pack('LSSSS', $self->{'Version'}, 0, 0, 0, 0)); } + else + { $fh->print(TTF_Pack('LSSS', $self->{'Version'}, 0, 0, 0)); } + } + + if (defined $self->{'GLYPH'}) + { + $goff = $fh->tell() - $loc; + $self->{'GLYPH'}->out($fh); + } + + if (defined $self->{'ATTACH'}) + { + my ($r); + + $aoff = $fh->tell() - $loc; + $fh->print(pack('n*', (0) x ($#{$self->{'ATTACH'}{'POINTS'}} + 3))); + foreach $r (@{$self->{'ATTACH'}{'POINTS'}}) + { + push (@offs, $fh->tell() - $loc - $aoff); + $fh->print(pack('n*', $#{$r} + 1, @$r)); + } + $coff = $fh->tell() - $loc - $aoff; + $self->{'ATTACH'}{'COVERAGE'}->out($fh); + $loc1 = $fh->tell(); + $fh->seek($aoff + $loc, 0); + $fh->print(pack('n*', $coff, $#offs + 1, @offs)); + $fh->seek($loc1, 0); + } + + if (defined $self->{'LIG'}) + { + my (@reftables, $ltables, $i, $j, $out, $r, $s); + + $ltables = {}; + $loff = $fh->tell() - $loc; + $out = pack('n*', + Font::TTF::Ttopen::ref_cache($self->{'LIG'}{'COVERAGE'}, $ltables, 0), + $#{$self->{'LIG'}{'LIGS'}} + 1, + (0) x ($#{$self->{'LIG'}{'LIGS'}} + 1)); + push (@reftables, [$ltables, 0]); + $i = 0; + foreach $r (@{$self->{'LIG'}{'LIGS'}}) + { + $ltables = {}; + $loc1 = length($out); + substr($out, ($i << 1) + 4, 2) = TTF_Pack('S', $loc1); + $out .= pack('n*', $#{$r} + 1, (0) x ($#{$r} + 1)); + @offs = (); $j = 0; + foreach $s (@$r) + { + substr($out, ($j << 1) + 2 + $loc1, 2) = + TTF_Pack('S', length($out) - $loc1); + $out .= TTF_Pack('SS', $s->{'FMT'}, $s->{'VAL'}); + $out .= pack('n', Font::TTF::Ttopen::ref_cache($s->{'DEVICE'}, + $ltables, length($out))) if ($s->{'FMT'} == 3); + $j++; + } + push (@reftables, [$ltables, $loc1]); + $i++; + } + Font::TTF::Ttopen::out_final($fh, $out, \@reftables); + } + + if (defined $self->{'MARKS'}) + { + $macoff = $fh->tell() - $loc; + $self->{'MARKS'}->out($fh); + } + + if (defined $self->{'MARKSETS'}) + { + + my (@reftables, $ctables, $c, $out); + $ctables = {}; + $mgsoff = $fh->tell() - $loc; + $out = TTF_Pack('SS', 1, $#{$self->{'MARKSETS'}}+1); + foreach $c (@{$self->{'MARKSETS'}}) + { + $out .= pack('N', Font::TTF::Ttopen::ref_cache($c, $ctables, length($out), 'N')); + } + push (@reftables, [$ctables, 0]); + Font::TTF::Ttopen::out_final($fh, $out, \@reftables); + } + + $loc1 = $fh->tell(); + $fh->seek($loc + 4, 0); + if ($mgsoff) + { $fh->print(TTF_Pack('S5', $goff, $aoff, $loff, $macoff, $mgsoff)); } + elsif ($macoff) + { $fh->print(TTF_Pack('S4', $goff, $aoff, $loff, $macoff)); } + else + { $fh->print(TTF_Pack('S3', $goff, $aoff, $loff)); } + $fh->seek($loc1, 0); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 10; +} + + +=head2 $t->update + +Sort COVERAGE tables. + +=cut + +sub update +{ + my ($self) = @_; + + return undef unless ($self->SUPER::update); + + unless ($Font::TTF::Coverage::dontsort) + { + if (defined $self->{'ATTACH'} and defined $self->{'ATTACH'}{'COVERAGE'} and !$self->{'ATTACH'}{'COVERAGE'}{'dontsort'} ) + { + my @map = $self->{'ATTACH'}{'COVERAGE'}->sort(); + if (defined $self->{'ATTACH'}{'POINTS'}) + { + # And also a POINTS array which now needs to be re-sorted + my $newpoints = []; + foreach (0 .. $#map) + { push @{$newpoints}, $self->{'ATTACH'}{'POINTS'}[$map[$_]]; } + $self->{'ATTACH'}{'POINTS'} = $newpoints; + } + } + if (defined $self->{'LIG'} and defined $self->{'LIG'}{'COVERAGE'} and !$self->{'LIG'}{'COVERAGE'}{'dontsort'} ) + { + my @map = $self->{'LIG'}{'COVERAGE'}->sort(); + if (defined $self->{'LIG'}{'LIGS'}) + { + # And also a LIGS array which now needs to be re-sorted + my $newligs = []; + foreach (0 .. $#map) + { push @{$newligs}, $self->{'LIG'}{'LIGS'}[$map[$_]]; } + $self->{'LIG'}{'LIGS'} = $newligs; + } + } + if (defined $self->{'MARKSETS'}) + { + foreach (@{$self->{'MARKSETS'}}) + {$_->sort();} # Don't care about map + } + } + + $self; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GPOS.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GPOS.pm new file mode 100644 index 0000000000..4df6582bda --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GPOS.pm @@ -0,0 +1,711 @@ +package Font::TTF::GPOS; + +=head1 NAME + +Font::TTF::GPOS - Support for Opentype GPOS tables in conjunction with TTOpen + +=head1 DESCRIPTION + +The GPOS table is one of the most complicated tables in the TTF spec and the +corresponding data structure abstraction is also not trivial. While much of the +structure of a GPOS is shared with a GSUB table via the L + +=head1 INSTANCE VARIABLES + +Here we describe the additions and lookup specific information for GPOS tables. +Unfortunately there is no one abstraction which seems to work comfortable for +all GPOS tables, so we will also examine how the variables are used for different +lookup types. + +The following are the values allowed in the ACTION_TYPE and MATCH_TYPE variables: + +=over 4 + +=item ACTION_TYPE + +This can take any of the following values + +=over 8 + +=item a + +The ACTION is an array of anchor tables + +=item o + +Offset. There is no RULE array. The ADJUST variable contains a value record (see +later in this description) + +=item v + +The ACTION is a value record. + +=item p + +Pair adjustment. The ACTION contains an array of two value records for the matched +two glyphs. + +=item e + +Exit and Entry records. The ACTION contains an array of two anchors corresponding +to the exit and entry anchors for the glyph. + +=item l + +Indicates a lookup based contextual rule as per the GSUB table. + +=back + +=item MATCH_TYPE + +This can take any of the following values + +=over 8 + +=item g + +A glyph array + +=item c + +An array of class values + +=item o + +An array of coverage tables + +=back + +=back + +The following variables are added for Attachment Positioning Subtables: + +=over 4 + +=item MATCH + +This contains an array of glyphs to match against for all RULES. It is much like +having the same MATCH string in all RULES. In the cases it is used so far, it only +ever contains one element. + +=item MARKS + +This contains a Mark array consisting of each element being a subarray of two +elements: + +=over 8 + +=item CLASS + +The class that this mark uses on its base + +=item ANCHOR + +The anchor with which to attach this mark glyph + +=back + +The base table for mark to base, ligature or mark attachment positioning is +structured with the ACTION containing an array of anchors corresponding to each +attachment class. For ligatures, there is more than one RULE in the RULE array +corresponding to each glyph in the coverage table. + +=back + +Other variables which are provided for informational purposes are: + +=over 4 + +=item VFMT + +Value format for the adjustment of the glyph matched by the coverage table. + +=item VFMT2 + +Value format used in pair adjustment for the second glyph in the pair + +=back + +=head2 Value Records + +There is a subtype used in GPOS tables called a value record. It is used to adjust +the position of a glyph from its default position. The value record is variable +length with a bitfield at the beginning to indicate which of the following +entries are included. The bitfield is not stored since it is recalculated at +write time. + +=over 4 + +=item XPlacement + +Horizontal adjustment for placement (not affecting other unattached glyphs) + +=item YPlacement + +Vertical adjustment for placement (not affecting other unattached glyphs) + +=item XAdvance + +Adjust the advance width glyph (used only in horizontal writing systems) + +=item YAdvance + +Adjust the vertical advance (used only in vertical writing systems) + +=item XPlaDevice + +Device table for device specific adjustment of horizontal placement + +=item YPlaDevice + +Device table for device specific adjustment of vertical placement + +=item XAdvDevice + +Device table for device specific adjustment of horizontal advance + +=item YAdDevice + +Device table for device specific adjustment of vertical advance + +=item XIdPlacement + +Horizontal placement metric id (for Multiple Master fonts - but that is all I know!) + +=item YIdPlacement + +Vertical placement metric id + +=item XIdAdvance + +Horizontal advance metric id + +=item YIdAdvance + +Vertical advance metric id + +=back + +=head1 CORRESPONDANCE TO LAYOUT TYPES + +Here is what is stored in the ACTION_TYPE and MATCH_TYPE for each of the known +GPOS subtable types: + + 1.1 1.2 2.1 2.2 3 4 5 6 7.1 7.2 7.3 8.1 8.2 8.3 + ACTION_TYPE o v p p e a a a l l l l l l + MATCH_TYPE g c g c o g c o + + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Ttopen; +use Font::TTF::Delta; +use Font::TTF::Anchor; +use Font::TTF::Utils; +use vars qw(@ISA); + +@ISA = qw(Font::TTF::Ttopen); + + +=head2 read_sub + +Reads the subtable into the data structures + +=cut + +sub read_sub +{ + my ($self, $fh, $main_lookup, $sindex) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($loc) = $fh->tell(); + my ($lookup) = $main_lookup->{'SUB'}[$sindex]; + my ($dat, $mcount, $scount, $i, $j, $count, $fmt, $fmt2, $cover, $srec, $subst); + my ($c1, $c2, $s, $moff, $boff); + + + if ($type == 8) + { + $fh->read($dat, 4); + ($fmt, $cover) = TTF_Unpack('S2', $dat); + if ($fmt < 3) + { + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + } + } else + { + $fh->read($dat, 6); + ($fmt, $cover, $count) = TTF_Unpack("S3", $dat); + } + unless ($fmt == 3 && ($type == 7 || $type == 8)) + { $lookup->{'COVERAGE'} = $self->read_cover($cover, $loc, $lookup, $fh, 1); } + + $lookup->{'FORMAT'} = $fmt; + if ($type == 1 && $fmt == 1) + { + $lookup->{'VFMT'} = $count; + $lookup->{'ADJUST'} = $self->read_value($count, $loc, $lookup, $fh); + $lookup->{'ACTION_TYPE'} = 'o'; + } elsif ($type == 1 && $fmt == 2) + { + $lookup->{'VFMT'} = $count; + $fh->read($dat, 2); + $mcount = unpack('n', $dat); + for ($i = 0; $i < $mcount; $i++) + { push (@{$lookup->{'RULES'}}, [{'ACTION' => + [$self->read_value($count, $loc, $lookup, $fh)]}]); } + $lookup->{'ACTION_TYPE'} = 'v'; + } elsif ($type == 2 && $fmt == 1) + { + $lookup->{'VFMT'} = $count; + $fh->read($dat, 4); + ($fmt2, $mcount) = unpack('n2', $dat); + $lookup->{'VFMT2'} = $fmt2; + $fh->read($dat, $mcount << 1); + foreach $s (unpack('n*', $dat)) + { + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $scount = TTF_Unpack('S', $dat); + $subst = []; + for ($i = 0; $i < $scount; $i++) + { + $srec = {}; + $fh->read($dat, 2); + $srec->{'MATCH'} = [TTF_Unpack('S', $dat)]; + $srec->{'ACTION'} = [$self->read_value($count, $loc, $lookup, $fh), + $self->read_value($fmt2, $loc, $lookup, $fh)]; + push (@$subst, $srec); + } + push (@{$lookup->{'RULES'}}, $subst); + } + $lookup->{'ACTION_TYPE'} = 'p'; + $lookup->{'MATCH_TYPE'} = 'g'; + } elsif ($type == 2 && $fmt == 2) + { + $fh->read($dat, 10); + ($lookup->{'VFMT2'}, $c1, $c2, $mcount, $scount) = TTF_Unpack('S*', $dat); + $lookup->{'CLASS'} = $self->read_cover($c1, $loc, $lookup, $fh, 0); + $lookup->{'MATCH'} = [$self->read_cover($c2, $loc, $lookup, $fh, 0)]; + $lookup->{'VFMT'} = $count; + for ($i = 0; $i < $mcount; $i++) + { + $subst = []; + for ($j = 0; $j < $scount; $j++) + { + $srec = {}; + $srec->{'ACTION'} = [$self->read_value($lookup->{'VFMT'}, $loc, $lookup, $fh), + $self->read_value($lookup->{'VFMT2'}, $loc, $lookup, $fh)]; + push (@$subst, $srec); + } + push (@{$lookup->{'RULES'}}, $subst); + } + $lookup->{'ACTION_TYPE'} = 'p'; + $lookup->{'MATCH_TYPE'} = 'c'; + } elsif ($type == 3 && $fmt == 1) + { + $fh->read($dat, $count << 2); + for ($i = 0; $i < $count; $i++) + { push (@{$lookup->{'RULES'}}, [{'ACTION' => + [$self->read_anchor(TTF_Unpack('S', substr($dat, $i << 2, 2)), + $loc, $lookup, $fh), + $self->read_anchor(TTF_Unpack('S', substr($dat, ($i << 2) + 2, 2)), + $loc, $lookup, $fh)]}]); } + $lookup->{'ACTION_TYPE'} = 'e'; + } elsif ($type == 4 || $type == 5 || $type == 6) + { + my (@offs, $mloc, $thisloc, $ncomp, $k); + + $lookup->{'MATCH'} = [$lookup->{'COVERAGE'}]; # Attaching mark + $lookup->{'COVERAGE'} = $self->read_cover($count, $loc, $lookup, $fh, 1); # base/lig/mark being attached to + $fh->read($dat, 6); + ($mcount, $moff, $boff) = TTF_Unpack('S*', $dat); + # Read MarkArray + $fh->seek($loc + $moff, 0); + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + for ($i = 0; $i < $count; $i++) + { + $fh->read($dat, 4); + push (@{$lookup->{'MARKS'}}, [TTF_Unpack('S', $dat), + $self->read_anchor(TTF_Unpack('S', substr($dat, 2, 2)) + $moff, + $loc, $lookup, $fh)]); + } + # Read BaseArray/LigatureArray/Mark2Array + $fh->seek($loc + $boff, 0); + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + $mloc = $fh->tell() - 2; + $thisloc = $mloc; + if ($type == 5) + { + $fh->read($dat, $count << 1); + @offs = TTF_Unpack('S*', $dat); + } + for ($i = 0; $i < $count; $i++) + { + if ($type == 5) + { + $thisloc = $mloc + $offs[$i]; + $fh->seek($thisloc, 0); + $fh->read($dat, 2); + $ncomp = TTF_Unpack('S', $dat); + } else + { $ncomp = 1; } + for ($j = 0; $j < $ncomp; $j++) + { + $subst = []; + $fh->read($dat, $mcount << 1); + for ($k = 0; $k < $mcount; $k++) + { push (@$subst, $self->read_anchor(TTF_Unpack('S', substr($dat, $k << 1, 2)), + $thisloc, $lookup, $fh)); } + + push (@{$lookup->{'RULES'}[$i]}, {'ACTION' => $subst}); + } + } + $lookup->{'ACTION_TYPE'} = 'a'; + } elsif ($type == 7 || $type == 8) + { $self->read_context($lookup, $fh, $type - 2, $fmt, $cover, $count, $loc); } + $lookup; +} + + +=head2 $t->extension + +Returns the table type number for the extension table + +=cut + +sub extension +{ return 9; } + + +=head2 $t->out_sub + +Outputs the subtable to the given filehandle + +=cut + +sub out_sub +{ + my ($self, $fh, $main_lookup, $index, $ctables, $base) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($lookup) = $main_lookup->{'SUB'}[$index]; + my ($fmt) = $lookup->{'FORMAT'}; + my ($out, $r, $s, $t, $i, $j, $vfmt, $vfmt2, $loc1); + my ($num) = $#{$lookup->{'RULES'}} + 1; + my ($mtables) = {}; + my (@reftables); + + if ($type == 1 && $fmt == 1) + { + $out = pack('n2', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base)); + $vfmt = $self->fmt_value($lookup->{'ADJUST'}); + $out .= pack('n', $vfmt) . $self->out_value($lookup->{'ADJUST'}, $vfmt, $ctables, 6 + $base); + } elsif ($type == 1 && $fmt == 2) + { + $vfmt = 0; + foreach $r (@{$lookup->{'RULES'}}) + { $vfmt |= $self->fmt_value($r->[0]{'ACTION'}[0]); } + $out = pack('n4', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $vfmt, $#{$lookup->{'RULES'}} + 1); + foreach $r (@{$lookup->{'RULES'}}) + { $out .= $self->out_value($r->[0]{'ACTION'}[0], $vfmt, $ctables, length($out) + $base); } + } elsif ($type == 2 && $fmt < 3) + { + $vfmt = 0; + $vfmt2 = 0; + foreach $r (@{$lookup->{'RULES'}}) + { + foreach $t (@$r) + { + $vfmt |= $self->fmt_value($t->{'ACTION'}[0]); + $vfmt2 |= $self->fmt_value($t->{'ACTION'}[1]); + } + } + if ($fmt == 1) + { + # start PairPosFormat1 subtable + $out = pack('n5', + $fmt, + Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $vfmt, + $vfmt2, + $#{$lookup->{'RULES'}} + 1); # PairSetCount + my $off = 0; + $off += length($out); + $off += 2 * ($#{$lookup->{'RULES'}} + 1); # there will be PairSetCount offsets here + my $pairsets = ''; + my (%cache); + foreach $r (@{$lookup->{'RULES'}}) # foreach PairSet table + { + # write offset to this PairSet at end of PairPosFormat1 table + if (defined $cache{"$r"}) + { $out .= pack('n', $cache{"$r"}); } + else + { + $out .= pack('n', $off); + $cache{"$r"} = $off; + + # generate PairSet itself (using $off as eventual offset within PairPos subtable) + my $pairset = pack('n', $#{$r} + 1); # PairValueCount + foreach $t (@$r) # foreach PairValueRecord + { + $pairset .= pack('n', $t->{'MATCH'}[0]); # SecondGlyph - MATCH has only one entry + $pairset .= + $self->out_value($t->{'ACTION'}[0], $vfmt, $ctables, $off + length($pairset) + $base); + $pairset .= + $self->out_value($t->{'ACTION'}[1], $vfmt2, $ctables, $off + length($pairset) + $base); + } + $off += length($pairset); + $pairsets .= $pairset; + } + } + $out .= $pairsets; + die "internal error: PairPos size not as calculated" if (length($out) != $off); + } else + { + $out = pack('n8', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $vfmt, $vfmt2, + Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 8 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 10 + $base), + $lookup->{'CLASS'}{'max'} + 1, $lookup->{'MATCH'}[0]{'max'} + 1); + + for ($i = 0; $i <= $lookup->{'CLASS'}{'max'}; $i++) + { + for ($j = 0; $j <= $lookup->{'MATCH'}[0]{'max'}; $j++) + { + $out .= $self->out_value($lookup->{'RULES'}[$i][$j]{'ACTION'}[0], $vfmt, $ctables, length($out) + $base); + $out .= $self->out_value($lookup->{'RULES'}[$i][$j]{'ACTION'}[1], $vfmt2, $ctables, length($out) + $base); + } + } + } + } elsif ($type == 3 && $fmt == 1) + { + $out = pack('n3', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $#{$lookup->{'RULES'}} + 1); + foreach $r (@{$lookup->{'RULES'}}) + { + $out .= pack('n2', Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[0], $ctables, length($out) + $base), + Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[1], $ctables, length($out) + 2 + $base)); + } + } elsif ($type == 4 || $type == 5 || $type == 6) + { + my ($loc_off, $loc_t, $ltables); + + $out = pack('n7', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 2 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 4 + $base), + $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1, 12, ($#{$lookup->{'MARKS'}} + 4) << 2, + $#{$lookup->{'MARKS'}} + 1); + foreach $r (@{$lookup->{'MARKS'}}) + { $out .= pack('n2', $r->[0], Font::TTF::Ttopen::ref_cache($r->[1], $mtables, length($out) + 2)); } + push (@reftables, [$mtables, 12]); + + $loc_t = length($out); + substr($out, 10, 2) = pack('n', $loc_t); + $out .= pack('n', $#{$lookup->{'RULES'}} + 1); + if ($type == 5) + { + $loc1 = length($out); + $out .= pack('n*', (0) x ($#{$lookup->{'RULES'}} + 1)); + } + $ltables = {}; + for ($i = 0; $i <= $#{$lookup->{'RULES'}}; $i++) + { + if ($type == 5) + { + $ltables = {}; + $loc_t = length($out); + substr($out, $loc1 + ($i << 1), 2) = TTF_Pack('S', $loc_t - $loc1 + 2); + } + + $r = $lookup->{'RULES'}[$i]; + $out .= pack('n', $#{$r} + 1) if ($type == 5); + foreach $t (@$r) + { + foreach $s (@{$t->{'ACTION'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($s, $ltables, length($out))); } + } + push (@reftables, [$ltables, $loc_t]) if ($type == 5); + } + push (@reftables, [$ltables, $loc_t]) unless ($type == 5); + $out = Font::TTF::Ttopen::out_final($fh, $out, \@reftables, 1); + } elsif ($type == 7 || $type == 8) + { $out = $self->out_context($lookup, $fh, $type - 2, $fmt, $ctables, $out, $num, $base); } +# push (@reftables, [$ctables, 0]); + $out; +} + + +=head2 $t->read_value($format, $base, $lookup, $fh) + +Reads a value record from the current location in the file, according to the +format given. + +=cut + +sub read_value +{ + my ($self, $fmt, $base, $lookup, $fh) = @_; + my ($flag) = 1; + my ($res) = {}; + my ($s, $i, $dat); + + $s = 0; + for ($i = 0; $i < 12; $i++) + { + $s++ if ($flag & $fmt); + $flag <<= 1; + } + + $fh->read($dat, $s << 1); + $flag = 1; $i = 0; + foreach $s (qw(XPlacement YPlacement XAdvance YAdvance)) + { + $res->{$s} = TTF_Unpack('s', substr($dat, $i++ << 1, 2)) if ($fmt & $flag); + $flag <<= 1; + } + + foreach $s (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice)) + { + if ($fmt & $flag) + { $res->{$s} = $self->read_delta(TTF_Unpack('S', substr($dat, $i++ << 1, 2)), + $base, $lookup, $fh); } + $flag <<= 1; + } + + foreach $s (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance)) + { + $res->{$s} = TTF_Unpack('S', substr($dat, $i++ << 1, 2)) if ($fmt & $flag); + $flag <<= 1; + } + $res; +} + + +=head2 $t->read_delta($offset, $base, $lookup, $fh) + +Reads a delta (device table) at the given offset if it hasn not already been read. +Store the offset and item in the lookup cache ($lookup->{' CACHE'}) + +=cut + +sub read_delta +{ + my ($self, $offset, $base, $lookup, $fh) = @_; + my ($loc) = $fh->tell(); + my ($res, $str); + + return undef unless $offset; + $str = sprintf("%X", $base + $offset); + return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str}; + $fh->seek($base + $offset, 0); + $res = Font::TTF::Delta->new->read($fh); + $fh->seek($loc, 0); + $lookup->{' CACHE'}{$str} = $res; + return $res; +} + + +=head2 $t->read_anchor($offset, $base, $lookup, $fh) + +Reads an Anchor table at the given offset if it has not already been read. + +=cut + +sub read_anchor +{ + my ($self, $offset, $base, $lookup, $fh) = @_; + my ($loc) = $fh->tell(); + my ($res, $str); + + return undef unless $offset; + $str = sprintf("%X", $base + $offset); + return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str}; + $fh->seek($base + $offset, 0); + $res = Font::TTF::Anchor->new->read($fh); + $fh->seek($loc, 0); + $lookup->{' CACHE'}{$str} = $res; + return $res; +} + + +=head2 $t->fmt_value + +Returns the value format for a given value record + +=cut + +sub fmt_value +{ + my ($self, $value) = @_; + my ($fmt) = 0; + my ($n); + + foreach $n (reverse qw(XPlacement YPlacement XAdvance YAdvance XPlaDevice YPlaDevice + XAdvDevice YAdvDevice XIdPlacement YIdPlacement XIdAdvance + YIdAdvance)) + { + $fmt <<= 1; + $fmt |= 1 if (defined $value->{$n} && (ref $value->{$n} || $value->{$n})); + } + $fmt; +} + + +=head2 $t->out_value + +Returns the output string for the outputting of the value for a given format. Also +updates the offset cache for any device tables referenced. + +=cut + +sub out_value +{ + my ($self, $value, $fmt, $tables, $offset) = @_; + my ($n, $flag, $out); + + $flag = 1; + foreach $n (qw(XPlacement YPlacement XAdvance YAdvance)) + { + $out .= pack('n', $value->{$n}) if ($flag & $fmt); + $flag <<= 1; + } + foreach $n (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice)) + { + if ($flag & $fmt) + { + $out .= pack('n', Font::TTF::Ttopen::ref_cache( + $value->{$n}, $tables, $offset + length($out))); + } + $flag <<= 1; + } + foreach $n (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance)) + { + $out .= pack('n', $value->{$n}) if ($flag & $fmt); + $flag <<= 1; + } + $out; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GSUB.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GSUB.pm new file mode 100644 index 0000000000..1550a3d02a --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GSUB.pm @@ -0,0 +1,299 @@ +package Font::TTF::GSUB; + +=head1 NAME + +Font::TTF::GSUB - Module support for the GSUB table in conjunction with TTOpen + +=head1 DESCRIPTION + +Handles the GSUB subtables in relation to Ttopen tables. Due to the variety of +different lookup types, the data structures are not all that straightforward, +although I have tried to make life easy for myself when using this! + +=head1 INSTANCE VARIABLES + +The structure of a GSUB table is the same as that given in L. +Here we give some of the semantics specific to GSUB lookups. + +=over 4 + +=item ACTION_TYPE + +This is a string taking one of 4 values indicating the nature of the information +in the ACTION array of the rule: + +=over 8 + +=item g + +The action contains a string of glyphs to replace the match string by + +=item l + +The action array contains a list of offsets and lookups to run, in order, on +the matched string + +=item a + +The action array is an unordered set of optional replacements for the matched +glyph. The application should make the selection somehow. + +=item o + +The action array is empty (in fact there is no rule array for this type of +rule) and the ADJUST value should be added to the glyph id to find the replacement +glyph id value + +=item r + +The action array is a list of replacement glyphs in coverage order. This ACTION_TYPE +is used only for Type 8 Reverse Chaining lookups which, by design, are single glyph +substitution. + +=back + +=item MATCH_TYPE + +This indicates which type of information the various MATCH arrays (MATCH, PRE, +POST) hold in the rule: + +=over 8 + +=item g + +The array holds a string of glyph ids which should match exactly + +=item c + +The array holds a sequence of class definitions which each glyph should +correspondingly match to + +=item o + +The array holds offsets to coverage tables + +=back + +=back + +=head1 CORRESPONDANCE TO LAYOUT TYPES + +The following table gives the values for ACTION_TYPE and MATCH_TYPE for each +of the 12 different lookup types found in the GSUB table definition: + + 1.1 1.2 2 3 4 5.1 5.2 5.3 6.1 6.2 6.3 8 + ACTION_TYPE o g g a g l l l l l l r + MATCH_TYPE g g c o g c o o + +Hopefully, the rest of the uses of the variables should make sense from this +table. + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::Ttopen; + +@ISA = qw(Font::TTF::Ttopen); + +=head2 $t->read_sub($fh, $lookup, $index) + +Asked by the superclass to read in from the given file the indexth subtable from +lookup number lookup. The file is positioned ready for the read. + +=cut + +sub read_sub +{ + my ($self, $fh, $main_lookup, $sindex) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($loc) = $fh->tell(); + my ($lookup) = $main_lookup->{'SUB'}[$sindex]; + my ($dat, $s, @subst, $t, $fmt, $cover, $count, $mcount, $scount, $i, $gid); + my (@srec); + + if ($type == 6) + { + $fh->read($dat, 4); + ($fmt, $cover) = TTF_Unpack('S2', $dat); + if ($fmt < 3) + { + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + } + } else + { + $fh->read($dat, 6); + ($fmt, $cover, $count) = TTF_Unpack("S3", $dat); + } + unless ($fmt == 3 && ($type == 5 || $type == 6)) + { $lookup->{'COVERAGE'} = $self->read_cover($cover, $loc, $lookup, $fh, 1); } + + $lookup->{'FORMAT'} = $fmt; + if ($type == 1 && $fmt == 1) + { + $count -= 65536 if ($count > 32767); + $lookup->{'ADJUST'} = $count; + $lookup->{'ACTION_TYPE'} = 'o'; + } elsif ($type == 1 && $fmt == 2) + { + $fh->read($dat, $count << 1); + @subst = TTF_Unpack('S*', $dat); + foreach $s (@subst) + { push(@{$lookup->{'RULES'}}, [{'ACTION' => [$s]}]); } + $lookup->{'ACTION_TYPE'} = 'g'; + } elsif ($type == 2 || $type == 3) + { + $fh->read($dat, $count << 1); # number of offsets + foreach $s (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + push(@{$lookup->{'RULES'}}, [{'ACTION' => [TTF_Unpack('S*', $dat)]}]); + } + $lookup->{'ACTION_TYPE'} = ($type == 2 ? 'g' : 'a'); + } elsif ($type == 4) + { + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { + @subst = (); + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + foreach $t (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s + $t, 0); + $fh->read($dat, 4); + ($gid, $mcount) = TTF_Unpack('S2', $dat); + $fh->read($dat, ($mcount - 1) << 1); + push(@subst, {'ACTION' => [$gid], 'MATCH' => [TTF_Unpack('S*', $dat)]}); + } + push(@{$lookup->{'RULES'}}, [@subst]); + } + $lookup->{'ACTION_TYPE'} = 'g'; + $lookup->{'MATCH_TYPE'} = 'g'; + } elsif ($type == 8) + { + $t = {}; + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'PRE'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'POST'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + $fh->read($dat, $count << 1); + $t->{'ACTION'} = [TTF_Unpack('S*', $dat)]; + $lookup->{'RULES'} = [[$t]]; + $lookup->{'ACTION_TYPE'} = 'r'; + $lookup->{'MATCH_TYPE'} = 'o'; + } elsif ($type == 5 || $type == 6) + { $self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc); } + $lookup; +} + + +=head2 $t->extension + +Returns the table type number for the extension table + +=cut + +sub extension +{ return 7; } + + +=head2 $t->out_sub($fh, $lookup, $index) + +Passed the filehandle to output to, suitably positioned, the lookup and subtable +index, this function outputs the subtable to $fh at that point. + +=cut + +sub out_sub +{ + my ($self, $fh, $main_lookup, $index, $ctables, $base) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($lookup) = $main_lookup->{'SUB'}[$index]; + my ($fmt) = $lookup->{'FORMAT'}; + my ($out, $r, $t, $i, $j, $offc, $offd, $numd); + my ($num) = $#{$lookup->{'RULES'}} + 1; + + if ($type == 1) + { + $out = pack("nn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base)); + if ($fmt == 1) + { $out .= pack("n", $lookup->{'ADJUST'}); } + else + { + $out .= pack("n", $num); + foreach $r (@{$lookup->{'RULES'}}) + { $out .= pack("n", $r->[0]{'ACTION'}[0]); } + } + } elsif ($type == 2 || $type == 3) + { + $out = pack("nnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $num); + $out .= pack('n*', (0) x $num); + $offc = length($out); + for ($i = 0; $i < $num; $i++) + { + $out .= pack("n*", $#{$lookup->{'RULES'}[$i][0]{'ACTION'}} + 1, + @{$lookup->{'RULES'}[$i][0]{'ACTION'}}); + substr($out, ($i << 1) + 6, 2) = pack('n', $offc); + $offc = length($out); + } + } elsif ($type == 8) + { + $out = pack("nn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base)); + $r = $lookup->{'RULES'}[0][0]; + $out .= pack('n', defined $r->{'PRE'} ? scalar @{$r->{'PRE'}} : 0); + foreach $t (@{$r->{'PRE'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'POST'} ? scalar @{$r->{'POST'}} : 0); + foreach $t (@{$r->{'POST'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack("n*", $#{$r->{'ACTION'}} + 1, @{$r->{'ACTION'}}); + } elsif ($type == 4 || $type == 5 || $type == 6) + { $out = $self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num, $base); } +# Font::TTF::Ttopen::out_final($fh, $out, [[$ctables, 0]]); + $out; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glat.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glat.pm new file mode 100644 index 0000000000..b341815686 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glat.pm @@ -0,0 +1,146 @@ +package Font::TTF::Glat; + +=head1 NAME + +Font::TTF::Glat - Hold glyph attributes + +=head1 DESCRIPTION + +Holds glyph attributes associated with each glyph. + +=over 4 + +=item Version + +Table format version + +=item attribs + +An array of hashes. On array entry for each glyph id. Since the glyph attributes are usually in a sparse +array, they are stored in a hash keyed by the attribute id and with the value as attribute value. + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($gloc) = $self->{' PARENT'}{'Gloc'}; + my ($fh) = $self->{' INFILE'}; + my ($numGlyphs); + my ($base) = $self->{' OFFSET'}; + my ($dat, $i); + + $gloc->read; + $numGlyphs = $gloc->{'numGlyphs'}; + $fh->seek($base, 0); + $fh->read($dat, 4); + ($self->{'Version'}) = TTF_Unpack('v', $dat); + + for ($i = 0; $i < $numGlyphs; $i++) + { + my ($j) = 0; + my ($num) = $gloc->{'locations'}[$i + 1] - $gloc->{'locations'}[$i]; + my ($first, $number, @vals); + $fh->seek($base + $gloc->{'locations'}[$i], 0); + $fh->read($dat, $num); + while ($j < $num) + { + if ($self->{'Version'} > 1) + { + ($first, $number) = unpack("n2", substr($dat, $j, 4)); + @vals = unpack("n$number", substr($dat, $j + 4, $number * 2)); + $j += ($number + 2) * 2; + } + else + { + ($first, $number) = unpack("C2", substr($dat, $j, 2)); + @vals = unpack("n$number", substr($dat, $j + 2, $number * 2)); + $j += $number * 2 + 2; + } + for (my $k = 0; $k < $number; $k++) + { $self->{'attribs'}[$i]{$first + $k} = $vals[$k]; } + } + } +} + +sub out +{ + my ($self, $fh) = @_; + my ($gloc) = $self->{' PARENT'}{'Gloc'}; + my ($numGlyphs) = 0; + my ($base) = $fh->tell(); + my ($i, $type); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $numGlyphs = scalar @{$self->{'attribs'}}; + if ($gloc->{'numAttrib'} > 256) + { + $self->{'Version'} = 2; + $type = "n"; + } + else + { + $self->{'Version'} = 1; + $type = "C"; + } + + $gloc->{'locations'} = []; + $fh->print(TTF_Pack('v', $self->{'Version'})); + for ($i = 0; $i < $numGlyphs; $i++) + { + my (@a) = sort {$a <=> $b} keys %{$self->{'attribs'}[$i]}; + push(@{$gloc->{'locations'}}, $fh->tell() - $base); + while (@a) + { + my ($first) = shift(@a); + my ($next) = $first; + my (@v, $j); + while (@a and $a[0] <= $next + 2) + { $next = shift(@a); } + for ($j = $first; $j <= $next; $j++) + { push (@v, $self->{'attribs'}[$i]{$j}); } + { $fh->print(pack("${type}2n*", $first, $next - $first + 1, @v)); } + } + } + push(@{$gloc->{'locations'}}, $fh->tell() - $base); +} + +=back + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Gloc.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Gloc.pm new file mode 100644 index 0000000000..6a0ee8367c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Gloc.pm @@ -0,0 +1,118 @@ +package Font::TTF::Gloc; + +=head1 NAME + +Font::TTF::Gloc - Offsets into Glat table for the start of the attributes for each glyph + +=head1 DESCRIPTION + +The Gloc table is a bit like the Loca table only for Graphite glyph attributes. The table +has the following elements: + +=over 4 + +=item Version + +Table format version + +=item numAttrib + +Maximum number of attributes associated with a glyph. + +=item locations + +An array of offsets into the Glat table for the start of each glyph + +=item names + +If defined, an array of name table name ids indexed by attribute number. + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($numGlyphs); + my ($dat, $flags); + + $fh->read($dat, 4); + ($self->{'Version'}) = TTF_Unpack("v", $dat); + $fh->read($dat, 4); + ($flags, $self->{'numAttrib'}) = TTF_Unpack("SS", $dat); + $numGlyphs = ($self->{' LENGTH'} - 8 - ($flags & 2 ? $self->{'numAttrib'} * 2 : 0)) / (($flags & 1) ? 4 : 2) - 1; + $self->{'numGlyphs'} = $numGlyphs; + if ($flags & 1) + { + $fh->read($dat, 4 * ($numGlyphs + 1)); + $self->{'locations'} = [unpack("N*", $dat)]; + } + else + { + $fh->read($dat, 2 * ($numGlyphs + 1)); + $self->{'locations'} = [unpack("n*", $dat)]; + } + if ($flags & 2) + { + $fh->read($dat, 2 * $self->{'numAttrib'}); + $self->{'names'} = [unpack("n*", $dat)]; + } + return $self; +} + +sub out +{ + my ($self, $fh) = @_; + my ($numGlyphs) = 0; + my ($flags, $num); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $numGlyphs = scalar @{$self->{' PARENT'}{'Glat'}{'attribs'}}; + $num = $self->{'numAttrib'}; + $flags = 1 if ($self->{'locations'}[-1] > 0xFFFF); + $flags |= 2 if ($self->{'names'}); + $fh->print(TTF_Pack("vSS", $self->{'Version'}, $flags, $num)); + $fh->write(pack(($flags & 1 ? "N" : "n") . ($numGlyphs + 1), @{$self->{'locations'}})); + if ($flags & 2) + { $fh->write(pack("n$num", @{$self->{'names'}})); } +} + +=back + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glyf.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glyf.pm new file mode 100644 index 0000000000..7a12e3f8ea --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glyf.pm @@ -0,0 +1,180 @@ +package Font::TTF::Glyf; + +=head1 NAME + +Font::TTF::Glyf - The Glyf data table + +=head1 DESCRIPTION + +This is a stub table. The real data is held in the loca table. If you want to get a glyf +look it up in the loca table as C<$f->{'loca'}{'glyphs'}[$num]>. It will not be here! + +The difference between reading this table as opposed to the loca table is that +reading this table will cause updated glyphs to be written out rather than just +copying the glyph information from the input file. This causes font writing to be +slower. So read the glyf as opposed to the loca table if you want to change glyf +data. Read the loca table only if you are just wanting to read the glyf information. + +This class is used when writing the glyphs though. + +=head1 METHODS + +=cut + + +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the C table instead! + +=cut + +sub read +{ + my ($self) = @_; + + $self->{' PARENT'}{'loca'}->read; + $self->{' read'} = 1; + $self; +} + +# Internal function called by loca -- decompresses WOFF data if needed. + +sub _read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + # Nothing else to do + $self; +} + +=head2 $t->out($fh) + +Writes out all the glyphs in the parent's location table, calculating a new +output location for each one. + +=cut + +# ' match for syntax coloring + +sub out +{ + my ($self, $fh) = @_; + my ($i, $loca, $offset, $numGlyphs); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $loca = $self->{' PARENT'}{'loca'}{'glyphs'}; + $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + $offset = 0; + for ($i = 0; $i < $numGlyphs; $i++) + { + next unless defined $loca->[$i]; + $loca->[$i]->update; + $loca->[$i]{' OUTLOC'} = $offset; + $loca->[$i]->out($fh); + $offset += $loca->[$i]{' OUTLEN'}; + } + $self->{' PARENT'}{'head'}{'indexToLocFormat'} = ($offset >= 0x20000); + $self; +} + + +=head2 $t->out_xml($context, $depth) + +Outputs all the glyphs in the glyph table just where they are supposed to be output! + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($loca, $i, $numGlyphs); + + $loca = $self->{' PARENT'}{'loca'}{'glyphs'}; + $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + for ($i = 0; $i < $numGlyphs; $i++) + { + $context->{'gid'} = $i; + $loca->[$i]->out_xml($context, $depth) if (defined $loca->[$i]); + } + + $self; +} + + +=head2 $t->XML_start($context, $tag, %attrs) + +Pass control to glyphs as they occur + +=cut + +sub XML_start +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'glyph') + { + $context->{'tree'}[-1] = Font::TTF::Glyph->new(read => 2, PARENT => $self->{' PARENT'}); + $context->{'receiver'} = $context->{'tree'}[-1]; + } +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Collect up glyphs and put them into the loca table + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'glyph') + { + unless (defined $context->{'glyphs'}) + { + if (defined $self->{' PARENT'}{'loca'}) + { $context->{'glyphs'} = $self->{' PARENT'}{'loca'}{'glyphs'}; } + else + { $context->{'glyphs'} = []; } + } + $context->{'glyphs'}[$attrs{'gid'}] = $context->{'tree'}[-1]; + return $context; + } else + { return $self->SUPER::XML_end(@_); } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glyph.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glyph.pm new file mode 100644 index 0000000000..4f0961e328 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Glyph.pm @@ -0,0 +1,902 @@ +package Font::TTF::Glyph; + +=head1 NAME + +Font::TTF::Glyph - Holds a information for a single glyph + +=head1 DESCRIPTION + +This is a single glyph description as held in a TT font. On creation only its +header is read. Thus you can get the bounding box of each glyph without having +to read all the other information. + +=head1 INSTANCE VARIABLES + +In addition to the named variables in a glyph header (C etc.), there are +also all capital instance variables for holding working information, mostly +from the location table. + +=head2 Variables for all glyphs: + +The standard attributes each glyph has are: + +=over 4 + +=item numberOfContours + +For simple glyphs this will be the count of contours. For compound glyphs this will be -1. + +=item xMin + +=item yMin + +=item xMax + +=item yMax + +These identify the bounding box of the glyph. + +=back + +There are also other, derived, instance variables for each glyph which are read +when the whole glyph is read (via C): + +=over 4 + +=item instLen + +Number of bytes in the hinting instructions (Warning this variable is deprecated, +use C{'hints'})> instead). + +=item hints + +The string containing the hinting code for the glyph + +=back + +=head2 Variables for simple glyphs (numberOfContours E= 0): + +=over 4 + +=item endPoints + +An array of endpoints for each contour in the glyph. There are +C contours in a glyph. The number of points in a glyph is +equal to the highest endpoint of a contour. + +=item numPoints + +This is a generated value which contains the total number of points for this simple glyph. + +=back + +There are also a number of arrays indexed by point number: + +=over 4 + +=item flags + +The flags associated with reading this point. The flags for a point are +recalculated for a point when it is Cd. Thus the flags are not very +useful. The only important bit is bit 0 which indicates whether the point is +an 'on' curve point, or an 'off' curve point. + +=item x + +The absolute x co-ordinate of the point. + +=item y + +The absolute y co-ordinate of the point + +=back + +=head2 Variables for compound glyphs (numberOfContours == -1): + +=over 4 + +=item metric + +This holds the component number (not its glyph number) of the component from +which the metrics for this glyph should be taken. + +=item comps + +This is an array of hashes for each component. Each hash has a number of +elements: + +=over 4 + +=item glyph + +The glyph number of the glyph which comprises this component of the composite. +NOTE: In some badly generated fonts, C may contain a numerical value +but that glyph might not actually exist in the font file. This could +occur in any glyph, but is particularly likely for glyphs that have +no strokes, such as SPACE, U+00A0 NO-BREAK SPACE, or +U+200B ZERO WIDTH SPACE. + +=item args + +An array of two arguments which may be an x, y co-ordinate or two attachment +points (one on the base glyph the other on the component). See flags for details. + +=item flag + +The flag for this component + +=item scale + +A 4 number array for component scaling. This allows stretching, rotating, etc. +Note that scaling applies to placement co-ordinates (rather than attachment points) +before locating rather than after. + +=back + +=item numPoints + +This is a generated value which contains the number of components read in for this +compound glyph. + +=back + +=head2 Private instance variables: + +=over 4 + +=item INFILE (P) + +The input file form which to read any information + +=item LOC (P) + +Location relative to the start of the glyf table in the read file + +=item BASE (P) + +The location of the glyf table in the read file + +=item LEN (P) + +This is the number of bytes required by the glyph. It should be kept up to date +by calling the C method whenever any of the glyph content changes. + +=item OUTLOC (P) + +Location relative to the start of the glyf table. This variable is only active +whilst the output process is going on. It is used to inform the location table +where the glyph is located, since the glyf table is output before the loca +table due to alphabetical ordering. + +=item OUTLEN (P) + +This indicates the length of the glyph data when it is output. This more +accurately reflects the internal memory form than the C variable which +only reflects the read file length. The C variable is only set after +calling C or C. + +=back + +=head2 Editing + +If you want to edit a glyph in some way, then you should read_dat the glyph, then +make your changes and then update the glyph or set the $g->{' isDirty'} variable. +The application must ensure that the following instance variables are +correct, from which update will calculate the rest, including the bounding box +information. + + numPoints + numberOfContours + endPoints + x, y, flags (only flags bit 0) + instLen + hints + +For components, the numPoints, x, y, endPoints & flags are not required but +the following information is required for each component. + + flag (bits 2, 10, 11, 12) + glyph + args + scale + metric (glyph instance variable) + + +=head1 METHODS + +=cut + +use strict; +use vars qw(%fields @field_info); +use Font::TTF::Utils; +use Font::TTF::Table; + +@field_info = ( + 'numberOfContours' => 's', + 'xMin' => 's', + 'yMin' => 's', + 'xMax' => 's', + 'yMax' => 's'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head1 Font::TTF::Glyph->new(%parms) + +Creates a new glyph setting various instance variables + +=cut + +sub new +{ + my ($class, %parms) = @_; + my ($self) = {}; + my ($p); + + bless $self, $class; + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + init unless defined $fields{'xMin'}; + $self; +} + + +=head2 $g->read + +Reads the header component of the glyph (numberOfContours and bounding box) and also the +glyph content, but into a data field rather than breaking it down into +its constituent structures. Use read_dat for this. + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($dat); + + return $self if (defined $self->{' read'} && $self->{' read'} > 0); + $self->{' read'} = 1; + $fh->seek($self->{' LOC'} + $self->{' BASE'}, 0); + $fh->read($dat, $self->{' LEN'}); + TTF_Read_Fields($self, $self->{' DAT'} = $dat, \%fields); + $self; +} + + +=head2 $g->read_dat + +Reads the contents of the glyph (components and curves, etc.) from the memory +store C into structures within the object. + +=cut + +sub read_dat +{ + my ($self) = @_; + my ($dat, $num, $max, $i, $flag, $len, $val, $val1, $fp); + + return $self if (defined $self->{' read'} && $self->{' read'} > 1); + $self->read unless $self->{' read'}; + $dat = $self->{' DAT'}; + $fp = 10; + $num = $self->{'numberOfContours'}; + if ($num > 0) + { + $self->{'endPoints'} = [unpack("n*", substr($dat, $fp, $num << 1))]; + $fp += $num << 1; + $max = 0; + foreach (@{$self->{'endPoints'}}) + { $max = $_ if $_ > $max; } +# print STDERR join(",", unpack('C*', $self->{" DAT"})); +# printf STDERR ("(%d,%d in %d=%d @ %d)", scalar @{$self->{'endPoints'}}, $max, length($dat), $self->{' LEN'}, $fp); + $max++ if (@{$self->{'endPoints'}}); + $self->{'numPoints'} = $max; + $self->{'instLen'} = unpack("n", substr($dat, $fp)); + $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'}); + $fp += 2 + $self->{'instLen'}; +# read the flags array + for ($i = 0; $i < $max; $i++) + { + $flag = unpack("C", substr($dat, $fp++)); + $self->{'flags'}[$i] = $flag; + if ($flag & 8) + { + $len = unpack("C", substr($dat, $fp++)); + while ($len-- > 0) + { + $i++; + $self->{'flags'}[$i] = $flag; + } + } + } +#read the x array + for ($i = 0; $i < $max; $i++) + { + $flag = $self->{'flags'}[$i]; + if ($flag & 2) + { + $val = unpack("C", substr($dat, $fp++)); + $val = -$val unless ($flag & 16); + } elsif ($flag & 16) + { $val = 0; } + else + { + $val = TTF_Unpack("s", substr($dat, $fp)); + $fp += 2; + } + $self->{'x'}[$i] = $i == 0 ? $val : $self->{'x'}[$i - 1] + $val; + } +#read the y array + for ($i = 0; $i < $max; $i++) + { + $flag = $self->{'flags'}[$i]; + if ($flag & 4) + { + $val = unpack("C", substr($dat, $fp++)); + $val = -$val unless ($flag & 32); + } elsif ($flag & 32) + { $val = 0; } + else + { + $val = TTF_Unpack("s", substr($dat, $fp)); + $fp += 2; + } + $self->{'y'}[$i] = $i == 0 ? $val : $self->{'y'}[$i - 1] + $val; + } + } + +# compound glyph + elsif ($num < 0) + { + $flag = 1 << 5; # cheat to get the loop going + for ($i = 0; $flag & 32; $i++) + { + ($flag, $self->{'comps'}[$i]{'glyph'}) = unpack("n2", substr($dat, $fp)); + $fp += 4; + $self->{'comps'}[$i]{'flag'} = $flag; + if ($flag & 1) # ARGS1_AND_2_ARE_WORDS + { + $self->{'comps'}[$i]{'args'} = [TTF_Unpack("s2", substr($dat, $fp))]; + $fp += 4; + } else + { + $self->{'comps'}[$i]{'args'} = [unpack("c2", substr($dat, $fp))]; + $fp += 2; + } + + if ($flag & 8) + { + $val = TTF_Unpack("F", substr($dat, $fp)); + $fp += 2; + $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val]; + } elsif ($flag & 64) + { + ($val, $val1) = TTF_Unpack("F2", substr($dat, $fp)); + $fp += 4; + $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val1]; + } elsif ($flag & 128) + { + $self->{'comps'}[$i]{'scale'} = [TTF_Unpack("F4", substr($dat, $fp))]; + $fp += 8; + } + $self->{'metric'} = $i if ($flag & 512); + } + $self->{'numPoints'} = $i; + if ($flag & 256) # HAVE_INSTRUCTIONS + { + $self->{'instLen'} = unpack("n", substr($dat, $fp)); + $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'}); + $fp += 2 + $self->{'instLen'}; + } + } + return undef if ($fp > length($dat)); + $self->{' read'} = 2; + $self; +} + + +=head2 $g->out($fh) + +Writes the glyph data to outfile + +=cut + +sub out +{ + my ($self, $fh) = @_; + + $self->read unless $self->{' read'}; + $self->update if $self->{' isDirty'}; + $fh->print($self->{' DAT'}); + $self->{' OUTLEN'} = length($self->{' DAT'}); + $self; +} + + +=head2 $g->out_xml($context, $depth) + +Outputs an XML description of the glyph + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($addr) = ($self =~ m/\((.+)\)$/o); + my ($k, $ndepth); + + if ($context->{'addresses'}{$addr}) + { + $context->{'fh'}->printf("%s\n", $depth, $context->{'gid'}, $context->{'addresses'}{$addr}); + return $self; + } + else + { + $context->{'fh'}->printf("%s\n", $depth, $context->{'gid'}); + } + + $ndepth = $depth . $context->{'indent'}; + $self->read_dat; + foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self}) + { + $self->XML_element($context, $ndepth, $k, $self->{$k}); + } + $context->{'fh'}->print("$depth\n"); + delete $context->{'done_points'}; + $self; +} + + +sub XML_element +{ + my ($self, $context, $depth, $key, $val) = @_; + my ($fh) = $context->{'fh'}; + my ($dind) = $depth . $context->{'indent'}; + my ($i); + + if ($self->{'numberOfContours'} >= 0 && ($key eq 'x' || $key eq 'y' || $key eq 'flags')) + { + return $self if ($context->{'done_points'}); + $context->{'done_points'} = 1; + + $fh->print("$depth\n"); + for ($i = 0; $i <= $#{$self->{'flags'}}; $i++) + { $fh->printf("%s\n", $dind, + $self->{'x'}[$i], $self->{'y'}[$i], $self->{'flags'}[$i]); } + $fh->print("$depth\n"); + } + elsif ($key eq 'hints') + { + my ($dat); + $fh->print("$depth\n"); +# Font::TTF::Utils::XML_hexdump($context, $depth . $context->{'indent'}, $self->{'hints'}); + $dat = Font::TTF::Utils::XML_binhint($self->{'hints'}) || ""; + $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/mg; + $fh->print("$depth$context->{'indent'}$dat"); + $fh->print("$depth\n"); + } + else + { return Font::TTF::Table::XML_element(@_); } + + $self; +} + +=head2 $g->dirty($val) + +This sets the dirty flag to the given value or 1 if no given value. It returns the +value of the flag + +=cut + +sub dirty +{ + my ($self, $val) = @_; + my ($res) = $self->{' isDirty'}; + + $self->{' isDirty'} = defined $val ? $val : 1; + $res; +} + +=head2 $g->update + +Generates a C<$self->{'DAT'}> from the internal structures, if the data has +been read into structures in the first place. If you are building a glyph +from scratch you will need to set the instance variable C<' isDirty'>. + +=cut + +sub update +{ + my ($self) = @_; + my ($dat, $loc, $len, $flag, $x, $y, $i, $comp, $num, @rflags, $repeat); + + return $self unless ($self->{' isDirty'}); + $self->read_dat->update_bbox; + $self->{' DAT'} = TTF_Out_Fields($self, \%fields, 10); + $num = $self->{'numberOfContours'}; + if ($num > 0) + { + $self->{' DAT'} .= pack("n*", @{$self->{'endPoints'}}); + $len = $self->{'instLen'}; + $self->{' DAT'} .= pack("n", $len); + $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)) if ($len > 0); + $repeat = 0; + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + $flag = $self->{'flags'}[$i] & 1; + if ($i == 0) + { + $x = $self->{'x'}[$i]; + $y = $self->{'y'}[$i]; + } else + { + $x = $self->{'x'}[$i] - $self->{'x'}[$i - 1]; + $y = $self->{'y'}[$i] - $self->{'y'}[$i - 1]; + } + $flag |= 16 if ($x == 0); + $flag |= 32 if ($y == 0); + if (($flag & 16) == 0 && $x < 256 && $x > -256) + { + $flag |= 2; + $flag |= 16 if ($x >= 0); + } + if (($flag & 32) == 0 && $y < 256 && $y > -256) + { + $flag |= 4; + $flag |= 32 if ($y >= 0); + } + if ($i > 0 && $rflags[-1] == $flag && $repeat < 255) + { + $repeat++; + } else + { + if ($repeat) + { + $rflags[-1] |= 8; + push @rflags, $repeat; + } + push @rflags, $flag; + $repeat = 0; + } + $self->{'flags'}[$i] = $flag; + } + # Add final repeat if needed, then pack up the flag bytes: + if ($repeat) + { + $rflags[-1] |= 8; + push @rflags, $repeat; + } + $self->{' DAT'} .= pack("C*", @rflags); + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + $flag = $self->{'flags'}[$i]; + $x = $self->{'x'}[$i] - (($i == 0) ? 0 : $self->{'x'}[$i - 1]); + if (($flag & 18) == 0) + { $self->{' DAT'} .= TTF_Pack("s", $x); } + elsif (($flag & 18) == 18) + { $self->{' DAT'} .= pack("C", $x); } + elsif (($flag & 18) == 2) + { $self->{' DAT'} .= pack("C", -$x); } + } + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + $flag = $self->{'flags'}[$i]; + $y = $self->{'y'}[$i] - (($i == 0) ? 0 : $self->{'y'}[$i - 1]); + if (($flag & 36) == 0) + { $self->{' DAT'} .= TTF_Pack("s", $y); } + elsif (($flag & 36) == 36) + { $self->{' DAT'} .= pack("C", $y); } + elsif (($flag & 36) == 4) + { $self->{' DAT'} .= pack("C", -$y); } + } + } + + elsif ($num < 0) + { + for ($i = 0; $i <= $#{$self->{'comps'}}; $i++) + { + $comp = $self->{'comps'}[$i]; + $flag = $comp->{'flag'} & 7158; # bits 2,10,11,12 + $flag |= 1 unless ($comp->{'args'}[0] > -129 && $comp->{'args'}[0] < 128 + && $comp->{'args'}[1] > -129 && $comp->{'args'}[1] < 128); + if (defined $comp->{'scale'}) + { + if ($comp->{'scale'}[1] == 0 && $comp->{'scale'}[2] == 0) + { + if ($comp->{'scale'}[0] == $comp->{'scale'}[3]) + { $flag |= 8 unless ($comp->{'scale'}[0] == 0 + || $comp->{'scale'}[0] == 1); } + else + { $flag |= 64; } + } else + { $flag |= 128; } + } + + $flag |= 512 if (defined $self->{'metric'} && $self->{'metric'} == $i); + if ($i == $#{$self->{'comps'}}) + { $flag |= 256 if (defined $self->{'instLen'} && $self->{'instLen'} > 0); } + else + { $flag |= 32; } + + $self->{' DAT'} .= pack("n", $flag); + $self->{' DAT'} .= pack("n", $comp->{'glyph'}); + $comp->{'flag'} = $flag; + + if ($flag & 1) + { $self->{' DAT'} .= TTF_Pack("s2", @{$comp->{'args'}}); } + else + { $self->{' DAT'} .= pack("CC", @{$comp->{'args'}}); } + + if ($flag & 8) + { $self->{' DAT'} .= TTF_Pack("F", $comp->{'scale'}[0]); } + elsif ($flag & 64) + { $self->{' DAT'} .= TTF_Pack("F2", $comp->{'scale'}[0], $comp->{'scale'}[3]); } + elsif ($flag & 128) + { $self->{' DAT'} .= TTF_Pack("F4", @{$comp->{'scale'}}); } + } + if (defined $self->{'instLen'} && $self->{'instLen'} > 0) + { + $len = $self->{'instLen'}; + $self->{' DAT'} .= pack("n", $len); + $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)); + } + } + my ($olen) = length($self->{' DAT'}); + $self->{' DAT'} .= ("\000") x (4 - ($olen & 3)) if ($olen & 3); + $self->{' OUTLEN'} = length($self->{' DAT'}); + $self->{' read'} = 2; # changed from 1 to 2 so we don't read_dat() again +# we leave numPoints and instLen since maxp stats use this + $self; +} + + +=head2 $g->update_bbox + +Updates the bounding box for this glyph according to the points in the glyph + +=cut + +sub update_bbox +{ + my ($self) = @_; + my ($num, $maxx, $minx, $maxy, $miny, $i, $comp, $x, $y, $compg); + + return $self unless (defined $self->{' read'} && $self->{' read'} > 1); # only if read_dat done + $miny = $minx = 65537; $maxx = $maxy = -65537; + $num = $self->{'numberOfContours'}; + if ($num > 0) + { + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + ($x, $y) = ($self->{'x'}[$i], $self->{'y'}[$i]); + + $maxx = $x if ($x > $maxx); + $minx = $x if ($x < $minx); + $maxy = $y if ($y > $maxy); + $miny = $y if ($y < $miny); + } + } + + elsif ($num < 0) + { + foreach $comp (@{$self->{'comps'}}) + { + my ($gnx, $gny, $gxx, $gxy); + my ($sxx, $sxy, $syx, $syy); + + my $otherg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]; + # work around bad fonts: see documentation for 'comps' above + next unless (defined $otherg); + $compg = $otherg->read->update_bbox; + ($gnx, $gny, $gxx, $gxy) = @{$compg}{'xMin', 'yMin', 'xMax', 'yMax'}; + if (defined $comp->{'scale'}) + { + ($sxx, $sxy, $syx, $syy) = @{$comp->{'scale'}}; + ($gnx, $gny, $gxx, $gxy) = ($gnx*$sxx+$gny*$syx + $comp->{'args'}[0], + $gnx*$sxy+$gny*$syy + $comp->{'args'}[1], + $gxx*$sxx+$gxy*$syx + $comp->{'args'}[0], + $gxx*$sxy+$gxy*$syy + $comp->{'args'}[1]); + } elsif ($comp->{'args'}[0] || $comp->{'args'}[1]) + { + $gnx += $comp->{'args'}[0]; + $gny += $comp->{'args'}[1]; + $gxx += $comp->{'args'}[0]; + $gxy += $comp->{'args'}[1]; + } + ($gnx, $gxx) = ($gxx, $gnx) if $gnx > $gxx; + ($gny, $gxy) = ($gxy, $gny) if $gny > $gxy; + $maxx = $gxx if $gxx > $maxx; + $minx = $gnx if $gnx < $minx; + $maxy = $gxy if $gxy > $maxy; + $miny = $gny if $gny < $miny; + } + } + $self->{'xMax'} = $maxx; + $self->{'xMin'} = $minx; + $self->{'yMax'} = $maxy; + $self->{'yMin'} = $miny; + $self; +} + + +=head2 $g->maxInfo + +Returns lots of information about a glyph so that the C table can update +itself. Returns array containing contributions of this glyph to maxPoints, maxContours, +maxCompositePoints, maxCompositeContours, maxSizeOfInstructions, maxComponentElements, +and maxComponentDepth. + +=cut + +sub maxInfo +{ + my ($self) = @_; + my (@res, $i, @n); + + $self->read_dat; # make sure we've read some data + $res[4] = length($self->{'hints'}) if defined $self->{'hints'}; + $res[6] = 1; + if ($self->{'numberOfContours'} > 0) + { + $res[0] = $self->{'numPoints'}; + $res[1] = $self->{'numberOfContours'}; + } elsif ($self->{'numberOfContours'} < 0) + { + for ($i = 0; $i <= $#{$self->{'comps'}}; $i++) + { + my $otherg = + $self->{' PARENT'}{'loca'}{'glyphs'} + [$self->{'comps'}[$i]{'glyph'}]; + + # work around bad fonts: see documentation for 'comps' above + next unless (defined $otherg ); + + @n = $otherg->maxInfo; + + $res[2] += $n[2] == 0 ? $n[0] : $n[2]; + $res[3] += $n[3] == 0 ? $n[1] : $n[3]; + $res[5]++; + $res[6] = $n[6] + 1 if ($n[6] >= $res[6]); + } + } + @res; +} + +=head2 $g->empty + +Empties the glyph of all information to the level of not having been read. +Useful for saving memory in apps with many glyphs being read + +=cut + +sub empty +{ + my ($self) = @_; + my (%keep) = map {(" $_" => 1)} ('LOC', 'OUTLOC', 'PARENT', 'INFILE', 'BASE', + 'OUTLEN', 'LEN'); + map {delete $self->{$_} unless $keep{$_}} keys %$self; + + $self; +} + + +=head2 $g->get_points + +This method creates point information for a compound glyph. The information is +stored in the same place as if the glyph was not a compound, but since +numberOfContours is negative, the glyph is still marked as being a compound + +=cut + +sub get_points +{ + my ($self) = @_; + my ($comp, $compg, $nump, $e, $i); + + $self->read_dat; + return undef unless ($self->{'numberOfContours'} < 0); + + foreach $comp (@{$self->{'comps'}}) + { + $compg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]; + # work around bad fonts: see documentation for 'comps' above + next unless (defined $compg ); + $compg->get_points; + + for ($i = 0; $i < $compg->{'numPoints'}; $i++) + { + my ($x, $y) = ($compg->{'x'}[$i], $compg->{'y'}[$i]); + if (defined $comp->{'scale'}) + { + ($x, $y) = ($x * $comp->{'scale'}[0] + $y * $comp->{'scale'}[2], + $x * $comp->{'scale'}[1] + $y * $comp->{'scale'}[3]); + } + if (defined $comp->{'args'}) + { ($x, $y) = ($x + $comp->{'args'}[0], $y + $comp->{'args'}[1]); } + push (@{$self->{'x'}}, $x); + push (@{$self->{'y'}}, $y); + push (@{$self->{'flags'}}, $compg->{'flags'}[$i]); + } + foreach $e (@{$compg->{'endPoints'}}) + { push (@{$self->{'endPoints'}}, $e + $nump); } + $nump += $compg->{'numPoints'}; + } + $self->{'numPoints'} = $nump; + $self; +} + + +=head2 $g->get_refs + +Returns an array of all the glyph ids that are used to make up this glyph. That +is all the compounds and their references and so on. If this glyph is not a +compound, then returns an empty array. + +Please note the warning about bad fonts that reference nonexistent glyphs +under INSTANCE VARIABLES above. This function will not attempt to +filter out nonexistent glyph numbers. + +=cut + +sub get_refs +{ + my ($self) = @_; + my (@res, $g); + + $self->read_dat; + return unless ($self->{'numberOfContours'} < 0); + foreach $g (@{$self->{'comps'}}) + { + push (@res, $g->{'glyph'}); + my $otherg = $self->{' PARENT'}{'loca'}{'glyphs'}[$g->{'glyph'}]; + # work around bad fonts: see documentation for 'comps' above + next unless (defined $otherg); + my @list = $otherg->get_refs; + push(@res, @list); + } + return @res; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +The instance variables used here are somewhat clunky and inconsistent with +the other tables. + +=item * + +C doesn't re-calculate the bounding box or C. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GrFeat.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GrFeat.pm new file mode 100644 index 0000000000..525ce99af5 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/GrFeat.pm @@ -0,0 +1,320 @@ +package Font::TTF::GrFeat; + +=head1 NAME + +Font::TTF::GrFeat - Graphite Font Features + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over 4 + +=item version + +=item features + +An array of hashes of the following form + +=over 8 + +=item feature + +feature id number + +=item name + +name index in name table + +=item exclusive + +exclusive flag + +=item default + +the default setting number + +=item settings + +hash of setting number against name string index + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +use Font::TTF::Utils; + +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the features from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($featureCount, $features); + + return $self if $self->{' read'}; + $self->SUPER::read_dat or return $self; + + ($self->{'version'}, $featureCount) = TTF_Unpack("vS", $self->{' dat'}); + + $features = []; + foreach (1 .. $featureCount) { + my ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex, $reserved); + if ($self->{'version'} == 1) + { + ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex) + = TTF_Unpack("SSLSS", substr($self->{' dat'}, $_ * 12, 12)); + #The version 1 Feat table ends with a feature (id 1) named NoName + #with zero settings but with an offset to the last entry in the setting + #array. This last setting has id 0 and an invalid name id. This last + #feature is changed to have one setting. + if ($_ == $featureCount && $nSettings == 0) {$nSettings = 1;} + } + else #version == 2 + {($feature, $nSettings, $reserved, $settingTable, $featureFlags, $nameIndex) + = TTF_Unpack("LSSLSS", substr($self->{' dat'}, 12 + ($_ - 1) * 16, 16))}; + $feature = + { + 'feature' => $feature, + 'name' => $nameIndex, + }; + + #interpret the featureFlags & store settings + $feature->{'exclusive'} = (($featureFlags & 0x8000) != 0); + + my @settings = TTF_Unpack("S*", substr($self->{' dat'}, $settingTable, $nSettings * 4)); + if ($featureFlags & 0x4000) + {$feature->{'default'} = $featureFlags & 0x00FF;} + else + {$feature->{'default'} = $settings[0];} + $feature->{'settings'} = {@settings}; + + push(@$features, $feature); + } + + $self->{'features'} = $features; + + delete $self->{' dat'}; # no longer needed, and may become obsolete + $self->{' read'} = 1; + $self; +} + +=head2 $t->out($fh) + +Writes the features to a TTF file + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($features, $numFeatures, $settings, $featureFlags, $featuresData, $settingsData); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $features = $self->{'features'}; + $numFeatures = @$features; + $featuresData = $settingsData = ''; + + foreach (@$features) { + $settings = $_->{'settings'}; + $featureFlags = ($_->{'exclusive'} ? 0x8000 : 0x0000); + +# output default setting first instead of using the featureFlags (as done below) +# $featureFlags = ($_->{'exclusive'} ? 0x8000 : 0x0000) | +# ($_->{'default'} != 0 ? 0x4000 | ($_->{'default'} & 0x00FF) +# : 0x0000); + if ($self->{'version'} == 1) + { + $featuresData .= TTF_Pack("SSLSS", + $_->{'feature'}, + scalar keys %$settings, + 12 + 12 * $numFeatures + length $settingsData, + $featureFlags, + $_->{'name'}); + } + else #version == 2 + { + $featuresData .= TTF_Pack("LSSLSS", + $_->{'feature'}, + scalar keys %$settings, + 0, + 12 + 16 * $numFeatures + length $settingsData, + $featureFlags, + $_->{'name'}); + } + + #output default setting first + #the settings may not be in their original order + my $defaultSetting = $_->{'default'}; + $settingsData .= TTF_Pack("SS", $defaultSetting, $settings->{$defaultSetting}); + foreach (sort {$a <=> $b} keys %$settings) { + if ($_ == $defaultSetting) {next;} #skip default setting + $settingsData .= TTF_Pack("SS", $_, $settings->{$_}); + } + } + + $fh->print(TTF_Pack("vSSL", $self->{'version'}, $numFeatures, 0, 0)); + $fh->print($featuresData); + $fh->print($settingsData); + + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($names, $features, $settings); + + $self->read; + + $names = $self->{' PARENT'}->{'name'}; + $names->read; + + $fh = 'STDOUT' unless defined $fh; + + $features = $self->{'features'}; + foreach (@$features) { + $fh->printf("Feature %s, %s, default: %d name %d # '%s'\n", + $_->{'feature'} > 0x01000000 ? '"' . $self->num_to_tag($_->{'feature'}) . '"' : $_->{'feature'}, + ($_->{'exclusive'} ? "exclusive" : "additive"), + $_->{'default'}, + $_->{'name'}, + $names->{'strings'}[$_->{'name'}][3][1]{1033}); + $settings = $_->{'settings'}; + foreach (sort { $a <=> $b } keys %$settings) { + $fh->printf("\tSetting %d, name %d # '%s'\n", + $_, $settings->{$_}, $names->{'strings'}[$settings->{$_}][3][1]{1033}); + } + } + + $self; +} + +sub settingName +{ + my ($self, $feature, $setting) = @_; + + $self->read; + + my $names = $self->{' PARENT'}->{'name'}; + $names->read; + + my $features = $self->{'features'}; + my ($featureEntry) = grep { $_->{'feature'} == $feature } @$features; + my $featureName = $names->{'strings'}[$featureEntry->{'name'}][3][1]{1033}; + my $settingName = $featureEntry->{'exclusive'} + ? $names->{'strings'}[$featureEntry->{'settings'}->{$setting}][3][1]{1033} + : $names->{'strings'}[$featureEntry->{'settings'}->{$setting & ~1}][3][1]{1033} + . (($setting & 1) == 0 ? " On" : " Off"); + + ($featureName, $settingName); +} + +=head2 $t->tag_to_num ($feat_str) + +Convert an alphanumeric feature id tag (string) to a number (32-bit). +Tags are normally 4 chars. Graphite ignores space +padding if it is present, so we do the same here. + +=cut + +sub tag_to_num +{ + my ($self, $feat_tag) = @_; + my $new_feat_num; + + if ($feat_tag > 0) + {$new_feat_num = $feat_tag;} # already a number, so just return it. + else + { + $feat_tag =~ s/[ \000]+$//o; # strip trailing nulls or space + $new_feat_num = unpack('N', pack('a4', $feat_tag)); #adds null padding on right if less than 4 chars + } + + return $new_feat_num; +} + +=head2 $t->num_to_tag ($feat_num) + +Convert a feature id number (32-bit) back to a tag (string). +Trailing space or null padding is removed. +Feature id numbers that do not represent alphanumeric tags +are returned unchanged. + +=cut + +sub num_to_tag +{ + my ($self, $feat_num) = @_; + my $new_feat_tag; + + if ($feat_num > 0x01000000) + { + $new_feat_tag = unpack('a4', pack('N', $feat_num)); + $new_feat_tag =~ s/[ \000]+$//o; # strip trailing nulls or space + } + else + {$new_feat_tag = $feat_num;} + + return $new_feat_tag; +} + +1; + +=head1 BUGS + +The version 1 Feat table ends with a feature (id 1) named NoName +with zero settings but with an offset to the last entry in the setting +array. This last setting has id 0 and an invalid name id. This last +feature is changed to have one setting. + +=head1 AUTHOR + +Alan Ward (derived from Jonathan Kew's Feat.pm). + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hdmx.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hdmx.pm new file mode 100644 index 0000000000..2b2f7c56b2 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hdmx.pm @@ -0,0 +1,172 @@ +package Font::TTF::Hdmx; + +=head1 NAME + +Font::TTF::Hdmx - Horizontal device metrics + +=head1 DESCRIPTION + +The table consists of an hash of device metric tables indexed by the ppem for +that subtable. Each subtable consists of an array of advance widths in pixels +for each glyph at that ppem (horizontally). + +=head1 INSTANCE VARIABLES + +Individual metrics are accessed using the following referencing: + + $f->{'hdmx'}{$ppem}[$glyph_num] + +In addition there is one instance variable: + +=over 4 + +=item Num + +Number of device tables. + +=back + +=head2 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the table into data structures + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($numg, $ppem, $i, $numt, $dat, $len); + + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + $fh->read($dat, 8); + ($self->{'Version'}, $numt, $len) = unpack("nnN", $dat); + $self->{'Num'} = $numt; + + for ($i = 0; $i < $numt; $i++) + { + $fh->read($dat, $len); + $ppem = unpack("C", $dat); + $self->{$ppem} = [unpack("C$numg", substr($dat, 2))]; + } + $self; +} + + +=head2 $t->out($fh) + +Outputs the device metrics for this font + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg, $i, $pad, $len, $numt, @ppem, $max); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + @ppem = grep(/^\d+$/, sort {$a <=> $b} keys %$self); + $pad = "\000" x (3 - ($numg + 1) % 4); + $len = $numg + 2 + length($pad); + $fh->print(pack("nnN", 0, $#ppem + 1, $len)); + for $i (@ppem) + { + $max = 0; + foreach (@{$self->{$i}}[0..($numg - 1)]) + { $max = $_ if $_ > $max; } + $fh->print(pack("C*", $i, $max, @{$self->{$i}}[0..($numg - 1)]) . $pad); + } + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + + +=head2 $t->tables_do(&func) + +For each subtable it calls &sub($ref, $ppem) + +=cut + +sub tables_do +{ + my ($self, $func) = @_; + my ($i); + + foreach $i (grep(/^\d+$/, %$self)) + { &$func($self->{$i}, $i); } + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Outputs device metrics a little more tidily + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self->SUPER::XML_element(@_) if (ref($value) ne 'ARRAY'); + $fh->print("$depth\n"); + for ($i = 0; $i <= $#{$value}; $i += 25) + { + $fh->print("$depth$context->{'indent'}". join(' ', @{$value}[$i .. $i + 24]) . "\n"); + } + $fh->print("$depth\n"); + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Head.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Head.pm new file mode 100644 index 0000000000..e2211babd3 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Head.pm @@ -0,0 +1,273 @@ +package Font::TTF::Head; + +=head1 NAME + +Font::TTF::Head - The head table for a TTF Font + +=head1 DESCRIPTION + +This is a very basic table with just instance variables as described in the +TTF documentation, using the same names. One of the most commonly used is +C. + +=head1 INSTANCE VARIABLES + +The C table has no internal instance variables beyond those common to all +tables and those specified in the standard: + + version + fontRevision + checkSumAdjustment + magicNumber + flags + unitsPerEm + created + modified + xMin + yMin + xMax + yMax + macStyle + lowestRecPPEM + fontDirectionHint + indexToLocFormat + glyphDataFormat + +The two dates are held as an array of two unsigned longs (32-bits) + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'fontRevision' => 'f', + 'checkSumAdjustment' => 'L', + 'magicNumber' => 'L', + 'flags' => 'S', + 'unitsPerEm' => 'S', + 'created' => 'L2', + 'modified' => 'L2', + 'xMin' => 's', + 'yMin' => 's', + 'xMax' => 's', + 'yMax' => 's', + 'macStyle' => 'S', + 'lowestRecPPEM' => 'S', + 'fontDirectionHint' => 's', + 'indexToLocFormat' => 's', + 'glyphDataFormat' => 's'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory thanks to some utility functions + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read || return $self; + + init unless defined $fields{'Ascender'}; + $self->{' INFILE'}->read($dat, 54); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. If in memory +(which is usually) the checkSumAdjustment field is set to 0 as per the default +if the file checksum is not to be considered. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; # this is never true +# $self->{'checkSumAdjustment'} = 0 unless $self->{' PARENT'}{' wantsig'}; + $fh->print(TTF_Out_Fields($self, \%fields, 54)); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 54; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Handles date process for the XML exporter + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($output, @time); + my (@month) = qw(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC); + + return $self->SUPER::XML_element(@_) unless ($key eq 'created' || $key eq 'modified'); + + @time = gmtime($self->getdate($key eq 'created')); + $output = sprintf("%d/%s/%d %d:%d:%d", $time[3], $month[$time[4]], $time[5] + 1900, + $time[2], $time[1], $time[0]); + $fh->print("$depth<$key>$output\n"); + $self; +} + + +=head2 $t->update + +Updates the head table based on the glyph data and the hmtx table + +=cut + +sub update +{ + my ($self) = @_; + my ($num, $i, $loc, $hmtx); + my ($xMin, $yMin, $xMax, $yMax, $lsbx); + + return undef unless ($self->SUPER::update); + + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + return undef unless (defined $self->{' PARENT'}{'hmtx'} && defined $self->{' PARENT'}{'loca'}); + $hmtx = $self->{' PARENT'}{'hmtx'}->read; + + $self->{' PARENT'}{'loca'}->update; + $hmtx->update; # if we updated, then the flags will be set anyway. + $lsbx = 1; + for ($i = 0; $i < $num; $i++) + { + $loc = $self->{' PARENT'}{'loca'}{'glyphs'}[$i]; + next unless defined $loc; + $loc->read->update_bbox; + $xMin = $loc->{'xMin'} if ($loc->{'xMin'} < $xMin || $i == 0); + $yMin = $loc->{'yMin'} if ($loc->{'yMin'} < $yMin || $i == 0); + $xMax = $loc->{'xMax'} if ($loc->{'xMax'} > $xMax); + $yMax = $loc->{'yMax'} if ($loc->{'yMax'} > $yMax); + $lsbx &= ($loc->{'xMin'} == $hmtx->{'lsb'}[$i]); + } + $self->{'xMin'} = $xMin; + $self->{'yMin'} = $yMin; + $self->{'xMax'} = $xMax; + $self->{'yMax'} = $yMax; + if ($lsbx) + { $self->{'flags'} |= 2; } + else + { $self->{'flags'} &= ~2; } + $self; +} + + +=head2 $t->getdate($is_create) + +Converts font modification time (or creation time if $is_create is set) to a 32-bit integer as returned +from time(). Returns undef if the value is out of range, either before the epoch or after the maximum +storable time. + +=cut + +sub getdate +{ + my ($self, $is_create) = @_; + my (@arr) = (@{$self->{$is_create ? 'created' : 'modified'}}); + + $arr[1] -= 2082844800; # seconds between 1/Jan/1904 and 1/Jan/1970 (midnight) + if ($arr[1] < 0) + { + $arr[1] += 0xFFFFFFF; $arr[1]++; + $arr[0]--; + } + return undef if $arr[0] != 0; + return $arr[1]; +} + + +=head2 $t->setdate($time, $is_create) + +Sets the time information for modification (or creation time if $is_create is set) according to the 32-bit +time information. + +=cut + +sub setdate +{ + my ($self, $time, $is_create) = @_; + my (@arr); + + $arr[1] = $time; + if ($arr[1] >= 0x83DA4F80) + { + $arr[1] -= 0xFFFFFFFF; + $arr[1]--; + $arr[0]++; + } + $arr[1] += 2082844800; + $self->{$is_create ? 'created' : 'modified'} = \@arr; + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hhea.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hhea.pm new file mode 100644 index 0000000000..a7d5fdcc19 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hhea.pm @@ -0,0 +1,182 @@ +package Font::TTF::Hhea; + +=head1 NAME + +Font::TTF::Hhea - Horizontal Header table + +=head1 DESCRIPTION + +This is a simplte table with just standards specified instance variables + +=head1 INSTANCE VARIABLES + + version + Ascender + Descender + LineGap + advanceWidthMax + minLeftSideBearing + minRightSideBearing + xMaxExtent + caretSlopeRise + caretSlopeRun + metricDataFormat + numberOfHMetrics + + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'Ascender' => 's', + 'Descender' => 's', + 'LineGap' => 's', + 'advanceWidthMax' => 'S', + 'minLeftSideBearing' => 's', + 'minRightSideBearing' => 's', + 'xMaxExtent' => 's', + 'caretSlopeRise' => 's', + 'caretSlopeRun' => 's', + 'metricDataFormat' => '+10s', + 'numberOfHMetrics' => 'S'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory as instance variables + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + init unless defined $fields{'Ascender'}; + $self->{' INFILE'}->read($dat, 36); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $self->{'numberOfHMetrics'} = $self->{' PARENT'}{'hmtx'}->numMetrics || $self->{'numberOfHMetrics'}; + $fh->print(TTF_Out_Fields($self, \%fields, 36)); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 36; +} + + +=head2 $t->update + +Updates various parameters in the hhea table from the hmtx table. + +=cut + +sub update +{ + my ($self) = @_; + my ($hmtx) = $self->{' PARENT'}{'hmtx'}; + my ($glyphs); + my ($num, $res); + my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext); + + return undef unless ($self->SUPER::update); + return undef unless (defined $hmtx && defined $self->{' PARENT'}{'loca'}); + + $hmtx->read->update; + $self->{' PARENT'}{'loca'}->read->update; + $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'}; + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + for ($i = 0; $i < $num; $i++) + { + $aw = $hmtx->{'advance'}[$i]; + $lsb = $hmtx->{'lsb'}[$i]; + if (defined $glyphs->[$i]) + { $ext = $lsb + $glyphs->[$i]->read->{'xMax'} - $glyphs->[$i]{'xMin'}; } + else + { $ext = $aw; } + $maw = $aw if ($aw > $maw); + $mlsb = $lsb if ($lsb < $mlsb or $i == 0); + $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0); + $mext = $ext if ($ext > $mext); + } + $self->{'advanceWidthMax'} = $maw; + $self->{'minLeftSideBearing'} = $mlsb; + $self->{'minRightSideBearing'} = $mrsb; + $self->{'xMaxExtent'} = $mext; + $self->{'numberOfHMetrics'} = $hmtx->numMetrics; + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hmtx.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hmtx.pm new file mode 100644 index 0000000000..9fba573ba4 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Hmtx.pm @@ -0,0 +1,224 @@ +package Font::TTF::Hmtx; + +=head1 NAME + +Font::TTF::Hmtx - Horizontal Metrics + +=head1 DESCRIPTION + +Contains the advance width and left side bearing for each glyph. Given the +compressability of the data onto disk, this table uses information from +other tables, and thus must do part of its output during the output of +other tables + +=head1 INSTANCE VARIABLES + +The horizontal metrics are kept in two arrays by glyph id. The variable names +do not start with a space + +=over 4 + +=item advance + +An array containing the advance width for each glyph + +=item lsb + +An array containing the left side bearing for each glyph + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the horizontal metrics from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($numh, $numg); + + $numh = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'}; + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + $self->_read($numg, $numh, "advance", "lsb"); +} + +sub _read +{ + my ($self, $numg, $numh, $tAdv, $tLsb) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($i, $dat); + + for ($i = 0; $i < $numh; $i++) + { + $fh->read($dat, 4); + ($self->{$tAdv}[$i], $self->{$tLsb}[$i]) = unpack("nn", $dat); + $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768); + } + + $i--; + while (++$i < $numg) + { + $fh->read($dat, 2); + $self->{$tAdv}[$i] = $self->{$tAdv}[$numh - 1]; + $self->{$tLsb}[$i] = unpack("n", $dat); + $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768); + } + $self; +} + +=head2 $t->numMetrics + +Calculates again the number of long metrics required to store the information +here. Returns undef if the table has not been read. + +=cut + +sub numMetrics +{ + my ($self) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($i); + + return undef unless $self->{' read'}; + + for ($i = $numg - 2; $i >= 0; $i--) + { last if ($self->{'advance'}[$i] != $self->{'advance'}[$i + 1]); } + + return $i + 2; +} + + +=head2 $t->out($fh) + +Writes the metrics to a TTF file. Assumes that the C has updated the +numHMetrics from here + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($numh) = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'}; + $self->_out($fh, $numg, $numh, "advance", "lsb"); +} + +sub _out +{ + my ($self, $fh, $numg, $numh, $tAdv, $tLsb) = @_; + my ($i, $lsb); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + for ($i = 0; $i < $numg; $i++) + { + $lsb = $self->{$tLsb}[$i]; + $lsb += 65536 if $lsb < 0; + if ($i >= $numh) + { $fh->print(pack("n", $lsb)); } + else + { $fh->print(pack("n2", $self->{$tAdv}[$i], $lsb)); } + } + $self; +} + + +=head2 $t->update + +Updates the lsb values from the xMin from the each glyph + +=cut + +sub update +{ + my ($self) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($i); + + return undef unless ($self->SUPER::update); +# lsb & xMin must always be the same, regardless of any flags! +# return $self unless ($self->{' PARENT'}{'head'}{'flags'} & 2); # lsb & xMin the same + + $self->{' PARENT'}{'loca'}->update; + for ($i = 0; $i < $numg; $i++) + { + my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i]; + if ($g) + { $self->{'lsb'}[$i] = $g->read->update_bbox->{'xMin'}; } + else + { $self->{'lsb'}[$i] = 0; } + } + $self->{' PARENT'}{'head'}{'flags'} |= 2; + $self; +} + + +=head2 $t->out_xml($context, $depth) + +Outputs the table in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($addr) = ($self =~ m/\((.+)\)$/o); + my ($i); + + if ($context->{'addresses'}{$addr}) + { + $fh->printf("%s<%s id_ref='%s'/>\n", $depth, $context->{'name'}, $addr); + return $self; + } + else + { $fh->printf("%s<%s id='%s'>\n", $depth, $context->{'name'}, $addr); } + + $self->read; + + for ($i = 0; $i < $numg; $i++) + { $fh->print("$depth$context->{'indent'}\n"); } + + $fh->print("$depth{'name'}>\n"); + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern.pm new file mode 100644 index 0000000000..1ff2728ead --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern.pm @@ -0,0 +1,364 @@ +package Font::TTF::Kern; + +=head1 NAME + +Font::TTF::Kern - Kerning tables + +=head1 DESCRIPTION + +Kerning tables are held as an ordered collection of subtables each giving +incremental information regarding the kerning of various pairs of glyphs. + +The basic structure of the kerning data structure is: + + $kern = $f->{'kern'}{'tables'}[$tnum]{'kerns'}{$leftnum}{$rightnum}; + +Due to the possible complexity of some kerning tables the above information +is insufficient. Reference also needs to be made to the type of the table and +the coverage field. + +=head1 INSTANCE VARIABLES + +The instance variables for a kerning table are relatively straightforward. + +=over 4 + +=item Version + +Version number of the kerning table + +=item Num + +Number of subtables in the kerning table + +=item tables + +Array of subtables in the kerning table + +Each subtable has a number of instance variables. + +=over 4 + +=item kern + +A two level hash array containing kerning values. The indexing is left +is via left class and right class. It may seem using hashes is strange, +but most tables are not type 2 and this method saves empty array values. + +=item type + +Stores the table type. Only type 0 and type 2 tables are specified for +TrueType so far. + +=item coverage + +A bit field of coverage information regarding the kerning value. See the +TrueType specification for details. + +=item Version + +Contains the version number of the table. + +=item Num + +Number of kerning pairs in this type 0 table. + +=item left + +An array indexed by glyph - left_first which returns a class number for +the glyph in type 2 tables. + +=item right + +An array indexed by glyph - right_first which returns a class number for +the glyph in type 2 tables. + +=item left_first + +the glyph number of the first element in the left array for type 2 tables. + +=item right_first + +the glyph number of the first element in the right array for type 2 tables. + +=item num_left + +Number of left classes + +=item num_right + +Number of right classes + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::Table; +use Font::TTF::Kern::Subtable; + +@ISA = qw(Font::TTF::Table); +my @subtables = qw(OrderedList StateTable ClassArray CompactClassArray); + +=head2 $t->read + +Reads the whole kerning table into structures + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($dat, $i, $numt, $len, $cov, $t); + + $fh->read($dat, 4); + ($self->{'Version'}, $numt) = unpack("n2", $dat); + if ($self->{'Version'} > 0) + { + $fh->read($dat, 4, 4); + ($self->{'Version'}, $numt) = TTF_Unpack("vL", $dat); + } + $self->{'Num'} = $numt; + + for ($i = 0; $i < $numt; $i++) + { + if ($self->{'Version'} > 0) + { + $fh->read($dat, 8); + my ($length, $coverage, $index) = unpack("Nnn", $dat); + my ($type) = $coverage & 0xFF; + $t = Font::TTF::Kern::Subtable->create($type, $coverage, $length); + $t->read($fh); + } + else + { + $t = $self->read_subtable($fh); + } + push (@{$self->{'tables'}}, $t); + } + $self; +} + +sub read_subtable +{ + my ($self, $fh) = @_; + my ($dat, $len, $cov, $t); + + $t = {}; + $fh->read($dat, 6); + ($t->{'Version'}, $len, $cov) = unpack("n3", $dat); + $t->{'coverage'} = $cov & 255; + $t->{'type'} = $cov >> 8; + if ($t->{'Version'} == 0) + { + # NB: Cambria is an example of a font that plays an unsual trick: The + # kern table is much larger than can be represented by the header $len + # would allow. So we use the number of pairs to figure out how much to read. + $fh->read($dat, 8); + $t->{'Num'} = unpack("n", $dat); + $fh->read($dat, $t->{'Num'} * 6); + my (@vals) = unpack("n*", $dat); + for (0 .. ($t->{'Num'} - 1)) + { + my ($f, $l, $v); + $f = shift @vals; + $l = shift @vals; + $v = shift @vals; + $v -= 65536 if ($v > 32767); + $t->{'kern'}{$f}{$l} = $v; + } + } elsif ($t->{'Version'} == 2) + { + my ($wid, $off, $numg, $maxl, $maxr, $j); + + $fh->read($dat, $len - 6); + $wid = unpack("n", $dat); + $off = unpack("n", substr($dat, 2)); + ($t->{'left_first'}, $numg) = unpack("n2", substr($dat, $off)); + $t->{'left'} = [unpack("n$numg", substr($dat, $off + 4))]; + foreach (@{$t->{'left'}}) + { + $_ /= $wid; + $maxl = $_ if ($_ > $maxl); + } + $t->{'left_max'} = $maxl; + + $off = unpack("n", substr($dat, 4)); + ($t->{'right_first'}, $numg) = unpack("n2", substr($dat, $off)); + $t->{'right'} = [unpack("n$numg", substr($dat, $off + 4))]; + foreach (@{$t->{'right'}}) + { + $_ >>= 1; + $maxr = $_ if ($_ > $maxr); + } + $t->{'right_max'} = $maxr; + + $off = unpack("n", substr($dat, 6)); + for ($j = 0; $j <= $maxl; $j++) + { + my ($k) = 0; + + map { $t->{'kern'}{$j}{$k} = $_ if $_; $k++; } + unpack("n$maxr", substr($dat, $off + $wid * $j)); + } + } + return $t; +} + + +=head2 $t->out($fh) + +Outputs the kerning tables to the given file + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i, $l, $r, $t); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + if ($self->{'Version'} > 0) + { $fh->print(TTF_Pack("vL", $self->{'Version'}, $self->{'Num'})); } + else + { $fh->print(pack("n2", $self->{'Version'}, $self->{'Num'})); } + + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $t = $self->{'tables'}[$i]; + + if ($self->{'Version'} > 0) + { $t->out($fh); } + else + { $self->out_subtable($fh, $t); } + } + $self; +} + + +sub out_subtable +{ + my ($self, $fh, $t) = @_; + my ($loc) = $fh->tell(); + my ($loc1, $l, $r); + + $fh->print(pack("nnn", $t->{'Version'}, 0, $t->{'coverage'})); + if ($t->{'Version'} == 0) + { + my ($dat); + foreach $l (sort {$a <=> $b} keys %{$t->{'kern'}}) + { + foreach $r (sort {$a <=> $b} keys %{$t->{'kern'}{$l}}) + { $dat .= TTF_Pack("SSs", $l, $r, $t->{'kern'}{$l}{$r}); } + } + $fh->print(TTF_Pack("SSSS", Font::TTF::Utils::TTF_bininfo(length($dat) / 6, 6))); + $fh->print($dat); + } elsif ($t->{'Version'} == 2) + { + my ($arr); + + $fh->print(pack("nnnn", $t->{'right_max'} << 1, 8, ($#{$t->{'left'}} + 7) << 1, + ($#{$t->{'left'}} + $#{$t->{'right'}} + 10) << 1)); + + $fh->print(pack("nn", $t->{'left_first'}, $#{$t->{'left'}} + 1)); + foreach (@{$t->{'left'}}) + { $fh->print(pack("C", $_ * (($t->{'left_max'} + 1) << 1))); } + + $fh->print(pack("nn", $t->{'right_first'}, $#{$t->{'right'}} + 1)); + foreach (@{$t->{'right'}}) + { $fh->print(pack("C", $_ << 1)); } + + $arr = "\000\000" x (($t->{'left_max'} + 1) * ($t->{'right_max'} + 1)); + foreach $l (keys %{$t->{'kern'}}) + { + foreach $r (keys %{$t->{'kern'}{$l}}) + { substr($arr, ($l * ($t->{'left_max'} + 1) + $r) << 1, 2) + = pack("n", $t->{'kern'}{$l}{$r}); } + } + $fh->print($arr); + } + $loc1 = $fh->tell(); + $fh->seek($loc + 2, 0); + $fh->print(pack("n", $loc1 - $loc)); + $fh->seek($loc1, 0); +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Handles outputting the kern hash into XML a little more tidily + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($f, $l); + + return $self->SUPER::XML_element(@_) unless ($key eq 'kern'); + $fh->print("$depth\n"); + foreach $f (sort {$a <=> $b} keys %{$value}) + { + foreach $l (sort {$a <=> $b} keys %{$value->{$f}}) + { $fh->print("$depth$context->{'indent'}\n"); } + } + $fh->print("$depth\n"); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +Only supports kerning table types 0 & 2. + +=item * + +No real support functions to I anything with the kerning tables yet. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/ClassArray.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/ClassArray.pm new file mode 100644 index 0000000000..c43446da9c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/ClassArray.pm @@ -0,0 +1,163 @@ +package Font::TTF::Kern::ClassArray; + +=head1 NAME + +Font::TTF::Kern::ClassArray - ClassArray Kern Subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + my $subtableStart = $fh->tell() - 8; + my $dat; + $fh->read($dat, 8); + my ($rowWidth, $leftClassTable, $rightClassTable, $array) = unpack("nnnn", $dat); + + $fh->seek($subtableStart + $leftClassTable, IO::File::SEEK_SET); + $fh->read($dat, 4); + my ($firstGlyph, $nGlyphs) = unpack("nn", $dat); + $fh->read($dat, $nGlyphs * 2); + my $leftClasses = []; + foreach (TTF_Unpack("S*", $dat)) { + push @{$leftClasses->[($_ - $array) / $rowWidth]}, $firstGlyph++; + } + + $fh->seek($subtableStart + $rightClassTable, IO::File::SEEK_SET); + $fh->read($dat, 4); + ($firstGlyph, $nGlyphs) = unpack("nn", $dat); + $fh->read($dat, $nGlyphs * 2); + my $rightClasses = []; + foreach (TTF_Unpack("S*", $dat)) { + push @{$rightClasses->[$_ / 2]}, $firstGlyph++; + } + + $fh->seek($subtableStart + $array, IO::File::SEEK_SET); + $fh->read($dat, $self->{'length'} - $array); + + my $offset = 0; + my $kernArray = []; + while ($offset < length($dat)) { + push @$kernArray, [ TTF_Unpack("s*", substr($dat, $offset, $rowWidth)) ]; + $offset += $rowWidth; + } + + $self->{'leftClasses'} = $leftClasses; + $self->{'rightClasses'} = $rightClasses; + $self->{'kernArray'} = $kernArray; + + $fh->seek($subtableStart + $self->{'length'}, IO::File::SEEK_SET); + + $self; +} + +=head2 $t->out_sub($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + +} + +sub dumpXML +{ + my ($self, $fh) = @_; + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + $fh->printf("\n"); + $self->dumpClasses($self->{'leftClasses'}, $fh); + $fh->printf("\n"); + + $fh->printf("\n"); + $self->dumpClasses($self->{'rightClasses'}, $fh); + $fh->printf("\n"); + + $fh->printf("\n"); + my $kernArray = $self->{'kernArray'}; + foreach (0 .. $#$kernArray) { + $fh->printf("\n", $_); + my $row = $kernArray->[$_]; + foreach (0 .. $#$row) { + $fh->printf("\n", $_, $row->[$_]); + } + $fh->printf("\n"); + } + $fh->printf("\n"); +} + +sub type +{ + return 'kernClassArray'; +} + + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/CompactClassArray.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/CompactClassArray.pm new file mode 100644 index 0000000000..a2f23453c6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/CompactClassArray.pm @@ -0,0 +1,103 @@ +package Font::TTF::Kern::CompactClassArray; + +=head1 NAME + +Font::TTF::Kern::CompactClassArray - Compact Class Array kern subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + die "incomplete"; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ + my ($self, $fh) = @_; + + die "incomplete"; + + $self; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + die "incomplete"; +} + + +sub type +{ + return 'kernCompactClassArray'; +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/OrderedList.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/OrderedList.pm new file mode 100644 index 0000000000..512693e2fe --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/OrderedList.pm @@ -0,0 +1,118 @@ +package Font::TTF::Kern::OrderedList; + +=head1 NAME + +Font::TTF::Kern::OrderedList - Ordered List Kern subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class, @options) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + my $dat; + $fh->read($dat, 8); + my ($nPairs, $searchRange, $entrySelector, $rangeShift) = unpack("nnnn", $dat); + + my $pairs = []; + foreach (1 .. $nPairs) { + $fh->read($dat, 6); + my ($left, $right, $kern) = TTF_Unpack("SSs", $dat); + push @$pairs, { 'left' => $left, 'right' => $right, 'kern' => $kern } if $kern != 0; + } + + $self->{'kernPairs'} = $pairs; + + $self; +} + +=head2 $t->out_sub($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ + my ($self, $fh) = @_; + + my $pairs = $self->{'kernPairs'}; + $fh->print(pack("nnnn", TTF_bininfo(scalar @$pairs, 6))); + + foreach (sort { $a->{'left'} <=> $b->{'left'} or $a->{'right'} <=> $b->{'right'} } @$pairs) { + $fh->print(TTF_Pack("SSs", $_->{'left'}, $_->{'right'}, $_->{'kern'})); + } +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub out_xml +{ + my ($self, $context, $depth, $k, $val) = @_; + my ($fh) = $context->{'fh'}; + + my $postVal = $self->post()->{'VAL'}; + + $fh = 'STDOUT' unless defined $fh; + foreach (@{$self->{'kernPairs'}}) { + $fh->printf("$depth$context->{'indent'}\n", $postVal->[$_->{'left'}], $postVal->[$_->{'right'}], $_->{'kern'}); + } +} + + +sub type +{ + return 'kernOrderedList'; +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/StateTable.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/StateTable.pm new file mode 100644 index 0000000000..6183130f96 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/StateTable.pm @@ -0,0 +1,153 @@ +package Font::TTF::Kern::StateTable; + +=head1 NAME + +Font::TTF::Kern::StateTable - State Table Kern subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Kern::Subtable; +use IO::File; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $stTableStart = $fh->tell(); + + my ($classes, $states, $entries) = AAT_read_state_table($fh, 0); + + foreach (@$entries) { + my $flags = $_->{'flags'}; + delete $_->{'flags'}; + $_->{'push'} = 1 if $flags & 0x8000; + $_->{'noAdvance'} = 1 if $flags & 0x4000; + $flags &= ~0xC000; + if ($flags != 0) { + my $kernList = []; + $fh->seek($stTableStart + $flags, IO::File::SEEK_SET); + while (1) { + $fh->read($dat, 2); + my $k = TTF_Unpack("s", $dat); + push @$kernList, ($k & ~1); + last if ($k & 1) != 0; + } + $_->{'kernList'} = $kernList; + } + } + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'entries'} = $entries; + + $fh->seek($stTableStart - 8 + $self->{'length'}, IO::File::SEEK_SET); + + $self; +} + +=head2 $t->out_sub($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ +} + +sub dumpXML +{ + my ($self, $fh) = @_; + + $fh->printf("\n"); + $self->dumpClasses($self->{'classes'}, $fh); + $fh->printf("\n"); + + $fh->printf("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\n", $_); + my $members = $states->[$_]; + foreach (0 .. $#$members) { + my $m = $members->[$_]; + $fh->printf("{'nextState'}); + $fh->printf(" push=\"1\"") if $m->{'push'}; + $fh->printf(" noAdvance=\"1\"") if $m->{'noAdvance'}; + if (exists $m->{'kernList'}) { + $fh->printf(">"); + foreach (@{$m->{'kernList'}}) { + $fh->printf("", $_); + } + $fh->printf("\n"); + } + else { + $fh->printf("/>\n"); + } + } + $fh->printf("\n"); + } + $fh->printf("\n"); +} + +sub type +{ + return 'kernStateTable'; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/Subtable.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/Subtable.pm new file mode 100644 index 0000000000..cbe6df3e94 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Kern/Subtable.pm @@ -0,0 +1,185 @@ +package Font::TTF::Kern::Subtable; + +=head1 NAME + +Font::TTF::Kern::Subtable - Kern Subtable superclass for AAT + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +require Font::TTF::Kern::OrderedList; +require Font::TTF::Kern::StateTable; +require Font::TTF::Kern::ClassArray; +require Font::TTF::Kern::CompactClassArray; + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + + bless $self, $class; +} + +sub create +{ + my ($class, $type, $coverage, $length) = @_; + + $class = ref($class) || $class; + + my $subclass; + if ($type == 0) { + $subclass = 'Font::TTF::Kern::OrderedList'; + } + elsif ($type == 1) { + $subclass = 'Font::TTF::Kern::StateTable'; + } + elsif ($type == 2) { + $subclass = 'Font::TTF::Kern::ClassArray'; + } + elsif ($type == 3) { + $subclass = 'Font::TTF::Kern::CompactClassArray'; + } + + my @options; + push @options,'vertical' if ($coverage & 0x8000) != 0; + push @options,'crossStream' if ($coverage & 0x4000) != 0; + push @options,'variation' if ($coverage & 0x2000) != 0; + + my ($subTable) = $subclass->new(@options); + + map { $subTable->{$_} = 1 } @options; + + $subTable->{'type'} = $type; + $subTable->{'length'} = $length; + + $subTable; +} + +=head2 $t->out($fh) + +Writes the table to a file + +=cut + +sub out +{ + my ($self, $fh) = @_; + + my $subtableStart = $fh->tell(); + my $type = $self->{'type'}; + my $coverage = $type; + $coverage += 0x8000 if $self->{'vertical'}; + $coverage += 0x4000 if $self->{'crossStream'}; + $coverage += 0x2000 if $self->{'variation'}; + + $fh->print(TTF_Pack("LSS", 0, $coverage, $self->{'tupleIndex'})); # placeholder for length + + $self->out_sub($fh); + + my $length = $fh->tell() - $subtableStart; + my $padBytes = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + $fh->seek($subtableStart, IO::File::SEEK_SET); + $fh->print(pack("N", $length)); + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub post +{ + my ($self) = @_; + + my $post = $self->{' PARENT'}{' PARENT'}{'post'}; + if (defined $post) { + $post->read; + } + else { + $post = {}; + } + + return $post; +} + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + $fh = 'STDOUT' unless defined $fh; +} + +=head2 $t->print_classes($fh) + +Prints a human-readable representation of the table + +=cut + +sub print_classes +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + my $classes = $self->{'classes'}; + foreach (0 .. $#$classes) { + my $class = $classes->[$_]; + if (defined $class) { + $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class)); + } + } +} + +sub dumpClasses +{ + my ($self, $classes, $fh) = @_; + my $post = $self->post(); + + foreach (0 .. $#$classes) { + my $c = $classes->[$_]; + if ($#$c > -1) { + $fh->printf("\n", $_); + foreach (@$c) { + $fh->printf("\n", $_, $post->{'VAL'}[$_]); + } + $fh->printf("\n"); + } + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/LTSH.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/LTSH.pm new file mode 100644 index 0000000000..9f59eb9062 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/LTSH.pm @@ -0,0 +1,110 @@ +package Font::TTF::LTSH; + +=head1 NAME + +Font::TTF::LTSH - Linear Threshold table + +=head1 DESCRIPTION + +Holds the linear threshold for each glyph. This is the ppem value at which a +glyph's metrics become linear. The value is set to 1 if a glyph's metrics are +always linear. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item glyphs + +An array of ppem values. One value per glyph + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($numg, $dat); + + $fh->read($dat, 4); + ($self->{'Version'}, $numg) = unpack("nn", $dat); + $self->{'Num'} = $numg; + + $fh->read($dat, $numg); + $self->{'glyphs'} = [unpack("C$numg", $dat)]; + $self; +} + + +=head2 $t->out($fh) + +Outputs the LTSH to the given fh. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + $fh->print(pack("nn", 0, $numg)); + $fh->print(pack("C$numg", @{$self->{'glyphs'}})); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Loca.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Loca.pm new file mode 100644 index 0000000000..8cddd0c6f9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Loca.pm @@ -0,0 +1,197 @@ +package Font::TTF::Loca; + +=head1 NAME + +Font::TTF::Loca - the Locations table, which is intimately tied to the glyf table + +=head1 DESCRIPTION + +The location table holds the directory of locations of each glyph within the +glyf table. Due to this relationship and the unimportance of the actual locations +when it comes to holding glyphs in memory, reading the location table results +in the creation of glyph objects for each glyph and stores them here. +So if you are looking for glyphs, do not look in the C table, look here +instead. + +Things get complicated if you try to change the glyph list within the one table. +The recommendation is to create another clean location object to replace this +table in the font, ensuring that the old table is read first and to transfer +or copy glyphs across from the read table to the new table. + +=head1 INSTANCE VARIABLES + +The instance variables do not start with a space + +=over 4 + +=item glyphs + +An array of glyph objects for each glyph. + +=item glyphtype + +A string containing the class name to create for each new glyph. If empty, +defaults to L. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +require Font::TTF::Glyph; + + +=head2 $t->new + +Creates a new location table making sure it has a glyphs array + +=cut + +sub new +{ + my ($class) = shift; + my ($res) = $class->SUPER::new(@_); + $res->{'glyphs'} = []; + $res; +} + +=head2 $t->read + +Reads the location table creating glyph objects (L) for each glyph +allowing their later reading. + +=cut + +sub read +{ + my ($self) = @_; + + # Do this before $self->SUPER::read because this can alter the file pointer: + my ($glyfLoc) = $self->{' PARENT'}{'glyf'}->_read->{' OFFSET'}; # May seek on $fh! + + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($locFmt) = $self->{' PARENT'}{'head'}{'indexToLocFormat'}; + my ($numGlyphs) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($dat, $last, $i, $loc); + + $fh->read($dat, $locFmt ? 4 : 2); + $last = unpack($locFmt ? "N" : "n", $dat); + for ($i = 0; $i < $numGlyphs; $i++) + { + $fh->read($dat, $locFmt ? 4 : 2); + $loc = unpack($locFmt ? "N" : "n", $dat); + $self->{'glyphs'}[$i] = ($self->{'glyphtype'} || "Font::TTF::Glyph")->new( + LOC => $last << ($locFmt ? 0 : 1), + OUTLOC => $last << ($locFmt ? 0 : 1), + PARENT => $self->{' PARENT'}, + INFILE => $self->{' PARENT'}{'glyf'}{' INFILE'}, + BASE => $glyfLoc, + OUTLEN => ($loc - $last) << ($locFmt ? 0 : 1), + LEN => ($loc - $last) << ($locFmt ? 0 : 1)) if ($loc != $last); + $last = $loc; + } + $self; +} + + +=head2 $t->out($fh) + +Writes the location table out to $fh. Notice that not having read the location +table implies that the glyf table has not been read either, so the numbers in +the location table are still valid. Let's hope that C and +C haven't changed otherwise we are in big trouble. + +The function uses the OUTLOC location in the glyph calculated when the glyf +table was attempted to be output. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($locFmt) = $self->{' PARENT'}{'head'}{'indexToLocFormat'}; + my ($numGlyphs) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($count, $i, $offset, $g); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + $count = 0; + for ($i = 0; $i < $numGlyphs; $i++) + { + $g = ($self->{'glyphs'}[$i]) || ""; + unless ($g) + { + $count++; + next; + } else + { + if ($locFmt) + { $fh->print(pack("N", $g->{' OUTLOC'}) x ($count + 1)); } + else + { $fh->print(pack("n", $g->{' OUTLOC'} >> 1) x ($count + 1)); } + $count = 0; + $offset = $g->{' OUTLOC'} + $g->{' OUTLEN'}; + } + } + $fh->print(pack($locFmt ? "N" : "n", ($locFmt ? $offset: $offset >> 1)) x ($count + 1)); +} + + +=head2 $t->out_xml($context, $depth) + +No need to output a loca table, this is dynamically generated + +=cut + +sub out_xml +{ return $_[0]; } + + +=head2 $t->glyphs_do(&func) + +Calls func for each glyph in this location table in numerical order: + + &func($glyph, $glyph_num) + +=cut + +sub glyphs_do +{ + my ($self, $func) = @_; + my ($i); + + for ($i = 0; $i <= $#{$self->{'glyphs'}}; $i++) + { &$func($self->{'glyphs'}[$i], $i) if defined $self->{'glyphs'}[$i]; } + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Manual.pod b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Manual.pod new file mode 100644 index 0000000000..ae07faaba0 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Manual.pod @@ -0,0 +1,220 @@ +=head1 NAME + +Font::TTF::Manual - Information regarding the whole module set + +=head1 INTRODUCTION + +This document looks at the whole issue of how the various modules in the +TrueType Font work together. As such it is partly information on this font +system and partly information on TrueType fonts in general. + +Due to the inter-relation between so many tables in a TrueType font, different +tables will make expectations as to which other tables exist. At the very least +a font should consist of a C table and a C table. The system has +been designed around the expectation that the necessary tables for font +rendering in the Windows environment exist. But inter table dependencies have +been kept to what are considered necessary. + +This module set is not meant as a simple to use, mindless, font editing suite, +but as a low-level, get your hands dirty, know what you are doing, set of +classes for those who understand the intricacies (and there are many) of +TrueType fonts. To this end, if you get something wrong in the data structures, +etc. then this module set won't tell you and will happily create fonts which +don't work. + +At the time of writing, not every TrueType table in existence has been +implemented! Only the core basic tables of TrueType 1.0 (i.e. no embedded bitmap +tables, no postscript type tables, no OpenType tables and no GX tables) have +been implemented. If you want to help by implementing another table or two, then +please go ahead and send me your code. For a full list of tables, see +L. + + +=head2 Design Principles + +PERL is not C++. C++ encourages methods to be written for changing and reading +each instance variable in a class. If we did this in this PERL program the +results would be rather large and slow. Instead, since most access will be read +access, we expose as much of the inner storage of an object to user access +directly via hash lookup. The advantage this gives are great. For example, by +following an instance variable chain, looking up the C parameter for a +particular glyph becomes: + + $f->{'loca'}{'glyphs'}[$glyph]{'yMax'} + +Or, if we are feeling very lazy and don't mind waiting: + + $f->{'loca'}{'glyphs'}[$f->{'cmap'}->ms_lookup(0x41)]{'yMax'} + +The disadvantage of this method is that it behoves module users to behave +themselves. Thus it does not hold your hand and ensure that if you make a change +to a table, that the table is marked as I, or that other tables are +updated accordingly. + +It is up to the application developer to understand the implications of the +changes they make to a font, and to take the necessary action to ensure that the +data they get out is what they want. Thus, you could go and change the C +value on a glyph and output a new font with this change, but it is up to you to +ensure that the font's bounding box details in the C table are correct, +and even that your changing C is well motivated. + +To help with using the system, each module (or table) will not only describe the +methods it supports, which are relatively few, but also the instance variables +it supports, which are many. Most of the variables directly reflect table +attributes as specified in the OpenType specification, available from Microsoft +(L), Adobe and Apple. A list of the names +used is also given in each module, but not necessarily with any further +description. After all, this code is not a TrueType manual as well! + + +=head2 Conventions + +There are various conventions used in this system. + +Firstly we consider the documentation conventions regarding instance variables. +Each instance variable is marked indicating whether it is a B<(P)>rivate +variable which users of the module are not expected to read and certainly not +write to or a B<(R)>ead only variable which users may well want to read but not +write to. + + +=head1 METHODS + +This section examines various methods and how the various modules work with +these methods. + + +=head2 read and read_dat + +Before the data structures for a table can be accessed, they need to be filled +in from somewhere. The usual way to do this is to read an existing TrueType +font. This may be achieved by: + + $f = Font::TTF::Font->open($filename) || die "Unable to read $filename"; + +This will open an existing font and read its directory header. Notice that at +this point, none of the tables in the font have been read. (Actually, the +C and C tables are read at this point too since they contain the +commonly required parameters of): + + $f->{'head'}{'unitsPerEm'} + $f->{'maxp'}{'numGlyphs'} + +In order to be able to access information from a table, it is first necessary to +C it. Consider trying to find the advance width of a space character +(U+0020). The following code should do it: + + $f = Font::TTF::Font->open($ARGV[0]); + $snum = $f->{'cmap'}->ms_lookup(0x0020); + $sadv = $f->{'hmtx'}{'advance'}[$snum]; + print $sadv; + +This would result in the value zero being printed, which is far from correct. +But why? The first line would correctly read the font directory. The second line +would, incidently, correctly locate the space character in the Windows cmap +(assuming a non symbol encoded font). The third line would not succeed in its +task since the C table has not been filled in from the font file. To +achieve what we want we would first need to cause it to be read: + + $f->{'hmtx'}->read; + $sadv = $f->{'hmtx'}{'advance'}[$snum]; + +Or for those who are too lazy to write multiple lines, C returns the +object it reads. Thus we could write: + + $sadv = $f->{'hmtx'}->read->{'advance'}[$snum]; + +Why, if we always have to read tables before accessing information from them, +did we not have to do this for the C table? The answer lies in the method +call. It senses that the table hasn't been read and reads it for us. This will +generally happen with all method calls, it is only when we do direct data access +that we have to take the responsibility to read the table first. + +Reading a table does not necessarily result in all the data being placed into +internal data structures. In the case of a simple table C is sufficient. +In fact, the normal case is that C reads the data from the file into +an instance variable called C<' dat'> (including the space) and not into the +data structures. + +This is true except for the C class which represents a single glyph. Here +the process is reversed. Reading a C reads the data for the glyph into +the C<' dat'> instance variable and sets various header attributes for the glyph +(C, C, etc.). The data is converted out of the variable into +data structures via the C method. + +The aim, therefore, is that C should do the natural thing (read into data +structures for those tables and elements for which it is helpful -- all except +C at present) and C should do the unnatural thing: read just +the binary data for normal tables and convert binary data to data structures for +Cs. + +In summary, therefore, use C unless you want to hack around with the +internals of glyphs in which case see L for more details. + + +=head2 update + +The aim of this method is to allow the various data elements in a C font +to update themselves. All tables know how to update themselves. All tables also +contain information which cannot be I but is new knowledge in the font. +As a result, certain tables do nothing when they are updated. We can, therefore, +build an update hierarchy of tables, with the independent tables at the bottom +and C at the top: + + +--loca + | + glyf--+--maxp + | + +---+--head + | + hmtx------+--hhea + + cmap-----OS/2 + + name-- + + post-- +There is an important universal dependency which it is up to the user to +keep up to date. This is C which is used to iterate over all +the glyphs. Note that the glyphs themselves are not held in the C table +but in the C table, so adding glyphs, etc. automatically involves keeping +the C table up to date. + +=head2 Creating fonts + +Suppose we were creating a font from scratch. How much information do we need +to supply and how much will C do for us? + +The following information is required: + + $f->{'loca'}{'glyphs'} + $f->{'head'}{'upem'} + $f->{'maxp'}{'numGlyphs'} (doesn't come from $f->{'loca'}{'glyphs'}) + $f->{'hmtx'}{'advance'} + $f->{'post'}['format'} + $f->{'post'}{'VAL'} + $f->{'cmap'} + $f->{'name'} + +Pretty much everything else is calculated for you. Details of what is needed +for a glyph may be found in L. Once we have all the +information we need (and there is lots more that you could add) then we simply + + $f->dirty; # mark all tables dirty + $f->update; # update the font + +=head1 AUTHOR + +Martin Hosken L. +(see CONTRIBUTORS for other authors). + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut + +1; diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Maxp.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Maxp.pm new file mode 100644 index 0000000000..ab67a0e700 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Maxp.pm @@ -0,0 +1,199 @@ +package Font::TTF::Maxp; + +=head1 NAME + +Font::TTF::Maxp - Maximum Profile table in a font + +=head1 DESCRIPTION + +A collection of useful instance variables following the TTF standard. Probably +the most used being C. Note that this particular value is +foundational and should be kept up to date by the application, it is not updated +by C. + +Handles table versions 0.5, 1.0 + +=head1 INSTANCE VARIABLES + +No others beyond those specified in the standard: + + numGlyphs + maxPoints + maxContours + maxCompositePoints + maxCompositeContours + maxZones + maxTwilightPoints + maxStorage + maxFunctionDefs + maxInstructionDefs + maxStackElements + maxSizeOfInstructions + maxComponentElements + maxComponentDepth + + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'numGlyphs' => 'S', + 'maxPoints' => 'S', + 'maxContours' => 'S', + 'maxCompositePoints' => 'S', + 'maxCompositeContours' => 'S', + 'maxZones' => 'S', + 'maxTwilightPoints' => 'S', + 'maxStorage' => 'S', + 'maxFunctionDefs' => 'S', + 'maxInstructionDefs' => 'S', + 'maxStackElements' => 'S', + 'maxSizeOfInstructions' => 'S', + 'maxComponentElements' => 'S', + 'maxComponentDepth' => 'S'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + + init unless defined $fields{'numGlyphs'}; # any key would do + $self->{' INFILE'}->read($dat, 4); + $self->{'version'} = TTF_Unpack("v", $dat); + + if ($self->{'version'} == 0.5) + { + $self->{' INFILE'}->read($dat, 2); + $self->{'numGlyphs'} = unpack("n", $dat); + } else + { + $self->{' INFILE'}->read($dat, 28); + TTF_Read_Fields($self, $dat, \%fields); + } + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + $fh->print(TTF_Pack("v", $self->{'version'})); + + if ($self->{'version'} == 0.5) + { $fh->print(pack("n", $self->{'numGlyphs'})); } + else + { $fh->print(TTF_Out_Fields($self, \%fields, 28)); } + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + + +=head2 $t->update + +Calculates all the maximum values for a font based on the glyphs in the font. +Only those fields which require hinting code interpretation are ignored and +left as they were read. + +=cut + +sub update +{ + my ($self) = @_; + my ($i, $num, @n, @m, $j); + my (@name) = qw(maxPoints maxContours maxCompositePoints maxCompositeContours + maxSizeOfInstructions maxComponentElements maxComponentDepth); + + return undef unless ($self->SUPER::update); + return undef if ($self->{'version'} == 0.5); # only got numGlyphs + return undef unless (defined $self->{' PARENT'}{'loca'}); + $self->{' PARENT'}{'loca'}->update; + $num = $self->{'numGlyphs'}; + + for ($i = 0; $i < $num; $i++) + { + my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i] || next; + + @n = $g->maxInfo; + + for ($j = 0; $j <= $#n; $j++) + { $m[$j] = $n[$j] if $n[$j] > $m[$j]; } + } + + foreach ('prep', 'fpgm') + { $m[4] = length($self->{' PARENT'}{$_}{' dat'}) + if (defined $self->{' PARENT'}{$_} + && length($self->{' PARENT'}{$_}{' dat'}) > $m[4]); + } + + for ($j = 0; $j <= $#name; $j++) + { $self->{$name[$j]} = $m[$j]; } + $self; +} +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort.pm new file mode 100644 index 0000000000..d9196d755c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort.pm @@ -0,0 +1,130 @@ +package Font::TTF::Mort; + +=head1 NAME + +Font::TTF::Mort - Glyph Metamorphosis table in a font + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Mort::Chain; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh, $numChains); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + + $fh->read($dat, 8); + ($self->{'version'}, $numChains) = TTF_Unpack("vL", $dat); + + my $chains = []; + foreach (1 .. $numChains) { + my $chain = new Font::TTF::Mort::Chain->new; + $chain->read($fh); + $chain->{' PARENT'} = $self; + push @$chains, $chain; + } + + $self->{'chains'} = $chains; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $chains = $self->{'chains'}; + $fh->print(TTF_Pack("vL", $self->{'version'}, scalar @$chains)); + + foreach (@$chains) { + $_->out($fh); + } +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read unless $self->{' read'}; + my $feat = $self->{' PARENT'}->{'feat'}; + $feat->read; + my $post = $self->{' PARENT'}->{'post'}; + $post->read; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\n", $self->{'version'}); + + my $chains = $self->{'chains'}; + foreach (@$chains) { + $_->print($fh); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Chain.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Chain.pm new file mode 100644 index 0000000000..c08ba7bfb7 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Chain.pm @@ -0,0 +1,206 @@ +package Font::TTF::Mort::Chain; + +=head1 NAME + +Font::TTF::Mort::Chain - Chain Mort subtable for AAT + +=cut + +use strict; +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Mort::Subtable; +use IO::File; + +=head2 $t->new + +=cut + +sub new +{ + my ($class, %parms) = @_; + my ($self) = {}; + my ($p); + + $class = ref($class) || $class; + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +=head2 $t->read($fh) + +Reads the chain into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $chainStart = $fh->tell(); + $fh->read($dat, 12); + my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat); + + my $featureEntries = []; + foreach (1 .. $nFeatureEntries) { + $fh->read($dat, 12); + my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat); + push @$featureEntries, { + 'type' => $featureType, + 'setting' => $featureSetting, + 'enable' => $enableFlags, + 'disable' => $disableFlags + }; + } + + my $subtables = []; + foreach (1 .. $nSubtables) { + my $subtableStart = $fh->tell(); + + $fh->read($dat, 8); + my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat); + my $type = $coverage & 0x0007; + + my $subtable = Font::TTF::Mort::Subtable->create($type, $coverage, $subFeatureFlags, $length); + $subtable->read($fh); + $subtable->{' PARENT'} = $self; + + push @$subtables, $subtable; + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); + } + + $self->{'defaultFlags'} = $defaultFlags; + $self->{'featureEntries'} = $featureEntries; + $self->{'subtables'} = $subtables; + + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + my $chainStart = $fh->tell(); + my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'}); + $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length + + foreach (@$featureEntries) { + $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'})); + } + + foreach (@$subtables) { + $_->out($fh); + } + + my $chainLength = $fh->tell() - $chainStart; + $fh->seek($chainStart + 4, IO::File::SEEK_SET); + $fh->print(pack("N", $chainLength)); + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the chain + +=cut + +sub feat +{ + my ($self) = @_; + + my $feat = $self->{' PARENT'}{' PARENT'}{'feat'}; + if (defined $feat) { + $feat->read; + } + else { + $feat = {}; + } + + return $feat; +} + +sub print +{ + my ($self, $fh) = @_; + + $fh->printf("version %f\n", $self->{'version'}); + + my $defaultFlags = $self->{'defaultFlags'}; + $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags); + + my $feat = $self->feat(); + my $featureEntries = $self->{'featureEntries'}; + foreach (@$featureEntries) { + $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n", + $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}, + $feat->settingName($_->{'type'}, $_->{'setting'})); + } + + my $subtables = $self->{'subtables'}; + foreach (@$subtables) { + my $type = $_->{'type'}; + my $subFeatureFlags = $_->{'subFeatureFlags'}; + $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n", + subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags, + "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"), + join(", ", + map { + join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) ) + } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries + ) ); + + $_->print($fh); + } +} + +sub subtable_type_ +{ + my ($val) = @_; + my ($res); + + my @types = ( + 'Rearrangement', + 'Contextual', + 'Ligature', + undef, + 'Non-contextual', + 'Insertion', + ); + $res = $types[$val] or ('Undefined (' . $val . ')'); + + $res; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Contextual.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Contextual.pm new file mode 100644 index 0000000000..1c70a19cd9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Contextual.pm @@ -0,0 +1,166 @@ +package Font::TTF::Mort::Contextual; + +=head1 NAME + +Font::TTF::Mort::Contextual - Contextual Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 10); + my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $self->{'length'} - 8]; + + foreach (@$entries) { + my $actions = $_->{'actions'}; + foreach (@$actions) { + $_ = $_ ? $_ - ($mappingTables / 2) : undef; + } + } + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))]; + + $self; +} + +=head2 $t->pack_sub() + +=cut + +sub pack_sub +{ + my ($self) = @_; + + my ($dat) = pack("nnnnn", (0) x 5); # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables + + my $classTable = length($dat); + my $classes = $self->{'classes'}; + $dat .= AAT_pack_classes($classes); + + my $stateArray = length($dat); + my $states = $self->{'states'}; + my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, + sub { + my $actions = $_->{'actions'}; + ( $_->{'flags'}, @$actions ) + } + ); + $dat .= $dat1; + + my $entryTable = length($dat); + my $offset = ($entryTable + 8 * @$entries) / 2; + foreach (@$entries) { + my ($nextState, $flags, @parts) = split /,/; + $dat .= pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts); + } + + my $mappingTables = length($dat); + my $mappings = $self->{'mappings'}; + $dat .= pack("n*", @$mappings); + + $dat1 = pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $mappings = $self->{'mappings'}; + foreach (0 .. $#$mappings) { + $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Insertion.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Insertion.pm new file mode 100644 index 0000000000..75d39aa6a8 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Insertion.pm @@ -0,0 +1,189 @@ +package Font::TTF::Mort::Insertion; + +=head1 NAME + +Font::TTF::Mort::Insertion - Insertion Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $subtableStart = $fh->tell(); + + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + my %insertListHash; + my $insertLists; + foreach (@$entries) { + my $flags = $_->{'flags'}; + my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f)); + my $actions = $_->{'actions'}; + foreach (0 .. 1) { + if ($insertCount[$_] > 0) { + $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET); + $fh->read($dat, $insertCount[$_] * 2); + if (not defined $insertListHash{$dat}) { + push @$insertLists, [unpack("n*", $dat)]; + $insertListHash{$dat} = $#$insertLists; + } + $actions->[$_] = $insertListHash{$dat}; + } + else { + $actions->[$_] = undef; + } + } + } + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'insertLists'} = $insertLists; + + $self; +} + +=head2 $t->pack_sub() + +=cut + +sub pack_sub +{ + my ($self) = @_; + + my ($dat) = pack("nnnn", (0) x 4); + + my $classTable = length($dat); + my $classes = $self->{'classes'}; + $dat .= AAT_pack_classes($classes); + + my $stateArray = length($dat); + my $states = $self->{'states'}; + my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, + sub { + my $actions = $_->{'actions'}; + ( $_->{'flags'}, @$actions ) + } + ); + $dat .= $dat1; + + my $entryTable = length($dat); + my $offset = ($entryTable + 8 * @$entries); + my @insListOffsets; + my $insertLists = $self->{'insertLists'}; + foreach (@$insertLists) { + push @insListOffsets, $offset; + $offset += 2 * scalar @$_; + } + foreach (@$entries) { + my ($nextState, $flags, @lists) = split /,/; + $flags &= ~0x03ff; + $flags |= (scalar @{$insertLists->[$lists[0]]}) << 5 if $lists[0] ne ''; + $flags |= (scalar @{$insertLists->[$lists[1]]}) if $lists[1] ne ''; + $dat .= pack("nnnn", $nextState, $flags, + map { $_ eq '' ? 0 : $insListOffsets[$_] } @lists); + } + + foreach (@$insertLists) { + $dat .= pack("n*", @$_); + } + + $dat1 = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $insertLists = $self->{'insertLists'}; + foreach (0 .. $#$insertLists) { + my $insertList = $insertLists->[$_]; + $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList)); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Ligature.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Ligature.pm new file mode 100644 index 0000000000..c5f1a08d70 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Ligature.pm @@ -0,0 +1,256 @@ +package Font::TTF::Mort::Ligature; + +=head1 NAME + +Font::TTF::Mort::Ligature - Ligature Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 0); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 14); + my ($stateSize, $classTable, $stateArray, $entryTable, + $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $self->{'length'} - 8]; + + my %actions; + my $actionLists; + foreach (@$entries) { + my $offset = $_->{'flags'} & 0x3fff; + $_->{'flags'} &= ~0x3fff; + if ($offset != 0) { + if (not defined $actions{$offset}) { + $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET); + my $actionList; + while (1) { + $fh->read($dat, 4); + my $action = unpack("N", $dat); + my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff)); + $component -= 0x40000000 if $component > 0x1fffffff; + $component -= $componentTable / 2; + push @$actionList, { 'store' => $store, 'component' => $component }; + last if $last; + } + push @$actionLists, $actionList; + $actions{$offset} = $#$actionLists; + } + $_->{'actions'} = $actions{$offset}; + } + } + + $self->{'componentTable'} = $componentTable; + my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))]; + foreach (@$components) { + $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable; + } + $self->{'components'} = $components; + + $self->{'ligatureTable'} = $ligatureTable; + $self->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))]; + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'actionLists'} = $actionLists; + + $self; +} + +=head2 $t->pack_sub($fh) + +=cut + +sub pack_sub +{ + my ($self) = @_; + my ($dat); + + $dat .= pack("nnnnnnn", (0) x 7); # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures + + my $classTable = length($dat); + my $classes = $self->{'classes'}; + $dat .= AAT_pack_classes($classes); + + my $stateArray = length($dat); + my $states = $self->{'states'}; + + my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, + sub { + ( $_->{'flags'} & 0xc000, $_->{'actions'} ) + } + ); + $dat .= $dat1; + + my $actionLists = $self->{'actionLists'}; + my %actionListOffset; + my $actionListDataLength = 0; + my @actionListEntries; + foreach (0 .. $#$entries) { + my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]); + if ($offset eq "") { + $offset = undef; + } + else { + if (defined $actionListOffset{$offset}) { + $offset = $actionListOffset{$offset}; + } + else { + $actionListOffset{$offset} = $actionListDataLength; + my $list = $actionLists->[$offset]; + $actionListDataLength += 4 * @$list; + push @actionListEntries, $list; + $offset = $actionListOffset{$offset}; + } + } + $entries->[$_] = [ $nextState, $flags, $offset ]; + } + my $entryTable = length($dat); + my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3; + foreach (@$entries) { + $_->[2] += $ligActionLists if defined $_->[2]; + $dat .= pack("nn", $_->[0], $_->[1] + $_->[2]); + } + $dat .= pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4)); + + die "internal error" unless length($dat) == $ligActionLists; + + my $componentTable = length($dat) + $actionListDataLength; + my $actionList; + foreach $actionList (@actionListEntries) { + foreach (0 .. $#$actionList) { + my $action = $actionList->[$_]; + my $val = $action->{'component'} + $componentTable / 2; + $val += 0x40000000 if $val < 0; + $val &= 0x3fffffff; + $val |= 0x40000000 if $action->{'store'}; + $val |= 0x80000000 if $_ == $#$actionList; + $dat .= pack("N", $val); + } + } + + die "internal error" unless length($dat) == $componentTable; + + my $components = $self->{'components'}; + my $ligatureTable = $componentTable + @$components * 2; + $dat .= pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components); + + my $ligatures = $self->{'ligatures'}; + $dat .= pack("n*", @$ligatures); + + $dat1 = pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "="); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $actionLists = $self->{'actionLists'}; + foreach (0 .. $#$actionLists) { + $fh->printf("\t\tList %d:\t", $_); + my $actionList = $actionLists->[$_]; + $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList)); + } + + my $ligatureTable = $self->{'ligatureTable'}; + + $fh->print("\n"); + my $components = $self->{'components'}; + foreach (0 .. $#$components) { + $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]); + } + + $fh->print("\n"); + my $ligatures = $self->{'ligatures'}; + foreach (0 .. $#$ligatures) { + $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Noncontextual.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Noncontextual.pm new file mode 100644 index 0000000000..52788cbaf7 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Noncontextual.pm @@ -0,0 +1,105 @@ +package Font::TTF::Mort::Noncontextual; + +=head1 NAME + +Font::TTF::Mort::Noncontextual - Noncontextual Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{'length'} - 8, undef); + $self->{'format'} = $format; + $self->{'lookup'} = $lookup; + + $self; +} + +=head2 $t->pack_sub($fh) + +=cut + +sub pack_sub +{ + my ($self) = @_; + + return AAT_pack_lookup($self->{'format'}, $self->{'lookup'}, 2, undef); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + my $lookup = $self->{'lookup'}; + $fh->printf("\t\tLookup format %d\n", $self->{'format'}); + if (defined $lookup) { + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]); + } + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Rearrangement.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Rearrangement.pm new file mode 100644 index 0000000000..2e3d393c6d --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Rearrangement.pm @@ -0,0 +1,118 @@ +package Font::TTF::Mort::Rearrangement; + +=head1 NAME + +Font::TTF::Mort::Rearrangement - Rearrangement Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + my ($classes, $states) = AAT_read_state_table($fh, 0); + $self->{'classes'} = $classes; + $self->{'states'} = $states; + + $self; +} + +=head2 $t->pack_sub() + +=cut + +sub pack_sub +{ + my ($self) = @_; + + return AAT_pack_state_table($self->{'classes'}, $self->{'states'}, 0); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + my @verbs = ( "0", "Ax->xA", "xD->Dx", "AxD->DxA", + "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx", + "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA", + "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA"); + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "<" if ($_->{'flags'} & 0x8000); + $flags .= ">" if ($_->{'flags'} & 0x2000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]); + } + $fh->print("\n"); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Subtable.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Subtable.pm new file mode 100644 index 0000000000..c5497d7269 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Mort/Subtable.pm @@ -0,0 +1,210 @@ +package Font::TTF::Mort::Subtable; + +=head1 NAME + +Font::TTF::Mort::Subtable - Mort subtable superclass for AAT + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +require Font::TTF::Mort::Rearrangement; +require Font::TTF::Mort::Contextual; +require Font::TTF::Mort::Ligature; +require Font::TTF::Mort::Noncontextual; +require Font::TTF::Mort::Insertion; + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + + bless $self, $class; +} + +sub create +{ + my ($class, $type, $coverage, $subFeatureFlags, $length) = @_; + + $class = ref($class) || $class; + + my $subclass; + if ($type == 0) { + $subclass = 'Font::TTF::Mort::Rearrangement'; + } + elsif ($type == 1) { + $subclass = 'Font::TTF::Mort::Contextual'; + } + elsif ($type == 2) { + $subclass = 'Font::TTF::Mort::Ligature'; + } + elsif ($type == 4) { + $subclass = 'Font::TTF::Mort::Noncontextual'; + } + elsif ($type == 5) { + $subclass = 'Font::TTF::Mort::Insertion'; + } + + my ($self) = $subclass->new( + (($coverage & 0x4000) ? 'RL' : 'LR'), + (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'), + $subFeatureFlags + ); + + $self->{'type'} = $type; + $self->{'length'} = $length; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file + +=cut + +sub out +{ + my ($self, $fh) = @_; + + my ($subtableStart) = $fh->tell(); + my ($type) = $self->{'type'}; + my ($coverage) = $type; + $coverage += 0x4000 if $self->{'direction'} eq 'RL'; + $coverage += 0x2000 if $self->{'orientation'} eq 'VH'; + $coverage += 0x8000 if $self->{'orientation'} eq 'V'; + + $fh->print(TTF_Pack("SSL", 0, $coverage, $self->{'subFeatureFlags'})); # placeholder for length + + my ($dat) = $self->pack_sub(); + $fh->print($dat); + + my ($length) = $fh->tell() - $subtableStart; + my ($padBytes) = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + $fh->seek($subtableStart, IO::File::SEEK_SET); + $fh->print(pack("n", $length)); + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub post +{ + my ($self) = @_; + + my ($post) = $self->{' PARENT'}{' PARENT'}{' PARENT'}{'post'}; + if (defined $post) { + $post->read; + } + else { + $post = {}; + } + + return $post; +} + +sub feat +{ + my ($self) = @_; + + return $self->{' PARENT'}->feat(); +} + +sub print +{ + my ($self, $fh) = @_; + + my ($feat) = $self->feat(); + my ($post) = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + my ($type) = $self->{'type'}; + my ($subFeatureFlags) = $self->{'subFeatureFlags'}; + my ($defaultFlags) = $self->{' PARENT'}{'defaultFlags'}; + my ($featureEntries) = $self->{' PARENT'}{'featureEntries'}; + $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n", + subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags, + "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"), + join(", ", + map { + join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) ) + } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries + ) ); +} + +sub subtable_type_ +{ + my ($val) = @_; + my ($res); + + my (@types) = ( + 'Rearrangement', + 'Contextual', + 'Ligature', + undef, + 'Non-contextual', + 'Insertion', + ); + $res = $types[$val] or ('Undefined (' . $val . ')'); + + $res; +} + +=head2 $t->print_classes($fh) + +Prints a human-readable representation of the table + +=cut + +sub print_classes +{ + my ($self, $fh) = @_; + + my ($post) = $self->post(); + + my ($classes) = $self->{'classes'}; + foreach (0 .. $#$classes) { + my $class = $classes->[$_]; + if (defined $class) { + $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class)); + } + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Name.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Name.pm new file mode 100644 index 0000000000..73b6a163b9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Name.pm @@ -0,0 +1,916 @@ +package Font::TTF::Name; + +=head1 NAME + +Font::TTF::Name - String table for a TTF font + +=head1 DESCRIPTION + +Strings are held by number, platform, encoding and language. Strings are +accessed as: + + $f->{'name'}{'strings'}[$number][$platform_id][$encoding_id]{$language_id} + +Notice that the language is held in an associative array due to its sparse +nature on some platforms such as Microsoft ($pid = 3). Notice also that the +array order is different from the stored array order (platform, encoding, +language, number) to allow for easy manipulation of strings by number (which is +what I guess most people will want to do). + +By default, C<$Font::TTF::Name::utf8> is set to 1, and strings will be stored as UTF8 wherever +possible. The method C can be used to find out if a string in a particular +platform and encoding will be returned as UTF8. Unicode strings are always +converted if utf8 is requested. Otherwise, strings are stored according to platform: + +You now have to set <$Font::TTF::Name::utf8> to 0 to get the old behaviour. + +=over 4 + +=item Apple Unicode (platform id = 0) + +Data is stored as network ordered UCS2. There is no encoding id for this platform +but there are language ids as per Mac language ids. + +=item Mac (platform id = 1) + +Data is stored as 8-bit binary data, leaving the interpretation to the user +according to encoding id. + +=item Unicode (platform id = 2) + +Currently stored as 16-bit network ordered UCS2. Upon release of Perl 5.005 this +will change to utf8 assuming current UCS2 semantics for all encoding ids. + +=item Windows (platform id = 3) + +As per Unicode, the data is currently stored as 16-bit network ordered UCS2. Upon +release of Perl 5.005 this will change to utf8 assuming current UCS2 semantics for +all encoding ids. + +=back + +=head1 INSTANCE VARIABLES + +=over 4 + +=item strings + +An array of arrays, etc. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA $VERSION @apple_encs @apple_encodings $utf8 $cp_1252 @cp_1252 %win_langs %langs_win %langs_mac @ms_langids @mac_langs); +use Font::TTF::Table; +use Font::TTF::Utils; +@ISA = qw(Font::TTF::Table); + +$utf8 = 1; + +{ + my ($count, $i); + eval {require Compress::Zlib;}; + unless ($@) + { + for ($i = 0; $i <= $#apple_encs; $i++) + { + $apple_encodings[0][$i] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $apple_encs[$i])))] + if (defined $apple_encs[$i]); + foreach (0 .. 127) + { $apple_encodings[0][$i][$_] = $_; } + $count = 0; + $apple_encodings[1][$i] = {map {$_ => $count++} @{$apple_encodings[0][$i]}}; + } + $cp_1252[0] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $cp_1252)))]; + $count = 0; + $cp_1252[1] = {map({$_ => $count++} @{$cp_1252[0]})}; + } + for ($i = 0; $i < $#ms_langids; $i++) + { + if (defined $ms_langids[$i][1]) + { + my ($j); + for ($j = 0; $j < $#{$ms_langids[$i][1]}; $j++) + { + my ($v) = $ms_langids[$i][1][$j]; + if ($v =~ m/^-/o) + { $win_langs{(($j + 1) << 10) + $i} = $ms_langids[$i][0] . $v; } + else + { $win_langs{(($j + 1) << 10) + $i} = $v; } + } + } + else + { $win_langs{$i + 0x400} = $ms_langids[$i][0]; } + } + %langs_win = map {my ($t) = $win_langs{$_}; my (@res) = ($t => $_); push (@res, $t => $_) if ($t =~ s/-.*$//o && ($_ & 0xFC00) == 0x400); @res} keys %win_langs; + $i = 0; + %langs_mac = map {$_ => $i++} @mac_langs; +} + + +$VERSION = 1.1; # MJPH 17-JUN-2000 Add utf8 support +# $VERSION = 1.001; # MJPH 10-AUG-1998 Put $number first in list + +=head2 $t->read + +Reads all the names into memory + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($dat, $num, $stroff, $i, $pid, $eid, $lid, $nid, $len, $off, $here); + + $fh->read($dat, 6); + ($num, $stroff) = unpack("x2nn", $dat); + for ($i = 0; $i < $num; $i++) + { + use bytes; # hack to fix bugs in 5.8.7 + read($fh, $dat, 12); + ($pid, $eid, $lid, $nid, $len, $off) = unpack("n6", $dat); + $here = $fh->tell(); + $fh->seek($self->{' OFFSET'} + $stroff + $off, 0); + $fh->read($dat, $len); + if ($utf8) + { + if ($pid == 1 && defined $apple_encodings[0][$eid]) + { $dat = TTF_word_utf8(pack("n*", map({$apple_encodings[0][$eid][$_]} unpack("C*", $dat)))); } + elsif ($pid == 2 && $eid == 2 && @cp_1252) + { $dat = TTF_word_utf8(pack("n*", map({$cp_1252[0][$_]} unpack("C*", $dat)))); } + elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1)) + { $dat = TTF_word_utf8($dat); } + } + $self->{'strings'}[$nid][$pid][$eid]{$lid} = $dat; + $fh->seek($here, 0); + } + $self; +} + + +=head2 $t->out($fh) + +Writes out all the strings + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($pid, $eid, $lid, $nid, $todo, @todo); + my ($len, $loc, $stroff, $endloc, $str_trans); + my (%dedup, @strings, @offsets, $strcount); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $strcount = 0; + $offsets[0] = 0; + $loc = $fh->tell(); + $fh->print(pack("n3", 0, 0, 0)); + foreach $nid (0 .. $#{$self->{'strings'}}) + { + foreach $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + foreach $lid (sort keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + $str_trans = $self->{'strings'}[$nid][$pid][$eid]{$lid}; + if ($utf8) + { + if ($pid == 1 && defined $apple_encodings[1][$eid]) + { $str_trans = pack("C*", + map({$apple_encodings[1][$eid]{$_} || 0x3F} unpack("n*", + TTF_utf8_word($str_trans)))); } + elsif ($pid == 2 && $eid == 2 && @cp_1252) + { $str_trans = pack("C*", + map({$cp_1252[1][$eid]{$_} || 0x3F} unpack("n*", + TTF_utf8_word($str_trans)))); } + elsif ($pid == 2 && $eid == 0) + { $str_trans =~ s/[\xc0-\xff][\x80-\xbf]+/?/og; } + elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1)) + { $str_trans = TTF_utf8_word($str_trans); } + } + my ($str_ind); + unless (defined $dedup{$str_trans}) + { + use bytes; + $dedup{$str_trans} = $strcount; + $strings[$strcount] = $str_trans; + $strcount++; + $offsets[$strcount] = $offsets[$strcount-1] + bytes::length($str_trans); + } + $str_ind = $dedup{$str_trans}; + push (@todo, [$pid, $eid, $lid, $nid, $str_ind]); + } + } + } + } + + @todo = (sort {$a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] + || $a->[3] <=> $b->[3]} @todo); + foreach $todo (@todo) + { $fh->print(pack("n6", @{$todo}[0..3], $offsets[$todo->[4]+1] - $offsets[$todo->[4]], $offsets[$todo->[4]])); } + + $stroff = $fh->tell() - $loc; + foreach my $str (@strings) + { $fh->print($str); } + + $endloc = $fh->tell(); + $fh->seek($loc, 0); + $fh->print(pack("n3", 0, $#todo + 1, $stroff)); + $fh->seek($endloc, 0); + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Outputs the string element in nice XML (which is all the table really!) + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($nid, $pid, $eid, $lid); + + return $self->SUPER::XML_element(@_) unless ($key eq 'strings'); + + foreach $nid (0 .. $#{$self->{'strings'}}) + { + next unless ref($self->{'strings'}[$nid]); +# $fh->print("$depth\n"); + foreach $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + foreach $lid (sort {$a <=> $b} keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + my ($lang) = $self->get_lang($pid, $lid) || $lid; + $fh->printf("%s\n%s%s%s\n%s\n", + $depth, $nid, $pid, $eid, $lang, $depth, + $context->{'indent'}, $self->{'strings'}[$nid][$pid][$eid]{$lid}, $depth); + } + } + } +# $fh->print("$depth\n"); + } + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Store strings in the right place + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'string') + { + my ($lid) = $self->find_name($attrs{'platform'}, $attrs{'language'}) || $attrs{'language'}; + $self->{'strings'}[$attrs{'id'}][$attrs{'platform'}][$attrs{'encoding'}]{$lid} + = $context->{'text'}; + return $context; + } + else + { return $self->SUPER::XML_end(@_); } +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + +=head2 is_utf8($pid, $eid) + +Returns whether a string of a given platform and encoding is going to be in UTF8 + +=cut + +sub is_utf8 +{ + my ($self, $pid, $eid) = @_; + + return ($utf8 && ($pid == 0 || $pid == 3 || ($pid == 2 && ($eid != 2 || @cp_1252)) + || ($pid == 1 && defined $apple_encodings[$eid]))); +} + + +=head2 find_name($nid) + +Hunts down a name in all the standard places and returns the string and for an +array context the pid, eid & lid as well + +=cut + +sub find_name +{ + my ($self, $nid) = @_; + my ($res, $pid, $eid, $lid, $look, $k); + + my (@lookup) = ([3, 1, 1033], [3, 1, -1], [3, 0, 1033], [3, 0, -1], [2, 1, -1], [2, 2, -1], [2, 0, -1], + [0, 0, 0], [1, 0, 0]); + foreach $look (@lookup) + { + ($pid, $eid, $lid) = @$look; + if ($lid == -1) + { + foreach $k (keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + if (($res = $self->{strings}[$nid][$pid][$eid]{$k}) ne '') + { + $lid = $k; + last; + } + } + } else + { $res = $self->{strings}[$nid][$pid][$eid]{$lid} } + if ($res ne '') + { return wantarray ? ($res, $pid, $eid, $lid) : $res; } + } + return ''; +} + + +=head2 remove_name($nid) + +Removes all strings with the given name id from the table. + +=cut + +sub remove_name +{ + my ($self, $nid) = @_; + + delete $self->{'strings'}[$nid]; +} + +=head2 set_name($nid, $str[, $lang[, @cover]]) + +Sets the given name id string to $str for all platforms and encodings that +this module can handle. If $lang is set, it is interpretted as a language +tag and if the particular language of a string is found to match, then +that string is changed, otherwise no change occurs. + +If supplied, @cover should be a list of references to two-element arrays +containing pid,eid pairs that should be added to the name table if not already present. + +This function does not add any names to the table unless @cover is supplied. + +=cut + +sub set_name +{ + my ($self, $nid, $str, $lang, @cover) = @_; + my ($pid, $eid, $lid, $c); + + foreach $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + my $strNL = $str; + $strNL =~ s/(?:\r?)\n/\r\n/og if $pid == 3; + $strNL =~ s/(?:\r?)\n/\r/og if $pid == 1; + foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + if (defined $self->{'strings'}[$nid][$pid][$eid]) + { + my ($isincover) = 0; + foreach $c (@cover) + { + if ($c->[0] == $pid && $c->[1] == $eid) + { + $isincover = 1; + last; + } + } + push(@cover, [$pid, $eid]) if (!$isincover); + } + foreach $lid (keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + next unless (!defined $lang || $self->match_lang($pid, $lid, $lang)); + $self->{'strings'}[$nid][$pid][$eid]{$lid} = $strNL; + foreach $c (0 .. $#cover) + { + next unless (defined $cover[$c] && $cover[$c][0] == $pid && $cover[$c][1] == $eid); + delete $cover[$c]; + last; + } + } + } + } + foreach $c (@cover) + { + next unless (defined $c && scalar @$c); + my ($pid, $eid) = @{$c}; + my ($lid) = $self->find_lang($pid, $lang); + my $strNL = $str; + $strNL =~ s/\n/\r\n/og if $pid == 3; + $strNL =~ s/\n/\r/og if $pid == 1; + $self->{'strings'}[$nid][$pid][$eid]{$lid} = $strNL; + } + return $self; +} + +=head2 Font::TTF::Name->match_lang($pid, $lid, $lang) + +Compares the language associated to the string of given platform and language +with the given language tag. If the language matches the tag (i.e. is equal +or more defined than the given language tag) returns true. This is calculated +by finding whether the associated language tag starts with the given language +tag. + +=cut + +sub match_lang +{ + my ($self, $pid, $lid, $lang) = @_; + my ($langid) = $self->get_lang($pid, $lid); + + return 1 if ($pid == 0); # all languages are equal in unicode since nothing defined + return ($lid == $lang) if ($lang != 0 || $lang eq '0'); + return !index(lc($langid), lc($lang)) || !index(lc($lang), lc($langid)); +} + +=head2 Font::TTF::Name->get_lang($pid, $lid) + +Returns the language tag associated with a particular platform and language id + +=cut + +sub get_lang +{ + my ($self, $pid, $lid) = @_; + + if ($pid == 3) + { return $win_langs{$lid}; } + elsif ($pid == 1) + { return $mac_langs[$lid]; } + return ''; +} + + +=head2 Font::TTF::Name->find_lang($pid, $lang) + +Looks up the language name and returns a lang id if one exists + +=cut + +sub find_lang +{ + my ($self, $pid, $lang) = @_; + + if ($pid == 3) + { return $langs_win{$lang}; } + elsif ($pid == 1) + { return $langs_mac{$lang}; } + return undef; +} + +=head2 Font::TTF::Name->pe_list() + +Returns an array of references to two-element arrays +containing pid,eid pairs that already exist in this name table. +Useful for creating @cover parameter to set_name(). + +=cut + +sub pe_list +{ + my ($self) = @_; + my (@cover, %ids); + + foreach my $nid (0 .. $#{$self->{'strings'}}) + { + if (defined $self->{'strings'}[$nid]) + { + foreach my $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + if (defined $self->{'strings'}[$nid][$pid]) + { + foreach my $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + if (defined $self->{'strings'}[$nid][$pid][$eid] && !$ids{$pid}{$eid}) + { + $ids{$pid}{$eid} = 1; + push @cover, [$pid, $eid]; + } + } + } + } + } + } + return @cover; +} + + +BEGIN { +@apple_encs = ( +<<'EOT', +M>)RES==NCW$`@.'G_S5Q*L(!#?+K1VO4:.W6IJA-:\^BM?>L>1&NP(A0Q$BL +M<*!62ZV8Z1)[K]BE$MR#O,=/7OW]7T&*6"NMI4K31EOMM)>N@XXZZ2Q#IBZZ +MZJ:['GKJ)4NVWOKHJ]\_/\!`@PR68XBAALDUW`@CC3+:&&.-,UZ>?!-,-,ED +M4TPUS70SS#3+;`7FF&N>0D7F6V"A119;8JEEEEMAI5566V.M==;;H-A&FVRV +MQ5;;_OTONJ3<%;?<5^NQ1YYXYJGG7GKME3?>>N^=#S[ZY(O/OOKNFU]^JO<[ +M!$?LLMO>$#OAH4-*4F+'[(L+E*F,6SH:%\9%]C@>1W&CN&%2:9QNO]-))5ZH +M<]9.!^/DQ/8X-V[@@#,AS0ZE+KB7R$ODA\:A26@>6H2FH9D?J17^)(I#3C@8 +MLD)V?:(^"BE.AN30,F0XK\(Y5UUVW0TW77/'W;H_;JM6HRJ1&95%M0Y'E5%5 +.5.U4]""JB`?E$` +EOT + +undef, +undef, +undef, +<<'EOT', +M>)RES[=/%```1O$WO8G_@$'J';W70Z2WHS>5WJN%8D6%D;BZ,3*P,;#C2D(8 +M,9&)08V)+4*(1((X2'(#[.:;7[[\*./_%D,L<<230"(!@B213`JII)%.!IED +MD4T.N>213P&%%%%,B!)N4LJMR[Z<"BJIHIH::JFCG@;"--)$,RVTTD8['732 +M13>WN<-=>NBECWX&&&2(848898QQ)IADBFEFF.4>]WG`0^:89X%%'O&8)SSE +M&<]9X@4O><4R*Y?_.ZRSRQ[[''#(1S[PB<]NL\D7OO&5[_S@9TR`(XXYX1=O +M.>4W9_SAG`O^7OF=O>XW*N)WV!%''7/<"2>=S?<\K5O(G[7?/Y>'``` +EOT + +<<'EOT', +M>)RED$LSEW$`A9_-^00L,H-^(=>4Y%^2J'1Q*Y+[I2(BHA`B?!%J6EM1*28S +M;9II[/PI*7*_%TUN\_*VZ%W:FN9LSYEGGD,\_Q?#$?SP)X"C!!)$,"&$$L8Q +MPCG."2(X222GB,+%:XR"42N,P5KG*-1))()H54KG.# +M--*Y20:WR"2+;'+()8]\"BBDB-O$PM +M==3SA`8::>(IS;3PC%;::'?X'^W#?&(0-Z-,,,,TL\PSQP)+K+#,*C]9XQ?K +M_.8/FVRPQ0[;[+&+S=_]_J;KX/Y6I?&U.JQ.Z[GU0@-VBNTR@;Q4G]ZI5V_U +MQG@83^-M?,PAXV6'VF'ZH&Z]4H_>J]]IO=:0W!K6B#[KBT;U56/ZIN\:UX1^ +?:%)3FM:,9C6G>2UH44M:UHI6'?)RES5=OSG$`0.$CYR.(A(3DUS]J4WOO59O6;&F+UMY[7R&(V'N^4ETZ=*"J +M:M:H=>E*0D1B)7HC1KC0[R#G^LEA,/]7((Z(EK2B-?&TH2WM:$\'.M*)SG0A +M@:YTHSL]Z$DO>M.'OO2C/P,8R*`&/X2A#&,X(QC)*$:3R!C&,H[Q3&`BDYC, +M%))(9BK3F,X,9C*+%%*9S1S22">#NN(MWO.>#.\GG(Y_YQ!>^DAT7 +M\8WZ$%$3$OC.#W(IYC=_^!N"1SWF*<]ZP1AO*:'`;*^0%V502J6'*8LRHRQR +M/.)Q3WC2TY[QG+D6FF^!19ZGR(M>BA*]3"'5(9Z8.>:YVSV-DD/CT"0T#RU" +MT]",G^YUG_L]8+$E7O6%!WUIF>4^]9K7?6R%E59YQUM6>]L:[WK/5][WH;7> +4M,X'/O&1-WSF_\` +EOT + +<<'EOT', +M>)RERT=.%5``0-&+7K'&!B(@X/L/^/3>ZZ?SZ=*K@`KVWOL:U!68.#!&8G2@ +M$Q?F5/=@SOB0XO\$$D2**:&4)&644T$E55130RUUU--`(TTTTT(K;;3302== +M=--#[[_?1S\###+$,".,DF:,<2:89(II9KC`+'/,L\`B2RRSPBIKK+/!13;9 +M8IM+7.8*.^QRE6M]SG`0]YQ&.>\)1G/.<%+WG%:][PEI0G +M/>5IL\SVC#F>-=<\\SUG@846>=Y@PFBQ)9::M,QR*ZRTRFIKK+4N!+[[CD]\ +M#I%?9O*-+XGH/N?BMON=CT7\B#MQUR5^^MY#ZH('7?:PJQYQS14/L!?S,S[$ +M=,SD*[]#DH\>==UC;K@8LD)V*`B%(3?D\2<4>=Q-3[B5R#'#66>LM\%&FVRV +GQ5;;;+?#3KOLML=>4_;9[X"##CGLB*.F'7/<"2>=)RED-DVUG$`1;=:U*Y%0C)5O^^/SSS/F>>9#"$JE7D>"D6\3S=>Q^MPU^JF +M&^M"2JJHIH9:ZJBG@4:::*:%M[32 +M1CL==_TNNNFAES[Z&6"0(889890QQIE@DG=,,% +MF;XTRVQSS#7/5[[VC<&8D?D66&C<(HLML=0RRZVPTBJ7K;;&6NNLM\%&FVRV +L):388:===MMCKP,..F2_(XXZYK#CMKGZS[YU-]QTRVUWW'7/?0]N`4(?0WT` +EOT + +<<'EOT', +M>)RED,5.0U$415=(D.X!$"ANMX^VN+M#D>+N[H4"Q5W^APF_PZ\PY.9-"`-& +MY.3LG>-"#_\3@P^'8OP$"%)"*6644T$E55130RUUU--`(TTTTT(K;;3302== +M=-OZ7OH(T<\`@PP19I@11AECG`DFF6*:&6:98YX%%EEBF15666.=#3;98IL= +M=MECGP,.B7#$,5%...6,&.=<<,D5U]QPRQWW//#($\^\\,J;G?_II)ETXS79 +M)L<$C<,['S[GYSY=?FWK6E>Z^?L'BK,:KP0E*DD>R?6E*-7E='DM9BA36A49XKI_!M<9D8J +EOT + +<<'EOT', +M>)RED,E3SW$8QU_77@<''+A]^Y5(2-F7+"%92\B^ES5ES]H,)L(8&21E*UNH +M&"8T8ZS3I(FS_T"$_`L^-^/D8)YY/^]Y/\L\"Y/Y/XN()T8"B0P@B8$,(IG! +MI#"$H0PCE>&DDG,((N99#.+VM8SP8**&0CF]C,%K:RC2*V +M4TP).]C)+G:SA[WLHY3]'.`@ASC,$-(*3WG:,R%ZSDK/!K[@1<][R2HO6^T5:ZSUJM>\[@UO +M6F>]M[SM'>]ZSX90_\"'-MIDLX^">ASPQ*?!M_C,Y[ZP->KE*U_[QK>^\WW( +CM/O!ML"=?K3#3[Z,*_AKOR]V^=5O=OO='_ZTQU^_`2-%:*`` +EOT + +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +<<'EOT', +M>)REC]=.E&$`1(\%&W@4004%_7:!I?>.Z-+[TJL*=K"`BH`*J,_"+2'A!7PW +MX;\2[LG<3#*9G!F2G$V!&'$***2(!,644$H9Y5102175U%!+'?4TT$@3S;30 +M2AN/:.\HSG +M+++$"U[RBM>\X2WO6&:%]WS@(Y]898W/?.$KZWQC@TVV^,X/?K+-#KO\XC=_ +M(OX!?T/"`0<=-$T+WG9 +M*U[UFNEF>%V]X4TSO666V=[VCG?-,==[WC?/?!_XT&#,N`466F3"8DLLMLD&W2#COMLML>>^V+=IX\2<7BCCGNA)-. +0.>V,L\XY[P*'[!\#D^='L@`` +EOT + +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +); + +$cp_1252 = ( +<<'EOT', +M>)P-SD-B'5```,#YJ6VE>DEM&[\VD]JVF?H./4'-U+93V[9M:SV;$141(Y74 +MTD@KG?0RR"B3S++(*IOL:%9-$0&YD?BH22(82XF)10.3(@U(DDB$;F_/]% +M0_Y0(!0*A4-\R!5RQ]R*BX\,#'4CB?]];B3)`@LMLM@22RVSW`HKK;):LC76 +M6F>]#3;:9+,MMMIFNQUVVF6W/?;:9[\##CKDL"-2''7,<2><=,II9YQUSGD7 +M7'3)95=<=0@` +EOT +); + + +@ms_langids = ( [""], + ['ar', ["-SA", "-IQ", "-EG", "-LY", "-DZ", "-MA", "-TN", + "-OM", "-YE", "-SY", "-JO", "-LB", "-KW", "-AE", + "-BH", "-QA", "-Ploc-SA", "-145"]], + ['bg-BG'], + ['ca-ES'], + ['zh', ['-TW', '-CN', '-HK', '-SG', '-MO', "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "zh", "-Hant"]], + ["cs-CZ"], + ["da-DK"], + ["de", ["-DE", "-CH", "-AT", "-LU", "-LI"]], + ["el-GR"], + ["en", ["-US", "-UK", "-AU", "-CA", "-NZ", "-IE", "-ZA", + "-JM", "029", "-BZ", "-TT", "-ZW", "-PH", "-ID", + "-HK", "-IN", "-MY", "-SG", "-AE", "-BH", "-EG", + "-JO", "-KW", "-TR", "-YE"]], + ["es", ["-ES", "-MX", "-ES", "-GT", "-CR", "-PA", "-DO", + "-VE", "-CO", "-PE", "-AR", "-EC", "-CL", "-UY", + "-PY", "-BO", "-SV", "-HN", "-NI", "-PR", "-US"]], + ["fi-FI"], + ["fr", ["-FR", "-BE", "-CA", "-CH", "-LU", "-MC", "", + "-RE", "-CG", "-SN", "-CM", "-CI", "-ML", "-MA", + "-HT"]], + ["he-IL"], + ["hu-HU"], + ["is-IS"], +# 0010 + ["it", ["-IT", "-CH"]], + ["ja-JP"], + ["ko-KR"], + ["nl", ["-NL", "-BE"]], + ["no", ["-bok-NO", "-nyn-NO", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "nn", "nb"]], + ["pl-PL"], + ["pt", ["-BR", "-PT"]], + ["rm-CH"], + ["ro", ["-RO", "_MD"]], + ["ru-RU"], + ["hr", ["-HR", "-Latn-CS", "Cyrl-CS", "-BA", "", "-Latn-BA", "-Cyrl-BA", + "", "". "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "bs-Cyrl", "bs-Latn", "sr-Cyrl", "sr-Latn", "", "bs", "sr"]], + ["sk-SK"], + ["sq-AL"], + ["sv", ["-SE", "-FI"]], + ["th-TH"], + ["tr-TR"], +# 0020 + ["ur", ["-PK", "tr-IN"]], + ["id-ID"], + ["uk-UA"], + ["be-BY"], + ["sl-SL"], + ["et-EE"], + ["lv-LV"], + ["lt-LT"], + ["tg", ["-Cyrl-TJ", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "-Cyrl"]], + ["fa-IR"], + ["vi-VN"], + ["hy-AM"], + ["az", ["-Latn-AZ", "-Cyrl-AZ", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "-Cyrl", "-Latn"]], + ["eu-ES"], + ["wen". ["wen-DE", "dsb-DE", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "dsb"]], + ["mk-MK"], +# 0030 + ["st"], + ["ts"], + ["tn-ZA"], + ["ven"], + ["xh-ZA"], + ["zu-ZA"], + ["af-ZA"], + ["ka-GE"], + ["fo-FO"], + ["hi-IN"], + ["mt"], + ["se", ["-NO", "-SE", "-FI", "smj-NO", "smj-SE", "sma-NO", "sma-SE", + "", "smn-FI", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "smn", "sms", "smj"]], + ["ga-IE"], + ["yi"], + ["ms", ["-MY", "-BN"]], + ["kk-KZ"], +# 0040 + ["ky-KG"], + ["sw-KE"], + ["tk-TM"], + ["uz", ["-Latn-UZ", "-Cyrl-UZ", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "-Cyrl", "-Latn"]], + ["tt-RU"], + ["bn", ["-IN", "-BD"]], + ["pa", ["-IN", "-Arab-PK", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "-Arab"]], + ["gu-IN"], + ["or-IN"], + ["ta-IN"], + ["te-IN"], + ["kn-IN"], + ["ml-IN"], + ["as-IN"], + ["mr-IN"], + ["sa-IN"], +# 0050 + ["mn", ["-Cyrl-MN", "-Mong-CN", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "-Cyrl", "-Mong"]], + ["bo", ["-CN", "-BT"]], + ["cy-GB"], + ["km-KH"], + ["lo-LA"], + ["my"], + ["gl-ES"], + ["kok-IN"], + ["mni"], + ["sd", ["-IN", "-PK", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Arab"]], + ["syr-SY"], + ["si-LK"], + ["chr", ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Cher"]], + ["iu", ["-Cans-CA", "-Latn-CA", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "-Cans", "-Latn"]], + ["am-ET"], + ["tmz", ["-Arab", "-Latn-DZ", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "-Latn"]], +# 0060 + ["ks"], + ["ne", ["-NP", "-IN"]], + ["fy-NL"], + ["ps-AF"], + ["fil-PH"], + ["dv-MV"], + ["bin-NG"], + ["fuv", ["-NG", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ff-Latn"]], + ["ha", ["-Latn-NG", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Latn"]], + ["ibb-NG"], + ["yo-NG"], + ["quz", ["-BO", "-EC", "-PE"]], + ["ns-ZA"], + ["ba-RU"], + ["lb-LU"], + ["kl-GL"], +# 0070 + ["ig-NG"], + ["kau"], + ["om"], + ["ti", ["-ET". "-ER"]], + ["gn"], + ["haw"], + ["la"], + ["so"], + ["ii-CN"], + ["pap"], + ["arn-CL"], + [""], # (unassigned) + ["moh-CA"], + [""], # (unassigned) + ["br-FR"], + [""], # (unassigned) +# 0080 + ["ug-CN"], + ["mi-NZ"], + ["oc-FR"], + ["co-FR"], + ["gsw-FR"], + ["sah-RU"], + ["qut-GT"], + ["rw-RW"], + ["wo-SN"], + [""], # (unassigned) + [""], # (unassigned) + [""], # (unassigned) + ["gbz-AF"], + [""], # (unassigned) + [""], # (unassigned) + [""], # (unassigned) +# 0090 + [""], # (unassigned) + ["gd-GB"], + ["ku", ["-Arab-IQ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Arab"]], + ["quc-CO"], +); +# 0501 = qps-ploc +# 05fe = qps-ploca +# 09ff = qps-plocm + +@mac_langs = ( + 'en', 'fr', 'de', 'it', 'nl', 'sv', 'es', 'da', 'pt', 'no', + 'he', 'ja', 'ar', 'fi', 'el', 'is', 'mt', 'tr', 'hr', 'zh-Hant', + 'ur', 'hi', 'th', 'ko', 'lt', 'pl', 'hu', 'et', 'lv', 'se', + 'fo', 'ru' ,'zh-Hans', 'nl', 'ga', 'sq', 'ro', 'cs', 'sk', + 'sl', 'yi', 'sr', 'mk', 'bg', 'uk', 'be', 'uz', 'kk', 'az-Cyrl', + 'az-Latn', 'hy', 'ka', 'mo', 'ky', 'abh', 'tuk', 'mn-Mong', 'mn-Cyrl', 'pst', + 'ku', 'ks', 'sd', 'bo', 'ne', 'sa', 'mr', 'bn', 'as', 'gu', + 'pa', 'or', 'ml', 'kn', 'ta', 'te', 'si', 'my', 'km', 'lo', + 'vi', 'id', 'tl', 'ms-Latn', 'ms-Arab', 'am', 'ti', 'tga', 'so', 'sw', + 'rw', 'rn', 'ny', 'mg', 'eo', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', 'cy', 'eu', + 'la', 'qu', 'gn', 'ay', 'tt', 'ug', 'dz', 'jv-Latn', 'su-Latn', + 'gl', 'af', 'br', 'iu', 'gd', 'gv', 'gd-IR-x-dotabove', 'to', 'el-polyton', 'kl', + 'az-Latn' +); + +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +Unicode type strings will be stored in utf8 for all known platforms, +once Perl 5.6 has been released and I can find all the mapping tables, etc. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OS_2.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OS_2.pm new file mode 100644 index 0000000000..b52312e184 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OS_2.pm @@ -0,0 +1,1036 @@ +package Font::TTF::OS_2; + +=head1 NAME + +Font::TTF::OS_2 - the OS/2 table in a TTF font + +=head1 DESCRIPTION + +The OS/2 table has two versions and forms, one an extension of the other. This +module supports both forms and the switching between them. + +=head1 INSTANCE VARIABLES + +No other variables than those in table and those in the standard: + + Version + xAvgCharWidth + usWeightClass + usWidthClass + fsType + ySubscriptXSize + ySubScriptYSize + ySubscriptXOffset + ySubscriptYOffset + ySuperscriptXSize + ySuperscriptYSize + ySuperscriptXOffset + ySuperscriptYOffset + yStrikeoutSize + yStrikeoutPosition + sFamilyClass + bFamilyType + bSerifStyle + bWeight + bProportion + bContrast + bStrokeVariation + bArmStyle + bLetterform + bMidline + bXheight + ulUnicodeRange1 + ulUnicodeRange2 + ulUnicodeRange3 + ulUnicodeRange4 + achVendID + fsSelection + usFirstCharIndex + usLastCharIndex + sTypoAscender + sTypoDescender + sTypoLineGap + usWinAscent + usWinDescent + ulCodePageRange1 + ulCodePageRange2 + xHeight + CapHeight + defaultChar + breakChar + maxLookups + +Notice that versions 0, 1, 2 & 3 of the table are supported. Notice also that the +Panose variable has been broken down into its elements. + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA @fields @lens @field_info @weights @ranges @codepages); +use Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'xAvgCharWidth' => 's', + 'usWeightClass' => 'S', + 'usWidthClass' => 'S', + 'fsType' => 's', + 'ySubscriptXSize' => 's', + 'ySubScriptYSize' => 's', + 'ySubscriptXOffset' => 's', + 'ySubscriptYOffset' => 's', + 'ySuperscriptXSize' => 's', + 'ySuperscriptYSize' => 's', + 'ySuperscriptXOffset' => 's', + 'ySuperscriptYOffset' => 's', + 'yStrikeoutSize' => 's', + 'yStrikeoutPosition' => 's', + 'sFamilyClass' => 's', + 'bFamilyType' => 'C', + 'bSerifStyle' => 'C', + 'bWeight' => 'C', + 'bProportion' => 'C', + 'bContrast' => 'C', + 'bStrokeVariation' => 'C', + 'bArmStyle' => 'C', + 'bLetterform' => 'C', + 'bMidline' => 'C', + 'bXheight' => 'C', + 'ulUnicodeRange1' => 'L', + 'ulUnicodeRange2' => 'L', + 'ulUnicodeRange3' => 'L', + 'ulUnicodeRange4' => 'L', + 'achVendID' => 'L', + 'fsSelection' => 'S', + 'usFirstCharIndex' => 'S', + 'usLastCharIndex' => 'S', + 'sTypoAscender' => 'S', + 'sTypoDescender' => 's', + 'sTypoLineGap' => 'S', + 'usWinAscent' => 'S', + 'usWinDescent' => 'S', + '' => '', + 'ulCodePageRange1' => 'L', + 'ulCodePageRange2' => 'L', + '' => '', + 'xHeight' => 's', + 'CapHeight' => 's', + 'defaultChar' => 'S', + 'breakChar' => 'S', + 'maxLookups' => 's', + '' => '', # i.e. v3 is basically same as v2 + '' => '' # i.e. v4 is structurally identical to v3 + ); + +@weights = qw(64 14 27 35 100 20 14 42 63 3 6 35 20 56 56 17 4 49 56 71 31 10 18 3 18 2 166); + +use Font::TTF::Utils; + +sub init +{ + my ($k, $v, $c, $n, $i, $t, $j); + + $n = 0; + @lens = (76, 84, 94, 94, 94); + for ($j = 0; $j < $#field_info; $j += 2) + { + if ($field_info[$j] eq '') + { + $n++; + next; + } + ($k, $v, $c) = TTF_Init_Fields($field_info[$j], $c, $field_info[$j+1]); + next unless defined $k && $k ne ""; + for ($i = $n; $i < 5; $i++) + { $fields[$i]{$k} = $v; } + } +} + + +=head2 $t->read + +Reads in the various values from disk (see details of OS/2 table) + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $ver); + + $self->SUPER::read or return $self; + + init unless defined $fields[2]{'xAvgCharWidth'}; + $self->{' INFILE'}->read($dat, 2); + $ver = unpack("n", $dat); + $self->{'Version'} = $ver; + if ($ver < 5) + { + $self->{' INFILE'}->read($dat, $lens[$ver]); + TTF_Read_Fields($self, $dat, $fields[$ver]); + } + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($ver); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $ver = $self->{'Version'}; + $fh->print(pack("n", $ver)); + $fh->print(TTF_Out_Fields($self, $fields[$ver], $lens[$ver])); + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Tidies up the hex values to output them in hex + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + + if ($key =~ m/^ul(?:Unicode|CodePage)Range\d$/o) + { $fh->printf("%s<%s>%08X\n", $depth, $key, $value, $key); } + elsif ($key eq 'achVendID') + { $fh->printf("%s<%s name='%s'/>\n", $depth, $key, pack('N', $value)); } + else + { return $self->SUPER::XML_element(@_); } + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Now handle them on the way back in + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag =~ m/^ul(?:Unicode|CodePage)Range\d$/o) + { return hex($context->{'text'}); } + elsif ($tag eq 'achVendID') + { return unpack('N', $attrs{'name'}); } + else + { return $self->SUPER::XML_end(@_); } +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 78; +} + +=head2 $t->update + +Updates the OS/2 table by getting information from other sources: + +Updates the C and C values based on the MS table in the +cmap. + +Updates the sTypoAscender, sTypoDescender & sTypoLineGap to be the same values +as Ascender, Descender and Linegap from the hhea table (assuming it is dirty) +and also sets usWinAscent to be the sum of Ascender+Linegap and usWinDescent to +be the negative of Descender. + +=cut + +sub update +{ + my ($self) = @_; + my ($map, @keys, $table, $i, $avg, $hmtx); + + return undef unless ($self->SUPER::update); + + $self->{' PARENT'}{'cmap'}->update; + $map = $self->{' PARENT'}{'cmap'}->find_ms || return undef; + $hmtx = $self->{' PARENT'}{'hmtx'}->read; + + @keys = sort {$a <=> $b} grep {$_ < 0x10000} keys %{$map->{'val'}}; + + $self->{'usFirstCharIndex'} = $keys[0]; + $self->{'usLastCharIndex'} = $keys[-1]; + + $table = $self->{' PARENT'}{'hhea'}->read; + + # try any way we can to get some real numbers passed around! + if (($self->{'fsSelection'} & 128) != 0) + { + # assume the user knows what they are doing and has sensible values already + } + elsif ($table->{'Ascender'} != 0 || $table->{'Descender'} != 0) + { + $self->{'sTypoAscender'} = $table->{'Ascender'}; + $self->{'sTypoDescender'} = $table->{'Descender'}; + $self->{'sTypoLineGap'} = $table->{'LineGap'}; + $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'}; + $self->{'usWinDescent'} = -$self->{'sTypoDescender'}; + } + elsif ($self->{'sTypoAscender'} != 0 || $self->{'sTypoDescender'} != 0) + { + $table->{'Ascender'} = $self->{'sTypoAscender'}; + $table->{'Descender'} = $self->{'sTypoDescender'}; + $table->{'LineGap'} = $self->{'sTypoLineGap'}; + $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'}; + $self->{'usWinDescent'} = -$self->{'sTypoDescender'}; + } + elsif ($self->{'usWinAscent'} != 0 || $self->{'usWinDescent'} != 0) + { + $self->{'sTypoAscender'} = $table->{'Ascender'} = $self->{'usWinAscent'}; + $self->{'sTypoDescender'} = $table->{'Descender'} = -$self->{'usWinDescent'}; + $self->{'sTypoLineGap'} = $table->{'LineGap'} = 0; + } + + if ($self->{'Version'} < 3) + { + for ($i = 0; $i < 26; $i++) + { $avg += $hmtx->{'advance'}[$map->{'val'}{$i + 0x0061}] * $weights[$i]; } + $avg += $hmtx->{'advance'}[$map->{'val'}{0x0020}] * $weights[-1]; + $self->{'xAvgCharWidth'} = $avg / 1000; + } + elsif ($self->{'Version'} > 2) + { + $i = 0; $avg = 0; + foreach (@{$hmtx->{'advance'}}) + { + next unless ($_); + $i++; + $avg += $_; + } + $avg /= $i if ($i); + $self->{'xAvgCharWidth'} = $avg; + } + + $self->{'ulUnicodeRange2'} &= ~0x2000000; + foreach $i (keys %{$map->{'val'}}) + { + if ($i >= 0x10000) + { + $self->{'ulUnicodeRange2'} |= 0x2000000; + last; + } + } + + $self->{'Version'} = 1 if (defined $self->{'ulCodePageRange1'} && $self->{'Version'} < 1); + $self->{'Version'} = 2 if (defined $self->{'maxLookups'} && $self->{'Version'} < 2); + + if ((exists $self->{' PARENT'}{'GPOS'} && $self->{' PARENT'}{'GPOS'}{' read'}) || + (exists $self->{' PARENT'}{'GSUB'} && $self->{' PARENT'}{'GSUB'}{' read'})) + { + # one or both of GPOS & GSUB exist and have been read or modified; so update usMaxContexts + my ($lp, $ls); + $lp = $self->{' PARENT'}{'GPOS'}->maxContext if exists $self->{' PARENT'}{'GPOS'}; + $ls = $self->{' PARENT'}{'GSUB'}->maxContext if exists $self->{' PARENT'}{'GSUB'}; + $self->{'maxLookups'} = $lp > $ls ? $lp : $ls; + } + + $self; +} + + +=head2 $t->guessRangeBits (\%map, [$cp_threshold, [%u_threshold]]) + +Set the ulCodePageRange and ulUnicodeRange fields based on characters actually present in the font. + +%map is a hash keyed by USV returning non-zero for characters present (e.g. use {'val'} +a from Unicode cmap). + +The two optional parameters are percentage of characters within the codepage or unicode range that need +to be present to constitute coverage. A threshold of 0 causes corresponding range bits to +be set if any characters are present at all, while a negative value causes the corresponding +range bits to be unchanged. Defaults are 50 and 0, respectively. + +For codepage bits, the threshold is percentage of characters between 0xC0 and 0xFF that need +to be present to constitute coverage). For codepages other than 1252, +characters (e.g., punctuation) that are defined identically to cp1252 are ignored +for the purposes of this percentage calculation. Looks only for SBCS codepages, not DBCS. + +For Unicode range bits that represent multiple ranges, e.g., bit 29 represents: + + Latin Extended Additional 1E00-1EFF + Latin Extended-C 2C60-2C7F + Latin Extended-D A720-A7FF + +the bit will be set if any of these ranges meet the threshold requirement. + +=cut + +sub guessRangeBits +{ + my ($self, $ucmap, $cp_threshold, $u_threshold) = @_; + $cp_threshold = 50 unless defined ($cp_threshold); + $u_threshold = 0 unless defined ($u_threshold); + my $j; # index into codepages or ranges + my $u; # USV + + unless (ref($codepages[0])) + { + # One-time work to convert range data + + # unpack codepages. But first make sure we have Zlib + eval {require Compress::Zlib} || croak("Cannot unpack codepage data Compress::Zlib not available"); + + for ($j = 0; $j <= $#codepages; $j++) + { + next unless $codepages[$j]; + $codepages[$j] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $codepages[$j])))]; + warn ("Got nothing for codepage # $j\n") if $#{$codepages[$j]} < 128; + } + + # convert Unicode array data to hash + my @newRanges; + for ($j = 0; $j <= $#ranges; $j++) + { + next unless $ranges[$j][2] =~ m/^([0-9a-f]{4,6})-([0-9a-f]{4,6})$/oi; + my $s = hex ($1); + my $e = hex ($2); + next unless $e > $s; + push @newRanges, {start => $s, end => $e, bit => $ranges[$j][0], name => $ranges[$j][1]}; + } + @ranges = sort {$a->{'end'} <=> $b->{'end'}} (@newRanges); + } + + if ($cp_threshold >= 0) + { + my $cpr; # codepage range vector + $cp_threshold = 100 if $cp_threshold > 100; + vec($cpr, 63 ,1) = 0; # Get all 64 bits into the vector + for $j (0 .. $#codepages) # For each codepage + { + # Count the number of chars from @range part of codepage that are present in the font + my $present = 0; + my $total = 0; + foreach (0x20 .. 0xFF) + { + $u = $codepages[$j][$_]; + next if $u == 0xFFFD; # Ignore undefined things in codepage + # For codepage 1252, ignore upper ansi altogether + # For other codepages, ignore characters that are same as in 1252. + next if $j > 0 ? $u == $codepages[0][$_] : $u > 0x007F; + $total++; + $present++ if exists $ucmap->{$u} && $ucmap->{$u} > 0; + } + #printf STDERR "DBG: Got $present / $total (%0.3f%%) in codepage bit $j\n", $present * 100 / $total; + #print STDERR "DBG: setting bit $j\n" if $cp_threshold == 0 ? ($present > 0) : (($present * 100 / $total) >= $cp_threshold); + vec($cpr, $j, 1) = 1 if $cp_threshold == 0 ? ($present > 0) : (($present * 100 / $total) >= $cp_threshold); + #print STDERR "\n"; + } + ($self->{'ulCodePageRange1'}, $self->{'ulCodePageRange2'}) = unpack ('V2', $cpr); + } + + if ($u_threshold >= 0) + { + my $ucr; # Unicode range vector + my @count; # Count of chars present in each range + $u_threshold = 100 if $u_threshold > 100; + vec($ucr, 127,1) = 0; # Get all 128 bits into the vector + $j = 0; +CHAR: for $u (sort {$a <=> $b} keys %{$ucmap}) + { + while ($u > $ranges[$j]{'end'}) + { + last CHAR if ++$j > $#ranges; + } + next if $u < $ranges[$j]{'start'}; + $count[$j]++ if $ucmap->{$u}; + } + foreach $j (0 .. $#ranges) + { + vec($ucr, $ranges[$j]{'bit'}, 1) = 1 if $u_threshold == 0 ? + ($count[$j] > 0) : + (($count[$j] * 100 / ($ranges[$j]{'end'} - $ranges[$j]{'start'} + 1)) >= $u_threshold); + } + ($self->{'ulUnicodeRange1'},$self->{'ulUnicodeRange2'},$self->{'ulUnicodeRange3'},$self->{'ulUnicodeRange4'}) = + unpack ('V4', $ucr); + } +} + +BEGIN { + +@codepages = ( +<<'EOT', # Bit 0: cp1252 +M>)P-R>-B%E```-#S+1O+O%NU;-MVRURV[7?H"3*7;2_;M6S;K=7Y>Q`1)8VT +MTDDO@XPRR2R+K++)+H><\"BJJI+(JJJJFNAIJJJ6V.NJJI[X&&FJDL2:::J:Y%EIJI;4VVFJGO0XZ +MZJ2S+KKJ)EYW/?342V]]]-5/?P,,-$B"P888:ICA1AAIE-'&&&N<\2:8:)+) +MIIAJFNEFF&F6V>:8:Y[Y%E@8$E-30J'(HE`LQ(408J*20I5(0J@;Z9::$IF? +MFO)_"X2"H4@H&F)#=,@3E1P3&QD><=\%% +MEUQVQ5777'?#3;?<=D>RN^ZY[X&''GGLB:>>>>Z%EUYY[8VWWGGO@X\^^>R+ +3K[[Y[H>??OGMCQ1_I?X#Q@N!>@`` +EOT + +<<'EOT', # Bit 1: cp1250 +M>)P-Q^=+U'$`Q_'WY^>LW%K=G:/OG6:VM4R[*RU'.7.EY2BW5E:.MOM?Z8%8 +MXB#!,O"1$8A$/2G:$D40$?6D2)`.NP=O>+T!8>&'/P$$$D0P&]C()D(()8QP +M(H@DBFABV,P6MF+#CH-8XH@G@6T8G+A()(GM)+.#%':RB]WL82_[V$\J:1S@ +M(.D<(H-,#N/&PQ&.DD4VQSA.#KGDD<\)3E)`(4444T(IIRBCG`HJJ>(TU=1P +MAK/44D<]#9SC/(TTT4P+K;313@>=7.`BE^CB,E>X2C<]]-+'-:YS@YO`08889H11,[7N-0Y?"2;9&./T*57-QJUZM6M8_;ZW&;N),_'&9:)-S+K7 +MZ5*+\:A!'1K1`'>M)>NM1XK +M0$TL*,M:4;:&5,TB3V3Q5&X%LJ00EF7CF1P\YX7"%*$\%?"25ZK@-6]4JV[> +MJY>/K*B53ZKA,U_DQU=Y%,0WA?)==GXHEI_\4K@BE:]"?O-'E?QE577J84U] ++_,.K-NO=?_3I:`(` +EOT + +<<'EOT', # Bit 2: cp1251 +M>)P%P=52%5``0-$-;!KISG,OW=W=#=(IV-W=_H+^@0^.CB,Z^J`^^&V.K@7$ +M$$L<$D\"B2213`JII'&*=#+()(ML#3;;89H==]MCG@$/.<,0Q9SG'>2YPD4MYQWT>\)!'/.8)3WG&\YHVQQH5B-T)YJ`DA1,)):#,Y])MB +MFJEFN!X*0U$H#64A&G)"[K^_D:A[8F>V02'WS+1SX9PV?E"R=\ +MY9N)?.>'"6[[CI_\XK=KD7PW^>.N\6ZY8Z999IMCKGGF6V"A119;8JEEEEMA +M,&+42JNLML9:ZZRWP4:;;+;%5MMLM\-.N^RVQU[[['?`08<<=L11QQQWPDFG +3G';&6>><=\%%EUQVQ=7_+3E$L0`` +EOT + +<<'EOT', # Bit 3: cp1253 +M>)PUB>^."+'_X$ +M,(U`@@AF.B&$$L8,#`ZYPESSCLBT3[%%HPDR$,<;AMF@WL;8U,A-H@DR("35.XVO\;,OA=+>XD9=R +M%>@>%512134UU%+GKO6X:*#1^--,"ZVT*9]V.NC4?3W00[KUB!X]UA,]U3,5 +MJDC%>JX2O5"I7JI,K_1:;_16[U2N][:E"E6J2M6J4:WJ]$'UN+>O15O>K3-_7KNW[HIW[IM_YH0(,:TK#^ZI]M_0=K +#AH5\ +EOT + +<<'EOT', # Bit 4: cp1254 +M>)PER6-ST'$``.#GOVPLM]9OJY9KR\NV[99M^SOT";)MV[S,NVQ=]JWKNN?E +M@TB,##+*)+,LLLHFNQQRRB6W//+*)[]8!1142&%%%%5,<7%*B%=2D"!1*:65 +MD:2L\ +M"2::9+(IIIIFNAEFFF6V.>::9[X%%H;UZ7]"L6A1B`])(82$F),A.4H+J5'7 +M]#__A2*A:(@+)4)BB`T%8NXE)$:#0]VHV[^+9EELB:6666Z%E599;8VUUEEO +M@XTVV6R+K;;9;H>==MEMC[WVV>^`@PXY[(BCCCGNA)-..>V,L\XY[X*++D7Q +M+KOBJFNNN^&F6VZ[XZY[47(TT'T///3(8T\\])Q%C]=7#@`X;L\3_X"Z)3*4E[G)9Q +MCFLR(MDK71'GN/K.)\[I.,_=\]X\+^"%@T$,1@QA*,/P9C@C&,DH?/!E-&,8 +MBQ_^C&,\$P@@D""""2&4,"9B.'$QB6DR_B?.X![``"[00"S67^9F_H]OI +MZG?Q`RL%7.<&A59&$<64<)-2.KE%.;>IX`Z55%%-#;7444\#C33QFV9::*6- +M=E6J2M6J4:WJ5*\&-:K)XU:S6M2J-K7KKN[IOA[HNWZH3S_UZW_97_1(C]6A +M)WJJ9WJN3KW02W7IE;KU6F_T5N_T7A_T49_T65_T53WZIMY_OWS,U^/^`\"V +"EBL` +EOT + +<<'EOT', # Bit 6: cp1256 +M>)P%P;=/%``8A^'W$'\J'*`"2N>[`XX.1^?.1N_UL``*=A'L8$,4-^.J$R,1 +M&Q$%%+N2N/@'N+@:%UN"BXDA./@\@(,@5A',:L0:UK*.$$)Q$D8X$:QG`QN) +M)(IH-K&9&&*)(YX$$DDB&<.%FQ122<-#.AEDDD4V.>221SY>"BBDB&)***6, +MXS"A7&.,J +MUQCGNLUHW.(LK5P#>^\X.?_%*CFECBMYK5HE:U\4?MZN"O.EE6@!7^6;A% +'Z--_?PY;L``` +EOT + +<<'EOT', # Bit 7: cp1257 +M>)P-B4=/%&``1-^L%`M86(1=FM\N106E]R)2;6`7%"P@%CI([_X5HT8E8N]1 +M.5GBV2@22;P("6G"S?HK"""0(()9S1K6LHX00EG/!C:RB3"< +MA+.9"")QX2:*:&*()8XM&#QXB2>!1)+8RC:VDTP*.]A)*FFDDT$F66230RYY +MY%-`(4444\(N2ME-&>544$D5U>QA+_O8SP%JJ.4@ASC,$8YRC..XR"4NTTH;[73021?=]-#+%?KH9X!!AAAFA%'&&&>" +M2::X:F;\/A-EB3-)QAB/M71+@=_''<='7EIW&;>),;'&:YPFW._S>.U6:/\' +MCN\VKUFN\HSGO.`OKU3/:][PEEF6 +M%*!4H2#>\5XNA2F$3QI5A+S*5;**U*0*5?%9-7SA*W/J4YD:U,Z"QC7)#P4J +M35(P/UF46TZ%LJPQ12I>>4I1L9I5J6I^J9;?K/!'_2I7HSKXIPE-.>;_`YNL +";XP` +EOT + +<<'EOT', # Bit 8: cp1258 +M>)PER>5.EF$`@.'KY;,[,%#1!U3L[NYNL+N[$_LR&;.= +M.J>S&>K<_>^Z$8D3DT=>^>170$&%%%9$4<445T))I906KXRRRBDO004559*H +MLBJ"),FJJJ:Z%#745$MM==153WT---1(8TTTU4QS+;342FMMM-5.>QUTU$EG +M773537<]]-1+;WWTU4]_`PPT2*HT@PTQU###C3#2**.-,=8XXTTPT22333'5 +M--/-,-,LL\TQUSSS+;#0(HLML=0RZ99;8:555EMC;=B9FQ,J1.M"Y9`20DB* +MRPH-_TJK*#4WYW^A?$@(E4)B2`ZE0WQ<=E+R7VL=I?U[4;H,F=;;8*---MMB +MJVVVVV&G77;;8Z]]]CO@H$,..^*H8XX[X:133COCK'/.1W$NN"C+)9==<=6U +M&-?=<#,JX5:LH-ON1!GNNN>^!QYZ)#O:$XMY[(FGGD4QS[WPTBNOO?'6NUCD +@O0\^1B5]BE7UV9)Q=C=52&U``!1?W11(@@00N`8*[4\'=W>KN[OHK_8#^8J=]Z.0!9E_.S,Z< +M!;+()H=<\LBG@$****:$4LJ0JH)T&2!AH)-)&BF19: +M2=-&.QUTTD4W/?321S\###+$,".,,L8X$TQRB^QSP"%'''/"*6=\X2G +M/.,Y+WC)*U[SAK>\XST?^,@G/O.%KWSC.S_X&7[__?.?D,ZL\X18B(=$2(94 +MB(3H1^"BRZY +@[(JKKKGNAIMNN>V.N^ZY[X&''GGLB:>>91[^`:-3=+0` +EOT + +undef, # Bit 17: Reserved +undef, # Bit 18: Reserved +undef, # Bit 19: Reserved +undef, # Bit 20: Reserved +undef, # Bit 21: Reserved +undef, # Bit 22: Reserved +undef, # Bit 23: Reserved +undef, # Bit 24: Reserved +undef, # Bit 25: Reserved +undef, # Bit 26: Reserved +undef, # Bit 27: Reserved +undef, # Bit 28: Reserved +undef, # Bit 29: Reserved +undef, # Bit 30: Reserved +undef, # Bit 31: Reserved +undef, # Bit 32: Reserved +undef, # Bit 33: Reserved +undef, # Bit 34: Reserved +undef, # Bit 35: Reserved +undef, # Bit 36: Reserved +undef, # Bit 37: Reserved +undef, # Bit 38: Reserved +undef, # Bit 39: Reserved +undef, # Bit 40: Reserved +undef, # Bit 41: Reserved +undef, # Bit 42: Reserved +undef, # Bit 43: Reserved +undef, # Bit 44: Reserved +undef, # Bit 45: Reserved +undef, # Bit 46: Reserved +undef, # Bit 47: Reserved + +<<'EOT', # Bit 48: cp869 +M>)Q%R>=7#0`]I+*/_:1Q@(.DX2OY`_W^Z/M!/-ZTT.!W.0!4Y`W1#-_58Q?_VEEIH5@F==*F5.K7IB9[J +MITK5I]\J4[GG5/E;308V56;F[S,I?NJTK5>F#IEF#)EJJ'JC$_ +M\[<("[=@PR+E4:VE6))E6H:E6;QEJ4Z/5*\&-:I)S>I0I[K,83Y69`5ZIN=V +M32_4K9=ZI=?JT1OUZJW>Z;T^Z),^ZK,*:*-#7_15WVC4=Q723I-^Z)?:]<<\ +'>/X"GB5Z;@`` +EOT + +<<'EOT', # Bit 49: cp866 +M>)P%P45#$P``AN$7_!0#<=088]381XYN&-W=#:,;N]N#!P\>C#_`P1_@S;_G +M\P`II'(#<9-;I'&;.]SE'NG<)X,'!,@DBVQRR"5('B'R"5-`A$****:$4J*4 +M$<.44T$E55130YQ:ZJBG@4:::*:%5MIHIX-.NN@F00^]]-'/`(,,,.<"RZY +MXB&/>,P3GO*,Y[S@):]XS1O>\H[W?.`CG_BL@#*5I6SE*%=!Y2FD?(55H(@* +M5:1BE:A4494I)JM<%:I4E:I5H[AJ5:=Z-:A136I6BUK5IG9UJ%-=ZE9"/>I5 +MGW_ZEW\[U3'O^\"K7O&A%[SF'6][RP'GN,5Q1XP33GK7FU[VN4^\YWE?^=1G +M/O*Q-[SN12_YTA<..=W?_-7?_<-?U*\!#6I(PQK1J,8TK@E-:DK3FM&LYI2B +:!4G+2M.:,I3D;S2??]%P:9`_ON;Z/\R_26T` +EOT + +<<'EOT', # Bit 50: cp865 +M>)P%P3=,%&``AN$7?FR(>BH@W>,_/A%%;-BQ*V*G]W9P1[=W:0X.#@P(BR,& +M([$,8B0F1J.)B'%D,0XD*K$W@AHIDNCS`#[X8O!C$I.9PE2FX<]T`IC!3&;A +M8#9SF$L@000SCQ!""2.<""*)8CY.HK&XB$$L():%Q+&(Q<2SA`26LHSEK&`E +MB:QB-6M8RSK6LX$D-K*)S6QA*]O8S@YVDLPN4MC-'O:RC_T213P&%%%%,":6X*:,<#UXJJ*2*:FJHI8Y#'.8(1SG&<4YPDE.^\)5/#/&#;_3RC!=\H(_?_.$G?QGC'R\9 +M8)1.7CF[?-IXRW=^,O8N16F;*5I7*E +M*4=%*E2!'`I4HN(5(92D8I4H7YFJ5H5*E:HZ5:I*'GF5IURE*T.UJE&(`G1) +M%]6B5ETPW;PV[>:)Z31/Z3&]YKJY8FZ8>S;*])D>&V?==%NO];B)P=R'EHSW$<#J$<(/NK3`*,AC6A,$YKBIQG-:4$H +M+6E%:\)H0UO:$4X$D40137MBB"6.#GAT)-Z*Z$1GNM"5;G0G@1[TI!>]Z4-? +M^I%(?P8PD$$,9@A#26(8PQE!,B-)812C&<-84DEC'..9P$0F,9DI3"6=:4QG +M!C.9Q6SF,)=YS&WYOP=T4$=UW/PZH5,Z:QF6:5F6 +M;3F6:WF6;P56J*<6I4I=TW6+Y;1V:*=V:Z_N:9_VZY".Z)A*=%)E.J\+*E>% +M+NFJJE2MF[JEV[JOQYSC(G74ZJXEZYEJ]5*O]5;O]5&?]44_5*,'>J2'>J-B +<2]<[?=`G?=5W/=%S_=0OO=(+?7.EP<`_%"[`E0`` +EOT + +<<'EOT', # Bit 52: cp863 +M>)P%P4E0#7``Q_%O_9&E>!(M4J__ZQJ_=4I;L.3@X=$A= +M'!N9:#+3HF+&,@W&.L/%Q3##N%3,<&#&6`X^'\`'7PS3F,X,_)C)+&8S!W\" +MF,L\',PGD`4$L9!%!!-"*&$L)IPE1!")DR@L+J(1,2QE&;$L)XYX5K"25220 +MR&K6D,1:UK&>#6QD$YM)9@M;V48*V]G!3G:QFU322">#/>QE'_LYP$$RR2*; +M''+)(Y\""BFBF!)**:.<"BIQ4T4U'KS44$L=]3302!.'.,P1CM),"\;,YAQ;O""Y[SD)Z]XPU]^ +M"UR\$M'G"?A_1S3U?4J2[Y*EIN52E? +M>:I6E@I4IE*5R*$@)2E>X4+)*E>%BI6K>M6H4IEJ4JWJY)%712I4MG+4J`:% +MR%^7=4GMZM!%,\1'TV7&38]YS*AY8GK-5=-G1FR$>6I&;:QU,V2]UN-RNJ+X +39=,9M*')P%P3=,U'$KHMBQ8V_8Z;T=W-'MO<+@X,"@L#BB +M1(UE$",QL403C;/8.V+7Q,$XF#CY/$`$D3CZ8?1G``,9Q&"&$,50AC$<'R,8 +MR2BB&O9P$8VL9DM9))%-CGDDD<^ +M!1121#$EE%)&.154$J2*:D*$J:&6.NIIH)$FMK*-[>Q@)[O8S1[VLH_]'.`@ +MASC,$8YRC&9[9#WVV)[84WMFS^V%O;17]MK>V%M[9^^MUSY8GWVT3_;9OMA7 +M^V;?[8?]Y"R=G/-?B&BCCU_\X1^_Z>$2-[D;\'&%.]SF#)>YI5-J4[LBE:R@ +MJI2O/%4K2P4J4ZE*Y%.TTI2J>*%TE:M"Q)P%P4=(%7``Q_&O_FU;O4K+W?/__%6F;=NVRZRTW'L]?<_=WD/MT*&#!]-+ +M1T,H)`\928<,C4SI$`2!1)@-VB($185F]/D`/OAB\&,2DYG"5*8QG1GX,Y-9 +MS,;!'.8RCP`"F<\"@@@FA%#""">"A3B)Q.(B"K&(Q2PAFJ7$$,LREK."E:QB +M-6N(8RWK6,\&-K*)S<2SA:UL8SL[V,DN=K.'!/:2R#[VO)1302555%-#+8T>-RT,%#NKG!;1[HFIK5(E]%R:U292E3 +M94I5M@I5H'PY%*`XQ2I,*%Y%*E:>,E2E6-:3*]I,X_I,GWFIKENVLT]&V'Z39>-MFXZK==Z7$Y7)+]M +2(G=L,/=MB+.!NVJE]3^&>7'F +EOT + +<<'EOT', # Bit 55: cp860 +M>)P%P4E0#7``Q_&O_G8A*MKD]7_]4F2/0F07*NW[]NJ]=DOVO0X=.CB@BV,T +MPU@.931FJ"DR6:8.%0?&#.I@&0[(&,;!YP-,P`O#1"8QF2E,91K3F8$W,YG% +M;'R8PUQ\\<.?>221SX%%%)$,264XJ*,\(E!7O*5/A[SG%Z>,FJE6A4J6J3I6JDEL>Y2E7Z)P-RE-W%W```-#[7[:6E_O%Y67;7BUKM5HMVSWTT&OU!;)MVSR9YV3K9)_: +MZST7$5'22"N=]#+(*)/,LL@JF^QRR"F7W/*(EE<^^1504"&%Q2BBJ&***Z&D +M4DH+RBBKG/(JJ"A6)955454UU=40IZ9::JNCKGKJ:Z"A1AIKHJEFFFNAI59: +M:Z.M=MKKH*-..NNBJVZZB]=#3PEZZ:V/OOKI;X"!!AELB$1##9-DN!&2C31* +MBM'&&&N<\2:8:)+)IIAJFNEFF&F6V>:8Z[0_7GGLJ8>>>>&U-U[ZX'VDFA-. +M.NNY4[[XYI/??D:JNNF^'Y:['1D0&>B1=S[[Y:,KD:*18@[;9(.##EAJO?UA +M85@4%H>H4-I1QQRQ-B2&KB$A]+?,RI`S1(>X$!MB@M#`$\=#GQ`?DD-2&!2Z +MA!0K[+/..>>=^??719=<#@5"UK`@S+?*A3#/-0]<=]57-^Q,/;?<=<\=;_VS +)P%P<52$``40-$+7$`%*>D&>3327=)("4A(HU@H=K<+%V[5'V#AC`O'+_#G +M/`=(()$D))D44CG#6+;7;898]]#CCD!C\9@G/.49SWG!2U[QFC>\Y1WO^F.F2EYRST3:S;#?;:6OM,M=N\YRTQDXO\(=_ +M\3U^Q,](C!JG#/LLC*-8BM,=\.\QQP>:J?/XZ +8;Y.]%CAKO8NV>,4&9ZSC=YQR^A\'$$.V +EOT + +<<'EOT', # Bit 58: cp852 +M>)P%P=M/S@$%)Z.1%^BG',HG8M2#L^C)]63ZJFG(M+!N;,+ +M%]WB'^C"QH:MBRYLKIBMF7'#*H=FS&9FN6%LIJW7"Q`.88030211+&,Y*UB) +MBVABB,5-'*N()X'5K&$M'A))(ID44DEC'>M)9P,;R<#8Q&8RV<)6LLAF&]O9 +MP4YVL9L]Y+"7?>SG`+GD<9!\"BBDB&)***6,<@YQF`HJ.4(5U1SE&,!@(T;B[00R]]]'.12USF +M"E>YQG4&&&2(848898QI_O.=+WQ5KZ+XIE)^R"L?/S7`JDSEJE10K?+S7K7J8Y%YA9CBD3/O?'"FG3GN\9?' +13'+?>:=^U:O!)IA8`NR$89P` +EOT + +<<'EOT', # Bit 59: cp775 +M>)P%PQ@)[LHHYP**@D09#=[V$L5^ZBFAOT@[30(A&CA"FB:,TO87YUJ\/"5F_MUF81J[4N#2I&"?(H785J48\Z-61N +M<]F8C=IUNV$C?."KJE7!;^9XHDH5JT2E\BNH9`4<#S,\6Q33#Q'V@>75\` +EOT + +<<'EOT', # Bit 60: cp737 +M>)P%P65W#@``AN';'FT8AFV&>>V1T]/3-;WN[M*=\\%QQMG!-IVOH]LFIKOK +M[_CJNH`.A"`ZTHG.=*$KW>A.#T+I22]Z$T8?^M*/*8RC>G,8":SF$T"][&,_]6I2LUIT0B=U +M2J=U1F=U3N=U01=U29<5U!5=U35=UPW=U"W=5JO:]%A/]%3/U*[G>J&7>J77 +M>J.W>J?W^J!/^JC/^J*O^J;O;G*S6QSB6!>[Q!E.=ZF3G>E\YSG780YWO.,< +M;9S@`A12(I#T0%5-/FX,$_P-K +#(&Q0 +EOT + +undef, # Bit 61: cp708 (unknown) + +<<'EOT', # Bit 62: cp850 +M>)P%P5-C$&```,#;UC&5[JV6WW++=0P^]5G\@V[9MV[;M.T2(E$QR +M*:242FIII)5.E/0RR"B3S++(*IOL@@XXZZ:R+KKKIKH>>>NFMC[X2]=/?``,-,M@00R499K@11AIE +MM#'&&F>\"2::9+(IIIIFNAF.^>V%AQZ[[XEG7GKEN7?>>NVP(TYXZJC/OOKH +MEQ_^N>JV[Q:Y[EK$7`^\\2+/;>>2>=)P%P3=,%&``AN$7?FR(>BH@(.#Q'Y^*(C;LV!LJ*+VW@SNZO1?`P<&!`6%Q +M1`D8RR!&8H(03$2,HXN3B4#LC5@B`4GT>0`??#'X,8G)3&$JT_!G.@',8":S +M<#";.TED'_LY0!+)'.00*:221CH9 +M9))%-CGDDD<^!1121#$EN"FE#`]>RJF@DBJJJ:&6PQSA*,`Y$WQBF+<,\HX/?.8+'QGA.U_IYQDO>,\`O_G#3_XRQC]> +M\9J;M-'NO.73S!#?^,4X/WC)';KIWS4,;:09,EXVQ;CJMUWI<3E<4HS:1 +1^S:41S;,V<`#M=+Z'T-Z<84` +EOT + +); + +# The following taken directly from OT Spec: + +@ranges = ( + [ 0, "Basic Latin", "0000-007F" ], + [ 1, "Latin-1 Supplement", "0080-00FF" ], + [ 2, "Latin Extended-A", "0100-017F" ], + [ 3, "Latin Extended-B", "0180-024F" ], + [ 4, "IPA Extensions", "0250-02AF" ], + [ 4, "Phonetic Extensions", "1D00-1D7F" ], + [ 4, "Phonetic Extensions Supplement", "1D80-1DBF" ], + [ 5, "Spacing Modifier Letters", "02B0-02FF" ], + [ 5, "Modifier Tone Letters", "A700-A71F" ], + [ 6, "Combining Diacritical Marks", "0300-036F" ], + [ 6, "Combining Diacritical Marks Supplement", "1DC0-1DFF" ], + [ 7, "Greek and Coptic", "0370-03FF" ], + [ 8, "Coptic", "2C80-2CFF" ], + [ 9, "Cyrillic", "0400-04FF" ], + [ 9, "Cyrillic Supplement", "0500-052F" ], + [ 9, "Cyrillic Extended-A", "2DE0-2DFF" ], + [ 9, "Cyrillic Extended-B", "A640-A69F" ], + [ 10, "Armenian", "0530-058F" ], + [ 11, "Hebrew", "0590-05FF" ], + [ 12, "Vai", "A500-A63F" ], + [ 13, "Arabic", "0600-06FF" ], + [ 13, "Arabic Supplement", "0750-077F" ], + [ 14, "NKo", "07C0-07FF" ], + [ 15, "Devanagari", "0900-097F" ], + [ 16, "Bengali", "0980-09FF" ], + [ 17, "Gurmukhi", "0A00-0A7F" ], + [ 18, "Gujarati", "0A80-0AFF" ], + [ 19, "Oriya", "0B00-0B7F" ], + [ 20, "Tamil", "0B80-0BFF" ], + [ 21, "Telugu", "0C00-0C7F" ], + [ 22, "Kannada", "0C80-0CFF" ], + [ 23, "Malayalam", "0D00-0D7F" ], + [ 24, "Thai", "0E00-0E7F" ], + [ 25, "Lao", "0E80-0EFF" ], + [ 26, "Georgian", "10A0-10FF" ], + [ 26, "Georgian Supplement", "2D00-2D2F" ], + [ 27, "Balinese", "1B00-1B7F" ], + [ 28, "Hangul Jamo", "1100-11FF" ], + [ 29, "Latin Extended Additional", "1E00-1EFF" ], + [ 29, "Latin Extended-C", "2C60-2C7F" ], + [ 29, "Latin Extended-D", "A720-A7FF" ], + [ 30, "Greek Extended", "1F00-1FFF" ], + [ 31, "General Punctuation", "2000-206F" ], + [ 31, "Supplemental Punctuation", "2E00-2E7F" ], + [ 32, "Superscripts And Subscripts", "2070-209F" ], + [ 33, "Currency Symbols", "20A0-20CF" ], + [ 34, "Combining Diacritical Marks For Symbols", "20D0-20FF" ], + [ 35, "Letterlike Symbols", "2100-214F" ], + [ 36, "Number Forms", "2150-218F" ], + [ 37, "Arrows", "2190-21FF" ], + [ 37, "Supplemental Arrows-A", "27F0-27FF" ], + [ 37, "Supplemental Arrows-B", "2900-297F" ], + [ 37, "Miscellaneous Symbols and Arrows", "2B00-2BFF" ], + [ 38, "Mathematical Operators", "2200-22FF" ], + [ 38, "Supplemental Mathematical Operators", "2A00-2AFF" ], + [ 38, "Miscellaneous Mathematical Symbols-A", "27C0-27EF" ], + [ 38, "Miscellaneous Mathematical Symbols-B", "2980-29FF" ], + [ 39, "Miscellaneous Technical", "2300-23FF" ], + [ 40, "Control Pictures", "2400-243F" ], + [ 41, "Optical Character Recognition", "2440-245F" ], + [ 42, "Enclosed Alphanumerics", "2460-24FF" ], + [ 43, "Box Drawing", "2500-257F" ], + [ 44, "Block Elements", "2580-259F" ], + [ 45, "Geometric Shapes", "25A0-25FF" ], + [ 46, "Miscellaneous Symbols", "2600-26FF" ], + [ 47, "Dingbats", "2700-27BF" ], + [ 48, "CJK Symbols And Punctuation", "3000-303F" ], + [ 49, "Hiragana", "3040-309F" ], + [ 50, "Katakana", "30A0-30FF" ], + [ 50, "Katakana Phonetic Extensions", "31F0-31FF" ], + [ 51, "Bopomofo", "3100-312F" ], + [ 51, "Bopomofo Extended", "31A0-31BF" ], + [ 52, "Hangul Compatibility Jamo", "3130-318F" ], + [ 53, "Phags-pa", "A840-A87F" ], + [ 54, "Enclosed CJK Letters And Months", "3200-32FF" ], + [ 55, "CJK Compatibility", "3300-33FF" ], + [ 56, "Hangul Syllables", "AC00-D7AF" ], + [ 57, "Non-Plane 0 * ", "D800-DFFF" ], + [ 58, "Phoenician", "10900-1091F" ], + [ 59, "CJK Unified Ideographs", "4E00-9FFF" ], + [ 59, "CJK Radicals Supplement", "2E80-2EFF" ], + [ 59, "Kangxi Radicals", "2F00-2FDF" ], + [ 59, "Ideographic Description Characters", "2FF0-2FFF" ], + [ 59, "CJK Unified Ideographs Extension A", "3400-4DBF" ], + [ 59, "CJK Unified Ideographs Extension B", "20000-2A6DF" ], + [ 59, "Kanbun", "3190-319F" ], + [ 60, "Private Use Area (plane 0)", "E000-F8FF" ], + [ 61, "CJK Strokes", "31C0-31EF" ], + [ 61, "CJK Compatibility Ideographs", "F900-FAFF" ], + [ 61, "CJK Compatibility Ideographs Supplement", "2F800-2FA1F" ], + [ 62, "Alphabetic Presentation Forms", "FB00-FB4F" ], + [ 63, "Arabic Presentation Forms-A", "FB50-FDFF" ], + [ 64, "Combining Half Marks", "FE20-FE2F" ], + [ 65, "Vertical Forms", "FE10-FE1F" ], + [ 65, "CJK Compatibility Forms", "FE30-FE4F" ], + [ 66, "Small Form Variants", "FE50-FE6F" ], + [ 67, "Arabic Presentation Forms-B", "FE70-FEFF" ], + [ 68, "Halfwidth And Fullwidth Forms", "FF00-FFEF" ], + [ 69, "Specials", "FFF0-FFFF" ], + [ 70, "Tibetan", "0F00-0FFF" ], + [ 71, "Syriac", "0700-074F" ], + [ 72, "Thaana", "0780-07BF" ], + [ 73, "Sinhala", "0D80-0DFF" ], + [ 74, "Myanmar", "1000-109F" ], + [ 75, "Ethiopic", "1200-137F" ], + [ 75, "Ethiopic Supplement", "1380-139F" ], + [ 75, "Ethiopic Extended", "2D80-2DDF" ], + [ 76, "Cherokee", "13A0-13FF" ], + [ 77, "Unified Canadian Aboriginal Syllabics", "1400-167F" ], + [ 78, "Ogham", "1680-169F" ], + [ 79, "Runic", "16A0-16FF" ], + [ 80, "Khmer", "1780-17FF" ], + [ 80, "Khmer Symbols", "19E0-19FF" ], + [ 81, "Mongolian", "1800-18AF" ], + [ 82, "Braille Patterns", "2800-28FF" ], + [ 83, "Yi Syllables", "A000-A48F" ], + [ 83, "Yi Radicals", "A490-A4CF" ], + [ 84, "Tagalog", "1700-171F" ], + [ 85, "Hanunoo", "1720-173F" ], + [ 85, "Buhid", "1740-175F" ], + [ 85, "Tagbanwa", "1760-177F" ], + [ 85, "Old Italic", "10300-1032F" ], + [ 86, "Gothic", "10330-1034F" ], + [ 87, "Deseret", "10400-1044F" ], + [ 88, "Byzantine Musical Symbols", "1D000-1D0FF" ], + [ 88, "Musical Symbols", "1D100-1D1FF" ], + [ 88, "Ancient Greek Musical Notation", "1D200-1D24F" ], + [ 89, "Mathematical Alphanumeric Symbols", "1D400-1D7FF" ], + [ 90, "Private Use (plane 15)", "FF000-FFFFD" ], + [ 90, "Private Use (plane 16)", "100000-10FFFD" ], + [ 91, "Variation Selectors", "FE00-FE0F" ], + [ 91, "Variation Selectors Supplement", "E0100-E01EF" ], + [ 92, "Tags", "E0000-E007F" ], + [ 93, "Limbu", "1900-194F" ], + [ 94, "Tai Le", "1950-197F" ], + [ 95, "New Tai Lue", "1980-19DF" ], + [ 96, "Buginese", "1A00-1A1F" ], + [ 97, "Glagolitic", "2C00-2C5F" ], + [ 98, "Tifinagh", "2D30-2D7F" ], + [ 99, "Yijing Hexagram Symbols", "4DC0-4DFF" ], + [ 100, "Syloti Nagri", "A800-A82F" ], + [ 101, "Linear B Syllabary", "10000-1007F" ], + [ 101, "Linear B Ideograms", "10080-100FF" ], + [ 101, "Aegean Numbers", "10100-1013F" ], + [ 102, "Ancient Greek Numbers", "10140-1018F" ], + [ 103, "Ugaritic", "10380-1039F" ], + [ 104, "Old Persian", "103A0-103DF" ], + [ 105, "Shavian", "10450-1047F" ], + [ 106, "Osmanya", "10480-104AF" ], + [ 107, "Cypriot Syllabary", "10800-1083F" ], + [ 108, "Kharoshthi", "10A00-10A5F" ], + [ 109, "Tai Xuan Jing Symbols", "1D300-1D35F" ], + [ 110, "Cuneiform", "12000-123FF" ], + [ 110, "Cuneiform Numbers and Punctuation", "12400-1247F" ], + [ 111, "Counting Rod Numerals", "1D360-1D37F" ], + [ 112, "Sundanese", "1B80-1BBF" ], + [ 113, "Lepcha", "1C00-1C4F" ], + [ 114, "Ol Chiki", "1C50-1C7F" ], + [ 115, "Saurashtra", "A880-A8DF" ], + [ 116, "Kayah Li", "A900-A92F" ], + [ 117, "Rejang", "A930-A95F" ], + [ 118, "Cham", "AA00-AA5F" ], + [ 119, "Ancient Symbols", "10190-101CF" ], + [ 120, "Phaistos Disc", "101D0-101FF" ], + [ 121, "Carian", "102A0-102DF" ], + [ 121, "Lycian", "10280-1029F" ], + [ 121, "Lydian", "10920-1093F" ], + [ 122, "Domino Tiles", "1F030-1F09F" ], + [ 122, "Mahjong Tiles", "1F000-1F02F" ], + [ 123-127, "Reserved", "" ], +); + +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OTTags.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OTTags.pm new file mode 100644 index 0000000000..41f7703acd --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OTTags.pm @@ -0,0 +1,1698 @@ +use utf8; # NB: This file includes non-ASCII string constants in UTF-8 encoding + +package Font::TTF::OTTags; + +=head1 NAME + +Font::TTF::OTTags - Utilities for TrueType/OpenType tags + +=head1 SYNOPSIS + + use Font::TTF::OTTags qw( %tttags %ttnames %iso639 readtagsfile ); + + # Look at built-in stuff: + $script_tag = $tttags{'SCRIPT'}{'Cypriot Syllabary'}; # returns 'cprt' + $lang_name = $ttnames{'LANGUAGE'}{'ALT '}; # returns 'Altai' + + # Map iso639-2 tag to/from OT lang tag + @isotags = $iso639{'ALT '}; # returns [ 'atv', 'alt' ] + $lang_tag = $iso639{'atv'}; # returns 'ALT ' + + # Read latest tags file to add to built-in definitions + readtagsfile ("C:\\Program Files\\Microsoft VOLT\\TAGS.txt"); + +First-level keys to %tttags and %ttnames are: + +=over + +=item SCRIPT + +retrieve script tag or name + +=item LANGUAGE + +retrieve language tag or name + +=item FEATURE + +retrieve feature tag or name + +=back + +Built-in data has been derived from the 2014-07-11 draft of the +3rd edition of ISO/IEC 14496-22 +(Information technology - Coding of audio-visual objects - Part 22: Open Font Format) +which, when finalized and approved, will replace the second edition (ISO/IEC 14496-22:2009). + +=head1 METHODS + +=cut + +use strict; +use vars qw( %tttags %ttnames %iso639 @EXPORT_OK @ISA ); +require Exporter; +@ISA = qw( Exporter ); +@EXPORT_OK = qw( %tttags %ttnames %iso639 readtagsfile); + + +# All data below derived Microsoft OpenType specification 1.6 + +%tttags = ( + +'SCRIPT' => { + "Adlam" => 'adlm', + "Ahom" => 'ahom', + "Anatolian Hieroglyphs" => 'hluw', + "Arabic" => 'arab', + "Armenian" => 'armn', + "Avestan" => 'avst', + "Balinese" => 'bali', + "Bamum" => 'bamu', + "Bassa Vah" => 'bass', + "Batak" => 'batk', + "Bengali" => 'beng', + "Bengali v.2" => 'bng2', + "Bhaiksuki" => 'bhks', + "Bopomofo" => 'bopo', + "Brahmi" => 'brah', + "Braille" => 'brai', + "Buginese" => 'bugi', + "Buhid" => 'buhd', + "Byzantine Music" => 'byzm', + "Canadian Syllabics" => 'cans', + "Carian" => 'cari', + "Caucasian Albanian" => 'aghb', + "Chakma" => 'cakm', + "Cham" => 'cham', + "Cherokee" => 'cher', + "CJK Ideographic" => 'hani', + "Coptic" => 'copt', + "Cypriot Syllabary" => 'cprt', + "Cyrillic" => 'cyrl', + "Default" => 'DFLT', + "Deseret" => 'dsrt', + "Devanagari" => 'deva', + "Devanagari v.2" => 'dev2', + "Duployan" => 'dupl', + "Egyptian hieroglyphs" => 'egyp', + "Elbasan" => 'elba', + "Ethiopic" => 'ethi', + "Georgian" => 'geor', + "Glagolitic" => 'glag', + "Gothic" => 'goth', + "Grantha" => 'gran', + "Greek" => 'grek', + "Gujarati" => 'gujr', + "Gujarati v.2" => 'gjr2', + "Gurmukhi" => 'guru', + "Gurmukhi v.2" => 'gur2', + "Hangul" => 'hang', + "Hangul Jamo" => 'jamo', + "Hanunoo" => 'hano', + "Hatran" => 'hatr', + "Hebrew" => 'hebr', + "Hiragana" => 'kana', + "Imperial Aramaic" => 'armi', + "Inscriptional Pahlavi" => 'phli', + "Inscriptional Parthian" => 'prti', + "Javanese" => 'java', + "Kaithi" => 'kthi', + "Kannada" => 'knda', + "Kannada v.2" => 'knd2', + "Katakana" => 'kana', + "Kayah Li" => 'kali', + "Kharosthi" => 'khar', + "Khmer" => 'khmr', + "Khojki" => 'khoj', + "Khudawadi" => 'sind', + "Lao" => 'lao ', + "Latin" => 'latn', + "Lepcha" => 'lepc', + "Limbu" => 'limb', + "Linear A" => 'lina', + "Linear B" => 'linb', + "Lisu (Fraser)" => 'lisu', + "Lycian" => 'lyci', + "Lydian" => 'lydi', + "Mahajani" => 'mahj', + "Marchen" => 'marc', + "Malayalam" => 'mlym', + "Malayalam v.2" => 'mlm2', + "Mandaic, Mandaean" => 'mand', + "Manichaean" => 'mani', + "Mathematical Alphanumeric Symbols" => 'math', + "Meitei Mayek (Meithei, Meetei)" => 'mtei', + "Mende Kikakui" => 'mend', + "Meroitic Cursive" => 'merc', + "Meroitic Hieroglyphs" => 'mero', + "Miao" => 'plrd', + "Modi" => 'modi', + "Mongolian" => 'mong', + "Mro" => 'mroo', + "Multani" => 'mult', + "Musical Symbols" => 'musc', + "Myanmar" => 'mymr', + "Myanmar v.2" => 'mym2', + "Nabataean" => 'nbat', + "Newa" => 'newa', + "New Tai Lue" => 'talu', + "N'Ko" => 'nko ', + "Odia (formerly Oriya)" => 'orya', + "Odia (formerly Oriya) v.2" => 'ory2', + "Ogham" => 'ogam', + "Ol Chiki" => 'olck', + "Old Italic" => 'ital', + "Old Hungarian" => 'hung', + "Old North Arabian" => 'narb', + "Old Permic" => 'perm', + "Old Persian Cuneiform" => 'xpeo', + "Old South Arabian" => 'sarb', + "Old Turkic, Orkhon Runic" => 'orkh', + "Osage" => 'osge', + "Osmanya" => 'osma', + "Pahawh Hmong" => 'hmng', + "Palmyrene" => 'palm', + "Pau Cin Hau" => 'pauc', + "Phags-pa" => 'phag', + "Phoenician" => 'phnx', + "Psalter Pahlavi" => 'phlp', + "Rejang" => 'rjng', + "Runic" => 'runr', + "Samaritan" => 'samr', + "Saurashtra" => 'saur', + "Sharada" => 'shrd', + "Shavian" => 'shaw', + "Siddham" => 'sidd', + "Sign Writing" => 'sgnw', + "Sinhala" => 'sinh', + "Sora Sompeng" => 'sora', + "Sumero-Akkadian Cuneiform" => 'xsux', + "Sundanese" => 'sund', + "Syloti Nagri" => 'sylo', + "Syriac" => 'syrc', + "Tagalog" => 'tglg', + "Tagbanwa" => 'tagb', + "Tai Le" => 'tale', + "Tai Tham (Lanna)" => 'lana', + "Tai Viet" => 'tavt', + "Takri" => 'takr', + "Tamil" => 'taml', + "Tamil v.2" => 'tml2', + "Tangut" => 'tang', + "Telugu" => 'telu', + "Telugu v.2" => 'tel2', + "Thaana" => 'thaa', + "Thai" => 'thai', + "Tibetan" => 'tibt', + "Tifinagh" => 'tfng', + "Tirhuta" => 'tirh', + "Ugaritic Cuneiform" => 'ugar', + "Vai" => 'vai ', + "Warang Citi" => 'wara', + "Yi" => 'yi ', + }, + +'LANGUAGE' => { + "Aari" => 'ARI ', + "Abaza" => 'ABA ', + "Abkhazian" => 'ABK ', + "Achi" => 'ACR ', + "Acholi" => 'ACH ', + "Adyghe" => 'ADY ', + "Afar" => 'AFR ', + "Afrikaans" => 'AFK ', + "Agaw" => 'AGW ', + "Aiton" => 'AIO ', + "Akan" => 'AKA ', + "Albanian" => 'SQI ', + "Alsatian" => 'ALS ', + "Altai" => 'ALT ', + "Amharic" => 'AMH ', + "Anglo-Saxon" => 'ANG ', + "Arabic" => 'ARA ', + "Aragonese" => 'ARG ', + "Arakwal" => 'RKW ', + "Armenian East" => 'HYE0', + "Armenian" => 'HYE ', + "Aromanian" => 'RUP ', + "Arpitan" => 'FRP ', + "Assamese" => 'ASM ', + "Asturian" => 'AST ', + "Athapaskan" => 'ATH ', + "Avar" => 'AVR ', + "Awadhi" => 'AWA ', + "Aymara" => 'AYM ', + "Azerbaijani" => 'AZE ', + "Badaga" => 'BAD ', + "Baghelkhandi" => 'BAG ', + "Bagri" => 'BGQ ', + "Balante" => 'BLN ', + "Balinese" => 'BAN ', + "Balkar" => 'BAL ', + "Balti" => 'BLT ', + "Baluchi" => 'BLI ', + "Bambara (Bamanankan)" => 'BMB ', + "Bamileke" => 'BML ', + "Banda" => 'BAD0', + "Bandjalang" => 'BDY ', + "BaoulĂ©" => 'BAU ', + "Bashkir" => 'BSH ', + "Basque" => 'EUQ ', + "Batak Simalungun" => 'BTS ', + "Batak Toba" => 'BBC ', + "Bavarian" => 'BAR ', + "Belarusian" => 'BEL ', + "Bemba" => 'BEM ', + "Bench" => 'BCH ', + "Bengali" => 'BEN ', + "Berber" => 'BBR ', + "Beti" => 'BTI ', + "Bhili" => 'BHI ', + "Bhojpuri" => 'BHO ', + "Bible Cree" => 'BCR ', + "Bikol" => 'BIK ', + "Bilen" => 'BIL ', + "Bishnupriya Manipuri" => 'BPY ', + "Bislama" => 'BIS ', + "Blackfoot" => 'BKF ', + "Bodo" => 'BRX ', + "Bosnian" => 'BOS ', + "Bouyei" => 'PCC ', + "Brahui" => 'BRH ', + "Braj Bhasha" => 'BRI ', + "Breton" => 'BRE ', + "Bugis" => 'BUG ', + "Bulgarian" => 'BGR ', + "Burmese" => 'BRM ', + "Burushaski" => 'BSK ', + "Cajun French" => 'FRC ', + "Carrier" => 'CRR ', + "Catalan" => 'CAT ', + "Cebuano" => 'CEB ', + "Central Yupik" => 'ESU ', + "Chaha Gurage" => 'CHG ', + "Chamorro" => 'CHA ', + "Chattisgarhi" => 'CHH ', + "Chechen" => 'CHE ', + "Cherokee" => 'CHR ', + "Cheyenne" => 'CHY ', + "Chichewa (Chewa, Nyanja)" => 'CHI ', + "Chiga" => 'CGG ', + "Chin" => 'QIN ', + "Chinese Phonetic" => 'ZHP ', + "Chinese Simplified" => 'ZHS ', + "Chinese Traditional" => 'ZHT ', + "Chinese, Hong Kong SAR" => 'ZHH ', + "Chipewyan" => 'CHP ', + "Chittagonian" => 'CTG ', + "Choctaw" => 'CHO ', + "Chukchi" => 'CHK ', + "Church Slavonic" => 'CSL ', + "Chuukese" => 'CHK0', + "Chuvash" => 'CHU ', + "Comorian" => 'CMR ', + "Coptic" => 'COP ', + "Cornish" => 'COR ', + "Corsican" => 'COS ', + "Cree" => 'CRE ', + "Creoles" => 'CPP ', + "Crimean Tatar" => 'CRT ', + "Croatian" => 'HRV ', + "Czech" => 'CSY ', + "Dan" => 'DNJ ', + "Dangme" => 'DNG ', + "Danish" => 'DAN ', + "Dargwa" => 'DAR ', + "Dari" => 'DRI ', + "Dayi" => 'DAX ', + "Dehong Dai" => 'TDD ', + "Dhangu" => 'DHG ', + "Dhuwal" => 'DUJ ', + "Dimli" => 'DIQ ', + "Dinka" => 'DNK ', + "Divehi (Dhivehi, Maldivian) (deprecated)" => 'DHV ', + "Divehi (Dhivehi, Maldivian)" => 'DIV ', + "Djambarrpuyngu" => 'DJR0', + "Dogri" => 'DGO ', + "Dogri" => 'DGR ', + "Dungan" => 'DUN ', + "Dutch (Flemish)" => 'FLE ', + "Dutch" => 'NLD ', + "Dzongkha" => 'DZN ', + "Eastern Cree" => 'ECR ', + "Eastern Maninkakan" => 'EMK ', + "Eastern Pwo Karen" => 'KJP ', + "Ebira" => 'EBI ', + "Edo" => 'EDO ', + "Efik" => 'EFI ', + "English" => 'ENG ', + "Erzya" => 'ERZ ', + "Esperanto" => 'NTO ', + "Estonian" => 'ETI ', + "Even" => 'EVN ', + "Evenki" => 'EVK ', + "Ewe" => 'EWE ', + "Fang" => 'FAN0', + "Fanti" => 'FAT ', + "Faroese" => 'FOS ', + "Fe'fe'" => 'FMP ', + "Fijian" => 'FJI ', + "Filipino" => 'PIL ', + "Finnish" => 'FIN ', + "Fon" => 'FON ', + "Forest Nenets" => 'FNE ', + "French Antillean" => 'FAN ', + "French" => 'FRA ', + "Frisian" => 'FRI ', + "Friulian" => 'FRL ', + "Fulah" => 'FUL ', + "Futa" => 'FTA ', + "Ga" => 'GAD ', + "Gagauz" => 'GAG ', + "Galician" => 'GAL ', + "Ganda" => 'LUG ', + "Garhwali" => 'GAW ', + "Garo" => 'GRO ', + "Garshuni" => 'GAR ', + "Ge'ez" => 'GEZ ', + "Georgian" => 'KAT ', + "German" => 'DEU ', + "Gilaki" => 'GLK ', + "Gilyak" => 'GIL ', + "Githabul" => 'GIH ', + "Gogo" => 'GOG ', + "Gondi" => 'GON ', + "Greek" => 'ELL ', + "Greenlandic" => 'GRN ', + "Guarani" => 'GUA ', + "Gujarati" => 'GUJ ', + "Gumatj" => 'GNN ', + "Gumuz" => 'GMZ ', + "Gupapuyngu" => 'GUF ', + "Gusii" => 'GUZ ', + "Haitian (Haitian Creole)" => 'HAI ', + "Halam" => 'HAL ', + "Hammer-Banna" => 'HBN ', + "Harari" => 'HRI ', + "Harauti" => 'HAR ', + "Haryanvi" => 'BGC ', + "Hausa" => 'HAU ', + "Hawaiian" => 'HAW ', + "Haya" => 'HAY ', + "Hazaragi" => 'HAZ ', + "Hebrew" => 'IWR ', + "Herero" => 'HER ', + "High Mari" => 'HMA ', + "Hiligaynon" => 'HIL ', + "Hindi" => 'HIN ', + "Hindko" => 'HND ', + "Hiri Motu" => 'HMO ', + "Hmong Daw" => 'MWW ', + "Hmong" => 'HMN ', + "Ho" => 'HO ', + "Hungarian" => 'HUN ', + "Iban" => 'IBA ', + "Ibibio" => 'IBB ', + "Icelandic" => 'ISL ', + "Ido" => 'IDO ', + "Igbo" => 'IBO ', + "Ijo languages" => 'IJO ', + "Ilokano" => 'ILO ', + "Inari Sami" => 'ISM ', + "Indonesian" => 'IND ', + "Ingush" => 'ING ', + "Interlingua" => 'INA ', + "Interlingue" => 'ILE ', + "Inuktitut" => 'INU ', + "Inupiat" => 'IPK ', + "Irish Traditional" => 'IRT ', + "Irish" => 'IRI ', + "Italian" => 'ITA ', + "Jamaican Creole" => 'JAM ', + "Japanese" => 'JAN ', + "Javanese" => 'JAV ', + "Jula" => 'JUL ', + "Kabardian" => 'KAB ', + "Kabuverdianu (Crioulo)" => 'KEA ', + "Kabyle" => 'KAB0', + "Kachchi" => 'KAC ', + "Kalenjin" => 'KAL ', + "Kalmyk" => 'KLM ', + "Kamba" => 'KMB ', + "Kanauji" => 'BJJ ', + "Kannada" => 'KAN ', + "Kanuri" => 'KNR ', + "Kaqchikel" => 'CAK ', + "Karachay" => 'KAR ', + "Karaim" => 'KRM ', + "Karakalpak" => 'KRK ', + "Karelian" => 'KRL ', + "Karen" => 'KRN ', + "Kashmiri" => 'KSH ', + "Kashubian" => 'CSB ', + "Kazakh" => 'KAZ ', + "Kebena" => 'KEB ', + "Kekchi" => 'KEK ', + "Khakass" => 'KHA ', + "Khamti Shan" => 'KHT ', + "Khanty-Kazim" => 'KHK ', + "Khanty-Shurishkar" => 'KHS ', + "Khanty-Vakhi" => 'KHV ', + "Khasi" => 'KSI ', + "Khmer" => 'KHM ', + "Khorasani Turkic" => 'KMZ ', + "Khowar" => 'KHW ', + "Khutsuri Georgian" => 'KGE ', + "Kikongo" => 'KON ', + "Kikuyu (Gikuyu)" => 'KIK ', + "Kildin Sami" => 'KSM ', + "Kinyarwanda" => 'RUA ', + "Kirghiz (Kyrgyz)" => 'KIR ', + "Kiribati (Gilbertese)" => 'GIL0', + "Kirmanjki" => 'KIU ', + "Kisii" => 'KIS ', + "Kituba" => 'MKW ', + "Kodagu" => 'KOD ', + "Kokni" => 'KKN ', + "Komi" => 'KOM ', + "Komi-Permyak" => 'KOP ', + "Komi-Zyrian" => 'KOZ ', + "Komo" => 'KMO ', + "Komso" => 'KMS ', + "Kongo" => 'KON0', + "Konkani" => 'KOK ', + "Koorete" => 'KRT ', + "Korean Old Hangul" => 'KOH ', + "Korean" => 'KOR ', + "Koryak" => 'KYK ', + "Kosraean" => 'KOS ', + "Kpelle (Guinea)" => 'GKP ', + "Kpelle (Liberia)" => 'XPE ', + "Kpelle" => 'KPL ', + "Krio" => 'KRI ', + "Krymchak" => 'JCT ', + "Kuanyama" => 'KUA ', + "Kui" => 'KUI ', + "Kulvi" => 'KUL ', + "Kumaoni" => 'KMN ', + "Kumyk" => 'KUM ', + "Kurdish" => 'KUR ', + "Kurukh" => 'KUU ', + "Kuy" => 'KUY ', + "K'iche'" => 'QUC ', + "L-Cree" => 'LCR ', + "Ladakhi" => 'LDK ', + "Ladin" => 'LAD ', + "Ladino" => 'JUD ', + "Lahuli" => 'LAH ', + "Lak" => 'LAK ', + "Laki" => 'LKI ', + "Lambani" => 'LAM ', + "Lampung" => 'LJP ', + "Lao" => 'LAO ', + "Latin" => 'LAT ', + "Latvian" => 'LVI ', + "Laz" => 'LAZ ', + "Lezgi" => 'LEZ ', + "Ligurian" => 'LIJ ', + "Limbu" => 'LMB ', + "Limburgish" => 'LIM ', + "Lingala" => 'LIN ', + "Lisu" => 'LIS ', + "Lithuanian" => 'LTH ', + "Lojban" => 'JBO ', + "Loma" => 'LOM ', + "Lombard" => 'LMO ', + "Lomwe" => 'LMW ', + "Low Mari" => 'LMA ', + "Low Saxon" => 'NDS ', + "Lower Sorbian" => 'LSB ', + "Luba-Katanga" => 'LUB ', + "Luba-Lulua" => 'LUA ', + "Lule Sami" => 'LSM ', + "Luo" => 'LUO ', + "Luri" => 'LRC ', + "Luxembourgish" => 'LTZ ', + "Luyia" => 'LUH ', + "LĂĽ" => 'XBD ', + "Macedonian" => 'MKD ', + "Madura" => 'MAD ', + "Magahi" => 'MAG ', + "Maithili" => 'MTH ', + "Majang" => 'MAJ ', + "Makasar" => 'MKR ', + "Makhuwa" => 'MAK ', + "Makonde" => 'KDE ', + "Malagasy" => 'MLG ', + "Malay" => 'MLY ', + "Malayalam Reformed" => 'MLR ', + "Malayalam Traditional" => 'MAL ', + "Male" => 'MLE ', + "Malinke" => 'MLN ', + "Maltese" => 'MTS ', + "Mam" => 'MAM ', + "Manchu" => 'MCH ', + "Mandar" => 'MDR ', + "Mandinka" => 'MND ', + "Maninka" => 'MNK ', + "Manipuri" => 'MNI ', + "Mansi" => 'MAN ', + "Manx" => 'MNX ', + "Maori" => 'MRI ', + "Mapudungun" => 'MAP ', + "Marathi" => 'MAR ', + "Marshallese" => 'MAH ', + "Marwari" => 'MAW ', + "Mayan" => 'MYN ', + "Mazanderani" => 'MZN ', + "Mbembe Tigon" => 'NZA ', + "Mbo" => 'MBO ', + "Mbundu" => 'MBN ', + "Me'en" => 'MEN ', + "Medumba" => 'BYV ', + "Mende" => 'MDE ', + "Meru" => 'MER ', + "Mewati" => 'WTM ', + "Minangkabau" => 'MIN ', + "Minjangbal" => 'XJB ', + "Mirandese" => 'MWL ', + "Mizo" => 'MIZ ', + "Mohawk" => 'MOH ', + "Moksha" => 'MOK ', + "Moldavian" => 'MOL ', + "Mon" => 'MON ', + "Mongolian" => 'MNG ', + "Moose Cree" => 'MCR ', + "Morisyen" => 'MFE ', + "Moroccan" => 'MOR ', + "Mossi" => 'MOS ', + "Mundari" => 'MUN ', + "Muscogee" => 'MUS ', + "N'Ko" => 'NKO ', + "N-Cree" => 'NCR ', + "Naga-Assamese" => 'NAG ', + "Nagari" => 'NGR ', + "Nahuatl" => 'NAH ', + "Nanai" => 'NAN ', + "Naskapi" => 'NAS ', + "Nauruan" => 'NAU ', + "Navajo" => 'NAV ', + "Ndau" => 'NDC ', + "Ndebele" => 'NDB ', + "Ndonga" => 'NDG ', + "Neapolitan" => 'NAP ', + "Nepali" => 'NEP ', + "Newari" => 'NEW ', + "Ngbaka" => 'NGA ', + "Nigerian Fulfulde" => 'FUV ', + "Nimadi" => 'NOE ', + "Nisi" => 'NIS ', + "Niuean" => 'NIU ', + "Nogai" => 'NOG ', + "Norfolk" => 'PIH ', + "North Slavey" => 'SCS ', + "Northern Sami" => 'NSM ', + "Northern Thai" => 'NTA ', + "Norway House Cree" => 'NHC ', + "Norwegian Nynorsk (Nynorsk, Norwegian)" => 'NYN ', + "Norwegian" => 'NOR ', + "Novial" => 'NOV ', + "Nyamwezi" => 'NYM ', + "Nyankole" => 'NKL ', + "Occitan" => 'OCI ', + "Odia (formerly Oriya)" => 'ORI ', + "Oji-Cree" => 'OCR ', + "Ojibway" => 'OJB ', + "Old Irish" => 'SGA ', + "Oromo" => 'ORO ', + "Ossetian" => 'OSS ', + "Pa'o Karen" => 'BLK ', + "Palauan" => 'PAU ', + "Palaung" => 'PLG ', + "Palestinian Aramaic" => 'PAA ', + "Pali" => 'PAL ', + "Palpa" => 'PAP ', + "Pampangan" => 'PAM ', + "Pangasinan" => 'PAG ', + "Papiamentu" => 'PAP0', + "Pashto" => 'PAS ', + "Pennsylvania German" => 'PDC ', + "Persian" => 'FAR ', + "Phake" => 'PHK ', + "Phonetic transcription - Americanist conventions" => 'APPH', + "Phonetic transcription - IPA conventions" => 'IPPH', + "Picard" => 'PCD ', + "Piemontese" => 'PMS ', + "Pocomchi" => 'POH ', + "Pohnpeian" => 'PON ', + "Polish" => 'PLK ', + "Polytonic Greek" => 'PGR ', + "Portuguese" => 'PTG ', + "Provencal" => 'PRO ', + "Punjabi" => 'PAN ', + "Quechua (Bolivia)" => 'QUH ', + "Quechua (Ecuador)" => 'QVI ', + "Quechua (Peru)" => 'QWH ', + "Quechua" => 'QUZ ', + "R-Cree" => 'RCR ', + "Rajasthani" => 'RAJ ', + "Rakhine" => 'ARK ', + "Rarotongan" => 'RAR ', + "Rejang" => 'REJ ', + "Riang" => 'RIA ', + "Ripuarian" => 'KSH0', + "Ritarungo" => 'RIT ', + "Romanian" => 'ROM ', + "Romansh" => 'RMS ', + "Romany" => 'ROY ', + "Rotuman" => 'RTM ', + "Rundi" => 'RUN ', + "Russian Buriat" => 'RBU ', + "Russian" => 'RUS ', + "Rusyn" => 'RSY ', + "Sadri" => 'SAD ', + "Sakha" => 'YAK ', + "Samoan" => 'SMO ', + "Samogitian" => 'SGS ', + "San Blas Kuna" => 'CUK ', + "Sango" => 'SGO ', + "Sanskrit" => 'SAN ', + "Santali" => 'SAT ', + "Sardinian" => 'SRD ', + "Sasak" => 'SAS ', + "Saterland Frisian" => 'STQ ', + "Sayisi" => 'SAY ', + "Scots" => 'SCO ', + "Scottish Gaelic (Gaelic)" => 'GAE ', + "Sekota" => 'SEK ', + "Selkup" => 'SEL ', + "Sena" => 'SNA ', + "Seraiki" => 'SRK ', + "Serbian" => 'SRB ', + "Serer" => 'SRR ', + "Shan" => 'SHN ', + "Shona" => 'SNA0', + "Sibe" => 'SIB ', + "Sicilian" => 'SCN ', + "Sidamo" => 'SID ', + "Silesian" => 'SZL ', + "Silte Gurage" => 'SIG ', + "Sindhi" => 'SND ', + "Sinhala (Sinhalese)" => 'SNH ', + "Skolt Sami" => 'SKS ', + "Slavey" => 'SLA ', + "Slovak" => 'SKY ', + "Slovenian" => 'SLV ', + "Sodo Gurage" => 'SOG ', + "Soga" => 'XOG ', + "Somali" => 'SML ', + "Songe" => 'SOP ', + "Soninke" => 'SNK ', + "Sotho, Northern" => 'NSO ', + "Sotho, Southern" => 'SOT ', + "South Slavey" => 'SSL ', + "Southern Kiwai" => 'KJD ', + "Southern Sami" => 'SSM ', + "Spanish" => 'ESP ', + "Standard Morrocan Tamazigh" => 'ZGH ', + "Sukuma" => 'SUK ', + "Sundanese" => 'SUN ', + "Suri" => 'SUR ', + "Sutu" => 'SXT ', + "Svan" => 'SVA ', + "Swadaya Aramaic" => 'SWA ', + "Swahili" => 'SWK ', + "Swati" => 'SWZ ', + "Swedish" => 'SVE ', + "Sylheti" => 'SYL ', + "Syriac" => 'SYR ', + "S'gaw Karen" => 'KSW ', + "TH-Cree" => 'TCR ', + "Tabasaran" => 'TAB ', + "Tachelhit" => 'SHI ', + "Tagalog" => 'TGL ', + "Tahitian" => 'THT ', + "Tajik" => 'TAJ ', + "Tamashek" => 'TMH ', + "Tamazight" => 'TZM ', + "Tamil" => 'TAM ', + "Tarifit" => 'RIF ', + "Tatar" => 'TAT ', + "Telugu" => 'TEL ', + "Temne" => 'TMN ', + "Tetum" => 'TET ', + "Thai" => 'THA ', + "Tibetan" => 'TIB ', + "Tigre" => 'TGR ', + "Tigrinya" => 'TGY ', + "Tiv" => 'TIV ', + "Todo" => 'TOD ', + "Tok Pisin" => 'TPI ', + "Toma" => 'TOD0', + "Tonga" => 'TNG ', + "Tongan" => 'TGN ', + "Torki" => 'AZB ', + "Tsonga" => 'TSG ', + "Tswana" => 'TNA ', + "Tulu" => 'TUL ', + "Tumbuka" => 'TUM ', + "Tundra Nenets" => 'TNE ', + "Turkish" => 'TRK ', + "Turkmen" => 'TKM ', + "Turoyo Aramaic" => 'TUA ', + "Tuvalu" => 'TVL ', + "Tuvin" => 'TUV ', + "Twi" => 'TWI ', + "Tzotzil" => 'TZO ', + "TĂ y" => 'TYZ ', + "Udmurt" => 'UDM ', + "Ukrainian" => 'UKR ', + "Umbundu" => 'UMB ', + "Upper Saxon" => 'SXU ', + "Upper Sorbian" => 'USB ', + "Urdu" => 'URD ', + "Uyghur" => 'UYG ', + "Uzbek" => 'UZB ', + "Venda" => 'VEN ', + "Venetian" => 'VEC ', + "Vietnamese" => 'VIT ', + "Vlax Romani" => 'RMY ', + "VolapĂĽk" => 'VOL ', + "Võro" => 'VRO ', + "Wa" => 'WA ', + "Wagdi" => 'WAG ', + "Walloon" => 'WLN ', + "Waray-Waray" => 'WAR ', + "Wayuu" => 'GUC ', + "Welsh" => 'WEL ', + "West-Cree" => 'WCR ', + "Western Kayah" => 'KYU ', + "Western Panjabi" => 'PNB ', + "Western Pwo Karen" => 'PWO ', + "Wolof" => 'WLF ', + "Woods Cree" => 'DCR ', + "Xhosa" => 'XHS ', + "Y-Cree" => 'YCR ', + "Yao" => 'YAO ', + "Yapese" => 'YAP ', + "Yi Classic" => 'YIC ', + "Yi Modern" => 'YIM ', + "Yiddish" => 'JII ', + "Yoruba" => 'YBA ', + "Zamboanga Chavacano" => 'CBK ', + "Zande" => 'ZND ', + "Zarma" => 'DJR ', + "Zazaki" => 'ZZA ', + "Zealandic" => 'ZEA ', + "Zhuang" => 'ZHA ', + "Zulu" => 'ZUL ', + }, + +'FEATURE' => { + "Above-base Forms" => 'abvf', + "Above-base Mark Positioning" => 'abvm', + "Above-base Substitutions" => 'abvs', + "Access All Alternates" => 'aalt', + "Akhands" => 'akhn', + "Alternate Annotation Forms" => 'nalt', + "Alternate Half Widths" => 'halt', + "Alternate Vertical Half Metrics" => 'vhal', + "Alternate Vertical Metrics" => 'valt', + "Alternative Fractions" => 'afrc', + "Below-base Forms" => 'blwf', + "Below-base Mark Positioning" => 'blwm', + "Below-base Substitutions" => 'blws', + "Capital Spacing" => 'cpsp', + "Case-Sensitive Forms" => 'case', + "Centered CJK Punctuation" => 'cpct', + "Character Variants 01" => 'cv01', + "Character Variants 02" => 'cv02', + "Character Variants 03" => 'cv03', + "Character Variants 04" => 'cv04', + "Character Variants 05" => 'cv05', + "Character Variants 06" => 'cv06', + "Character Variants 07" => 'cv07', + "Character Variants 08" => 'cv08', + "Character Variants 09" => 'cv09', + "Character Variants 10" => 'cv10', + "Character Variants 11" => 'cv11', + "Character Variants 12" => 'cv12', + "Character Variants 13" => 'cv13', + "Character Variants 14" => 'cv14', + "Character Variants 15" => 'cv15', + "Character Variants 16" => 'cv16', + "Character Variants 17" => 'cv17', + "Character Variants 18" => 'cv18', + "Character Variants 19" => 'cv19', + "Character Variants 20" => 'cv20', + "Character Variants 21" => 'cv21', + "Character Variants 22" => 'cv22', + "Character Variants 23" => 'cv23', + "Character Variants 24" => 'cv24', + "Character Variants 25" => 'cv25', + "Character Variants 26" => 'cv26', + "Character Variants 27" => 'cv27', + "Character Variants 28" => 'cv28', + "Character Variants 29" => 'cv29', + "Character Variants 30" => 'cv30', + "Character Variants 31" => 'cv31', + "Character Variants 32" => 'cv32', + "Character Variants 33" => 'cv33', + "Character Variants 34" => 'cv34', + "Character Variants 35" => 'cv35', + "Character Variants 36" => 'cv36', + "Character Variants 37" => 'cv37', + "Character Variants 38" => 'cv38', + "Character Variants 39" => 'cv39', + "Character Variants 40" => 'cv40', + "Character Variants 41" => 'cv41', + "Character Variants 42" => 'cv42', + "Character Variants 43" => 'cv43', + "Character Variants 44" => 'cv44', + "Character Variants 45" => 'cv45', + "Character Variants 46" => 'cv46', + "Character Variants 47" => 'cv47', + "Character Variants 48" => 'cv48', + "Character Variants 49" => 'cv49', + "Character Variants 50" => 'cv50', + "Character Variants 51" => 'cv51', + "Character Variants 52" => 'cv52', + "Character Variants 53" => 'cv53', + "Character Variants 54" => 'cv54', + "Character Variants 55" => 'cv55', + "Character Variants 56" => 'cv56', + "Character Variants 57" => 'cv57', + "Character Variants 58" => 'cv58', + "Character Variants 59" => 'cv59', + "Character Variants 60" => 'cv60', + "Character Variants 61" => 'cv61', + "Character Variants 62" => 'cv62', + "Character Variants 63" => 'cv63', + "Character Variants 64" => 'cv64', + "Character Variants 65" => 'cv65', + "Character Variants 66" => 'cv66', + "Character Variants 67" => 'cv67', + "Character Variants 68" => 'cv68', + "Character Variants 69" => 'cv69', + "Character Variants 70" => 'cv70', + "Character Variants 71" => 'cv71', + "Character Variants 72" => 'cv72', + "Character Variants 73" => 'cv73', + "Character Variants 74" => 'cv74', + "Character Variants 75" => 'cv75', + "Character Variants 76" => 'cv76', + "Character Variants 77" => 'cv77', + "Character Variants 78" => 'cv78', + "Character Variants 79" => 'cv79', + "Character Variants 80" => 'cv80', + "Character Variants 81" => 'cv81', + "Character Variants 82" => 'cv82', + "Character Variants 83" => 'cv83', + "Character Variants 84" => 'cv84', + "Character Variants 85" => 'cv85', + "Character Variants 86" => 'cv86', + "Character Variants 87" => 'cv87', + "Character Variants 88" => 'cv88', + "Character Variants 89" => 'cv89', + "Character Variants 90" => 'cv90', + "Character Variants 91" => 'cv91', + "Character Variants 92" => 'cv92', + "Character Variants 93" => 'cv93', + "Character Variants 94" => 'cv94', + "Character Variants 95" => 'cv95', + "Character Variants 96" => 'cv96', + "Character Variants 97" => 'cv97', + "Character Variants 98" => 'cv98', + "Character Variants 99" => 'cv99', + "Conjunct Form After Ro" => 'cfar', + "Conjunct Forms" => 'cjct', + "Contextual Alternates" => 'calt', + "Contextual Ligatures" => 'clig', + "Contextual Swash" => 'cswh', + "Cursive Positioning" => 'curs', + "Denominators" => 'dnom', + "Discretionary Ligatures" => 'dlig', + "Distances" => 'dist', + "Dotless Forms" => 'dtls', + "Expert Forms" => 'expt', + "Final Glyph on Line Alternates" => 'falt', + "Flattened ascent forms" => 'flac', + "Fractions" => 'frac', + "Full Widths" => 'fwid', + "Glyph Composition / Decomposition" => 'ccmp', + "Halant Forms" => 'haln', + "Half Forms" => 'half', + "Half Widths" => 'hwid', + "Hangul" => 'hngl', + "Historical Forms" => 'hist', + "Historical Ligatures" => 'hlig', + "Hojo Kanji Forms (JIS X 0212-1990 Kanji Forms)" => 'hojo', + "Horizontal Kana Alternates" => 'hkna', + "Initial Forms" => 'init', + "Isolated Forms" => 'isol', + "Italics" => 'ital', + "JIS2004 Forms" => 'jp04', + "JIS78 Forms" => 'jp78', + "JIS83 Forms" => 'jp83', + "JIS90 Forms" => 'jp90', + "Justification Alternates" => 'jalt', + "Kerning" => 'kern', + "Leading Jamo Forms" => 'ljmo', + "Left Bounds" => 'lfbd', + "Left-to-right glyph alternates" => 'ltra', + "Left-to-right mirrored forms" => 'ltrm', + "Lining Figures" => 'lnum', + "Localized Forms" => 'locl', + "Mark Positioning via Substitution" => 'mset', + "Mark Positioning" => 'mark', + "Mark to Mark Positioning" => 'mkmk', + "Math script style alternates" => 'ssty', + "Mathematical Greek" => 'mgrk', + "Medial Forms #2" => 'med2', + "Medial Forms" => 'medi', + "NLC Kanji Forms" => 'nlck', + "Nukta Forms" => 'nukt', + "Numerators" => 'numr', + "Oldstyle Figures" => 'onum', + "Optical Bounds" => 'opbd', + "Optical size" => 'size', + "Ordinals" => 'ordn', + "Ornaments" => 'ornm', + "Petite Capitals From Capitals" => 'c2pc', + "Petite Capitals" => 'pcap', + "Post-base Forms" => 'pstf', + "Post-base Substitutions" => 'psts', + "Pre-Base Forms" => 'pref', + "Pre-base Substitutions" => 'pres', + "Proportional Alternate Vertical Metrics" => 'vpal', + "Proportional Alternate Widths" => 'palt', + "Proportional Figures" => 'pnum', + "Proportional Kana" => 'pkna', + "Proportional Widths" => 'pwid', + "Quarter Widths" => 'qwid', + "Rakar Forms" => 'rkrf', + "Randomize" => 'rand', + "Reph Forms" => 'rphf', + "Required Contextual Alternates" => 'rclt', + "Required Ligatures" => 'rlig', + "Right Bounds" => 'rtbd', + "Right-to-left alternates" => 'rtla', + "Right-to-left mirrored forms" => 'rtlm', + "Ruby Notation Forms" => 'ruby', + "Scientific Inferiors" => 'sinf', + "Simplified Forms" => 'smpl', + "Slashed Zero" => 'zero', + "Small Capitals From Capitals" => 'c2sc', + "Small Capitals" => 'smcp', + "Standard Ligatures" => 'liga', + "Stretching Glyph Decomposition" => 'stch', + "Stylistic Alternates" => 'salt', + "Stylistic Set 1" => 'ss01', + "Stylistic Set 10" => 'ss10', + "Stylistic Set 11" => 'ss11', + "Stylistic Set 12" => 'ss12', + "Stylistic Set 13" => 'ss13', + "Stylistic Set 14" => 'ss14', + "Stylistic Set 15" => 'ss15', + "Stylistic Set 16" => 'ss16', + "Stylistic Set 17" => 'ss17', + "Stylistic Set 18" => 'ss18', + "Stylistic Set 19" => 'ss19', + "Stylistic Set 2" => 'ss02', + "Stylistic Set 20" => 'ss20', + "Stylistic Set 3" => 'ss03', + "Stylistic Set 4" => 'ss04', + "Stylistic Set 5" => 'ss05', + "Stylistic Set 6" => 'ss06', + "Stylistic Set 7" => 'ss07', + "Stylistic Set 8" => 'ss08', + "Stylistic Set 9" => 'ss09', + "Subscript" => 'subs', + "Superscript" => 'sups', + "Swash" => 'swsh', + "Tabular Figures" => 'tnum', + "Terminal Forms #2" => 'fin2', + "Terminal Forms #3" => 'fin3', + "Terminal Forms" => 'fina', + "Third Widths" => 'twid', + "Titling" => 'titl', + "Traditional Forms" => 'trad', + "Traditional Name Forms" => 'tnam', + "Trailing Jamo Forms" => 'tjmo', + "Unicase" => 'unic', + "Vattu Variants" => 'vatu', + "Vertical Alternates and Rotation" => 'vrt2', + "Vertical Kana Alternates" => 'vkna', + "Vertical Kerning" => 'vkrn', + "Vertical Writing" => 'vert', + "Vowel Jamo Forms" => 'vjmo', + }, + +); + +%iso639 = ( + 'ABA ' => 'abq', + 'ABK ' => 'abk', + 'ACH ' => 'ach', + 'ACR ' => 'acr', + 'ADY ' => 'ady', + 'AFK ' => 'afr', + 'AFR ' => 'aar', + 'AGW ' => 'ahg', + 'AIO ' => 'aio', + 'AKA ' => 'aka', + 'ALS ' => 'gsw', + 'ALT ' => 'atv alt', + 'AMH ' => 'amh', + 'ANG ' => 'ang', + 'ARA ' => 'ara', + 'ARG ' => 'arg', + 'ARI ' => 'aiw', + 'ARK ' => 'mhv rmz rki', + 'ASM ' => 'asm', + 'AST ' => 'ast', + 'ATH ' => 'apk apj apl apm apw nav bea sek bcr caf crx clc gwi haa chp dgr scs xsl srs ing hoi koy hup ktw mvb wlk coq ctc gce tol tuu kkz tgx tht aht tfn taa tau tcb kuu tce ttm txc', + 'AVR ' => 'ava', + 'AWA ' => 'awa', + 'AYM ' => 'aym', + 'AZB ' => 'azb', + 'AZE ' => 'aze', + 'BAD ' => 'bfq', + 'BAD0' => 'bad', + 'BAG ' => 'bfy', + 'BAL ' => 'krc', + 'BAN ' => 'ban', + 'BAR ' => 'bar', + 'BAU ' => 'bci', + 'BBC ' => 'bbc', + 'BCH ' => 'bcq', + 'BDY ' => 'bdy', + 'BEL ' => 'bel', + 'BEM ' => 'bem', + 'BEN ' => 'ben', + 'BGC ' => 'bgc', + 'BGQ ' => 'bgq', + 'BGR ' => 'bul', + 'BHI ' => 'bhi bhb', + 'BHO ' => 'bho', + 'BIK ' => 'bik bhk bcl bto cts bln', + 'BIL ' => 'byn', + 'BIS ' => 'bis', + 'BJJ ' => 'bjj', + 'BKF ' => 'bla', + 'BLI ' => 'bal', + 'BLK ' => 'blk', + 'BLN ' => 'bjt ble', + 'BLT ' => 'bft', + 'BMB ' => 'bam', + 'BOS ' => 'bos', + 'BPY ' => 'bpy', + 'BRE ' => 'bre', + 'BRH ' => 'brh', + 'BRI ' => 'bra', + 'BRM ' => 'mya', + 'BRX ' => 'brx', + 'BSH ' => 'bak', + "BSK " => 'bsk', + 'BTI ' => 'btb', + 'BTS ' => 'bts', + 'BUG ' => 'bug', + "BYV " => 'byv', + 'CAK ' => 'cak', + 'CAT ' => 'cat', + 'CBK ' => 'cbk', + 'CEB ' => 'ceb', + 'CGG ' => 'cgg', + 'CHA ' => 'cha', + 'CHE ' => 'che', + 'CHG ' => 'sgw', + 'CHH ' => 'hne', + 'CHI ' => 'nya', + 'CHK ' => 'ckt', + 'CHK0' => 'chk', + 'CHO ' => 'cho', + 'CHP ' => 'chp', + 'CHR ' => 'chr', + 'CHU ' => 'chv', + 'CHY ' => 'chy', + 'CMR ' => 'swb wlc wni zdj', + 'COP ' => 'cop', + 'COR ' => 'cor', + 'COS ' => 'cos', + 'CPP ' => 'cpp', + 'CRE ' => 'cre', + 'CRR ' => 'crx caf', + 'CRT ' => 'crh', + 'CSB ' => 'csb', + 'CSL ' => 'chu', + 'CSY ' => 'ces', + 'CTG ' => 'ctg', + 'CUK ' => 'cuk', + 'DAN ' => 'dan', + 'DAR ' => 'dar', + 'DAX ' => 'dax', + 'DCR ' => 'cwd', + 'DEU ' => 'deu', + 'DGO ' => 'dgo', + 'DGR ' => 'doi', + 'DHG ' => 'dhg', + 'DHV ' => 'div', + 'DIQ ' => 'diq', + 'DIV ' => 'div', + 'DJR ' => 'dje', + 'DJR0' => 'djr', + 'DNG ' => 'ada', + 'DNJ ' => 'dnj', + 'DNK ' => 'din', + 'DRI ' => 'prs', + 'DUJ ' => 'duj', + 'DUN ' => 'dng', + 'DZN ' => 'dzo', + 'EBI ' => 'igb', + 'ECR ' => 'crj crl', + 'EDO ' => 'bin', + 'EFI ' => 'efi', + 'ELL ' => 'ell', + 'EMK ' => 'emk', + 'ENG ' => 'eng', + 'ERZ ' => 'myv', + 'ESP ' => 'spa', + 'ESU ' => 'esu', + 'ETI ' => 'est', + 'EUQ ' => 'eus', + 'EVK ' => 'evn', + 'EVN ' => 'eve', + 'EWE ' => 'ewe', + 'FAN ' => 'acf', + 'FAN0' => 'fan', + 'FAR ' => 'fas', + 'FAT ' => 'fat', + 'FIN ' => 'fin', + 'FJI ' => 'fij', + 'FLE ' => 'vls', + "FMP " => 'fmp', + 'FNE ' => 'enf', + 'FON ' => 'fon', + 'FOS ' => 'fao', + 'FRA ' => 'fra', + 'FRC ' => 'frc', + 'FRI ' => 'fry', + 'FRL ' => 'fur', + 'FRP ' => 'frp', + 'FTA ' => 'fuf', + 'FUL ' => 'ful', + 'FUV ' => 'fuv', + 'GAD ' => 'gaa', + 'GAE ' => 'gla', + 'GAG ' => 'gag', + 'GAL ' => 'glg', + 'GAW ' => 'gbm', + 'GEZ ' => 'gez', + 'GIH ' => 'gih', + 'GIL ' => 'niv', + 'GIL0' => 'gil', + 'GKP ' => 'gkp', + 'GLK ' => 'glk', + 'GMZ ' => 'guk', + 'GNN ' => 'gnn', + 'GOG ' => 'gog', + 'GON ' => 'gon gno ggo', + 'GRN ' => 'kal', + 'GRO ' => 'grt', + 'GUA ' => 'grn', + 'GUC ' => 'guc', + 'GUF ' => 'guf', + 'GUJ ' => 'guj', + 'GUZ ' => 'guz', + 'HAI ' => 'hat', + 'HAL ' => 'flm', + 'HAR ' => 'hoj', + 'HAU ' => 'hau', + 'HAW ' => 'haw', + 'HAY ' => 'hay', + 'HAZ ' => 'haz', + 'HBN ' => 'amf', + 'HER ' => 'her', + 'HIL ' => 'hil', + 'HIN ' => 'hin', + 'HMA ' => 'mrj', + 'HMN ' => 'hmn', + 'HMO ' => 'hmo', + 'HND ' => 'hno hnd', + 'HO ' => 'hoc', + 'HRI ' => 'har', + 'HRV ' => 'hrv', + 'HUN ' => 'hun', + 'HYE ' => 'hye', + 'HYE0' => 'hye', + 'IBA ' => 'iba', + 'IBB ' => 'ibb', + 'IBO ' => 'ibo', + 'IDO ' => 'ido', + 'IJO ' => 'ijc', + 'ILE ' => 'ile', + 'ILO ' => 'ilo', + 'INA ' => 'ina', + 'IND ' => 'ind', + 'ING ' => 'inh', + 'INU ' => 'iku', + 'IPK ' => 'ipk', + 'IRI ' => 'gle', + 'IRT ' => 'gle', + 'ISL ' => 'isl', + 'ISM ' => 'smn', + 'ITA ' => 'ita', + 'IWR ' => 'heb', + 'JAM ' => 'jam', + 'JAN ' => 'jpn', + 'JAV ' => 'jav', + 'JBO ' => 'jbo', + "JCT " => 'jct', + 'JII ' => 'yid', + 'JUD ' => 'lad', + 'JUL ' => 'dyu', + 'KAB ' => 'kbd', + 'KAB0' => 'kab', + 'KAC ' => 'kfr', + 'KAL ' => 'kln', + 'KAN ' => 'kan', + 'KAR ' => 'krc', + 'KAT ' => 'kat', + 'KAZ ' => 'kaz', + 'KDE ' => 'kde', + 'KEA ' => 'kea', + 'KEB ' => 'ktb', + 'KEK ' => 'kek', + 'KGE ' => 'kat', + 'KHA ' => 'kjh', + 'KHK ' => 'kca', + 'KHM ' => 'khm', + 'KHS ' => 'kca', + 'KHT ' => 'kht', + 'KHV ' => 'kca', + 'KHW ' => 'khw', + 'KIK ' => 'kik', + 'KIR ' => 'kir', + 'KIS ' => 'kqs kss', + 'KIU ' => 'kiu', + 'KJD ' => 'kjd', + 'KJP ' => 'kjp', + 'KKN ' => 'kex', + 'KLM ' => 'xal', + 'KMB ' => 'kam', + 'KMN ' => 'kfy', + 'KMO ' => 'kmw', + 'KMS ' => 'kxc', + "KMZ " => 'kmz', + 'KNR ' => 'kau', + 'KOD ' => 'kfa', + 'KOH ' => 'okm', + 'KOK ' => 'kok', + 'KOM ' => 'kom', + 'KON ' => 'ktu', + 'KON0' => 'kon', + 'KOP ' => 'koi', + 'KOR ' => 'kor', + 'KOS ' => 'kos', + 'KOZ ' => 'kpv', + 'KPL ' => 'kpe', + 'KRI ' => 'kri', + 'KRK ' => 'kaa', + 'KRL ' => 'krl', + 'KRM ' => 'kdr', + 'KRN ' => 'kar', + 'KRT ' => 'kqy', + 'KSH ' => 'kas', + 'KSH0' => 'ksh', + 'KSI ' => 'kha', + 'KSM ' => 'sjd', + 'KSW ' => 'ksw', + 'KUA ' => 'kua', + 'KUI ' => 'kxu', + 'KUL ' => 'kfx', + 'KUM ' => 'kum', + 'KUR ' => 'kur', + 'KUU ' => 'kru', + 'KUY ' => 'kdt', + 'KYK ' => 'kpy', + 'KYU ' => 'kyu', + 'LAD ' => 'lld', + 'LAH ' => 'bfu', + 'LAK ' => 'lbe', + 'LAM ' => 'lmn', + 'LAO ' => 'lao', + 'LAT ' => 'lat', + 'LAZ ' => 'lzz', + 'LCR ' => 'crm', + 'LDK ' => 'lbj', + 'LEZ ' => 'lez', + 'LIJ ' => 'lij', + 'LIM ' => 'lim', + 'LIN ' => 'lin', + 'LIS ' => 'lis', + 'LJP ' => 'ljp', + 'LKI ' => 'lki', + 'LMA ' => 'mhr', + 'LMB ' => 'lif', + 'LMO ' => 'lmo', + 'LMW ' => 'ngl', + 'LOM ' => 'lom', + 'LRC ' => 'lrc luz bqi zum', + 'LSB ' => 'dsb', + 'LSM ' => 'smj', + 'LTH ' => 'lit', + 'LTZ ' => 'ltz', + 'LUA ' => 'lua', + 'LUB ' => 'lub', + 'LUG ' => 'lug', + 'LUH ' => 'luy', + 'LUO ' => 'luo', + 'LVI ' => 'lav', + 'MAD ' => 'mad', + 'MAG ' => 'mag', + 'MAH ' => 'mah', + 'MAJ ' => 'mpe', + 'MAK ' => 'vmw', + 'MAL ' => 'mal', + 'MAM ' => 'mam', + 'MAN ' => 'mns', + 'MAP ' => 'arn', + 'MAR ' => 'mar', + 'MAW ' => 'mwr dhd rwr mve wry mtr swv', + 'MBN ' => 'kmb', + "MBO " => 'mbo', + 'MCH ' => 'mnc', + 'MCR ' => 'crm', + 'MDE ' => 'men', + 'MDR ' => 'mdr', + 'MEN ' => 'mym', + 'MER ' => 'mer', + 'MFE ' => 'mfe', + 'MIN ' => 'min', + 'MIZ ' => 'lus', + 'MKD ' => 'mkd', + 'MKR ' => 'mak', + 'MKW ' => 'mkw', + 'MLE ' => 'mdy', + 'MLG ' => 'mlg', + 'MLN ' => 'mlq', + 'MLR ' => 'mal', + 'MLY ' => 'msa', + 'MND ' => 'mnk', + 'MNG ' => 'mon', + 'MNI ' => 'mni', + 'MNK ' => 'man mnk myq mku msc emk mwk mlq', + 'MNX ' => 'glv', + 'MOH ' => 'mho', + 'MOK ' => 'mdf', + 'MOL ' => 'mol', + 'MON ' => 'mnw', + 'MOS ' => 'mos', + 'MRI ' => 'mri', + 'MTH ' => 'mai', + 'MTS ' => 'mlt', + 'MUN ' => 'unr', + 'MUS ' => 'mus', + 'MWL ' => 'mwl', + 'MWW ' => 'mww', + 'MYN ' => 'myn', + 'MZN ' => 'mzn', + 'NAG ' => 'nag', + 'NAH ' => 'nah', + 'NAN ' => 'gld', + 'NAP ' => 'nap', + 'NAS ' => 'nsk', + 'NAU ' => 'nau', + 'NAV ' => 'nav', + 'NCR ' => 'csw', + 'NDB ' => 'nbl nde', + 'NDC ' => 'ndc', + 'NDG ' => 'ndo', + 'NDS ' => 'nds', + 'NEP ' => 'nep', + 'NEW ' => 'new', + 'NGA ' => 'nga', + 'NHC ' => 'csw', + 'NIS ' => 'dap', + 'NIU ' => 'niu', + 'NKL ' => 'nyn', + 'NKO ' => 'ngo', + 'NLD ' => 'nld', + 'NOE ' => 'noe', + 'NOG ' => 'nog', + 'NOR ' => 'nob', + 'NOV ' => 'nov', + 'NSM ' => 'sme', + 'NSO ' => 'nso', + 'NTA ' => 'nod', + 'NTO ' => 'epo', + 'NYM ' => 'nym', + 'NYN ' => 'nno', + "NZA " => 'nza', + 'OCI ' => 'oci', + 'OCR ' => 'ojs', + 'OJB ' => 'oji', + 'ORI ' => 'ori', + 'ORO ' => 'orm', + 'OSS ' => 'oss', + 'PAA ' => 'sam', + 'PAG ' => 'pag', + 'PAL ' => 'pli', + 'PAM ' => 'pam', + 'PAN ' => 'pan', + 'PAP ' => 'plp', + 'PAP0' => 'pap', + 'PAS ' => 'pus', + 'PAU ' => 'pau', + 'PCC ' => 'pcc', + 'PCD ' => 'pcd', + 'PDC ' => 'pdc', + 'PGR ' => 'ell', + 'PHK ' => 'phk', + 'PIH ' => 'pih', + 'PIL ' => 'fil', + 'PLG ' => 'pce rbb pll', + 'PLK ' => 'pol', + 'PMS ' => 'pms', + 'PNB ' => 'pnb', + 'POH ' => 'poh', + 'PON ' => 'pon', + 'PRO ' => 'pro', + 'PTG ' => 'por', + 'PWO ' => 'pwo', + 'QIN ' => 'bgr cnh cnw czt sez tcp csy ctd flm pck tcz zom cmr dao hlt cka cnk mrh mwg cbl cnb csh', + 'QUC ' => 'quc', + 'QUH ' => 'quh', + 'QUZ ' => 'quz', + 'QVI ' => 'qvi', + 'QWH ' => 'qwh', + 'RAJ ' => 'raj', + 'RAR ' => 'rar', + 'RBU ' => 'bxr', + 'RCR ' => 'atj', + 'REJ ' => 'rej', + 'RIA ' => 'ria', + 'RIF ' => 'rif', + 'RIT ' => 'rit', + 'RKW ' => 'rkw', + 'RMS ' => 'roh', + 'RMY ' => 'rmy', + 'ROM ' => 'ron', + 'ROY ' => 'rom', + 'RSY ' => 'rue', + 'RTM ' => 'rtm', + 'RUA ' => 'kin', + 'RUN ' => 'run', + 'RUP ' => 'rup', + 'RUS ' => 'rus', + 'SAD ' => 'sck', + 'SAN ' => 'san', + 'SAS ' => 'sas', + 'SAT ' => 'sat', + 'SAY ' => 'chp', + 'SCN ' => 'scn', + 'SCO ' => 'sco', + "SCS " => 'scs', + 'SEK ' => 'xan', + 'SEL ' => 'sel', + 'SGA ' => 'sga', + 'SGO ' => 'sag', + 'SGS ' => 'sgs', + 'SHI ' => 'shi', + 'SHN ' => 'shn', + 'SIB ' => 'sjo', + 'SID ' => 'sid', + 'SIG ' => 'xst', + 'SKS ' => 'sms', + 'SKY ' => 'slk', + "SLA " => 'scs xsl', + 'SLV ' => 'slv', + 'SML ' => 'som', + 'SMO ' => 'smo', + 'SNA ' => 'she', + 'SNA0' => 'sna', + 'SND ' => 'snd', + 'SNH ' => 'sin', + 'SNK ' => 'snk', + 'SOG ' => 'gru', + 'SOP ' => 'sop', + 'SOT ' => 'sot', + 'SQI ' => 'gsw', + 'SRB ' => 'srp', + 'SRD ' => 'srd', + 'SRK ' => 'skr', + 'SRR ' => 'srr', + 'SSL ' => 'xsl', + 'SSM ' => 'sma', + 'STQ ' => 'stq', + 'SUK ' => 'suk', + 'SUN ' => 'sun', + 'SUR ' => 'suq', + 'SVA ' => 'sva', + 'SVE ' => 'swe', + 'SWA ' => 'aii', + 'SWK ' => 'swa', + 'SWZ ' => 'ssw', + 'SXT ' => 'ngo', + 'SXU ' => 'sxu', + 'SYL ' => 'syl', + 'SYR ' => 'syr', + 'SZL ' => 'szl', + 'TAB ' => 'tab', + 'TAJ ' => 'tgk', + 'TAM ' => 'tam', + 'TAT ' => 'tat', + 'TCR ' => 'cwd', + 'TDD ' => 'tdd', + 'TEL ' => 'tel', + 'TET ' => 'tet', + 'TGL ' => 'tgl', + 'TGN ' => 'ton', + 'TGR ' => 'tig', + 'TGY ' => 'tir', + 'THA ' => 'tha', + 'THT ' => 'tah', + 'TIB ' => 'bod', + 'TIV ' => 'tiv', + 'TKM ' => 'tuk', + 'TMH ' => 'tmh', + 'TMN ' => 'tem', + 'TNA ' => 'tsn', + 'TNE ' => 'enh', + 'TNG ' => 'toi', + 'TOD ' => 'xal', + 'TOD0' => 'tod', + 'TPI ' => 'tpi', + 'TRK ' => 'tur', + 'TSG ' => 'tso', + 'TUA ' => 'tru', + 'TUL ' => 'tcy', + 'TUM ' => 'tum', + 'TUV ' => 'tyv', + 'TVL ' => 'tvl', + 'TWI ' => 'twi', + 'TYZ ' => 'tyz', + 'TZM ' => 'tzm', + 'TZO ' => 'tzo', + 'UDM ' => 'udm', + 'UKR ' => 'ukr', + 'UMB ' => 'umb', + 'URD ' => 'urd', + 'USB ' => 'hsb', + 'UYG ' => 'uig', + 'UZB ' => 'uzb uzn uzs', + 'VEC ' => 'vec', + 'VEN ' => 'ven', + 'VIT ' => 'vie', + 'VOL ' => 'vol', + 'VRO ' => 'vro', + 'WA ' => 'wbm', + 'WAG ' => 'wbr', + 'WAR ' => 'war', + 'WCR ' => 'crk', + 'WEL ' => 'cym', + 'WLF ' => 'wol', + 'WLN ' => 'wln', + 'WTM ' => 'wtm', + 'XBD ' => 'khb', + 'XHS ' => 'xho', + 'XJB ' => 'xjb', + 'XOG ' => 'xog', + 'XPE ' => 'xpe', + 'YAK ' => 'sah', + 'YAO ' => 'yao', + 'YAP ' => 'yap', + 'YBA ' => 'yor', + 'YCR ' => 'cre', + 'YIM ' => 'iii', + 'ZEA ' => 'zea', + 'ZGH ' => 'zgh', + 'ZHA ' => 'zha', + 'ZHH ' => 'zho', + 'ZHP ' => 'zho', + 'ZHS ' => 'zho', + 'ZHT ' => 'zho', + 'ZND ' => 'zne', + 'ZUL ' => 'zul', + 'ZZA ' => 'zza', +); + +{ + foreach my $s (qw ( SCRIPT LANGUAGE FEATURE ) ) + { + map { $ttnames{$s}{$tttags{$s}{$_}} = $_ } keys %{$tttags{$s}}; + } + + # For ISO639 info, the raw data is a space-separated list of ISO639 + # language IDs. We convert that list to an array. + + foreach my $tag (keys %iso639) + { + my $list = $iso639{$tag}; + $iso639{$tag} = [ split(' ', $list) ]; + # Also set the reverse mapping: + map { $iso639{$_} = $tag } @{$iso639{$tag}}; + } +} + + +=head2 readtagsfile ( filename ) + +Read a file in the syntax of Tags.txt (included with Microsoft VOLT) to obtain additional/replacement tag definitions. + +Returns 0 if cannot open the file; else 1. + +=cut + +sub readtagsfile +{ + my $fname = shift; + open (TAGS, $fname) or return 0; + my ($what, $name, $tag); + while () + { + ($what, $name, $tag) = (m/"([^"]*)", "([^"]*)", "([^"]*)"/); #" + $ttnames{$what}{$tag} = $name; + $tttags{$what}{$name} = $tag; + } + close TAGS; + return 1; +} + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OldCmap.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OldCmap.pm new file mode 100644 index 0000000000..75091495b3 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OldCmap.pm @@ -0,0 +1,370 @@ +package Font::TTF::OldCmap; + +=head1 NAME + +Font::TTF::OldCmap - Character map table + +This module is deprecated + +=head1 DESCRIPTION + +Looks after the character map. The primary structure used for handling a cmap +is the L which handles the segmented arrays of format 4 tables, +and in a simpler form for format 0 tables. + +Due to the complexity of working with segmented arrays, most of the handling of +such arrays is via methods rather than via instance variables. + +One important feature of a format 4 table is that it always contains a segment +with a final address of 0xFFFF. If you are creating a table from scratch this is +important (although L can work quite happily without it). + + +=head1 INSTANCE VARIABLES + +The instance variables listed here are not preceded by a space due to their +emulating structural information in the font. + +=over 4 + +=item Num + +Number of subtables in this table + +=item Tables + +An array of subtables ([0..Num-1]) + +=back + +Each subtables also has its own instance variables which are, again, not +preceded by a space. + +=over 4 + +=item Platform + +The platform number for this subtable + +=item Encoding + +The encoding number for this subtable + +=item Format + +Gives the stored format of this subtable + +=item Ver + +Gives the version (or language) information for this subtable + +=item val + +This points to a L which contains the content of the particular +subtable. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; +require Font::TTF::Segarr; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the cmap into memory. Format 4 subtables read the whole subtable and +fill in the segmented array accordingly. + +Format 2 subtables are not read at all. + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $i, $j, $k, $id, @ids, $s); + my ($start, $end, $range, $delta, $form, $len, $num, $ver); + my ($fh) = $self->{' INFILE'}; + + $fh->read($dat, 4); + $self->{'Num'} = unpack("x2n", $dat); + $self->{'Tables'} = []; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = {}; + $fh->read($dat, 8); + ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat)); + $s->{'LOC'} += $self->{' OFFSET'}; + push(@{$self->{'Tables'}}, $s); + } + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + $fh->seek($s->{'LOC'}, 0); + $fh->read($dat, 6); + ($form, $len, $ver) = (unpack("n3", $dat)); + + $s->{'Format'} = $form; + $s->{'Ver'} = $ver; + if ($form == 0) + { + $s->{'val'} = Font::TTF::Segarr->new; + $fh->read($dat, 256); + $s->{'val'}->fastadd_segment(0, 2, unpack("C*", $dat)); + $s->{'Start'} = 0; + $s->{'Num'} = 256; + } elsif ($form == 6) + { + my ($start, $ecount); + + $fh->read($dat, 4); + ($start, $ecount) = unpack("n2", $dat); + $fh->read($dat, $ecount << 1); + $s->{'val'} = Font::TTF::Segarr->new; + $s->{'val'}->fastadd_segment($start, 2, unpack("n*", $dat)); + $s->{'Start'} = $start; + $s->{'Num'} = $ecount; + } elsif ($form == 2) + { +# no idea what to do here yet + } elsif ($form == 4) + { + $fh->read($dat, 8); + $num = unpack("n", $dat); + $num >>= 1; + $fh->read($dat, $len - 14); + $s->{'val'} = Font::TTF::Segarr->new; + for ($j = 0; $j < $num; $j++) + { + $end = unpack("n", substr($dat, $j << 1, 2)); + $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2)); + $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2)); + $delta -= 65536 if $delta > 32767; + $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2)); + @ids = (); + for ($k = $start; $k <= $end; $k++) + { + if ($range == 0) + { $id = $k + $delta; } + else + { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 + + 2 + ($k - $start) * 2 + $range, 2)) + $delta; } + $id -= 65536 if $id > 65536; + push (@ids, $id); + } + $s->{'val'}->fastadd_segment($start, 0, @ids); + } + $s->{'val'}->tidy; + $s->{'Num'} = 0x10000; # always ends here + $s->{'Start'} = $s->{'val'}[0]{'START'}; + } + } + $self; +} + + +=head2 $t->ms_lookup($uni) + +Given a Unicode value in the MS table (Platform 3, Encoding 1) locates that +table and looks up the appropriate glyph number from it. + +=cut + +sub ms_lookup +{ + my ($self, $uni) = @_; + + $self->find_ms || return undef unless (defined $self->{' mstable'}); + return $self->{' mstable'}{'val'}->at($uni); +} + + +=head2 $t->find_ms + +Finds the Microsoft Unicode table and sets the C instance variable +to it if found. Returns the table it finds. + +=cut + +sub find_ms +{ + my ($self) = @_; + my ($i, $s, $alt); + + return $self->{' mstable'} if defined $self->{' mstable'}; + $self->read; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + if ($s->{'Platform'} == 3) + { + $self->{' mstable'} = $s; + last if ($s->{'Encoding'} == 1); + } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1)) + { $self->{' mstable'} = $s; } + } + $self->{' mstable'}; +} + + +=head2 $t->out($fh) + +Writes out a cmap table to a filehandle. If it has not been read, then +just copies from input file to output + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($loc, $s, $i, $base_loc, $j); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $base_loc = $fh->tell(); + $fh->print(pack("n2", 0, $self->{'Num'})); + + for ($i = 0; $i < $self->{'Num'}; $i++) + { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); } + + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + $s->{'val'}->tidy; + $s->{' outloc'} = $fh->tell(); + $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'})); # come back for length + if ($s->{'Format'} == 0) + { + $fh->print(pack("C256", $s->{'val'}->at(0, 256))); + } elsif ($s->{'Format'} == 6) + { + $fh->print(pack("n2", $s->{'Start'}, $s->{'Num'})); + $fh->print(pack("n*", $s->{'val'}->at($s->{'Start'}, $s->{'Num'}))); + } elsif ($s->{'Format'} == 2) + { + } elsif ($s->{'Format'} == 4) + { + my ($num, $sRange, $eSel); + my (@deltas, $delta, @range, $flat, $k, $segs, $count); + + $num = $#{$s->{'val'}} + 1; + $segs = $s->{'val'}; + for ($sRange = 1, $eSel = 0; $sRange <= $num; $eSel++) + { $sRange <<= 1;} + $eSel--; + $fh->print(pack("n4", $num * 2, $sRange, $eSel, ($num * 2) - $sRange)); + $fh->print(pack("n*", map {$_->{'START'} + $_->{'LEN'} - 1} @$segs)); + $fh->print(pack("n", 0)); + $fh->print(pack("n*", map {$_->{'START'}} @$segs)); + + for ($j = 0; $j < $num; $j++) + { + $delta = $segs->[$j]{'VAL'}[0]; $flat = 1; + for ($k = 1; $k < $segs->[$j]{'LEN'}; $k++) + { + if ($segs->[$j]{'VAL'}[$k] == 0) + { $flat = 0; } + if ($delta + $k != $segs->[$j]{'VAL'}[$k]) + { + $delta = 0; + last; + } + } + push (@range, $flat); + push (@deltas, ($delta ? $delta - $segs->[$j]{'START'} : 0)); + } + $fh->print(pack("n*", @deltas)); + + $count = 0; + for ($j = 0; $j < $num; $j++) + { + $delta = $deltas[$j]; + if ($delta != 0 && $range[$j] == 1) + { $range[$j] = 0; } + else + { + $range[$j] = ($count + $num - $j) << 1; + $count += $segs->[$j]{'LEN'}; + } + } + + $fh->print(pack("n*", @range)); + + for ($j = 0; $j < $num; $j++) + { + next if ($range[$j] == 0); + for ($k = 0; $k < $segs->[$j]{'LEN'}; $k++) + { $fh->print(pack("n", $segs->[$j]{'VAL'}[$k])); } + } + } + + $loc = $fh->tell(); + $fh->seek($s->{' outloc'} + 2, 0); + $fh->print(pack("n", $loc - $s->{' outloc'})); + $fh->seek($base_loc + 8 + ($i << 3), 0); + $fh->print(pack("N", $s->{' outloc'} - $base_loc)); + $fh->seek($loc, 0); + } + $self; +} + + +=head2 @map = $t->reverse([$num]) + +Returns a reverse map of the table of given number or the Microsoft +cmap. I.e. given a glyph gives the Unicode value for it. + +=cut + +sub reverse +{ + my ($self, $tnum) = @_; + my ($table) = defined $tnum ? $self->{'Tables'}[$tnum] : $self->find_ms; + my (@res, $i, $s, $first); + + foreach $s (@{$table->{'val'}}) + { + $first = $s->{'START'}; + map {$res[$_] = $first unless $res[$_]; $first++;} @{$s->{'VAL'}}; + } + @res; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +No support for format 2 tables (MBCS) + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OldMort.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OldMort.pm new file mode 100644 index 0000000000..517709c798 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/OldMort.pm @@ -0,0 +1,722 @@ +package Font::TTF::OldMort; + +=head1 NAME + +Font::TTF::OldMort - Glyph Metamorphosis table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +table version number (Fixed: currently 1.0) + +=item chains + +list of metamorphosis chains, each of which has its own fields: + +=over + +=item defaultFlags + +chain's default subfeature flags (UInt32) + +=item featureEntries + +list of feature entries, each of which has fields: + +=over + +=item type + +=item setting + +=item enable + +=item disable + +=back + +=item subtables + +list of metamorphosis subtables, each of which has fields: + +=over + +=item type + +subtable type (0: rearrangement; 1: contextual substitution; 2: ligature; +4: non-contextual substitution; 5: insertion) + +=item direction + +processing direction ('LR' or 'RL') + +=item orientation + +applies to text in which orientation ('VH', 'V', or 'H') + +=item subFeatureFlags + +the subfeature flags controlling whether the table is used (UInt32) + +=back + +Further fields depend on the type of subtable: + +=over + +Rearrangement table: + +=over + +=item classes + +array of lists of glyphs + +=item states + +array of arrays of hashes{'nextState', 'flags'} + +=back + +Contextual substitution table: + +=over + +=item classes + +array of lists of glyphs + +=item states + +array of array of hashes{'nextState', 'flags', 'actions'}, where C +is an array of two elements which are offsets to be added to [marked, current] +glyph to get index into C (or C if no mapping to be applied) + +=item mappings + +list of glyph codes mapped to through the state table mappings + +=back + +Ligature table: + +Non-contextual substitution table: + +Insertion table: + +=back + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Table); + +=over + +=back + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh, $numChains); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + + $fh->read($dat, 8); + ($self->{'version'}, $numChains) = TTF_Unpack("fL", $dat); + + my $chains = []; + foreach (1 .. $numChains) { + my $chainStart = $fh->tell(); + $fh->read($dat, 12); + my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat); + my $featureEntries = []; + foreach (1 .. $nFeatureEntries) { + $fh->read($dat, 12); + my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat); + push @$featureEntries, { + 'type' => $featureType, + 'setting' => $featureSetting, + 'enable' => $enableFlags, + 'disable' => $disableFlags + }; + } + my $subtables = []; + foreach (1 .. $nSubtables) { + my $subtableStart = $fh->tell(); + $fh->read($dat, 8); + my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat); + my $type = $coverage & 0x0007; + + my $subtable = { + 'type' => $type, + 'direction' => (($coverage & 0x4000) ? 'RL' : 'LR'), + 'orientation' => (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'), + 'subFeatureFlags' => $subFeatureFlags + }; + + if ($type == 0) { # rearrangement + my ($classes, $states) = AAT_read_state_table($fh, 0); + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + } + + elsif ($type == 1) { # contextual + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 10); + my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $length - 8]; + + foreach (@$entries) { + my $actions = $_->{'actions'}; + foreach (@$actions) { + $_ = $_ ? $_ - ($mappingTables / 2) : undef; + } + } + + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + $subtable->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))]; + } + + elsif ($type == 2) { # ligature + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 0); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 14); + my ($stateSize, $classTable, $stateArray, $entryTable, + $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $length - 8]; + + my %actions; + my $actionLists; + foreach (@$entries) { + my $offset = $_->{'flags'} & 0x3fff; + $_->{'flags'} &= ~0x3fff; + if ($offset != 0) { + if (not defined $actions{$offset}) { + $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET); + my $actionList; + while (1) { + $fh->read($dat, 4); + my $action = unpack("N", $dat); + my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff)); + $component -= 0x40000000 if $component > 0x1fffffff; + $component -= $componentTable / 2; + push @$actionList, { 'store' => $store, 'component' => $component }; + last if $last; + } + push @$actionLists, $actionList; + $actions{$offset} = $#$actionLists; + } + $_->{'actions'} = $actions{$offset}; + } + } + + $subtable->{'componentTable'} = $componentTable; + my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))]; + foreach (@$components) { + $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable; + } + $subtable->{'components'} = $components; + + $subtable->{'ligatureTable'} = $ligatureTable; + $subtable->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))]; + + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + $subtable->{'actionLists'} = $actionLists; + } + + elsif ($type == 4) { # non-contextual + my ($format, $lookup) = AAT_read_lookup($fh, 2, $length - 8, undef); + $subtable->{'format'} = $format; + $subtable->{'lookup'} = $lookup; + } + + elsif ($type == 5) { # insertion + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + my %insertListHash; + my $insertLists; + foreach (@$entries) { + my $flags = $_->{'flags'}; + my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f)); + my $actions = $_->{'actions'}; + foreach (0 .. 1) { + if ($insertCount[$_] > 0) { + $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET); + $fh->read($dat, $insertCount[$_] * 2); + if (not defined $insertListHash{$dat}) { + push @$insertLists, [unpack("n*", $dat)]; + $insertListHash{$dat} = $#$insertLists; + } + $actions->[$_] = $insertListHash{$dat}; + } + else { + $actions->[$_] = undef; + } + } + } + + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + $subtable->{'insertLists'} = $insertLists; + } + + else { + die "unknown subtable type"; + } + + push @$subtables, $subtable; + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); + } + + push @$chains, { + 'defaultFlags' => $defaultFlags, + 'featureEntries' => $featureEntries, + 'subtables' => $subtables + }; + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); + } + + $self->{'chains'} = $chains; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $chains = $self->{'chains'}; + $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$chains)); + + foreach (@$chains) { + my $chainStart = $fh->tell(); + my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'}); + $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length + + foreach (@$featureEntries) { + $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'})); + } + + foreach (@$subtables) { + my $subtableStart = $fh->tell(); + my $type = $_->{'type'}; + my $coverage = $type; + $coverage += 0x4000 if $_->{'direction'} eq 'RL'; + $coverage += 0x2000 if $_->{'orientation'} eq 'VH'; + $coverage += 0x8000 if $_->{'orientation'} eq 'V'; + + $fh->print(TTF_Pack("SSL", 0, $coverage, $_->{'subFeatureFlags'})); # placeholder for length + + if ($type == 0) { # rearrangement + AAT_write_state_table($fh, $_->{'classes'}, $_->{'states'}, 0); + } + + elsif ($type == 1) { # contextual + my $stHeader = $fh->tell(); + $fh->print(pack("nnnnn", (0) x 5)); # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables + + my $classTable = $fh->tell() - $stHeader; + my $classes = $_->{'classes'}; + AAT_write_classes($fh, $classes); + + my $stateArray = $fh->tell() - $stHeader; + my $states = $_->{'states'}; + my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states, + sub { + my $actions = $_->{'actions'}; + ( $_->{'flags'}, @$actions ) + } + ); + + my $entryTable = $fh->tell() - $stHeader; + my $offset = ($entryTable + 8 * @$entries) / 2; + foreach (@$entries) { + my ($nextState, $flags, @parts) = split /,/; + $fh->print(pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts)); + } + + my $mappingTables = $fh->tell() - $stHeader; + my $mappings = $_->{'mappings'}; + $fh->print(pack("n*", @$mappings)); + + my $loc = $fh->tell(); + $fh->seek($stHeader, IO::File::SEEK_SET); + $fh->print(pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables)); + $fh->seek($loc, IO::File::SEEK_SET); + } + + elsif ($type == 2) { # ligature + my $stHeader = $fh->tell(); + $fh->print(pack("nnnnnnn", (0) x 7)); # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures + + my $classTable = $fh->tell() - $stHeader; + my $classes = $_->{'classes'}; + AAT_write_classes($fh, $classes); + + my $stateArray = $fh->tell() - $stHeader; + my $states = $_->{'states'}; + + my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states, + sub { + ( $_->{'flags'} & 0xc000, $_->{'actions'} ) + } + ); + + my $actionLists = $_->{'actionLists'}; + my %actionListOffset; + my $actionListDataLength = 0; + my @actionListEntries; + foreach (0 .. $#$entries) { + my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]); + if ($offset eq "") { + $offset = undef; + } + else { + if (defined $actionListOffset{$offset}) { + $offset = $actionListOffset{$offset}; + } + else { + $actionListOffset{$offset} = $actionListDataLength; + my $list = $actionLists->[$offset]; + $actionListDataLength += 4 * @$list; + push @actionListEntries, $list; + $offset = $actionListOffset{$offset}; + } + } + $entries->[$_] = [ $nextState, $flags, $offset ]; + } + my $entryTable = $fh->tell() - $stHeader; + my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3; + foreach (@$entries) { + $_->[2] += $ligActionLists if defined $_->[2]; + $fh->print(pack("nn", $_->[0], $_->[1] + $_->[2])); + } + $fh->print(pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4))); + + die "internal error" if $fh->tell() != $ligActionLists + $stHeader; + + my $componentTable = $fh->tell() - $stHeader + $actionListDataLength; + my $actionList; + foreach $actionList (@actionListEntries) { + foreach (0 .. $#$actionList) { + my $action = $actionList->[$_]; + my $val = $action->{'component'} + $componentTable / 2; + $val += 0x40000000 if $val < 0; + $val &= 0x3fffffff; + $val |= 0x40000000 if $action->{'store'}; + $val |= 0x80000000 if $_ == $#$actionList; + $fh->print(pack("N", $val)); + } + } + + die "internal error" if $fh->tell() != $componentTable + $stHeader; + + my $components = $_->{'components'}; + my $ligatureTable = $componentTable + @$components * 2; + $fh->print(pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components)); + + my $ligatures = $_->{'ligatures'}; + $fh->print(pack("n*", @$ligatures)); + + my $loc = $fh->tell(); + $fh->seek($stHeader, IO::File::SEEK_SET); + $fh->print(pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable)); + $fh->seek($loc, IO::File::SEEK_SET); + } + + elsif ($type == 4) { # non-contextual + AAT_write_lookup($fh, $_->{'format'}, $_->{'lookup'}, 2, undef); + } + + elsif ($type == 5) { # insertion + } + + else { + die "unknown subtable type"; + } + + my $length = $fh->tell() - $subtableStart; + my $padBytes = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + $fh->seek($subtableStart, IO::File::SEEK_SET); + $fh->print(pack("n", $length)); + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); + } + + my $chainLength = $fh->tell() - $chainStart; + $fh->seek($chainStart + 4, IO::File::SEEK_SET); + $fh->print(pack("N", $chainLength)); + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); + } +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read; + my $feat = $self->{' PARENT'}->{'feat'}; + $feat->read; + my $post = $self->{' PARENT'}->{'post'}; + $post->read; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\n", $self->{'version'}); + + my $chains = $self->{'chains'}; + foreach (@$chains) { + my $defaultFlags = $_->{'defaultFlags'}; + $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags); + + my $featureEntries = $_->{'featureEntries'}; + foreach (@$featureEntries) { + $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n", + $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}, + $feat->settingName($_->{'type'}, $_->{'setting'})); + } + + my $subtables = $_->{'subtables'}; + foreach (@$subtables) { + my $type = $_->{'type'}; + my $subFeatureFlags = $_->{'subFeatureFlags'}; + $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n", + subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags, + "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"), + join(", ", + map { + join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) ) + } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries + ) ); + + if ($type == 0) { # rearrangement + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + my @verbs = ( "0", "Ax->xA", "xD->Dx", "AxD->DxA", + "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx", + "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA", + "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA"); + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "<" if ($_->{'flags'} & 0x8000); + $flags .= ">" if ($_->{'flags'} & 0x2000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]); + } + $fh->print("\n"); + } + } + + elsif ($type == 1) { # contextual + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $mappings = $_->{'mappings'}; + foreach (0 .. $#$mappings) { + $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]); + } + } + + elsif ($type == 2) { # ligature + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "="); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $actionLists = $_->{'actionLists'}; + foreach (0 .. $#$actionLists) { + $fh->printf("\t\tList %d:\t", $_); + my $actionList = $actionLists->[$_]; + $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList)); + } + + my $ligatureTable = $_->{'ligatureTable'}; + + $fh->print("\n"); + my $components = $_->{'components'}; + foreach (0 .. $#$components) { + $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]); + } + + $fh->print("\n"); + my $ligatures = $_->{'ligatures'}; + foreach (0 .. $#$ligatures) { + $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]); + } + } + + elsif ($type == 4) { # non-contextual + my $lookup = $_->{'lookup'}; + $fh->printf("\t\tLookup format %d\n", $_->{'format'}); + if (defined $lookup) { + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]); + } + } + } + + elsif ($type == 5) { # insertion + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $insertLists = $_->{'insertLists'}; + foreach (0 .. $#$insertLists) { + my $insertList = $insertLists->[$_]; + $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList)); + } + } + + else { + # unknown + } + } + } +} + +sub print_classes_ +{ + my ($fh, $subtable, $post) = @_; + + my $classes = $subtable->{'classes'}; + foreach (0 .. $#$classes) { + my $class = $classes->[$_]; + if (defined $class) { + $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class)); + } + } +} + +sub subtable_type_ +{ + my ($val) = @_; + my ($res); + + my @types = ( + 'Rearrangement', + 'Contextual', + 'Ligature', + undef, + 'Non-contextual', + 'Insertion', + ); + $res = $types[$val] or ('Undefined (' . $val . ')'); + + $res; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/PCLT.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/PCLT.pm new file mode 100644 index 0000000000..d9a2c6f19e --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/PCLT.pm @@ -0,0 +1,143 @@ +package Font::TTF::PCLT; + +=head1 NAME + +Font::TTF::PCLT - PCLT TrueType font table + +=head1 DESCRIPTION + +The PCLT table holds various pieces HP-PCL specific information. Information +here is generally not used by other software, except for the xHeight and +CapHeight which are stored here (if the table exists in a font). + +=head1 INSTANCE VARIABLES + +Only from table and the standard: + + version + FontNumber + Pitch + xHeight + Style + TypeFamily + CapHeight + SymbolSet + Typeface + CharacterComplement + FileName + StrokeWeight + WidthType + SerifStyle + +Notice that C, C and C return arrays +of unsigned characters of the appropriate length + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'FontNumber' => 'L', + 'Pitch' => 'S', + 'xHeight' => 'S', + 'Style' => 'S', + 'TypeFamily' => 'S', + 'CapHeight' => 'S', + 'SymbolSet' => 'S', + 'Typeface' => 'C16', + 'CharacterComplement' => 'C8', + 'FileName' => 'C6', + 'StrokeWeight' => 'C', + 'WidthType' => 'C', + 'SerifStyle' => 'c'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory thanks to some utility functions + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read || return $self; + + init unless defined $fields{'xHeight'}; + $self->{' INFILE'}->read($dat, 54); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + $fh->print(TTF_Out_Fields($self, \%fields, 54)); +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 54; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/PSNames.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/PSNames.pm new file mode 100644 index 0000000000..686889e6b6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/PSNames.pm @@ -0,0 +1,4458 @@ +package Font::TTF::PSNames; + +=head1 NAME + +Font::TTF::PSNames - Utilities for Postscript glyph name processing + +=head1 SYNOPSIS + + use Font::TTF::PSNames qw(parse lookup); + $name = lookup($uni); + $uni = parse($name); + +=head1 METHODS + +=cut + +use strict; +use vars qw(%names %agl @EXPORT_OK @ISA); +require Exporter; +@ISA = qw( Exporter ); +@EXPORT_OK = qw( parse lookup); + +# Adobe Glyph List for New Fonts +# from http://partners.adobe.com/asn/tech/type/aglfn13.txt + +%names = ( + '0020' => 'space', + '0021' => 'exclam', + '0022' => 'quotedbl', + '0023' => 'numbersign', + '0024' => 'dollar', + '0025' => 'percent', + '0026' => 'ampersand', + '0027' => 'quotesingle', + '0028' => 'parenleft', + '0029' => 'parenright', + '002A' => 'asterisk', + '002B' => 'plus', + '002C' => 'comma', + '002D' => 'hyphen', + '002E' => 'period', + '002F' => 'slash', + '0030' => 'zero', + '0031' => 'one', + '0032' => 'two', + '0033' => 'three', + '0034' => 'four', + '0035' => 'five', + '0036' => 'six', + '0037' => 'seven', + '0038' => 'eight', + '0039' => 'nine', + '003A' => 'colon', + '003B' => 'semicolon', + '003C' => 'less', + '003D' => 'equal', + '003E' => 'greater', + '003F' => 'question', + '0040' => 'at', + '0041' => 'A', + '0042' => 'B', + '0043' => 'C', + '0044' => 'D', + '0045' => 'E', + '0046' => 'F', + '0047' => 'G', + '0048' => 'H', + '0049' => 'I', + '004A' => 'J', + '004B' => 'K', + '004C' => 'L', + '004D' => 'M', + '004E' => 'N', + '004F' => 'O', + '0050' => 'P', + '0051' => 'Q', + '0052' => 'R', + '0053' => 'S', + '0054' => 'T', + '0055' => 'U', + '0056' => 'V', + '0057' => 'W', + '0058' => 'X', + '0059' => 'Y', + '005A' => 'Z', + '005B' => 'bracketleft', + '005C' => 'backslash', + '005D' => 'bracketright', + '005E' => 'asciicircum', + '005F' => 'underscore', + '0060' => 'grave', + '0061' => 'a', + '0062' => 'b', + '0063' => 'c', + '0064' => 'd', + '0065' => 'e', + '0066' => 'f', + '0067' => 'g', + '0068' => 'h', + '0069' => 'i', + '006A' => 'j', + '006B' => 'k', + '006C' => 'l', + '006D' => 'm', + '006E' => 'n', + '006F' => 'o', + '0070' => 'p', + '0071' => 'q', + '0072' => 'r', + '0073' => 's', + '0074' => 't', + '0075' => 'u', + '0076' => 'v', + '0077' => 'w', + '0078' => 'x', + '0079' => 'y', + '007A' => 'z', + '007B' => 'braceleft', + '007C' => 'bar', + '007D' => 'braceright', + '007E' => 'asciitilde', +# '00A0' => 'space', + '00A1' => 'exclamdown', + '00A2' => 'cent', + '00A3' => 'sterling', + '00A4' => 'currency', + '00A5' => 'yen', + '00A6' => 'brokenbar', + '00A7' => 'section', + '00A8' => 'dieresis', + '00A9' => 'copyright', + '00AA' => 'ordfeminine', + '00AB' => 'guillemotleft', + '00AC' => 'logicalnot', +# '00AD' => 'hyphen', + '00AE' => 'registered', + '00AF' => 'macron', + '00B0' => 'degree', + '00B1' => 'plusminus', + '00B2' => 'twosuperior', + '00B3' => 'threesuperior', + '00B4' => 'acute', + '00B5' => 'mu', + '00B6' => 'paragraph', + '00B7' => 'periodcentered', + '00B8' => 'cedilla', + '00B9' => 'onesuperior', + '00BA' => 'ordmasculine', + '00BB' => 'guillemotright', + '00BC' => 'onequarter', + '00BD' => 'onehalf', + '00BE' => 'threequarters', + '00BF' => 'questiondown', + '00C0' => 'Agrave', + '00C1' => 'Aacute', + '00C2' => 'Acircumflex', + '00C3' => 'Atilde', + '00C4' => 'Adieresis', + '00C5' => 'Aring', + '00C6' => 'AE', + '00C7' => 'Ccedilla', + '00C8' => 'Egrave', + '00C9' => 'Eacute', + '00CA' => 'Ecircumflex', + '00CB' => 'Edieresis', + '00CC' => 'Igrave', + '00CD' => 'Iacute', + '00CE' => 'Icircumflex', + '00CF' => 'Idieresis', + '00D0' => 'Eth', + '00D1' => 'Ntilde', + '00D2' => 'Ograve', + '00D3' => 'Oacute', + '00D4' => 'Ocircumflex', + '00D5' => 'Otilde', + '00D6' => 'Odieresis', + '00D7' => 'multiply', + '00D8' => 'Oslash', + '00D9' => 'Ugrave', + '00DA' => 'Uacute', + '00DB' => 'Ucircumflex', + '00DC' => 'Udieresis', + '00DD' => 'Yacute', + '00DE' => 'Thorn', + '00DF' => 'germandbls', + '00E0' => 'agrave', + '00E1' => 'aacute', + '00E2' => 'acircumflex', + '00E3' => 'atilde', + '00E4' => 'adieresis', + '00E5' => 'aring', + '00E6' => 'ae', + '00E7' => 'ccedilla', + '00E8' => 'egrave', + '00E9' => 'eacute', + '00EA' => 'ecircumflex', + '00EB' => 'edieresis', + '00EC' => 'igrave', + '00ED' => 'iacute', + '00EE' => 'icircumflex', + '00EF' => 'idieresis', + '00F0' => 'eth', + '00F1' => 'ntilde', + '00F2' => 'ograve', + '00F3' => 'oacute', + '00F4' => 'ocircumflex', + '00F5' => 'otilde', + '00F6' => 'odieresis', + '00F7' => 'divide', + '00F8' => 'oslash', + '00F9' => 'ugrave', + '00FA' => 'uacute', + '00FB' => 'ucircumflex', + '00FC' => 'udieresis', + '00FD' => 'yacute', + '00FE' => 'thorn', + '00FF' => 'ydieresis', + '0100' => 'Amacron', + '0101' => 'amacron', + '0102' => 'Abreve', + '0103' => 'abreve', + '0104' => 'Aogonek', + '0105' => 'aogonek', + '0106' => 'Cacute', + '0107' => 'cacute', + '0108' => 'Ccircumflex', + '0109' => 'ccircumflex', + '010A' => 'Cdotaccent', + '010B' => 'cdotaccent', + '010C' => 'Ccaron', + '010D' => 'ccaron', + '010E' => 'Dcaron', + '010F' => 'dcaron', + '0110' => 'Dcroat', + '0111' => 'dcroat', + '0112' => 'Emacron', + '0113' => 'emacron', + '0114' => 'Ebreve', + '0115' => 'ebreve', + '0116' => 'Edotaccent', + '0117' => 'edotaccent', + '0118' => 'Eogonek', + '0119' => 'eogonek', + '011A' => 'Ecaron', + '011B' => 'ecaron', + '011C' => 'Gcircumflex', + '011D' => 'gcircumflex', + '011E' => 'Gbreve', + '011F' => 'gbreve', + '0120' => 'Gdotaccent', + '0121' => 'gdotaccent', + '0122' => 'Gcommaaccent', + '0123' => 'gcommaaccent', + '0124' => 'Hcircumflex', + '0125' => 'hcircumflex', + '0126' => 'Hbar', + '0127' => 'hbar', + '0128' => 'Itilde', + '0129' => 'itilde', + '012A' => 'Imacron', + '012B' => 'imacron', + '012C' => 'Ibreve', + '012D' => 'ibreve', + '012E' => 'Iogonek', + '012F' => 'iogonek', + '0130' => 'Idotaccent', + '0131' => 'dotlessi', + '0132' => 'IJ', + '0133' => 'ij', + '0134' => 'Jcircumflex', + '0135' => 'jcircumflex', + '0136' => 'Kcommaaccent', + '0137' => 'kcommaaccent', + '0138' => 'kgreenlandic', + '0139' => 'Lacute', + '013A' => 'lacute', + '013B' => 'Lcommaaccent', + '013C' => 'lcommaaccent', + '013D' => 'Lcaron', + '013E' => 'lcaron', + '013F' => 'Ldot', + '0140' => 'ldot', + '0141' => 'Lslash', + '0142' => 'lslash', + '0143' => 'Nacute', + '0144' => 'nacute', + '0145' => 'Ncommaaccent', + '0146' => 'ncommaaccent', + '0147' => 'Ncaron', + '0148' => 'ncaron', + '0149' => 'napostrophe', + '014A' => 'Eng', + '014B' => 'eng', + '014C' => 'Omacron', + '014D' => 'omacron', + '014E' => 'Obreve', + '014F' => 'obreve', + '0150' => 'Ohungarumlaut', + '0151' => 'ohungarumlaut', + '0152' => 'OE', + '0153' => 'oe', + '0154' => 'Racute', + '0155' => 'racute', + '0156' => 'Rcommaaccent', + '0157' => 'rcommaaccent', + '0158' => 'Rcaron', + '0159' => 'rcaron', + '015A' => 'Sacute', + '015B' => 'sacute', + '015C' => 'Scircumflex', + '015D' => 'scircumflex', + '015E' => 'Scedilla', + '015F' => 'scedilla', + '0160' => 'Scaron', + '0161' => 'scaron', + '0162' => 'Tcommaaccent', + '0163' => 'tcommaaccent', + '0164' => 'Tcaron', + '0165' => 'tcaron', + '0166' => 'Tbar', + '0167' => 'tbar', + '0168' => 'Utilde', + '0169' => 'utilde', + '016A' => 'Umacron', + '016B' => 'umacron', + '016C' => 'Ubreve', + '016D' => 'ubreve', + '016E' => 'Uring', + '016F' => 'uring', + '0170' => 'Uhungarumlaut', + '0171' => 'uhungarumlaut', + '0172' => 'Uogonek', + '0173' => 'uogonek', + '0174' => 'Wcircumflex', + '0175' => 'wcircumflex', + '0176' => 'Ycircumflex', + '0177' => 'ycircumflex', + '0178' => 'Ydieresis', + '0179' => 'Zacute', + '017A' => 'zacute', + '017B' => 'Zdotaccent', + '017C' => 'zdotaccent', + '017D' => 'Zcaron', + '017E' => 'zcaron', + '017F' => 'longs', + '0192' => 'florin', + '01A0' => 'Ohorn', + '01A1' => 'ohorn', + '01AF' => 'Uhorn', + '01B0' => 'uhorn', + '01E6' => 'Gcaron', + '01E7' => 'gcaron', + '01FA' => 'Aringacute', + '01FB' => 'aringacute', + '01FC' => 'AEacute', + '01FD' => 'aeacute', + '01FE' => 'Oslashacute', + '01FF' => 'oslashacute', + '0218' => 'Scommaaccent', + '0219' => 'scommaaccent', +# '021A' => 'Tcommaaccent', +# '021B' => 'tcommaaccent', + '02BC' => 'afii57929', + '02BD' => 'afii64937', + '02C6' => 'circumflex', + '02C7' => 'caron', +# '02C9' => 'macron', + '02D8' => 'breve', + '02D9' => 'dotaccent', + '02DA' => 'ring', + '02DB' => 'ogonek', + '02DC' => 'tilde', + '02DD' => 'hungarumlaut', + '0300' => 'gravecomb', + '0301' => 'acutecomb', + '0303' => 'tildecomb', + '0309' => 'hookabovecomb', + '0323' => 'dotbelowcomb', + '0384' => 'tonos', + '0385' => 'dieresistonos', + '0386' => 'Alphatonos', + '0387' => 'anoteleia', + '0388' => 'Epsilontonos', + '0389' => 'Etatonos', + '038A' => 'Iotatonos', + '038C' => 'Omicrontonos', + '038E' => 'Upsilontonos', + '038F' => 'Omegatonos', + '0390' => 'iotadieresistonos', + '0391' => 'Alpha', + '0392' => 'Beta', + '0393' => 'Gamma', +# '0394' => 'Delta', + '0395' => 'Epsilon', + '0396' => 'Zeta', + '0397' => 'Eta', + '0398' => 'Theta', + '0399' => 'Iota', + '039A' => 'Kappa', + '039B' => 'Lambda', + '039C' => 'Mu', + '039D' => 'Nu', + '039E' => 'Xi', + '039F' => 'Omicron', + '03A0' => 'Pi', + '03A1' => 'Rho', + '03A3' => 'Sigma', + '03A4' => 'Tau', + '03A5' => 'Upsilon', + '03A6' => 'Phi', + '03A7' => 'Chi', + '03A8' => 'Psi', +# '03A9' => 'Omega', + '03AA' => 'Iotadieresis', + '03AB' => 'Upsilondieresis', + '03AC' => 'alphatonos', + '03AD' => 'epsilontonos', + '03AE' => 'etatonos', + '03AF' => 'iotatonos', + '03B0' => 'upsilondieresistonos', + '03B1' => 'alpha', + '03B2' => 'beta', + '03B3' => 'gamma', + '03B4' => 'delta', + '03B5' => 'epsilon', + '03B6' => 'zeta', + '03B7' => 'eta', + '03B8' => 'theta', + '03B9' => 'iota', + '03BA' => 'kappa', + '03BB' => 'lambda', +# '03BC' => 'mu', + '03BD' => 'nu', + '03BE' => 'xi', + '03BF' => 'omicron', + '03C0' => 'pi', + '03C1' => 'rho', + '03C2' => 'sigma1', + '03C3' => 'sigma', + '03C4' => 'tau', + '03C5' => 'upsilon', + '03C6' => 'phi', + '03C7' => 'chi', + '03C8' => 'psi', + '03C9' => 'omega', + '03CA' => 'iotadieresis', + '03CB' => 'upsilondieresis', + '03CC' => 'omicrontonos', + '03CD' => 'upsilontonos', + '03CE' => 'omegatonos', + '03D1' => 'theta1', + '03D2' => 'Upsilon1', + '03D5' => 'phi1', + '03D6' => 'omega1', + '0401' => 'afii10023', + '0402' => 'afii10051', + '0403' => 'afii10052', + '0404' => 'afii10053', + '0405' => 'afii10054', + '0406' => 'afii10055', + '0407' => 'afii10056', + '0408' => 'afii10057', + '0409' => 'afii10058', + '040A' => 'afii10059', + '040B' => 'afii10060', + '040C' => 'afii10061', + '040E' => 'afii10062', + '040F' => 'afii10145', + '0410' => 'afii10017', + '0411' => 'afii10018', + '0412' => 'afii10019', + '0413' => 'afii10020', + '0414' => 'afii10021', + '0415' => 'afii10022', + '0416' => 'afii10024', + '0417' => 'afii10025', + '0418' => 'afii10026', + '0419' => 'afii10027', + '041A' => 'afii10028', + '041B' => 'afii10029', + '041C' => 'afii10030', + '041D' => 'afii10031', + '041E' => 'afii10032', + '041F' => 'afii10033', + '0420' => 'afii10034', + '0421' => 'afii10035', + '0422' => 'afii10036', + '0423' => 'afii10037', + '0424' => 'afii10038', + '0425' => 'afii10039', + '0426' => 'afii10040', + '0427' => 'afii10041', + '0428' => 'afii10042', + '0429' => 'afii10043', + '042A' => 'afii10044', + '042B' => 'afii10045', + '042C' => 'afii10046', + '042D' => 'afii10047', + '042E' => 'afii10048', + '042F' => 'afii10049', + '0430' => 'afii10065', + '0431' => 'afii10066', + '0432' => 'afii10067', + '0433' => 'afii10068', + '0434' => 'afii10069', + '0435' => 'afii10070', + '0436' => 'afii10072', + '0437' => 'afii10073', + '0438' => 'afii10074', + '0439' => 'afii10075', + '043A' => 'afii10076', + '043B' => 'afii10077', + '043C' => 'afii10078', + '043D' => 'afii10079', + '043E' => 'afii10080', + '043F' => 'afii10081', + '0440' => 'afii10082', + '0441' => 'afii10083', + '0442' => 'afii10084', + '0443' => 'afii10085', + '0444' => 'afii10086', + '0445' => 'afii10087', + '0446' => 'afii10088', + '0447' => 'afii10089', + '0448' => 'afii10090', + '0449' => 'afii10091', + '044A' => 'afii10092', + '044B' => 'afii10093', + '044C' => 'afii10094', + '044D' => 'afii10095', + '044E' => 'afii10096', + '044F' => 'afii10097', + '0451' => 'afii10071', + '0452' => 'afii10099', + '0453' => 'afii10100', + '0454' => 'afii10101', + '0455' => 'afii10102', + '0456' => 'afii10103', + '0457' => 'afii10104', + '0458' => 'afii10105', + '0459' => 'afii10106', + '045A' => 'afii10107', + '045B' => 'afii10108', + '045C' => 'afii10109', + '045E' => 'afii10110', + '045F' => 'afii10193', + '0462' => 'afii10146', + '0463' => 'afii10194', + '0472' => 'afii10147', + '0473' => 'afii10195', + '0474' => 'afii10148', + '0475' => 'afii10196', + '0490' => 'afii10050', + '0491' => 'afii10098', + '04D9' => 'afii10846', + '05B0' => 'afii57799', + '05B1' => 'afii57801', + '05B2' => 'afii57800', + '05B3' => 'afii57802', + '05B4' => 'afii57793', + '05B5' => 'afii57794', + '05B6' => 'afii57795', + '05B7' => 'afii57798', + '05B8' => 'afii57797', + '05B9' => 'afii57806', + '05BB' => 'afii57796', + '05BC' => 'afii57807', + '05BD' => 'afii57839', + '05BE' => 'afii57645', + '05BF' => 'afii57841', + '05C0' => 'afii57842', + '05C1' => 'afii57804', + '05C2' => 'afii57803', + '05C3' => 'afii57658', + '05D0' => 'afii57664', + '05D1' => 'afii57665', + '05D2' => 'afii57666', + '05D3' => 'afii57667', + '05D4' => 'afii57668', + '05D5' => 'afii57669', + '05D6' => 'afii57670', + '05D7' => 'afii57671', + '05D8' => 'afii57672', + '05D9' => 'afii57673', + '05DA' => 'afii57674', + '05DB' => 'afii57675', + '05DC' => 'afii57676', + '05DD' => 'afii57677', + '05DE' => 'afii57678', + '05DF' => 'afii57679', + '05E0' => 'afii57680', + '05E1' => 'afii57681', + '05E2' => 'afii57682', + '05E3' => 'afii57683', + '05E4' => 'afii57684', + '05E5' => 'afii57685', + '05E6' => 'afii57686', + '05E7' => 'afii57687', + '05E8' => 'afii57688', + '05E9' => 'afii57689', + '05EA' => 'afii57690', + '05F0' => 'afii57716', + '05F1' => 'afii57717', + '05F2' => 'afii57718', + '060C' => 'afii57388', + '061B' => 'afii57403', + '061F' => 'afii57407', + '0621' => 'afii57409', + '0622' => 'afii57410', + '0623' => 'afii57411', + '0624' => 'afii57412', + '0625' => 'afii57413', + '0626' => 'afii57414', + '0627' => 'afii57415', + '0628' => 'afii57416', + '0629' => 'afii57417', + '062A' => 'afii57418', + '062B' => 'afii57419', + '062C' => 'afii57420', + '062D' => 'afii57421', + '062E' => 'afii57422', + '062F' => 'afii57423', + '0630' => 'afii57424', + '0631' => 'afii57425', + '0632' => 'afii57426', + '0633' => 'afii57427', + '0634' => 'afii57428', + '0635' => 'afii57429', + '0636' => 'afii57430', + '0637' => 'afii57431', + '0638' => 'afii57432', + '0639' => 'afii57433', + '063A' => 'afii57434', + '0640' => 'afii57440', + '0641' => 'afii57441', + '0642' => 'afii57442', + '0643' => 'afii57443', + '0644' => 'afii57444', + '0645' => 'afii57445', + '0646' => 'afii57446', + '0647' => 'afii57470', + '0648' => 'afii57448', + '0649' => 'afii57449', + '064A' => 'afii57450', + '064B' => 'afii57451', + '064C' => 'afii57452', + '064D' => 'afii57453', + '064E' => 'afii57454', + '064F' => 'afii57455', + '0650' => 'afii57456', + '0651' => 'afii57457', + '0652' => 'afii57458', + '0660' => 'afii57392', + '0661' => 'afii57393', + '0662' => 'afii57394', + '0663' => 'afii57395', + '0664' => 'afii57396', + '0665' => 'afii57397', + '0666' => 'afii57398', + '0667' => 'afii57399', + '0668' => 'afii57400', + '0669' => 'afii57401', + '066A' => 'afii57381', + '066D' => 'afii63167', + '0679' => 'afii57511', + '067E' => 'afii57506', + '0686' => 'afii57507', + '0688' => 'afii57512', + '0691' => 'afii57513', + '0698' => 'afii57508', + '06A4' => 'afii57505', + '06AF' => 'afii57509', + '06BA' => 'afii57514', + '06D2' => 'afii57519', + '06D5' => 'afii57534', + '1E80' => 'Wgrave', + '1E81' => 'wgrave', + '1E82' => 'Wacute', + '1E83' => 'wacute', + '1E84' => 'Wdieresis', + '1E85' => 'wdieresis', + '1EF2' => 'Ygrave', + '1EF3' => 'ygrave', + '200C' => 'afii61664', + '200D' => 'afii301', + '200E' => 'afii299', + '200F' => 'afii300', + '2012' => 'figuredash', + '2013' => 'endash', + '2014' => 'emdash', + '2015' => 'afii00208', + '2017' => 'underscoredbl', + '2018' => 'quoteleft', + '2019' => 'quoteright', + '201A' => 'quotesinglbase', + '201B' => 'quotereversed', + '201C' => 'quotedblleft', + '201D' => 'quotedblright', + '201E' => 'quotedblbase', + '2020' => 'dagger', + '2021' => 'daggerdbl', + '2022' => 'bullet', + '2024' => 'onedotenleader', + '2025' => 'twodotenleader', + '2026' => 'ellipsis', + '202C' => 'afii61573', + '202D' => 'afii61574', + '202E' => 'afii61575', + '2030' => 'perthousand', + '2032' => 'minute', + '2033' => 'second', + '2039' => 'guilsinglleft', + '203A' => 'guilsinglright', + '203C' => 'exclamdbl', + '2044' => 'fraction', +# '2070' => 'zerosuperior', +# '2074' => 'foursuperior', +# '2075' => 'fivesuperior', +# '2076' => 'sixsuperior', +# '2077' => 'sevensuperior', +# '2078' => 'eightsuperior', +# '2079' => 'ninesuperior', +# '207D' => 'parenleftsuperior', +# '207E' => 'parenrightsuperior', +# '207F' => 'nsuperior', +# '2080' => 'zeroinferior', +# '2081' => 'oneinferior', +# '2082' => 'twoinferior', +# '2083' => 'threeinferior', +# '2084' => 'fourinferior', +# '2085' => 'fiveinferior', +# '2086' => 'sixinferior', +# '2087' => 'seveninferior', +# '2088' => 'eightinferior', +# '2089' => 'nineinferior', +# '208D' => 'parenleftinferior', +# '208E' => 'parenrightinferior', + '20A1' => 'colonmonetary', + '20A3' => 'franc', + '20A4' => 'lira', + '20A7' => 'peseta', + '20AA' => 'afii57636', + '20AB' => 'dong', + '20AC' => 'Euro', + '2105' => 'afii61248', + '2111' => 'Ifraktur', + '2113' => 'afii61289', + '2116' => 'afii61352', + '2118' => 'weierstrass', + '211C' => 'Rfraktur', + '211E' => 'prescription', + '2122' => 'trademark', + '2126' => 'Omega', + '212E' => 'estimated', + '2135' => 'aleph', + '2153' => 'onethird', + '2154' => 'twothirds', + '215B' => 'oneeighth', + '215C' => 'threeeighths', + '215D' => 'fiveeighths', + '215E' => 'seveneighths', + '2190' => 'arrowleft', + '2191' => 'arrowup', + '2192' => 'arrowright', + '2193' => 'arrowdown', + '2194' => 'arrowboth', + '2195' => 'arrowupdn', + '21A8' => 'arrowupdnbse', + '21B5' => 'carriagereturn', + '21D0' => 'arrowdblleft', + '21D1' => 'arrowdblup', + '21D2' => 'arrowdblright', + '21D3' => 'arrowdbldown', + '21D4' => 'arrowdblboth', + '2200' => 'universal', + '2202' => 'partialdiff', + '2203' => 'existential', + '2205' => 'emptyset', + '2206' => 'Delta', + '2207' => 'gradient', + '2208' => 'element', + '2209' => 'notelement', + '220B' => 'suchthat', + '220F' => 'product', + '2211' => 'summation', + '2212' => 'minus', +# '2215' => 'fraction', + '2217' => 'asteriskmath', +# '2219' => 'periodcentered', + '221A' => 'radical', + '221D' => 'proportional', + '221E' => 'infinity', + '221F' => 'orthogonal', + '2220' => 'angle', + '2227' => 'logicaland', + '2228' => 'logicalor', + '2229' => 'intersection', + '222A' => 'union', + '222B' => 'integral', + '2234' => 'therefore', + '223C' => 'similar', + '2245' => 'congruent', + '2248' => 'approxequal', + '2260' => 'notequal', + '2261' => 'equivalence', + '2264' => 'lessequal', + '2265' => 'greaterequal', + '2282' => 'propersubset', + '2283' => 'propersuperset', + '2284' => 'notsubset', + '2286' => 'reflexsubset', + '2287' => 'reflexsuperset', + '2295' => 'circleplus', + '2297' => 'circlemultiply', + '22A5' => 'perpendicular', + '22C5' => 'dotmath', + '2302' => 'house', + '2310' => 'revlogicalnot', + '2320' => 'integraltp', + '2321' => 'integralbt', + '2329' => 'angleleft', + '232A' => 'angleright', + '2500' => 'SF100000', + '2502' => 'SF110000', + '250C' => 'SF010000', + '2510' => 'SF030000', + '2514' => 'SF020000', + '2518' => 'SF040000', + '251C' => 'SF080000', + '2524' => 'SF090000', + '252C' => 'SF060000', + '2534' => 'SF070000', + '253C' => 'SF050000', + '2550' => 'SF430000', + '2551' => 'SF240000', + '2552' => 'SF510000', + '2553' => 'SF520000', + '2554' => 'SF390000', + '2555' => 'SF220000', + '2556' => 'SF210000', + '2557' => 'SF250000', + '2558' => 'SF500000', + '2559' => 'SF490000', + '255A' => 'SF380000', + '255B' => 'SF280000', + '255C' => 'SF270000', + '255D' => 'SF260000', + '255E' => 'SF360000', + '255F' => 'SF370000', + '2560' => 'SF420000', + '2561' => 'SF190000', + '2562' => 'SF200000', + '2563' => 'SF230000', + '2564' => 'SF470000', + '2565' => 'SF480000', + '2566' => 'SF410000', + '2567' => 'SF450000', + '2568' => 'SF460000', + '2569' => 'SF400000', + '256A' => 'SF540000', + '256B' => 'SF530000', + '256C' => 'SF440000', + '2580' => 'upblock', + '2584' => 'dnblock', + '2588' => 'block', + '258C' => 'lfblock', + '2590' => 'rtblock', + '2591' => 'ltshade', + '2592' => 'shade', + '2593' => 'dkshade', + '25A0' => 'filledbox', + '25A1' => 'H22073', + '25AA' => 'H18543', + '25AB' => 'H18551', + '25AC' => 'filledrect', + '25B2' => 'triagup', + '25BA' => 'triagrt', + '25BC' => 'triagdn', + '25C4' => 'triaglf', + '25CA' => 'lozenge', + '25CB' => 'circle', + '25CF' => 'H18533', + '25D8' => 'invbullet', + '25D9' => 'invcircle', + '25E6' => 'openbullet', + '263A' => 'smileface', + '263B' => 'invsmileface', + '263C' => 'sun', + '2640' => 'female', + '2642' => 'male', + '2660' => 'spade', + '2663' => 'club', + '2665' => 'heart', + '2666' => 'diamond', + '266A' => 'musicalnote', + '266B' => 'musicalnotedbl', + 'FB00' => 'ff', + 'FB01' => 'fi', + 'FB02' => 'fl', + 'FB03' => 'ffi', + 'FB04' => 'ffl', + 'FB1F' => 'afii57705', + 'FB2A' => 'afii57694', + 'FB2B' => 'afii57695', + 'FB35' => 'afii57723', + 'FB4B' => 'afii57700', +); + +# Adobe Glyph List 2.0 (sans those in glyph list for *new* fonts) -- thus +# these are all historic names that could occur in fonts +# from http://partners.adobe.com/asn/tech/type/glyphlist.txt + +%agl = ( + 'AEmacron' => "\x{01E2}", + 'AEsmall' => "\x{F7E6}", + 'Aacutesmall' => "\x{F7E1}", + 'Abreveacute' => "\x{1EAE}", + 'Abrevecyrillic' => "\x{04D0}", + 'Abrevedotbelow' => "\x{1EB6}", + 'Abrevegrave' => "\x{1EB0}", + 'Abrevehookabove' => "\x{1EB2}", + 'Abrevetilde' => "\x{1EB4}", + 'Acaron' => "\x{01CD}", + 'Acircle' => "\x{24B6}", + 'Acircumflexacute' => "\x{1EA4}", + 'Acircumflexdotbelow' => "\x{1EAC}", + 'Acircumflexgrave' => "\x{1EA6}", + 'Acircumflexhookabove' => "\x{1EA8}", + 'Acircumflexsmall' => "\x{F7E2}", + 'Acircumflextilde' => "\x{1EAA}", + 'Acute' => "\x{F6C9}", + 'Acutesmall' => "\x{F7B4}", + 'Acyrillic' => "\x{0410}", + 'Adblgrave' => "\x{0200}", + 'Adieresiscyrillic' => "\x{04D2}", + 'Adieresismacron' => "\x{01DE}", + 'Adieresissmall' => "\x{F7E4}", + 'Adotbelow' => "\x{1EA0}", + 'Adotmacron' => "\x{01E0}", + 'Agravesmall' => "\x{F7E0}", + 'Ahookabove' => "\x{1EA2}", + 'Aiecyrillic' => "\x{04D4}", + 'Ainvertedbreve' => "\x{0202}", + 'Amonospace' => "\x{FF21}", + 'Aringbelow' => "\x{1E00}", + 'Aringsmall' => "\x{F7E5}", + 'Asmall' => "\x{F761}", + 'Atildesmall' => "\x{F7E3}", + 'Aybarmenian' => "\x{0531}", + 'Bcircle' => "\x{24B7}", + 'Bdotaccent' => "\x{1E02}", + 'Bdotbelow' => "\x{1E04}", + 'Becyrillic' => "\x{0411}", + 'Benarmenian' => "\x{0532}", + 'Bhook' => "\x{0181}", + 'Blinebelow' => "\x{1E06}", + 'Bmonospace' => "\x{FF22}", + 'Brevesmall' => "\x{F6F4}", + 'Bsmall' => "\x{F762}", + 'Btopbar' => "\x{0182}", + 'Caarmenian' => "\x{053E}", + 'Caron' => "\x{F6CA}", + 'Caronsmall' => "\x{F6F5}", + 'Ccedillaacute' => "\x{1E08}", + 'Ccedillasmall' => "\x{F7E7}", + 'Ccircle' => "\x{24B8}", + 'Cdot' => "\x{010A}", + 'Cedillasmall' => "\x{F7B8}", + 'Chaarmenian' => "\x{0549}", + 'Cheabkhasiancyrillic' => "\x{04BC}", + 'Checyrillic' => "\x{0427}", + 'Chedescenderabkhasiancyrillic' => "\x{04BE}", + 'Chedescendercyrillic' => "\x{04B6}", + 'Chedieresiscyrillic' => "\x{04F4}", + 'Cheharmenian' => "\x{0543}", + 'Chekhakassiancyrillic' => "\x{04CB}", + 'Cheverticalstrokecyrillic' => "\x{04B8}", + 'Chook' => "\x{0187}", + 'Circumflexsmall' => "\x{F6F6}", + 'Cmonospace' => "\x{FF23}", + 'Coarmenian' => "\x{0551}", + 'Csmall' => "\x{F763}", + 'DZ' => "\x{01F1}", + 'DZcaron' => "\x{01C4}", + 'Daarmenian' => "\x{0534}", + 'Dafrican' => "\x{0189}", + 'Dcedilla' => "\x{1E10}", + 'Dcircle' => "\x{24B9}", + 'Dcircumflexbelow' => "\x{1E12}", + 'Ddotaccent' => "\x{1E0A}", + 'Ddotbelow' => "\x{1E0C}", + 'Decyrillic' => "\x{0414}", + 'Deicoptic' => "\x{03EE}", + 'Deltagreek' => "\x{0394}", + 'Dhook' => "\x{018A}", + 'Dieresis' => "\x{F6CB}", + 'DieresisAcute' => "\x{F6CC}", + 'DieresisGrave' => "\x{F6CD}", + 'Dieresissmall' => "\x{F7A8}", + 'Digammagreek' => "\x{03DC}", + 'Djecyrillic' => "\x{0402}", + 'Dlinebelow' => "\x{1E0E}", + 'Dmonospace' => "\x{FF24}", + 'Dotaccentsmall' => "\x{F6F7}", + 'Dslash' => "\x{0110}", + 'Dsmall' => "\x{F764}", + 'Dtopbar' => "\x{018B}", + 'Dz' => "\x{01F2}", + 'Dzcaron' => "\x{01C5}", + 'Dzeabkhasiancyrillic' => "\x{04E0}", + 'Dzecyrillic' => "\x{0405}", + 'Dzhecyrillic' => "\x{040F}", + 'Eacutesmall' => "\x{F7E9}", + 'Ecedillabreve' => "\x{1E1C}", + 'Echarmenian' => "\x{0535}", + 'Ecircle' => "\x{24BA}", + 'Ecircumflexacute' => "\x{1EBE}", + 'Ecircumflexbelow' => "\x{1E18}", + 'Ecircumflexdotbelow' => "\x{1EC6}", + 'Ecircumflexgrave' => "\x{1EC0}", + 'Ecircumflexhookabove' => "\x{1EC2}", + 'Ecircumflexsmall' => "\x{F7EA}", + 'Ecircumflextilde' => "\x{1EC4}", + 'Ecyrillic' => "\x{0404}", + 'Edblgrave' => "\x{0204}", + 'Edieresissmall' => "\x{F7EB}", + 'Edot' => "\x{0116}", + 'Edotbelow' => "\x{1EB8}", + 'Efcyrillic' => "\x{0424}", + 'Egravesmall' => "\x{F7E8}", + 'Eharmenian' => "\x{0537}", + 'Ehookabove' => "\x{1EBA}", + 'Eightroman' => "\x{2167}", + 'Einvertedbreve' => "\x{0206}", + 'Eiotifiedcyrillic' => "\x{0464}", + 'Elcyrillic' => "\x{041B}", + 'Elevenroman' => "\x{216A}", + 'Emacronacute' => "\x{1E16}", + 'Emacrongrave' => "\x{1E14}", + 'Emcyrillic' => "\x{041C}", + 'Emonospace' => "\x{FF25}", + 'Encyrillic' => "\x{041D}", + 'Endescendercyrillic' => "\x{04A2}", + 'Enghecyrillic' => "\x{04A4}", + 'Enhookcyrillic' => "\x{04C7}", + 'Eopen' => "\x{0190}", + 'Ercyrillic' => "\x{0420}", + 'Ereversed' => "\x{018E}", + 'Ereversedcyrillic' => "\x{042D}", + 'Escyrillic' => "\x{0421}", + 'Esdescendercyrillic' => "\x{04AA}", + 'Esh' => "\x{01A9}", + 'Esmall' => "\x{F765}", + 'Etarmenian' => "\x{0538}", + 'Ethsmall' => "\x{F7F0}", + 'Etilde' => "\x{1EBC}", + 'Etildebelow' => "\x{1E1A}", + 'Ezh' => "\x{01B7}", + 'Ezhcaron' => "\x{01EE}", + 'Ezhreversed' => "\x{01B8}", + 'Fcircle' => "\x{24BB}", + 'Fdotaccent' => "\x{1E1E}", + 'Feharmenian' => "\x{0556}", + 'Feicoptic' => "\x{03E4}", + 'Fhook' => "\x{0191}", + 'Fitacyrillic' => "\x{0472}", + 'Fiveroman' => "\x{2164}", + 'Fmonospace' => "\x{FF26}", + 'Fourroman' => "\x{2163}", + 'Fsmall' => "\x{F766}", + 'GBsquare' => "\x{3387}", + 'Gacute' => "\x{01F4}", + 'Gammaafrican' => "\x{0194}", + 'Gangiacoptic' => "\x{03EA}", + 'Gcedilla' => "\x{0122}", + 'Gcircle' => "\x{24BC}", + 'Gdot' => "\x{0120}", + 'Gecyrillic' => "\x{0413}", + 'Ghadarmenian' => "\x{0542}", + 'Ghemiddlehookcyrillic' => "\x{0494}", + 'Ghestrokecyrillic' => "\x{0492}", + 'Gheupturncyrillic' => "\x{0490}", + 'Ghook' => "\x{0193}", + 'Gimarmenian' => "\x{0533}", + 'Gjecyrillic' => "\x{0403}", + 'Gmacron' => "\x{1E20}", + 'Gmonospace' => "\x{FF27}", + 'Grave' => "\x{F6CE}", + 'Gravesmall' => "\x{F760}", + 'Gsmall' => "\x{F767}", + 'Gsmallhook' => "\x{029B}", + 'Gstroke' => "\x{01E4}", + 'HPsquare' => "\x{33CB}", + 'Haabkhasiancyrillic' => "\x{04A8}", + 'Hadescendercyrillic' => "\x{04B2}", + 'Hardsigncyrillic' => "\x{042A}", + 'Hbrevebelow' => "\x{1E2A}", + 'Hcedilla' => "\x{1E28}", + 'Hcircle' => "\x{24BD}", + 'Hdieresis' => "\x{1E26}", + 'Hdotaccent' => "\x{1E22}", + 'Hdotbelow' => "\x{1E24}", + 'Hmonospace' => "\x{FF28}", + 'Hoarmenian' => "\x{0540}", + 'Horicoptic' => "\x{03E8}", + 'Hsmall' => "\x{F768}", + 'Hungarumlaut' => "\x{F6CF}", + 'Hungarumlautsmall' => "\x{F6F8}", + 'Hzsquare' => "\x{3390}", + 'IAcyrillic' => "\x{042F}", + 'IUcyrillic' => "\x{042E}", + 'Iacutesmall' => "\x{F7ED}", + 'Icaron' => "\x{01CF}", + 'Icircle' => "\x{24BE}", + 'Icircumflexsmall' => "\x{F7EE}", + 'Icyrillic' => "\x{0406}", + 'Idblgrave' => "\x{0208}", + 'Idieresisacute' => "\x{1E2E}", + 'Idieresiscyrillic' => "\x{04E4}", + 'Idieresissmall' => "\x{F7EF}", + 'Idot' => "\x{0130}", + 'Idotbelow' => "\x{1ECA}", + 'Iebrevecyrillic' => "\x{04D6}", + 'Iecyrillic' => "\x{0415}", + 'Igravesmall' => "\x{F7EC}", + 'Ihookabove' => "\x{1EC8}", + 'Iicyrillic' => "\x{0418}", + 'Iinvertedbreve' => "\x{020A}", + 'Iishortcyrillic' => "\x{0419}", + 'Imacroncyrillic' => "\x{04E2}", + 'Imonospace' => "\x{FF29}", + 'Iniarmenian' => "\x{053B}", + 'Iocyrillic' => "\x{0401}", + 'Iotaafrican' => "\x{0196}", + 'Ismall' => "\x{F769}", + 'Istroke' => "\x{0197}", + 'Itildebelow' => "\x{1E2C}", + 'Izhitsacyrillic' => "\x{0474}", + 'Izhitsadblgravecyrillic' => "\x{0476}", + 'Jaarmenian' => "\x{0541}", + 'Jcircle' => "\x{24BF}", + 'Jecyrillic' => "\x{0408}", + 'Jheharmenian' => "\x{054B}", + 'Jmonospace' => "\x{FF2A}", + 'Jsmall' => "\x{F76A}", + 'KBsquare' => "\x{3385}", + 'KKsquare' => "\x{33CD}", + 'Kabashkircyrillic' => "\x{04A0}", + 'Kacute' => "\x{1E30}", + 'Kacyrillic' => "\x{041A}", + 'Kadescendercyrillic' => "\x{049A}", + 'Kahookcyrillic' => "\x{04C3}", + 'Kastrokecyrillic' => "\x{049E}", + 'Kaverticalstrokecyrillic' => "\x{049C}", + 'Kcaron' => "\x{01E8}", + 'Kcedilla' => "\x{0136}", + 'Kcircle' => "\x{24C0}", + 'Kdotbelow' => "\x{1E32}", + 'Keharmenian' => "\x{0554}", + 'Kenarmenian' => "\x{053F}", + 'Khacyrillic' => "\x{0425}", + 'Kheicoptic' => "\x{03E6}", + 'Khook' => "\x{0198}", + 'Kjecyrillic' => "\x{040C}", + 'Klinebelow' => "\x{1E34}", + 'Kmonospace' => "\x{FF2B}", + 'Koppacyrillic' => "\x{0480}", + 'Koppagreek' => "\x{03DE}", + 'Ksicyrillic' => "\x{046E}", + 'Ksmall' => "\x{F76B}", + 'LJ' => "\x{01C7}", + 'LL' => "\x{F6BF}", + 'Lcedilla' => "\x{013B}", + 'Lcircle' => "\x{24C1}", + 'Lcircumflexbelow' => "\x{1E3C}", + 'Ldotaccent' => "\x{013F}", + 'Ldotbelow' => "\x{1E36}", + 'Ldotbelowmacron' => "\x{1E38}", + 'Liwnarmenian' => "\x{053C}", + 'Lj' => "\x{01C8}", + 'Ljecyrillic' => "\x{0409}", + 'Llinebelow' => "\x{1E3A}", + 'Lmonospace' => "\x{FF2C}", + 'Lslashsmall' => "\x{F6F9}", + 'Lsmall' => "\x{F76C}", + 'MBsquare' => "\x{3386}", + 'Macron' => "\x{F6D0}", + 'Macronsmall' => "\x{F7AF}", + 'Macute' => "\x{1E3E}", + 'Mcircle' => "\x{24C2}", + 'Mdotaccent' => "\x{1E40}", + 'Mdotbelow' => "\x{1E42}", + 'Menarmenian' => "\x{0544}", + 'Mmonospace' => "\x{FF2D}", + 'Msmall' => "\x{F76D}", + 'Mturned' => "\x{019C}", + 'NJ' => "\x{01CA}", + 'Ncedilla' => "\x{0145}", + 'Ncircle' => "\x{24C3}", + 'Ncircumflexbelow' => "\x{1E4A}", + 'Ndotaccent' => "\x{1E44}", + 'Ndotbelow' => "\x{1E46}", + 'Nhookleft' => "\x{019D}", + 'Nineroman' => "\x{2168}", + 'Nj' => "\x{01CB}", + 'Njecyrillic' => "\x{040A}", + 'Nlinebelow' => "\x{1E48}", + 'Nmonospace' => "\x{FF2E}", + 'Nowarmenian' => "\x{0546}", + 'Nsmall' => "\x{F76E}", + 'Ntildesmall' => "\x{F7F1}", + 'OEsmall' => "\x{F6FA}", + 'Oacutesmall' => "\x{F7F3}", + 'Obarredcyrillic' => "\x{04E8}", + 'Obarreddieresiscyrillic' => "\x{04EA}", + 'Ocaron' => "\x{01D1}", + 'Ocenteredtilde' => "\x{019F}", + 'Ocircle' => "\x{24C4}", + 'Ocircumflexacute' => "\x{1ED0}", + 'Ocircumflexdotbelow' => "\x{1ED8}", + 'Ocircumflexgrave' => "\x{1ED2}", + 'Ocircumflexhookabove' => "\x{1ED4}", + 'Ocircumflexsmall' => "\x{F7F4}", + 'Ocircumflextilde' => "\x{1ED6}", + 'Ocyrillic' => "\x{041E}", + 'Odblacute' => "\x{0150}", + 'Odblgrave' => "\x{020C}", + 'Odieresiscyrillic' => "\x{04E6}", + 'Odieresissmall' => "\x{F7F6}", + 'Odotbelow' => "\x{1ECC}", + 'Ogoneksmall' => "\x{F6FB}", + 'Ogravesmall' => "\x{F7F2}", + 'Oharmenian' => "\x{0555}", + 'Ohm' => "\x{2126}", + 'Ohookabove' => "\x{1ECE}", + 'Ohornacute' => "\x{1EDA}", + 'Ohorndotbelow' => "\x{1EE2}", + 'Ohorngrave' => "\x{1EDC}", + 'Ohornhookabove' => "\x{1EDE}", + 'Ohorntilde' => "\x{1EE0}", + 'Oi' => "\x{01A2}", + 'Oinvertedbreve' => "\x{020E}", + 'Omacronacute' => "\x{1E52}", + 'Omacrongrave' => "\x{1E50}", + 'Omegacyrillic' => "\x{0460}", + 'Omegagreek' => "\x{03A9}", + 'Omegaroundcyrillic' => "\x{047A}", + 'Omegatitlocyrillic' => "\x{047C}", + 'Omonospace' => "\x{FF2F}", + 'Oneroman' => "\x{2160}", + 'Oogonek' => "\x{01EA}", + 'Oogonekmacron' => "\x{01EC}", + 'Oopen' => "\x{0186}", + 'Oslashsmall' => "\x{F7F8}", + 'Osmall' => "\x{F76F}", + 'Ostrokeacute' => "\x{01FE}", + 'Otcyrillic' => "\x{047E}", + 'Otildeacute' => "\x{1E4C}", + 'Otildedieresis' => "\x{1E4E}", + 'Otildesmall' => "\x{F7F5}", + 'Pacute' => "\x{1E54}", + 'Pcircle' => "\x{24C5}", + 'Pdotaccent' => "\x{1E56}", + 'Pecyrillic' => "\x{041F}", + 'Peharmenian' => "\x{054A}", + 'Pemiddlehookcyrillic' => "\x{04A6}", + 'Phook' => "\x{01A4}", + 'Piwrarmenian' => "\x{0553}", + 'Pmonospace' => "\x{FF30}", + 'Psicyrillic' => "\x{0470}", + 'Psmall' => "\x{F770}", + 'Qcircle' => "\x{24C6}", + 'Qmonospace' => "\x{FF31}", + 'Qsmall' => "\x{F771}", + 'Raarmenian' => "\x{054C}", + 'Rcedilla' => "\x{0156}", + 'Rcircle' => "\x{24C7}", + 'Rdblgrave' => "\x{0210}", + 'Rdotaccent' => "\x{1E58}", + 'Rdotbelow' => "\x{1E5A}", + 'Rdotbelowmacron' => "\x{1E5C}", + 'Reharmenian' => "\x{0550}", + 'Ringsmall' => "\x{F6FC}", + 'Rinvertedbreve' => "\x{0212}", + 'Rlinebelow' => "\x{1E5E}", + 'Rmonospace' => "\x{FF32}", + 'Rsmall' => "\x{F772}", + 'Rsmallinverted' => "\x{0281}", + 'Rsmallinvertedsuperior' => "\x{02B6}", + 'Sacutedotaccent' => "\x{1E64}", + 'Sampigreek' => "\x{03E0}", + 'Scarondotaccent' => "\x{1E66}", + 'Scaronsmall' => "\x{F6FD}", + 'Schwa' => "\x{018F}", + 'Schwacyrillic' => "\x{04D8}", + 'Schwadieresiscyrillic' => "\x{04DA}", + 'Scircle' => "\x{24C8}", + 'Sdotaccent' => "\x{1E60}", + 'Sdotbelow' => "\x{1E62}", + 'Sdotbelowdotaccent' => "\x{1E68}", + 'Seharmenian' => "\x{054D}", + 'Sevenroman' => "\x{2166}", + 'Shaarmenian' => "\x{0547}", + 'Shacyrillic' => "\x{0428}", + 'Shchacyrillic' => "\x{0429}", + 'Sheicoptic' => "\x{03E2}", + 'Shhacyrillic' => "\x{04BA}", + 'Shimacoptic' => "\x{03EC}", + 'Sixroman' => "\x{2165}", + 'Smonospace' => "\x{FF33}", + 'Softsigncyrillic' => "\x{042C}", + 'Ssmall' => "\x{F773}", + 'Stigmagreek' => "\x{03DA}", + 'Tcedilla' => "\x{0162}", + 'Tcircle' => "\x{24C9}", + 'Tcircumflexbelow' => "\x{1E70}", + 'Tdotaccent' => "\x{1E6A}", + 'Tdotbelow' => "\x{1E6C}", + 'Tecyrillic' => "\x{0422}", + 'Tedescendercyrillic' => "\x{04AC}", + 'Tenroman' => "\x{2169}", + 'Tetsecyrillic' => "\x{04B4}", + 'Thook' => "\x{01AC}", + 'Thornsmall' => "\x{F7FE}", + 'Threeroman' => "\x{2162}", + 'Tildesmall' => "\x{F6FE}", + 'Tiwnarmenian' => "\x{054F}", + 'Tlinebelow' => "\x{1E6E}", + 'Tmonospace' => "\x{FF34}", + 'Toarmenian' => "\x{0539}", + 'Tonefive' => "\x{01BC}", + 'Tonesix' => "\x{0184}", + 'Tonetwo' => "\x{01A7}", + 'Tretroflexhook' => "\x{01AE}", + 'Tsecyrillic' => "\x{0426}", + 'Tshecyrillic' => "\x{040B}", + 'Tsmall' => "\x{F774}", + 'Twelveroman' => "\x{216B}", + 'Tworoman' => "\x{2161}", + 'Uacutesmall' => "\x{F7FA}", + 'Ucaron' => "\x{01D3}", + 'Ucircle' => "\x{24CA}", + 'Ucircumflexbelow' => "\x{1E76}", + 'Ucircumflexsmall' => "\x{F7FB}", + 'Ucyrillic' => "\x{0423}", + 'Udblacute' => "\x{0170}", + 'Udblgrave' => "\x{0214}", + 'Udieresisacute' => "\x{01D7}", + 'Udieresisbelow' => "\x{1E72}", + 'Udieresiscaron' => "\x{01D9}", + 'Udieresiscyrillic' => "\x{04F0}", + 'Udieresisgrave' => "\x{01DB}", + 'Udieresismacron' => "\x{01D5}", + 'Udieresissmall' => "\x{F7FC}", + 'Udotbelow' => "\x{1EE4}", + 'Ugravesmall' => "\x{F7F9}", + 'Uhookabove' => "\x{1EE6}", + 'Uhornacute' => "\x{1EE8}", + 'Uhorndotbelow' => "\x{1EF0}", + 'Uhorngrave' => "\x{1EEA}", + 'Uhornhookabove' => "\x{1EEC}", + 'Uhorntilde' => "\x{1EEE}", + 'Uhungarumlautcyrillic' => "\x{04F2}", + 'Uinvertedbreve' => "\x{0216}", + 'Ukcyrillic' => "\x{0478}", + 'Umacroncyrillic' => "\x{04EE}", + 'Umacrondieresis' => "\x{1E7A}", + 'Umonospace' => "\x{FF35}", + 'Upsilonacutehooksymbolgreek' => "\x{03D3}", + 'Upsilonafrican' => "\x{01B1}", + 'Upsilondieresishooksymbolgreek' => "\x{03D4}", + 'Upsilonhooksymbol' => "\x{03D2}", + 'Ushortcyrillic' => "\x{040E}", + 'Usmall' => "\x{F775}", + 'Ustraightcyrillic' => "\x{04AE}", + 'Ustraightstrokecyrillic' => "\x{04B0}", + 'Utildeacute' => "\x{1E78}", + 'Utildebelow' => "\x{1E74}", + 'Vcircle' => "\x{24CB}", + 'Vdotbelow' => "\x{1E7E}", + 'Vecyrillic' => "\x{0412}", + 'Vewarmenian' => "\x{054E}", + 'Vhook' => "\x{01B2}", + 'Vmonospace' => "\x{FF36}", + 'Voarmenian' => "\x{0548}", + 'Vsmall' => "\x{F776}", + 'Vtilde' => "\x{1E7C}", + 'Wcircle' => "\x{24CC}", + 'Wdotaccent' => "\x{1E86}", + 'Wdotbelow' => "\x{1E88}", + 'Wmonospace' => "\x{FF37}", + 'Wsmall' => "\x{F777}", + 'Xcircle' => "\x{24CD}", + 'Xdieresis' => "\x{1E8C}", + 'Xdotaccent' => "\x{1E8A}", + 'Xeharmenian' => "\x{053D}", + 'Xmonospace' => "\x{FF38}", + 'Xsmall' => "\x{F778}", + 'Yacutesmall' => "\x{F7FD}", + 'Yatcyrillic' => "\x{0462}", + 'Ycircle' => "\x{24CE}", + 'Ydieresissmall' => "\x{F7FF}", + 'Ydotaccent' => "\x{1E8E}", + 'Ydotbelow' => "\x{1EF4}", + 'Yericyrillic' => "\x{042B}", + 'Yerudieresiscyrillic' => "\x{04F8}", + 'Yhook' => "\x{01B3}", + 'Yhookabove' => "\x{1EF6}", + 'Yiarmenian' => "\x{0545}", + 'Yicyrillic' => "\x{0407}", + 'Yiwnarmenian' => "\x{0552}", + 'Ymonospace' => "\x{FF39}", + 'Ysmall' => "\x{F779}", + 'Ytilde' => "\x{1EF8}", + 'Yusbigcyrillic' => "\x{046A}", + 'Yusbigiotifiedcyrillic' => "\x{046C}", + 'Yuslittlecyrillic' => "\x{0466}", + 'Yuslittleiotifiedcyrillic' => "\x{0468}", + 'Zaarmenian' => "\x{0536}", + 'Zcaronsmall' => "\x{F6FF}", + 'Zcircle' => "\x{24CF}", + 'Zcircumflex' => "\x{1E90}", + 'Zdot' => "\x{017B}", + 'Zdotbelow' => "\x{1E92}", + 'Zecyrillic' => "\x{0417}", + 'Zedescendercyrillic' => "\x{0498}", + 'Zedieresiscyrillic' => "\x{04DE}", + 'Zhearmenian' => "\x{053A}", + 'Zhebrevecyrillic' => "\x{04C1}", + 'Zhecyrillic' => "\x{0416}", + 'Zhedescendercyrillic' => "\x{0496}", + 'Zhedieresiscyrillic' => "\x{04DC}", + 'Zlinebelow' => "\x{1E94}", + 'Zmonospace' => "\x{FF3A}", + 'Zsmall' => "\x{F77A}", + 'Zstroke' => "\x{01B5}", + 'aabengali' => "\x{0986}", + 'aadeva' => "\x{0906}", + 'aagujarati' => "\x{0A86}", + 'aagurmukhi' => "\x{0A06}", + 'aamatragurmukhi' => "\x{0A3E}", + 'aarusquare' => "\x{3303}", + 'aavowelsignbengali' => "\x{09BE}", + 'aavowelsigndeva' => "\x{093E}", + 'aavowelsigngujarati' => "\x{0ABE}", + 'abbreviationmarkarmenian' => "\x{055F}", + 'abbreviationsigndeva' => "\x{0970}", + 'abengali' => "\x{0985}", + 'abopomofo' => "\x{311A}", + 'abreveacute' => "\x{1EAF}", + 'abrevecyrillic' => "\x{04D1}", + 'abrevedotbelow' => "\x{1EB7}", + 'abrevegrave' => "\x{1EB1}", + 'abrevehookabove' => "\x{1EB3}", + 'abrevetilde' => "\x{1EB5}", + 'acaron' => "\x{01CE}", + 'acircle' => "\x{24D0}", + 'acircumflexacute' => "\x{1EA5}", + 'acircumflexdotbelow' => "\x{1EAD}", + 'acircumflexgrave' => "\x{1EA7}", + 'acircumflexhookabove' => "\x{1EA9}", + 'acircumflextilde' => "\x{1EAB}", + 'acutebelowcmb' => "\x{0317}", + 'acutecmb' => "\x{0301}", + 'acutedeva' => "\x{0954}", + 'acutelowmod' => "\x{02CF}", + 'acutetonecmb' => "\x{0341}", + 'acyrillic' => "\x{0430}", + 'adblgrave' => "\x{0201}", + 'addakgurmukhi' => "\x{0A71}", + 'adeva' => "\x{0905}", + 'adieresiscyrillic' => "\x{04D3}", + 'adieresismacron' => "\x{01DF}", + 'adotbelow' => "\x{1EA1}", + 'adotmacron' => "\x{01E1}", + 'aekorean' => "\x{3150}", + 'aemacron' => "\x{01E3}", + 'afii08941' => "\x{20A4}", + 'afii10063' => "\x{F6C4}", + 'afii10064' => "\x{F6C5}", + 'afii10192' => "\x{F6C6}", + 'afii10831' => "\x{F6C7}", + 'afii10832' => "\x{F6C8}", + 'agujarati' => "\x{0A85}", + 'agurmukhi' => "\x{0A05}", + 'ahiragana' => "\x{3042}", + 'ahookabove' => "\x{1EA3}", + 'aibengali' => "\x{0990}", + 'aibopomofo' => "\x{311E}", + 'aideva' => "\x{0910}", + 'aiecyrillic' => "\x{04D5}", + 'aigujarati' => "\x{0A90}", + 'aigurmukhi' => "\x{0A10}", + 'aimatragurmukhi' => "\x{0A48}", + 'ainarabic' => "\x{0639}", + 'ainfinalarabic' => "\x{FECA}", + 'aininitialarabic' => "\x{FECB}", + 'ainmedialarabic' => "\x{FECC}", + 'ainvertedbreve' => "\x{0203}", + 'aivowelsignbengali' => "\x{09C8}", + 'aivowelsigndeva' => "\x{0948}", + 'aivowelsigngujarati' => "\x{0AC8}", + 'akatakana' => "\x{30A2}", + 'akatakanahalfwidth' => "\x{FF71}", + 'akorean' => "\x{314F}", + 'alef' => "\x{05D0}", + 'alefarabic' => "\x{0627}", + 'alefdageshhebrew' => "\x{FB30}", + 'aleffinalarabic' => "\x{FE8E}", + 'alefhamzaabovearabic' => "\x{0623}", + 'alefhamzaabovefinalarabic' => "\x{FE84}", + 'alefhamzabelowarabic' => "\x{0625}", + 'alefhamzabelowfinalarabic' => "\x{FE88}", + 'alefhebrew' => "\x{05D0}", + 'aleflamedhebrew' => "\x{FB4F}", + 'alefmaddaabovearabic' => "\x{0622}", + 'alefmaddaabovefinalarabic' => "\x{FE82}", + 'alefmaksuraarabic' => "\x{0649}", + 'alefmaksurafinalarabic' => "\x{FEF0}", + 'alefmaksurainitialarabic' => "\x{FEF3}", + 'alefmaksuramedialarabic' => "\x{FEF4}", + 'alefpatahhebrew' => "\x{FB2E}", + 'alefqamatshebrew' => "\x{FB2F}", + 'allequal' => "\x{224C}", + 'amonospace' => "\x{FF41}", + 'ampersandmonospace' => "\x{FF06}", + 'ampersandsmall' => "\x{F726}", + 'amsquare' => "\x{33C2}", + 'anbopomofo' => "\x{3122}", + 'angbopomofo' => "\x{3124}", + 'angkhankhuthai' => "\x{0E5A}", + 'anglebracketleft' => "\x{3008}", + 'anglebracketleftvertical' => "\x{FE3F}", + 'anglebracketright' => "\x{3009}", + 'anglebracketrightvertical' => "\x{FE40}", + 'angstrom' => "\x{212B}", + 'anudattadeva' => "\x{0952}", + 'anusvarabengali' => "\x{0982}", + 'anusvaradeva' => "\x{0902}", + 'anusvaragujarati' => "\x{0A82}", + 'apaatosquare' => "\x{3300}", + 'aparen' => "\x{249C}", + 'apostrophearmenian' => "\x{055A}", + 'apostrophemod' => "\x{02BC}", + 'apple' => "\x{F8FF}", + 'approaches' => "\x{2250}", + 'approxequalorimage' => "\x{2252}", + 'approximatelyequal' => "\x{2245}", + 'araeaekorean' => "\x{318E}", + 'araeakorean' => "\x{318D}", + 'arc' => "\x{2312}", + 'arighthalfring' => "\x{1E9A}", + 'aringbelow' => "\x{1E01}", + 'arrowdashdown' => "\x{21E3}", + 'arrowdashleft' => "\x{21E0}", + 'arrowdashright' => "\x{21E2}", + 'arrowdashup' => "\x{21E1}", + 'arrowdownleft' => "\x{2199}", + 'arrowdownright' => "\x{2198}", + 'arrowdownwhite' => "\x{21E9}", + 'arrowheaddownmod' => "\x{02C5}", + 'arrowheadleftmod' => "\x{02C2}", + 'arrowheadrightmod' => "\x{02C3}", + 'arrowheadupmod' => "\x{02C4}", + 'arrowhorizex' => "\x{F8E7}", + 'arrowleftdbl' => "\x{21D0}", + 'arrowleftdblstroke' => "\x{21CD}", + 'arrowleftoverright' => "\x{21C6}", + 'arrowleftwhite' => "\x{21E6}", + 'arrowrightdblstroke' => "\x{21CF}", + 'arrowrightheavy' => "\x{279E}", + 'arrowrightoverleft' => "\x{21C4}", + 'arrowrightwhite' => "\x{21E8}", + 'arrowtableft' => "\x{21E4}", + 'arrowtabright' => "\x{21E5}", + 'arrowupdownbase' => "\x{21A8}", + 'arrowupleft' => "\x{2196}", + 'arrowupleftofdown' => "\x{21C5}", + 'arrowupright' => "\x{2197}", + 'arrowupwhite' => "\x{21E7}", + 'arrowvertex' => "\x{F8E6}", + 'asciicircummonospace' => "\x{FF3E}", + 'asciitildemonospace' => "\x{FF5E}", + 'ascript' => "\x{0251}", + 'ascriptturned' => "\x{0252}", + 'asmallhiragana' => "\x{3041}", + 'asmallkatakana' => "\x{30A1}", + 'asmallkatakanahalfwidth' => "\x{FF67}", + 'asteriskaltonearabic' => "\x{066D}", + 'asteriskarabic' => "\x{066D}", + 'asteriskmonospace' => "\x{FF0A}", + 'asterisksmall' => "\x{FE61}", + 'asterism' => "\x{2042}", + 'asuperior' => "\x{F6E9}", + 'asymptoticallyequal' => "\x{2243}", + 'atmonospace' => "\x{FF20}", + 'atsmall' => "\x{FE6B}", + 'aturned' => "\x{0250}", + 'aubengali' => "\x{0994}", + 'aubopomofo' => "\x{3120}", + 'audeva' => "\x{0914}", + 'augujarati' => "\x{0A94}", + 'augurmukhi' => "\x{0A14}", + 'aulengthmarkbengali' => "\x{09D7}", + 'aumatragurmukhi' => "\x{0A4C}", + 'auvowelsignbengali' => "\x{09CC}", + 'auvowelsigndeva' => "\x{094C}", + 'auvowelsigngujarati' => "\x{0ACC}", + 'avagrahadeva' => "\x{093D}", + 'aybarmenian' => "\x{0561}", + 'ayin' => "\x{05E2}", + 'ayinaltonehebrew' => "\x{FB20}", + 'ayinhebrew' => "\x{05E2}", + 'babengali' => "\x{09AC}", + 'backslashmonospace' => "\x{FF3C}", + 'badeva' => "\x{092C}", + 'bagujarati' => "\x{0AAC}", + 'bagurmukhi' => "\x{0A2C}", + 'bahiragana' => "\x{3070}", + 'bahtthai' => "\x{0E3F}", + 'bakatakana' => "\x{30D0}", + 'barmonospace' => "\x{FF5C}", + 'bbopomofo' => "\x{3105}", + 'bcircle' => "\x{24D1}", + 'bdotaccent' => "\x{1E03}", + 'bdotbelow' => "\x{1E05}", + 'beamedsixteenthnotes' => "\x{266C}", + 'because' => "\x{2235}", + 'becyrillic' => "\x{0431}", + 'beharabic' => "\x{0628}", + 'behfinalarabic' => "\x{FE90}", + 'behinitialarabic' => "\x{FE91}", + 'behiragana' => "\x{3079}", + 'behmedialarabic' => "\x{FE92}", + 'behmeeminitialarabic' => "\x{FC9F}", + 'behmeemisolatedarabic' => "\x{FC08}", + 'behnoonfinalarabic' => "\x{FC6D}", + 'bekatakana' => "\x{30D9}", + 'benarmenian' => "\x{0562}", + 'bet' => "\x{05D1}", + 'betasymbolgreek' => "\x{03D0}", + 'betdagesh' => "\x{FB31}", + 'betdageshhebrew' => "\x{FB31}", + 'bethebrew' => "\x{05D1}", + 'betrafehebrew' => "\x{FB4C}", + 'bhabengali' => "\x{09AD}", + 'bhadeva' => "\x{092D}", + 'bhagujarati' => "\x{0AAD}", + 'bhagurmukhi' => "\x{0A2D}", + 'bhook' => "\x{0253}", + 'bihiragana' => "\x{3073}", + 'bikatakana' => "\x{30D3}", + 'bilabialclick' => "\x{0298}", + 'bindigurmukhi' => "\x{0A02}", + 'birusquare' => "\x{3331}", + 'blackcircle' => "\x{25CF}", + 'blackdiamond' => "\x{25C6}", + 'blackdownpointingtriangle' => "\x{25BC}", + 'blackleftpointingpointer' => "\x{25C4}", + 'blackleftpointingtriangle' => "\x{25C0}", + 'blacklenticularbracketleft' => "\x{3010}", + 'blacklenticularbracketleftvertical' => "\x{FE3B}", + 'blacklenticularbracketright' => "\x{3011}", + 'blacklenticularbracketrightvertical' => "\x{FE3C}", + 'blacklowerlefttriangle' => "\x{25E3}", + 'blacklowerrighttriangle' => "\x{25E2}", + 'blackrectangle' => "\x{25AC}", + 'blackrightpointingpointer' => "\x{25BA}", + 'blackrightpointingtriangle' => "\x{25B6}", + 'blacksmallsquare' => "\x{25AA}", + 'blacksmilingface' => "\x{263B}", + 'blacksquare' => "\x{25A0}", + 'blackstar' => "\x{2605}", + 'blackupperlefttriangle' => "\x{25E4}", + 'blackupperrighttriangle' => "\x{25E5}", + 'blackuppointingsmalltriangle' => "\x{25B4}", + 'blackuppointingtriangle' => "\x{25B2}", + 'blank' => "\x{2423}", + 'blinebelow' => "\x{1E07}", + 'bmonospace' => "\x{FF42}", + 'bobaimaithai' => "\x{0E1A}", + 'bohiragana' => "\x{307C}", + 'bokatakana' => "\x{30DC}", + 'bparen' => "\x{249D}", + 'bqsquare' => "\x{33C3}", + 'braceex' => "\x{F8F4}", + 'braceleftbt' => "\x{F8F3}", + 'braceleftmid' => "\x{F8F2}", + 'braceleftmonospace' => "\x{FF5B}", + 'braceleftsmall' => "\x{FE5B}", + 'bracelefttp' => "\x{F8F1}", + 'braceleftvertical' => "\x{FE37}", + 'bracerightbt' => "\x{F8FE}", + 'bracerightmid' => "\x{F8FD}", + 'bracerightmonospace' => "\x{FF5D}", + 'bracerightsmall' => "\x{FE5C}", + 'bracerighttp' => "\x{F8FC}", + 'bracerightvertical' => "\x{FE38}", + 'bracketleftbt' => "\x{F8F0}", + 'bracketleftex' => "\x{F8EF}", + 'bracketleftmonospace' => "\x{FF3B}", + 'bracketlefttp' => "\x{F8EE}", + 'bracketrightbt' => "\x{F8FB}", + 'bracketrightex' => "\x{F8FA}", + 'bracketrightmonospace' => "\x{FF3D}", + 'bracketrighttp' => "\x{F8F9}", + 'brevebelowcmb' => "\x{032E}", + 'brevecmb' => "\x{0306}", + 'breveinvertedbelowcmb' => "\x{032F}", + 'breveinvertedcmb' => "\x{0311}", + 'breveinverteddoublecmb' => "\x{0361}", + 'bridgebelowcmb' => "\x{032A}", + 'bridgeinvertedbelowcmb' => "\x{033A}", + 'bstroke' => "\x{0180}", + 'bsuperior' => "\x{F6EA}", + 'btopbar' => "\x{0183}", + 'buhiragana' => "\x{3076}", + 'bukatakana' => "\x{30D6}", + 'bulletinverse' => "\x{25D8}", + 'bulletoperator' => "\x{2219}", + 'bullseye' => "\x{25CE}", + 'caarmenian' => "\x{056E}", + 'cabengali' => "\x{099A}", + 'cadeva' => "\x{091A}", + 'cagujarati' => "\x{0A9A}", + 'cagurmukhi' => "\x{0A1A}", + 'calsquare' => "\x{3388}", + 'candrabindubengali' => "\x{0981}", + 'candrabinducmb' => "\x{0310}", + 'candrabindudeva' => "\x{0901}", + 'candrabindugujarati' => "\x{0A81}", + 'capslock' => "\x{21EA}", + 'careof' => "\x{2105}", + 'caronbelowcmb' => "\x{032C}", + 'caroncmb' => "\x{030C}", + 'cbopomofo' => "\x{3118}", + 'ccedillaacute' => "\x{1E09}", + 'ccircle' => "\x{24D2}", + 'ccurl' => "\x{0255}", + 'cdot' => "\x{010B}", + 'cdsquare' => "\x{33C5}", + 'cedillacmb' => "\x{0327}", + 'centigrade' => "\x{2103}", + 'centinferior' => "\x{F6DF}", + 'centmonospace' => "\x{FFE0}", + 'centoldstyle' => "\x{F7A2}", + 'centsuperior' => "\x{F6E0}", + 'chaarmenian' => "\x{0579}", + 'chabengali' => "\x{099B}", + 'chadeva' => "\x{091B}", + 'chagujarati' => "\x{0A9B}", + 'chagurmukhi' => "\x{0A1B}", + 'chbopomofo' => "\x{3114}", + 'cheabkhasiancyrillic' => "\x{04BD}", + 'checkmark' => "\x{2713}", + 'checyrillic' => "\x{0447}", + 'chedescenderabkhasiancyrillic' => "\x{04BF}", + 'chedescendercyrillic' => "\x{04B7}", + 'chedieresiscyrillic' => "\x{04F5}", + 'cheharmenian' => "\x{0573}", + 'chekhakassiancyrillic' => "\x{04CC}", + 'cheverticalstrokecyrillic' => "\x{04B9}", + 'chieuchacirclekorean' => "\x{3277}", + 'chieuchaparenkorean' => "\x{3217}", + 'chieuchcirclekorean' => "\x{3269}", + 'chieuchkorean' => "\x{314A}", + 'chieuchparenkorean' => "\x{3209}", + 'chochangthai' => "\x{0E0A}", + 'chochanthai' => "\x{0E08}", + 'chochingthai' => "\x{0E09}", + 'chochoethai' => "\x{0E0C}", + 'chook' => "\x{0188}", + 'cieucacirclekorean' => "\x{3276}", + 'cieucaparenkorean' => "\x{3216}", + 'cieuccirclekorean' => "\x{3268}", + 'cieuckorean' => "\x{3148}", + 'cieucparenkorean' => "\x{3208}", + 'cieucuparenkorean' => "\x{321C}", + 'circleot' => "\x{2299}", # Actual Adobe glyph list entry -- identified as typo, May 2008 + 'circledot' => "\x{2299}", # What it should have been + 'circlepostalmark' => "\x{3036}", + 'circlewithlefthalfblack' => "\x{25D0}", + 'circlewithrighthalfblack' => "\x{25D1}", + 'circumflexbelowcmb' => "\x{032D}", + 'circumflexcmb' => "\x{0302}", + 'clear' => "\x{2327}", + 'clickalveolar' => "\x{01C2}", + 'clickdental' => "\x{01C0}", + 'clicklateral' => "\x{01C1}", + 'clickretroflex' => "\x{01C3}", + 'clubsuitblack' => "\x{2663}", + 'clubsuitwhite' => "\x{2667}", + 'cmcubedsquare' => "\x{33A4}", + 'cmonospace' => "\x{FF43}", + 'cmsquaredsquare' => "\x{33A0}", + 'coarmenian' => "\x{0581}", + 'colonmonospace' => "\x{FF1A}", + 'colonsign' => "\x{20A1}", + 'colonsmall' => "\x{FE55}", + 'colontriangularhalfmod' => "\x{02D1}", + 'colontriangularmod' => "\x{02D0}", + 'commaabovecmb' => "\x{0313}", + 'commaaboverightcmb' => "\x{0315}", + 'commaaccent' => "\x{F6C3}", + 'commaarabic' => "\x{060C}", + 'commaarmenian' => "\x{055D}", + 'commainferior' => "\x{F6E1}", + 'commamonospace' => "\x{FF0C}", + 'commareversedabovecmb' => "\x{0314}", + 'commareversedmod' => "\x{02BD}", + 'commasmall' => "\x{FE50}", + 'commasuperior' => "\x{F6E2}", + 'commaturnedabovecmb' => "\x{0312}", + 'commaturnedmod' => "\x{02BB}", + 'compass' => "\x{263C}", + 'contourintegral' => "\x{222E}", + 'control' => "\x{2303}", + 'controlACK' => "\x{0006}", + 'controlBEL' => "\x{0007}", + 'controlBS' => "\x{0008}", + 'controlCAN' => "\x{0018}", + 'controlCR' => "\x{000D}", + 'controlDC1' => "\x{0011}", + 'controlDC2' => "\x{0012}", + 'controlDC3' => "\x{0013}", + 'controlDC4' => "\x{0014}", + 'controlDEL' => "\x{007F}", + 'controlDLE' => "\x{0010}", + 'controlEM' => "\x{0019}", + 'controlENQ' => "\x{0005}", + 'controlEOT' => "\x{0004}", + 'controlESC' => "\x{001B}", + 'controlETB' => "\x{0017}", + 'controlETX' => "\x{0003}", + 'controlFF' => "\x{000C}", + 'controlFS' => "\x{001C}", + 'controlGS' => "\x{001D}", + 'controlHT' => "\x{0009}", + 'controlLF' => "\x{000A}", + 'controlNAK' => "\x{0015}", + 'controlRS' => "\x{001E}", + 'controlSI' => "\x{000F}", + 'controlSO' => "\x{000E}", + 'controlSOT' => "\x{0002}", + 'controlSTX' => "\x{0001}", + 'controlSUB' => "\x{001A}", + 'controlSYN' => "\x{0016}", + 'controlUS' => "\x{001F}", + 'controlVT' => "\x{000B}", + 'copyrightsans' => "\x{F8E9}", + 'copyrightserif' => "\x{F6D9}", + 'cornerbracketleft' => "\x{300C}", + 'cornerbracketlefthalfwidth' => "\x{FF62}", + 'cornerbracketleftvertical' => "\x{FE41}", + 'cornerbracketright' => "\x{300D}", + 'cornerbracketrighthalfwidth' => "\x{FF63}", + 'cornerbracketrightvertical' => "\x{FE42}", + 'corporationsquare' => "\x{337F}", + 'cosquare' => "\x{33C7}", + 'coverkgsquare' => "\x{33C6}", + 'cparen' => "\x{249E}", + 'cruzeiro' => "\x{20A2}", + 'cstretched' => "\x{0297}", + 'curlyand' => "\x{22CF}", + 'curlyor' => "\x{22CE}", + 'cyrBreve' => "\x{F6D1}", + 'cyrFlex' => "\x{F6D2}", + 'cyrbreve' => "\x{F6D4}", + 'cyrflex' => "\x{F6D5}", + 'daarmenian' => "\x{0564}", + 'dabengali' => "\x{09A6}", + 'dadarabic' => "\x{0636}", + 'dadeva' => "\x{0926}", + 'dadfinalarabic' => "\x{FEBE}", + 'dadinitialarabic' => "\x{FEBF}", + 'dadmedialarabic' => "\x{FEC0}", + 'dagesh' => "\x{05BC}", + 'dageshhebrew' => "\x{05BC}", + 'dagujarati' => "\x{0AA6}", + 'dagurmukhi' => "\x{0A26}", + 'dahiragana' => "\x{3060}", + 'dakatakana' => "\x{30C0}", + 'dalarabic' => "\x{062F}", + 'dalet' => "\x{05D3}", + 'daletdagesh' => "\x{FB33}", + 'daletdageshhebrew' => "\x{FB33}", + 'dalethatafpatah' => "\x{05D3}\x{05B2}", + 'dalethatafpatahhebrew' => "\x{05D3}\x{05B2}", + 'dalethatafsegol' => "\x{05D3}\x{05B1}", + 'dalethatafsegolhebrew' => "\x{05D3}\x{05B1}", + 'dalethebrew' => "\x{05D3}", + 'dalethiriq' => "\x{05D3}\x{05B4}", + 'dalethiriqhebrew' => "\x{05D3}\x{05B4}", + 'daletholam' => "\x{05D3}\x{05B9}", + 'daletholamhebrew' => "\x{05D3}\x{05B9}", + 'daletpatah' => "\x{05D3}\x{05B7}", + 'daletpatahhebrew' => "\x{05D3}\x{05B7}", + 'daletqamats' => "\x{05D3}\x{05B8}", + 'daletqamatshebrew' => "\x{05D3}\x{05B8}", + 'daletqubuts' => "\x{05D3}\x{05BB}", + 'daletqubutshebrew' => "\x{05D3}\x{05BB}", + 'daletsegol' => "\x{05D3}\x{05B6}", + 'daletsegolhebrew' => "\x{05D3}\x{05B6}", + 'daletsheva' => "\x{05D3}\x{05B0}", + 'daletshevahebrew' => "\x{05D3}\x{05B0}", + 'dalettsere' => "\x{05D3}\x{05B5}", + 'dalettserehebrew' => "\x{05D3}\x{05B5}", + 'dalfinalarabic' => "\x{FEAA}", + 'dammaarabic' => "\x{064F}", + 'dammalowarabic' => "\x{064F}", + 'dammatanaltonearabic' => "\x{064C}", + 'dammatanarabic' => "\x{064C}", + 'danda' => "\x{0964}", + 'dargahebrew' => "\x{05A7}", + 'dargalefthebrew' => "\x{05A7}", + 'dasiapneumatacyrilliccmb' => "\x{0485}", + 'dblGrave' => "\x{F6D3}", + 'dblanglebracketleft' => "\x{300A}", + 'dblanglebracketleftvertical' => "\x{FE3D}", + 'dblanglebracketright' => "\x{300B}", + 'dblanglebracketrightvertical' => "\x{FE3E}", + 'dblarchinvertedbelowcmb' => "\x{032B}", + 'dblarrowleft' => "\x{21D4}", + 'dblarrowright' => "\x{21D2}", + 'dbldanda' => "\x{0965}", + 'dblgrave' => "\x{F6D6}", + 'dblgravecmb' => "\x{030F}", + 'dblintegral' => "\x{222C}", + 'dbllowline' => "\x{2017}", + 'dbllowlinecmb' => "\x{0333}", + 'dbloverlinecmb' => "\x{033F}", + 'dblprimemod' => "\x{02BA}", + 'dblverticalbar' => "\x{2016}", + 'dblverticallineabovecmb' => "\x{030E}", + 'dbopomofo' => "\x{3109}", + 'dbsquare' => "\x{33C8}", + 'dcedilla' => "\x{1E11}", + 'dcircle' => "\x{24D3}", + 'dcircumflexbelow' => "\x{1E13}", + 'ddabengali' => "\x{09A1}", + 'ddadeva' => "\x{0921}", + 'ddagujarati' => "\x{0AA1}", + 'ddagurmukhi' => "\x{0A21}", + 'ddalarabic' => "\x{0688}", + 'ddalfinalarabic' => "\x{FB89}", + 'dddhadeva' => "\x{095C}", + 'ddhabengali' => "\x{09A2}", + 'ddhadeva' => "\x{0922}", + 'ddhagujarati' => "\x{0AA2}", + 'ddhagurmukhi' => "\x{0A22}", + 'ddotaccent' => "\x{1E0B}", + 'ddotbelow' => "\x{1E0D}", + 'decimalseparatorarabic' => "\x{066B}", + 'decimalseparatorpersian' => "\x{066B}", + 'decyrillic' => "\x{0434}", + 'dehihebrew' => "\x{05AD}", + 'dehiragana' => "\x{3067}", + 'deicoptic' => "\x{03EF}", + 'dekatakana' => "\x{30C7}", + 'deleteleft' => "\x{232B}", + 'deleteright' => "\x{2326}", + 'deltaturned' => "\x{018D}", + 'denominatorminusonenumeratorbengali' => "\x{09F8}", + 'dezh' => "\x{02A4}", + 'dhabengali' => "\x{09A7}", + 'dhadeva' => "\x{0927}", + 'dhagujarati' => "\x{0AA7}", + 'dhagurmukhi' => "\x{0A27}", + 'dhook' => "\x{0257}", + 'dialytikatonos' => "\x{0385}", + 'dialytikatonoscmb' => "\x{0344}", + 'diamondsuitwhite' => "\x{2662}", + 'dieresisacute' => "\x{F6D7}", + 'dieresisbelowcmb' => "\x{0324}", + 'dieresiscmb' => "\x{0308}", + 'dieresisgrave' => "\x{F6D8}", + 'dihiragana' => "\x{3062}", + 'dikatakana' => "\x{30C2}", + 'dittomark' => "\x{3003}", + 'divides' => "\x{2223}", + 'divisionslash' => "\x{2215}", + 'djecyrillic' => "\x{0452}", + 'dlinebelow' => "\x{1E0F}", + 'dlsquare' => "\x{3397}", + 'dmacron' => "\x{0111}", + 'dmonospace' => "\x{FF44}", + 'dochadathai' => "\x{0E0E}", + 'dodekthai' => "\x{0E14}", + 'dohiragana' => "\x{3069}", + 'dokatakana' => "\x{30C9}", + 'dollarinferior' => "\x{F6E3}", + 'dollarmonospace' => "\x{FF04}", + 'dollaroldstyle' => "\x{F724}", + 'dollarsmall' => "\x{FE69}", + 'dollarsuperior' => "\x{F6E4}", + 'dorusquare' => "\x{3326}", + 'dotaccentcmb' => "\x{0307}", + 'dotbelowcmb' => "\x{0323}", + 'dotkatakana' => "\x{30FB}", + 'dotlessj' => "\x{F6BE}", + 'dotlessjstrokehook' => "\x{0284}", + 'dottedcircle' => "\x{25CC}", + 'doubleyodpatah' => "\x{FB1F}", + 'doubleyodpatahhebrew' => "\x{FB1F}", + 'downtackbelowcmb' => "\x{031E}", + 'downtackmod' => "\x{02D5}", + 'dparen' => "\x{249F}", + 'dsuperior' => "\x{F6EB}", + 'dtail' => "\x{0256}", + 'dtopbar' => "\x{018C}", + 'duhiragana' => "\x{3065}", + 'dukatakana' => "\x{30C5}", + 'dz' => "\x{01F3}", + 'dzaltone' => "\x{02A3}", + 'dzcaron' => "\x{01C6}", + 'dzcurl' => "\x{02A5}", + 'dzeabkhasiancyrillic' => "\x{04E1}", + 'dzecyrillic' => "\x{0455}", + 'dzhecyrillic' => "\x{045F}", + 'earth' => "\x{2641}", + 'ebengali' => "\x{098F}", + 'ebopomofo' => "\x{311C}", + 'ecandradeva' => "\x{090D}", + 'ecandragujarati' => "\x{0A8D}", + 'ecandravowelsigndeva' => "\x{0945}", + 'ecandravowelsigngujarati' => "\x{0AC5}", + 'ecedillabreve' => "\x{1E1D}", + 'echarmenian' => "\x{0565}", + 'echyiwnarmenian' => "\x{0587}", + 'ecircle' => "\x{24D4}", + 'ecircumflexacute' => "\x{1EBF}", + 'ecircumflexbelow' => "\x{1E19}", + 'ecircumflexdotbelow' => "\x{1EC7}", + 'ecircumflexgrave' => "\x{1EC1}", + 'ecircumflexhookabove' => "\x{1EC3}", + 'ecircumflextilde' => "\x{1EC5}", + 'ecyrillic' => "\x{0454}", + 'edblgrave' => "\x{0205}", + 'edeva' => "\x{090F}", + 'edot' => "\x{0117}", + 'edotbelow' => "\x{1EB9}", + 'eegurmukhi' => "\x{0A0F}", + 'eematragurmukhi' => "\x{0A47}", + 'efcyrillic' => "\x{0444}", + 'egujarati' => "\x{0A8F}", + 'eharmenian' => "\x{0567}", + 'ehbopomofo' => "\x{311D}", + 'ehiragana' => "\x{3048}", + 'ehookabove' => "\x{1EBB}", + 'eibopomofo' => "\x{311F}", + 'eightarabic' => "\x{0668}", + 'eightbengali' => "\x{09EE}", + 'eightcircle' => "\x{2467}", + 'eightcircleinversesansserif' => "\x{2791}", + 'eightdeva' => "\x{096E}", + 'eighteencircle' => "\x{2471}", + 'eighteenparen' => "\x{2485}", + 'eighteenperiod' => "\x{2499}", + 'eightgujarati' => "\x{0AEE}", + 'eightgurmukhi' => "\x{0A6E}", + 'eighthackarabic' => "\x{0668}", + 'eighthangzhou' => "\x{3028}", + 'eighthnotebeamed' => "\x{266B}", + 'eightideographicparen' => "\x{3227}", + 'eightinferior' => "\x{2088}", + 'eightmonospace' => "\x{FF18}", + 'eightoldstyle' => "\x{F738}", + 'eightparen' => "\x{247B}", + 'eightperiod' => "\x{248F}", + 'eightpersian' => "\x{06F8}", + 'eightroman' => "\x{2177}", + 'eightsuperior' => "\x{2078}", + 'eightthai' => "\x{0E58}", + 'einvertedbreve' => "\x{0207}", + 'eiotifiedcyrillic' => "\x{0465}", + 'ekatakana' => "\x{30A8}", + 'ekatakanahalfwidth' => "\x{FF74}", + 'ekonkargurmukhi' => "\x{0A74}", + 'ekorean' => "\x{3154}", + 'elcyrillic' => "\x{043B}", + 'elevencircle' => "\x{246A}", + 'elevenparen' => "\x{247E}", + 'elevenperiod' => "\x{2492}", + 'elevenroman' => "\x{217A}", + 'ellipsisvertical' => "\x{22EE}", + 'emacronacute' => "\x{1E17}", + 'emacrongrave' => "\x{1E15}", + 'emcyrillic' => "\x{043C}", + 'emdashvertical' => "\x{FE31}", + 'emonospace' => "\x{FF45}", + 'emphasismarkarmenian' => "\x{055B}", + 'enbopomofo' => "\x{3123}", + 'encyrillic' => "\x{043D}", + 'endashvertical' => "\x{FE32}", + 'endescendercyrillic' => "\x{04A3}", + 'engbopomofo' => "\x{3125}", + 'enghecyrillic' => "\x{04A5}", + 'enhookcyrillic' => "\x{04C8}", + 'enspace' => "\x{2002}", + 'eokorean' => "\x{3153}", + 'eopen' => "\x{025B}", + 'eopenclosed' => "\x{029A}", + 'eopenreversed' => "\x{025C}", + 'eopenreversedclosed' => "\x{025E}", + 'eopenreversedhook' => "\x{025D}", + 'eparen' => "\x{24A0}", + 'equalmonospace' => "\x{FF1D}", + 'equalsmall' => "\x{FE66}", + 'equalsuperior' => "\x{207C}", + 'erbopomofo' => "\x{3126}", + 'ercyrillic' => "\x{0440}", + 'ereversed' => "\x{0258}", + 'ereversedcyrillic' => "\x{044D}", + 'escyrillic' => "\x{0441}", + 'esdescendercyrillic' => "\x{04AB}", + 'esh' => "\x{0283}", + 'eshcurl' => "\x{0286}", + 'eshortdeva' => "\x{090E}", + 'eshortvowelsigndeva' => "\x{0946}", + 'eshreversedloop' => "\x{01AA}", + 'eshsquatreversed' => "\x{0285}", + 'esmallhiragana' => "\x{3047}", + 'esmallkatakana' => "\x{30A7}", + 'esmallkatakanahalfwidth' => "\x{FF6A}", + 'esuperior' => "\x{F6EC}", + 'etarmenian' => "\x{0568}", + 'etilde' => "\x{1EBD}", + 'etildebelow' => "\x{1E1B}", + 'etnahtafoukhhebrew' => "\x{0591}", + 'etnahtafoukhlefthebrew' => "\x{0591}", + 'etnahtahebrew' => "\x{0591}", + 'etnahtalefthebrew' => "\x{0591}", + 'eturned' => "\x{01DD}", + 'eukorean' => "\x{3161}", + 'euro' => "\x{20AC}", + 'evowelsignbengali' => "\x{09C7}", + 'evowelsigndeva' => "\x{0947}", + 'evowelsigngujarati' => "\x{0AC7}", + 'exclamarmenian' => "\x{055C}", + 'exclamdownsmall' => "\x{F7A1}", + 'exclammonospace' => "\x{FF01}", + 'exclamsmall' => "\x{F721}", + 'ezh' => "\x{0292}", + 'ezhcaron' => "\x{01EF}", + 'ezhcurl' => "\x{0293}", + 'ezhreversed' => "\x{01B9}", + 'ezhtail' => "\x{01BA}", + 'fadeva' => "\x{095E}", + 'fagurmukhi' => "\x{0A5E}", + 'fahrenheit' => "\x{2109}", + 'fathaarabic' => "\x{064E}", + 'fathalowarabic' => "\x{064E}", + 'fathatanarabic' => "\x{064B}", + 'fbopomofo' => "\x{3108}", + 'fcircle' => "\x{24D5}", + 'fdotaccent' => "\x{1E1F}", + 'feharabic' => "\x{0641}", + 'feharmenian' => "\x{0586}", + 'fehfinalarabic' => "\x{FED2}", + 'fehinitialarabic' => "\x{FED3}", + 'fehmedialarabic' => "\x{FED4}", + 'feicoptic' => "\x{03E5}", + 'fifteencircle' => "\x{246E}", + 'fifteenparen' => "\x{2482}", + 'fifteenperiod' => "\x{2496}", + 'finalkaf' => "\x{05DA}", + 'finalkafdagesh' => "\x{FB3A}", + 'finalkafdageshhebrew' => "\x{FB3A}", + 'finalkafhebrew' => "\x{05DA}", + 'finalkafqamats' => "\x{05DA}\x{05B8}", + 'finalkafqamatshebrew' => "\x{05DA}\x{05B8}", + 'finalkafsheva' => "\x{05DA}\x{05B0}", + 'finalkafshevahebrew' => "\x{05DA}\x{05B0}", + 'finalmem' => "\x{05DD}", + 'finalmemhebrew' => "\x{05DD}", + 'finalnun' => "\x{05DF}", + 'finalnunhebrew' => "\x{05DF}", + 'finalpe' => "\x{05E3}", + 'finalpehebrew' => "\x{05E3}", + 'finaltsadi' => "\x{05E5}", + 'finaltsadihebrew' => "\x{05E5}", + 'firsttonechinese' => "\x{02C9}", + 'fisheye' => "\x{25C9}", + 'fitacyrillic' => "\x{0473}", + 'fivearabic' => "\x{0665}", + 'fivebengali' => "\x{09EB}", + 'fivecircle' => "\x{2464}", + 'fivecircleinversesansserif' => "\x{278E}", + 'fivedeva' => "\x{096B}", + 'fivegujarati' => "\x{0AEB}", + 'fivegurmukhi' => "\x{0A6B}", + 'fivehackarabic' => "\x{0665}", + 'fivehangzhou' => "\x{3025}", + 'fiveideographicparen' => "\x{3224}", + 'fiveinferior' => "\x{2085}", + 'fivemonospace' => "\x{FF15}", + 'fiveoldstyle' => "\x{F735}", + 'fiveparen' => "\x{2478}", + 'fiveperiod' => "\x{248C}", + 'fivepersian' => "\x{06F5}", + 'fiveroman' => "\x{2174}", + 'fivesuperior' => "\x{2075}", + 'fivethai' => "\x{0E55}", + 'fmonospace' => "\x{FF46}", + 'fmsquare' => "\x{3399}", + 'fofanthai' => "\x{0E1F}", + 'fofathai' => "\x{0E1D}", + 'fongmanthai' => "\x{0E4F}", + 'forall' => "\x{2200}", + 'fourarabic' => "\x{0664}", + 'fourbengali' => "\x{09EA}", + 'fourcircle' => "\x{2463}", + 'fourcircleinversesansserif' => "\x{278D}", + 'fourdeva' => "\x{096A}", + 'fourgujarati' => "\x{0AEA}", + 'fourgurmukhi' => "\x{0A6A}", + 'fourhackarabic' => "\x{0664}", + 'fourhangzhou' => "\x{3024}", + 'fourideographicparen' => "\x{3223}", + 'fourinferior' => "\x{2084}", + 'fourmonospace' => "\x{FF14}", + 'fournumeratorbengali' => "\x{09F7}", + 'fouroldstyle' => "\x{F734}", + 'fourparen' => "\x{2477}", + 'fourperiod' => "\x{248B}", + 'fourpersian' => "\x{06F4}", + 'fourroman' => "\x{2173}", + 'foursuperior' => "\x{2074}", + 'fourteencircle' => "\x{246D}", + 'fourteenparen' => "\x{2481}", + 'fourteenperiod' => "\x{2495}", + 'fourthai' => "\x{0E54}", + 'fourthtonechinese' => "\x{02CB}", + 'fparen' => "\x{24A1}", + 'gabengali' => "\x{0997}", + 'gacute' => "\x{01F5}", + 'gadeva' => "\x{0917}", + 'gafarabic' => "\x{06AF}", + 'gaffinalarabic' => "\x{FB93}", + 'gafinitialarabic' => "\x{FB94}", + 'gafmedialarabic' => "\x{FB95}", + 'gagujarati' => "\x{0A97}", + 'gagurmukhi' => "\x{0A17}", + 'gahiragana' => "\x{304C}", + 'gakatakana' => "\x{30AC}", + 'gammalatinsmall' => "\x{0263}", + 'gammasuperior' => "\x{02E0}", + 'gangiacoptic' => "\x{03EB}", + 'gbopomofo' => "\x{310D}", + 'gcedilla' => "\x{0123}", + 'gcircle' => "\x{24D6}", + 'gdot' => "\x{0121}", + 'gecyrillic' => "\x{0433}", + 'gehiragana' => "\x{3052}", + 'gekatakana' => "\x{30B2}", + 'geometricallyequal' => "\x{2251}", + 'gereshaccenthebrew' => "\x{059C}", + 'gereshhebrew' => "\x{05F3}", + 'gereshmuqdamhebrew' => "\x{059D}", + 'gershayimaccenthebrew' => "\x{059E}", + 'gershayimhebrew' => "\x{05F4}", + 'getamark' => "\x{3013}", + 'ghabengali' => "\x{0998}", + 'ghadarmenian' => "\x{0572}", + 'ghadeva' => "\x{0918}", + 'ghagujarati' => "\x{0A98}", + 'ghagurmukhi' => "\x{0A18}", + 'ghainarabic' => "\x{063A}", + 'ghainfinalarabic' => "\x{FECE}", + 'ghaininitialarabic' => "\x{FECF}", + 'ghainmedialarabic' => "\x{FED0}", + 'ghemiddlehookcyrillic' => "\x{0495}", + 'ghestrokecyrillic' => "\x{0493}", + 'gheupturncyrillic' => "\x{0491}", + 'ghhadeva' => "\x{095A}", + 'ghhagurmukhi' => "\x{0A5A}", + 'ghook' => "\x{0260}", + 'ghzsquare' => "\x{3393}", + 'gihiragana' => "\x{304E}", + 'gikatakana' => "\x{30AE}", + 'gimarmenian' => "\x{0563}", + 'gimel' => "\x{05D2}", + 'gimeldagesh' => "\x{FB32}", + 'gimeldageshhebrew' => "\x{FB32}", + 'gimelhebrew' => "\x{05D2}", + 'gjecyrillic' => "\x{0453}", + 'glottalinvertedstroke' => "\x{01BE}", + 'glottalstop' => "\x{0294}", + 'glottalstopinverted' => "\x{0296}", + 'glottalstopmod' => "\x{02C0}", + 'glottalstopreversed' => "\x{0295}", + 'glottalstopreversedmod' => "\x{02C1}", + 'glottalstopreversedsuperior' => "\x{02E4}", + 'glottalstopstroke' => "\x{02A1}", + 'glottalstopstrokereversed' => "\x{02A2}", + 'gmacron' => "\x{1E21}", + 'gmonospace' => "\x{FF47}", + 'gohiragana' => "\x{3054}", + 'gokatakana' => "\x{30B4}", + 'gparen' => "\x{24A2}", + 'gpasquare' => "\x{33AC}", + 'gravebelowcmb' => "\x{0316}", + 'gravecmb' => "\x{0300}", + 'gravedeva' => "\x{0953}", + 'gravelowmod' => "\x{02CE}", + 'gravemonospace' => "\x{FF40}", + 'gravetonecmb' => "\x{0340}", + 'greaterequalorless' => "\x{22DB}", + 'greatermonospace' => "\x{FF1E}", + 'greaterorequivalent' => "\x{2273}", + 'greaterorless' => "\x{2277}", + 'greateroverequal' => "\x{2267}", + 'greatersmall' => "\x{FE65}", + 'gscript' => "\x{0261}", + 'gstroke' => "\x{01E5}", + 'guhiragana' => "\x{3050}", + 'gukatakana' => "\x{30B0}", + 'guramusquare' => "\x{3318}", + 'gysquare' => "\x{33C9}", + 'haabkhasiancyrillic' => "\x{04A9}", + 'haaltonearabic' => "\x{06C1}", + 'habengali' => "\x{09B9}", + 'hadescendercyrillic' => "\x{04B3}", + 'hadeva' => "\x{0939}", + 'hagujarati' => "\x{0AB9}", + 'hagurmukhi' => "\x{0A39}", + 'haharabic' => "\x{062D}", + 'hahfinalarabic' => "\x{FEA2}", + 'hahinitialarabic' => "\x{FEA3}", + 'hahiragana' => "\x{306F}", + 'hahmedialarabic' => "\x{FEA4}", + 'haitusquare' => "\x{332A}", + 'hakatakana' => "\x{30CF}", + 'hakatakanahalfwidth' => "\x{FF8A}", + 'halantgurmukhi' => "\x{0A4D}", + 'hamzaarabic' => "\x{0621}", + 'hamzadammaarabic' => "\x{0621}\x{064F}", + 'hamzadammatanarabic' => "\x{0621}\x{064C}", + 'hamzafathaarabic' => "\x{0621}\x{064E}", + 'hamzafathatanarabic' => "\x{0621}\x{064B}", + 'hamzalowarabic' => "\x{0621}", + 'hamzalowkasraarabic' => "\x{0621}\x{0650}", + 'hamzalowkasratanarabic' => "\x{0621}\x{064D}", + 'hamzasukunarabic' => "\x{0621}\x{0652}", + 'hangulfiller' => "\x{3164}", + 'hardsigncyrillic' => "\x{044A}", + 'harpoonleftbarbup' => "\x{21BC}", + 'harpoonrightbarbup' => "\x{21C0}", + 'hasquare' => "\x{33CA}", + 'hatafpatah' => "\x{05B2}", + 'hatafpatah16' => "\x{05B2}", + 'hatafpatah23' => "\x{05B2}", + 'hatafpatah2f' => "\x{05B2}", + 'hatafpatahhebrew' => "\x{05B2}", + 'hatafpatahnarrowhebrew' => "\x{05B2}", + 'hatafpatahquarterhebrew' => "\x{05B2}", + 'hatafpatahwidehebrew' => "\x{05B2}", + 'hatafqamats' => "\x{05B3}", + 'hatafqamats1b' => "\x{05B3}", + 'hatafqamats28' => "\x{05B3}", + 'hatafqamats34' => "\x{05B3}", + 'hatafqamatshebrew' => "\x{05B3}", + 'hatafqamatsnarrowhebrew' => "\x{05B3}", + 'hatafqamatsquarterhebrew' => "\x{05B3}", + 'hatafqamatswidehebrew' => "\x{05B3}", + 'hatafsegol' => "\x{05B1}", + 'hatafsegol17' => "\x{05B1}", + 'hatafsegol24' => "\x{05B1}", + 'hatafsegol30' => "\x{05B1}", + 'hatafsegolhebrew' => "\x{05B1}", + 'hatafsegolnarrowhebrew' => "\x{05B1}", + 'hatafsegolquarterhebrew' => "\x{05B1}", + 'hatafsegolwidehebrew' => "\x{05B1}", + 'hbopomofo' => "\x{310F}", + 'hbrevebelow' => "\x{1E2B}", + 'hcedilla' => "\x{1E29}", + 'hcircle' => "\x{24D7}", + 'hdieresis' => "\x{1E27}", + 'hdotaccent' => "\x{1E23}", + 'hdotbelow' => "\x{1E25}", + 'he' => "\x{05D4}", + 'heartsuitblack' => "\x{2665}", + 'heartsuitwhite' => "\x{2661}", + 'hedagesh' => "\x{FB34}", + 'hedageshhebrew' => "\x{FB34}", + 'hehaltonearabic' => "\x{06C1}", + 'heharabic' => "\x{0647}", + 'hehebrew' => "\x{05D4}", + 'hehfinalaltonearabic' => "\x{FBA7}", + 'hehfinalalttwoarabic' => "\x{FEEA}", + 'hehfinalarabic' => "\x{FEEA}", + 'hehhamzaabovefinalarabic' => "\x{FBA5}", + 'hehhamzaaboveisolatedarabic' => "\x{FBA4}", + 'hehinitialaltonearabic' => "\x{FBA8}", + 'hehinitialarabic' => "\x{FEEB}", + 'hehiragana' => "\x{3078}", + 'hehmedialaltonearabic' => "\x{FBA9}", + 'hehmedialarabic' => "\x{FEEC}", + 'heiseierasquare' => "\x{337B}", + 'hekatakana' => "\x{30D8}", + 'hekatakanahalfwidth' => "\x{FF8D}", + 'hekutaarusquare' => "\x{3336}", + 'henghook' => "\x{0267}", + 'herutusquare' => "\x{3339}", + 'het' => "\x{05D7}", + 'hethebrew' => "\x{05D7}", + 'hhook' => "\x{0266}", + 'hhooksuperior' => "\x{02B1}", + 'hieuhacirclekorean' => "\x{327B}", + 'hieuhaparenkorean' => "\x{321B}", + 'hieuhcirclekorean' => "\x{326D}", + 'hieuhkorean' => "\x{314E}", + 'hieuhparenkorean' => "\x{320D}", + 'hihiragana' => "\x{3072}", + 'hikatakana' => "\x{30D2}", + 'hikatakanahalfwidth' => "\x{FF8B}", + 'hiriq' => "\x{05B4}", + 'hiriq14' => "\x{05B4}", + 'hiriq21' => "\x{05B4}", + 'hiriq2d' => "\x{05B4}", + 'hiriqhebrew' => "\x{05B4}", + 'hiriqnarrowhebrew' => "\x{05B4}", + 'hiriqquarterhebrew' => "\x{05B4}", + 'hiriqwidehebrew' => "\x{05B4}", + 'hlinebelow' => "\x{1E96}", + 'hmonospace' => "\x{FF48}", + 'hoarmenian' => "\x{0570}", + 'hohipthai' => "\x{0E2B}", + 'hohiragana' => "\x{307B}", + 'hokatakana' => "\x{30DB}", + 'hokatakanahalfwidth' => "\x{FF8E}", + 'holam' => "\x{05B9}", + 'holam19' => "\x{05B9}", + 'holam26' => "\x{05B9}", + 'holam32' => "\x{05B9}", + 'holamhebrew' => "\x{05B9}", + 'holamnarrowhebrew' => "\x{05B9}", + 'holamquarterhebrew' => "\x{05B9}", + 'holamwidehebrew' => "\x{05B9}", + 'honokhukthai' => "\x{0E2E}", + 'hookcmb' => "\x{0309}", + 'hookpalatalizedbelowcmb' => "\x{0321}", + 'hookretroflexbelowcmb' => "\x{0322}", + 'hoonsquare' => "\x{3342}", + 'horicoptic' => "\x{03E9}", + 'horizontalbar' => "\x{2015}", + 'horncmb' => "\x{031B}", + 'hotsprings' => "\x{2668}", + 'hparen' => "\x{24A3}", + 'hsuperior' => "\x{02B0}", + 'hturned' => "\x{0265}", + 'huhiragana' => "\x{3075}", + 'huiitosquare' => "\x{3333}", + 'hukatakana' => "\x{30D5}", + 'hukatakanahalfwidth' => "\x{FF8C}", + 'hungarumlautcmb' => "\x{030B}", + 'hv' => "\x{0195}", + 'hypheninferior' => "\x{F6E5}", + 'hyphenmonospace' => "\x{FF0D}", + 'hyphensmall' => "\x{FE63}", + 'hyphensuperior' => "\x{F6E6}", + 'hyphentwo' => "\x{2010}", + 'iacyrillic' => "\x{044F}", + 'ibengali' => "\x{0987}", + 'ibopomofo' => "\x{3127}", + 'icaron' => "\x{01D0}", + 'icircle' => "\x{24D8}", + 'icyrillic' => "\x{0456}", + 'idblgrave' => "\x{0209}", + 'ideographearthcircle' => "\x{328F}", + 'ideographfirecircle' => "\x{328B}", + 'ideographicallianceparen' => "\x{323F}", + 'ideographiccallparen' => "\x{323A}", + 'ideographiccentrecircle' => "\x{32A5}", + 'ideographicclose' => "\x{3006}", + 'ideographiccomma' => "\x{3001}", + 'ideographiccommaleft' => "\x{FF64}", + 'ideographiccongratulationparen' => "\x{3237}", + 'ideographiccorrectcircle' => "\x{32A3}", + 'ideographicearthparen' => "\x{322F}", + 'ideographicenterpriseparen' => "\x{323D}", + 'ideographicexcellentcircle' => "\x{329D}", + 'ideographicfestivalparen' => "\x{3240}", + 'ideographicfinancialcircle' => "\x{3296}", + 'ideographicfinancialparen' => "\x{3236}", + 'ideographicfireparen' => "\x{322B}", + 'ideographichaveparen' => "\x{3232}", + 'ideographichighcircle' => "\x{32A4}", + 'ideographiciterationmark' => "\x{3005}", + 'ideographiclaborcircle' => "\x{3298}", + 'ideographiclaborparen' => "\x{3238}", + 'ideographicleftcircle' => "\x{32A7}", + 'ideographiclowcircle' => "\x{32A6}", + 'ideographicmedicinecircle' => "\x{32A9}", + 'ideographicmetalparen' => "\x{322E}", + 'ideographicmoonparen' => "\x{322A}", + 'ideographicnameparen' => "\x{3234}", + 'ideographicperiod' => "\x{3002}", + 'ideographicprintcircle' => "\x{329E}", + 'ideographicreachparen' => "\x{3243}", + 'ideographicrepresentparen' => "\x{3239}", + 'ideographicresourceparen' => "\x{323E}", + 'ideographicrightcircle' => "\x{32A8}", + 'ideographicsecretcircle' => "\x{3299}", + 'ideographicselfparen' => "\x{3242}", + 'ideographicsocietyparen' => "\x{3233}", + 'ideographicspace' => "\x{3000}", + 'ideographicspecialparen' => "\x{3235}", + 'ideographicstockparen' => "\x{3231}", + 'ideographicstudyparen' => "\x{323B}", + 'ideographicsunparen' => "\x{3230}", + 'ideographicsuperviseparen' => "\x{323C}", + 'ideographicwaterparen' => "\x{322C}", + 'ideographicwoodparen' => "\x{322D}", + 'ideographiczero' => "\x{3007}", + 'ideographmetalcircle' => "\x{328E}", + 'ideographmooncircle' => "\x{328A}", + 'ideographnamecircle' => "\x{3294}", + 'ideographsuncircle' => "\x{3290}", + 'ideographwatercircle' => "\x{328C}", + 'ideographwoodcircle' => "\x{328D}", + 'ideva' => "\x{0907}", + 'idieresisacute' => "\x{1E2F}", + 'idieresiscyrillic' => "\x{04E5}", + 'idotbelow' => "\x{1ECB}", + 'iebrevecyrillic' => "\x{04D7}", + 'iecyrillic' => "\x{0435}", + 'ieungacirclekorean' => "\x{3275}", + 'ieungaparenkorean' => "\x{3215}", + 'ieungcirclekorean' => "\x{3267}", + 'ieungkorean' => "\x{3147}", + 'ieungparenkorean' => "\x{3207}", + 'igujarati' => "\x{0A87}", + 'igurmukhi' => "\x{0A07}", + 'ihiragana' => "\x{3044}", + 'ihookabove' => "\x{1EC9}", + 'iibengali' => "\x{0988}", + 'iicyrillic' => "\x{0438}", + 'iideva' => "\x{0908}", + 'iigujarati' => "\x{0A88}", + 'iigurmukhi' => "\x{0A08}", + 'iimatragurmukhi' => "\x{0A40}", + 'iinvertedbreve' => "\x{020B}", + 'iishortcyrillic' => "\x{0439}", + 'iivowelsignbengali' => "\x{09C0}", + 'iivowelsigndeva' => "\x{0940}", + 'iivowelsigngujarati' => "\x{0AC0}", + 'ikatakana' => "\x{30A4}", + 'ikatakanahalfwidth' => "\x{FF72}", + 'ikorean' => "\x{3163}", + 'ilde' => "\x{02DC}", + 'iluyhebrew' => "\x{05AC}", + 'imacroncyrillic' => "\x{04E3}", + 'imageorapproximatelyequal' => "\x{2253}", + 'imatragurmukhi' => "\x{0A3F}", + 'imonospace' => "\x{FF49}", + 'increment' => "\x{2206}", + 'iniarmenian' => "\x{056B}", + 'integralbottom' => "\x{2321}", + 'integralex' => "\x{F8F5}", + 'integraltop' => "\x{2320}", + 'intisquare' => "\x{3305}", + 'iocyrillic' => "\x{0451}", + 'iotalatin' => "\x{0269}", + 'iparen' => "\x{24A4}", + 'irigurmukhi' => "\x{0A72}", + 'ismallhiragana' => "\x{3043}", + 'ismallkatakana' => "\x{30A3}", + 'ismallkatakanahalfwidth' => "\x{FF68}", + 'issharbengali' => "\x{09FA}", + 'istroke' => "\x{0268}", + 'isuperior' => "\x{F6ED}", + 'iterationhiragana' => "\x{309D}", + 'iterationkatakana' => "\x{30FD}", + 'itildebelow' => "\x{1E2D}", + 'iubopomofo' => "\x{3129}", + 'iucyrillic' => "\x{044E}", + 'ivowelsignbengali' => "\x{09BF}", + 'ivowelsigndeva' => "\x{093F}", + 'ivowelsigngujarati' => "\x{0ABF}", + 'izhitsacyrillic' => "\x{0475}", + 'izhitsadblgravecyrillic' => "\x{0477}", + 'jaarmenian' => "\x{0571}", + 'jabengali' => "\x{099C}", + 'jadeva' => "\x{091C}", + 'jagujarati' => "\x{0A9C}", + 'jagurmukhi' => "\x{0A1C}", + 'jbopomofo' => "\x{3110}", + 'jcaron' => "\x{01F0}", + 'jcircle' => "\x{24D9}", + 'jcrossedtail' => "\x{029D}", + 'jdotlessstroke' => "\x{025F}", + 'jecyrillic' => "\x{0458}", + 'jeemarabic' => "\x{062C}", + 'jeemfinalarabic' => "\x{FE9E}", + 'jeeminitialarabic' => "\x{FE9F}", + 'jeemmedialarabic' => "\x{FEA0}", + 'jeharabic' => "\x{0698}", + 'jehfinalarabic' => "\x{FB8B}", + 'jhabengali' => "\x{099D}", + 'jhadeva' => "\x{091D}", + 'jhagujarati' => "\x{0A9D}", + 'jhagurmukhi' => "\x{0A1D}", + 'jheharmenian' => "\x{057B}", + 'jis' => "\x{3004}", + 'jmonospace' => "\x{FF4A}", + 'jparen' => "\x{24A5}", + 'jsuperior' => "\x{02B2}", + 'kabashkircyrillic' => "\x{04A1}", + 'kabengali' => "\x{0995}", + 'kacute' => "\x{1E31}", + 'kacyrillic' => "\x{043A}", + 'kadescendercyrillic' => "\x{049B}", + 'kadeva' => "\x{0915}", + 'kaf' => "\x{05DB}", + 'kafarabic' => "\x{0643}", + 'kafdagesh' => "\x{FB3B}", + 'kafdageshhebrew' => "\x{FB3B}", + 'kaffinalarabic' => "\x{FEDA}", + 'kafhebrew' => "\x{05DB}", + 'kafinitialarabic' => "\x{FEDB}", + 'kafmedialarabic' => "\x{FEDC}", + 'kafrafehebrew' => "\x{FB4D}", + 'kagujarati' => "\x{0A95}", + 'kagurmukhi' => "\x{0A15}", + 'kahiragana' => "\x{304B}", + 'kahookcyrillic' => "\x{04C4}", + 'kakatakana' => "\x{30AB}", + 'kakatakanahalfwidth' => "\x{FF76}", + 'kappasymbolgreek' => "\x{03F0}", + 'kapyeounmieumkorean' => "\x{3171}", + 'kapyeounphieuphkorean' => "\x{3184}", + 'kapyeounpieupkorean' => "\x{3178}", + 'kapyeounssangpieupkorean' => "\x{3179}", + 'karoriisquare' => "\x{330D}", + 'kashidaautoarabic' => "\x{0640}", + 'kashidaautonosidebearingarabic' => "\x{0640}", + 'kasmallkatakana' => "\x{30F5}", + 'kasquare' => "\x{3384}", + 'kasraarabic' => "\x{0650}", + 'kasratanarabic' => "\x{064D}", + 'kastrokecyrillic' => "\x{049F}", + 'katahiraprolongmarkhalfwidth' => "\x{FF70}", + 'kaverticalstrokecyrillic' => "\x{049D}", + 'kbopomofo' => "\x{310E}", + 'kcalsquare' => "\x{3389}", + 'kcaron' => "\x{01E9}", + 'kcedilla' => "\x{0137}", + 'kcircle' => "\x{24DA}", + 'kdotbelow' => "\x{1E33}", + 'keharmenian' => "\x{0584}", + 'kehiragana' => "\x{3051}", + 'kekatakana' => "\x{30B1}", + 'kekatakanahalfwidth' => "\x{FF79}", + 'kenarmenian' => "\x{056F}", + 'kesmallkatakana' => "\x{30F6}", + 'khabengali' => "\x{0996}", + 'khacyrillic' => "\x{0445}", + 'khadeva' => "\x{0916}", + 'khagujarati' => "\x{0A96}", + 'khagurmukhi' => "\x{0A16}", + 'khaharabic' => "\x{062E}", + 'khahfinalarabic' => "\x{FEA6}", + 'khahinitialarabic' => "\x{FEA7}", + 'khahmedialarabic' => "\x{FEA8}", + 'kheicoptic' => "\x{03E7}", + 'khhadeva' => "\x{0959}", + 'khhagurmukhi' => "\x{0A59}", + 'khieukhacirclekorean' => "\x{3278}", + 'khieukhaparenkorean' => "\x{3218}", + 'khieukhcirclekorean' => "\x{326A}", + 'khieukhkorean' => "\x{314B}", + 'khieukhparenkorean' => "\x{320A}", + 'khokhaithai' => "\x{0E02}", + 'khokhonthai' => "\x{0E05}", + 'khokhuatthai' => "\x{0E03}", + 'khokhwaithai' => "\x{0E04}", + 'khomutthai' => "\x{0E5B}", + 'khook' => "\x{0199}", + 'khorakhangthai' => "\x{0E06}", + 'khzsquare' => "\x{3391}", + 'kihiragana' => "\x{304D}", + 'kikatakana' => "\x{30AD}", + 'kikatakanahalfwidth' => "\x{FF77}", + 'kiroguramusquare' => "\x{3315}", + 'kiromeetorusquare' => "\x{3316}", + 'kirosquare' => "\x{3314}", + 'kiyeokacirclekorean' => "\x{326E}", + 'kiyeokaparenkorean' => "\x{320E}", + 'kiyeokcirclekorean' => "\x{3260}", + 'kiyeokkorean' => "\x{3131}", + 'kiyeokparenkorean' => "\x{3200}", + 'kiyeoksioskorean' => "\x{3133}", + 'kjecyrillic' => "\x{045C}", + 'klinebelow' => "\x{1E35}", + 'klsquare' => "\x{3398}", + 'kmcubedsquare' => "\x{33A6}", + 'kmonospace' => "\x{FF4B}", + 'kmsquaredsquare' => "\x{33A2}", + 'kohiragana' => "\x{3053}", + 'kohmsquare' => "\x{33C0}", + 'kokaithai' => "\x{0E01}", + 'kokatakana' => "\x{30B3}", + 'kokatakanahalfwidth' => "\x{FF7A}", + 'kooposquare' => "\x{331E}", + 'koppacyrillic' => "\x{0481}", + 'koreanstandardsymbol' => "\x{327F}", + 'koroniscmb' => "\x{0343}", + 'kparen' => "\x{24A6}", + 'kpasquare' => "\x{33AA}", + 'ksicyrillic' => "\x{046F}", + 'ktsquare' => "\x{33CF}", + 'kturned' => "\x{029E}", + 'kuhiragana' => "\x{304F}", + 'kukatakana' => "\x{30AF}", + 'kukatakanahalfwidth' => "\x{FF78}", + 'kvsquare' => "\x{33B8}", + 'kwsquare' => "\x{33BE}", + 'labengali' => "\x{09B2}", + 'ladeva' => "\x{0932}", + 'lagujarati' => "\x{0AB2}", + 'lagurmukhi' => "\x{0A32}", + 'lakkhangyaothai' => "\x{0E45}", + 'lamaleffinalarabic' => "\x{FEFC}", + 'lamalefhamzaabovefinalarabic' => "\x{FEF8}", + 'lamalefhamzaaboveisolatedarabic' => "\x{FEF7}", + 'lamalefhamzabelowfinalarabic' => "\x{FEFA}", + 'lamalefhamzabelowisolatedarabic' => "\x{FEF9}", + 'lamalefisolatedarabic' => "\x{FEFB}", + 'lamalefmaddaabovefinalarabic' => "\x{FEF6}", + 'lamalefmaddaaboveisolatedarabic' => "\x{FEF5}", + 'lamarabic' => "\x{0644}", + 'lambdastroke' => "\x{019B}", + 'lamed' => "\x{05DC}", + 'lameddagesh' => "\x{FB3C}", + 'lameddageshhebrew' => "\x{FB3C}", + 'lamedhebrew' => "\x{05DC}", + 'lamedholam' => "\x{05DC}\x{05B9}", + 'lamedholamdagesh' => "\x{05DC}\x{05B9}\x{05BC}", + 'lamedholamdageshhebrew' => "\x{05DC}\x{05B9}\x{05BC}", + 'lamedholamhebrew' => "\x{05DC}\x{05B9}", + 'lamfinalarabic' => "\x{FEDE}", + 'lamhahinitialarabic' => "\x{FCCA}", + 'laminitialarabic' => "\x{FEDF}", + 'lamjeeminitialarabic' => "\x{FCC9}", + 'lamkhahinitialarabic' => "\x{FCCB}", + 'lamlamhehisolatedarabic' => "\x{FDF2}", + 'lammedialarabic' => "\x{FEE0}", + 'lammeemhahinitialarabic' => "\x{FD88}", + 'lammeeminitialarabic' => "\x{FCCC}", + 'lammeemjeeminitialarabic' => "\x{FEDF}\x{FEE4}\x{FEA0}", + 'lammeemkhahinitialarabic' => "\x{FEDF}\x{FEE4}\x{FEA8}", + 'largecircle' => "\x{25EF}", + 'lbar' => "\x{019A}", + 'lbelt' => "\x{026C}", + 'lbopomofo' => "\x{310C}", + 'lcedilla' => "\x{013C}", + 'lcircle' => "\x{24DB}", + 'lcircumflexbelow' => "\x{1E3D}", + 'ldotaccent' => "\x{0140}", + 'ldotbelow' => "\x{1E37}", + 'ldotbelowmacron' => "\x{1E39}", + 'leftangleabovecmb' => "\x{031A}", + 'lefttackbelowcmb' => "\x{0318}", + 'lessequalorgreater' => "\x{22DA}", + 'lessmonospace' => "\x{FF1C}", + 'lessorequivalent' => "\x{2272}", + 'lessorgreater' => "\x{2276}", + 'lessoverequal' => "\x{2266}", + 'lesssmall' => "\x{FE64}", + 'lezh' => "\x{026E}", + 'lhookretroflex' => "\x{026D}", + 'liwnarmenian' => "\x{056C}", + 'lj' => "\x{01C9}", + 'ljecyrillic' => "\x{0459}", + 'll' => "\x{F6C0}", + 'lladeva' => "\x{0933}", + 'llagujarati' => "\x{0AB3}", + 'llinebelow' => "\x{1E3B}", + 'llladeva' => "\x{0934}", + 'llvocalicbengali' => "\x{09E1}", + 'llvocalicdeva' => "\x{0961}", + 'llvocalicvowelsignbengali' => "\x{09E3}", + 'llvocalicvowelsigndeva' => "\x{0963}", + 'lmiddletilde' => "\x{026B}", + 'lmonospace' => "\x{FF4C}", + 'lmsquare' => "\x{33D0}", + 'lochulathai' => "\x{0E2C}", + 'logicalnotreversed' => "\x{2310}", + 'lolingthai' => "\x{0E25}", + 'lowlinecenterline' => "\x{FE4E}", + 'lowlinecmb' => "\x{0332}", + 'lowlinedashed' => "\x{FE4D}", + 'lparen' => "\x{24A7}", + 'lsquare' => "\x{2113}", + 'lsuperior' => "\x{F6EE}", + 'luthai' => "\x{0E26}", + 'lvocalicbengali' => "\x{098C}", + 'lvocalicdeva' => "\x{090C}", + 'lvocalicvowelsignbengali' => "\x{09E2}", + 'lvocalicvowelsigndeva' => "\x{0962}", + 'lxsquare' => "\x{33D3}", + 'mabengali' => "\x{09AE}", + 'macronbelowcmb' => "\x{0331}", + 'macroncmb' => "\x{0304}", + 'macronlowmod' => "\x{02CD}", + 'macronmonospace' => "\x{FFE3}", + 'macute' => "\x{1E3F}", + 'madeva' => "\x{092E}", + 'magujarati' => "\x{0AAE}", + 'magurmukhi' => "\x{0A2E}", + 'mahapakhhebrew' => "\x{05A4}", + 'mahapakhlefthebrew' => "\x{05A4}", + 'mahiragana' => "\x{307E}", + 'maichattawalowleftthai' => "\x{F895}", + 'maichattawalowrightthai' => "\x{F894}", + 'maichattawathai' => "\x{0E4B}", + 'maichattawaupperleftthai' => "\x{F893}", + 'maieklowleftthai' => "\x{F88C}", + 'maieklowrightthai' => "\x{F88B}", + 'maiekthai' => "\x{0E48}", + 'maiekupperleftthai' => "\x{F88A}", + 'maihanakatleftthai' => "\x{F884}", + 'maihanakatthai' => "\x{0E31}", + 'maitaikhuleftthai' => "\x{F889}", + 'maitaikhuthai' => "\x{0E47}", + 'maitholowleftthai' => "\x{F88F}", + 'maitholowrightthai' => "\x{F88E}", + 'maithothai' => "\x{0E49}", + 'maithoupperleftthai' => "\x{F88D}", + 'maitrilowleftthai' => "\x{F892}", + 'maitrilowrightthai' => "\x{F891}", + 'maitrithai' => "\x{0E4A}", + 'maitriupperleftthai' => "\x{F890}", + 'maiyamokthai' => "\x{0E46}", + 'makatakana' => "\x{30DE}", + 'makatakanahalfwidth' => "\x{FF8F}", + 'mansyonsquare' => "\x{3347}", + 'maqafhebrew' => "\x{05BE}", + 'mars' => "\x{2642}", + 'masoracirclehebrew' => "\x{05AF}", + 'masquare' => "\x{3383}", + 'mbopomofo' => "\x{3107}", + 'mbsquare' => "\x{33D4}", + 'mcircle' => "\x{24DC}", + 'mcubedsquare' => "\x{33A5}", + 'mdotaccent' => "\x{1E41}", + 'mdotbelow' => "\x{1E43}", + 'meemarabic' => "\x{0645}", + 'meemfinalarabic' => "\x{FEE2}", + 'meeminitialarabic' => "\x{FEE3}", + 'meemmedialarabic' => "\x{FEE4}", + 'meemmeeminitialarabic' => "\x{FCD1}", + 'meemmeemisolatedarabic' => "\x{FC48}", + 'meetorusquare' => "\x{334D}", + 'mehiragana' => "\x{3081}", + 'meizierasquare' => "\x{337E}", + 'mekatakana' => "\x{30E1}", + 'mekatakanahalfwidth' => "\x{FF92}", + 'mem' => "\x{05DE}", + 'memdagesh' => "\x{FB3E}", + 'memdageshhebrew' => "\x{FB3E}", + 'memhebrew' => "\x{05DE}", + 'menarmenian' => "\x{0574}", + 'merkhahebrew' => "\x{05A5}", + 'merkhakefulahebrew' => "\x{05A6}", + 'merkhakefulalefthebrew' => "\x{05A6}", + 'merkhalefthebrew' => "\x{05A5}", + 'mhook' => "\x{0271}", + 'mhzsquare' => "\x{3392}", + 'middledotkatakanahalfwidth' => "\x{FF65}", + 'middot' => "\x{00B7}", + 'mieumacirclekorean' => "\x{3272}", + 'mieumaparenkorean' => "\x{3212}", + 'mieumcirclekorean' => "\x{3264}", + 'mieumkorean' => "\x{3141}", + 'mieumpansioskorean' => "\x{3170}", + 'mieumparenkorean' => "\x{3204}", + 'mieumpieupkorean' => "\x{316E}", + 'mieumsioskorean' => "\x{316F}", + 'mihiragana' => "\x{307F}", + 'mikatakana' => "\x{30DF}", + 'mikatakanahalfwidth' => "\x{FF90}", + 'minusbelowcmb' => "\x{0320}", + 'minuscircle' => "\x{2296}", + 'minusmod' => "\x{02D7}", + 'minusplus' => "\x{2213}", + 'miribaarusquare' => "\x{334A}", + 'mirisquare' => "\x{3349}", + 'mlonglegturned' => "\x{0270}", + 'mlsquare' => "\x{3396}", + 'mmcubedsquare' => "\x{33A3}", + 'mmonospace' => "\x{FF4D}", + 'mmsquaredsquare' => "\x{339F}", + 'mohiragana' => "\x{3082}", + 'mohmsquare' => "\x{33C1}", + 'mokatakana' => "\x{30E2}", + 'mokatakanahalfwidth' => "\x{FF93}", + 'molsquare' => "\x{33D6}", + 'momathai' => "\x{0E21}", + 'moverssquare' => "\x{33A7}", + 'moverssquaredsquare' => "\x{33A8}", + 'mparen' => "\x{24A8}", + 'mpasquare' => "\x{33AB}", + 'mssquare' => "\x{33B3}", + 'msuperior' => "\x{F6EF}", + 'mturned' => "\x{026F}", + 'mu1' => "\x{00B5}", + 'muasquare' => "\x{3382}", + 'muchgreater' => "\x{226B}", + 'muchless' => "\x{226A}", + 'mufsquare' => "\x{338C}", + 'mugreek' => "\x{03BC}", + 'mugsquare' => "\x{338D}", + 'muhiragana' => "\x{3080}", + 'mukatakana' => "\x{30E0}", + 'mukatakanahalfwidth' => "\x{FF91}", + 'mulsquare' => "\x{3395}", + 'mumsquare' => "\x{339B}", + 'munahhebrew' => "\x{05A3}", + 'munahlefthebrew' => "\x{05A3}", + 'musicflatsign' => "\x{266D}", + 'musicsharpsign' => "\x{266F}", + 'mussquare' => "\x{33B2}", + 'muvsquare' => "\x{33B6}", + 'muwsquare' => "\x{33BC}", + 'mvmegasquare' => "\x{33B9}", + 'mvsquare' => "\x{33B7}", + 'mwmegasquare' => "\x{33BF}", + 'mwsquare' => "\x{33BD}", + 'nabengali' => "\x{09A8}", + 'nabla' => "\x{2207}", + 'nadeva' => "\x{0928}", + 'nagujarati' => "\x{0AA8}", + 'nagurmukhi' => "\x{0A28}", + 'nahiragana' => "\x{306A}", + 'nakatakana' => "\x{30CA}", + 'nakatakanahalfwidth' => "\x{FF85}", + 'nasquare' => "\x{3381}", + 'nbopomofo' => "\x{310B}", + 'nbspace' => "\x{00A0}", + 'ncedilla' => "\x{0146}", + 'ncircle' => "\x{24DD}", + 'ncircumflexbelow' => "\x{1E4B}", + 'ndotaccent' => "\x{1E45}", + 'ndotbelow' => "\x{1E47}", + 'nehiragana' => "\x{306D}", + 'nekatakana' => "\x{30CD}", + 'nekatakanahalfwidth' => "\x{FF88}", + 'newsheqelsign' => "\x{20AA}", + 'nfsquare' => "\x{338B}", + 'ngabengali' => "\x{0999}", + 'ngadeva' => "\x{0919}", + 'ngagujarati' => "\x{0A99}", + 'ngagurmukhi' => "\x{0A19}", + 'ngonguthai' => "\x{0E07}", + 'nhiragana' => "\x{3093}", + 'nhookleft' => "\x{0272}", + 'nhookretroflex' => "\x{0273}", + 'nieunacirclekorean' => "\x{326F}", + 'nieunaparenkorean' => "\x{320F}", + 'nieuncieuckorean' => "\x{3135}", + 'nieuncirclekorean' => "\x{3261}", + 'nieunhieuhkorean' => "\x{3136}", + 'nieunkorean' => "\x{3134}", + 'nieunpansioskorean' => "\x{3168}", + 'nieunparenkorean' => "\x{3201}", + 'nieunsioskorean' => "\x{3167}", + 'nieuntikeutkorean' => "\x{3166}", + 'nihiragana' => "\x{306B}", + 'nikatakana' => "\x{30CB}", + 'nikatakanahalfwidth' => "\x{FF86}", + 'nikhahitleftthai' => "\x{F899}", + 'nikhahitthai' => "\x{0E4D}", + 'ninearabic' => "\x{0669}", + 'ninebengali' => "\x{09EF}", + 'ninecircle' => "\x{2468}", + 'ninecircleinversesansserif' => "\x{2792}", + 'ninedeva' => "\x{096F}", + 'ninegujarati' => "\x{0AEF}", + 'ninegurmukhi' => "\x{0A6F}", + 'ninehackarabic' => "\x{0669}", + 'ninehangzhou' => "\x{3029}", + 'nineideographicparen' => "\x{3228}", + 'nineinferior' => "\x{2089}", + 'ninemonospace' => "\x{FF19}", + 'nineoldstyle' => "\x{F739}", + 'nineparen' => "\x{247C}", + 'nineperiod' => "\x{2490}", + 'ninepersian' => "\x{06F9}", + 'nineroman' => "\x{2178}", + 'ninesuperior' => "\x{2079}", + 'nineteencircle' => "\x{2472}", + 'nineteenparen' => "\x{2486}", + 'nineteenperiod' => "\x{249A}", + 'ninethai' => "\x{0E59}", + 'nj' => "\x{01CC}", + 'njecyrillic' => "\x{045A}", + 'nkatakana' => "\x{30F3}", + 'nkatakanahalfwidth' => "\x{FF9D}", + 'nlegrightlong' => "\x{019E}", + 'nlinebelow' => "\x{1E49}", + 'nmonospace' => "\x{FF4E}", + 'nmsquare' => "\x{339A}", + 'nnabengali' => "\x{09A3}", + 'nnadeva' => "\x{0923}", + 'nnagujarati' => "\x{0AA3}", + 'nnagurmukhi' => "\x{0A23}", + 'nnnadeva' => "\x{0929}", + 'nohiragana' => "\x{306E}", + 'nokatakana' => "\x{30CE}", + 'nokatakanahalfwidth' => "\x{FF89}", + 'nonbreakingspace' => "\x{00A0}", + 'nonenthai' => "\x{0E13}", + 'nonuthai' => "\x{0E19}", + 'noonarabic' => "\x{0646}", + 'noonfinalarabic' => "\x{FEE6}", + 'noonghunnaarabic' => "\x{06BA}", + 'noonghunnafinalarabic' => "\x{FB9F}", + 'noonhehinitialarabic' => "\x{FEE7}\x{FEEC}", + 'nooninitialarabic' => "\x{FEE7}", + 'noonjeeminitialarabic' => "\x{FCD2}", + 'noonjeemisolatedarabic' => "\x{FC4B}", + 'noonmedialarabic' => "\x{FEE8}", + 'noonmeeminitialarabic' => "\x{FCD5}", + 'noonmeemisolatedarabic' => "\x{FC4E}", + 'noonnoonfinalarabic' => "\x{FC8D}", + 'notcontains' => "\x{220C}", + 'notelementof' => "\x{2209}", + 'notgreater' => "\x{226F}", + 'notgreaternorequal' => "\x{2271}", + 'notgreaternorless' => "\x{2279}", + 'notidentical' => "\x{2262}", + 'notless' => "\x{226E}", + 'notlessnorequal' => "\x{2270}", + 'notparallel' => "\x{2226}", + 'notprecedes' => "\x{2280}", + 'notsucceeds' => "\x{2281}", + 'notsuperset' => "\x{2285}", + 'nowarmenian' => "\x{0576}", + 'nparen' => "\x{24A9}", + 'nssquare' => "\x{33B1}", + 'nsuperior' => "\x{207F}", + 'nuhiragana' => "\x{306C}", + 'nukatakana' => "\x{30CC}", + 'nukatakanahalfwidth' => "\x{FF87}", + 'nuktabengali' => "\x{09BC}", + 'nuktadeva' => "\x{093C}", + 'nuktagujarati' => "\x{0ABC}", + 'nuktagurmukhi' => "\x{0A3C}", + 'numbersignmonospace' => "\x{FF03}", + 'numbersignsmall' => "\x{FE5F}", + 'numeralsigngreek' => "\x{0374}", + 'numeralsignlowergreek' => "\x{0375}", + 'numero' => "\x{2116}", + 'nun' => "\x{05E0}", + 'nundagesh' => "\x{FB40}", + 'nundageshhebrew' => "\x{FB40}", + 'nunhebrew' => "\x{05E0}", + 'nvsquare' => "\x{33B5}", + 'nwsquare' => "\x{33BB}", + 'nyabengali' => "\x{099E}", + 'nyadeva' => "\x{091E}", + 'nyagujarati' => "\x{0A9E}", + 'nyagurmukhi' => "\x{0A1E}", + 'oangthai' => "\x{0E2D}", + 'obarred' => "\x{0275}", + 'obarredcyrillic' => "\x{04E9}", + 'obarreddieresiscyrillic' => "\x{04EB}", + 'obengali' => "\x{0993}", + 'obopomofo' => "\x{311B}", + 'ocandradeva' => "\x{0911}", + 'ocandragujarati' => "\x{0A91}", + 'ocandravowelsigndeva' => "\x{0949}", + 'ocandravowelsigngujarati' => "\x{0AC9}", + 'ocaron' => "\x{01D2}", + 'ocircle' => "\x{24DE}", + 'ocircumflexacute' => "\x{1ED1}", + 'ocircumflexdotbelow' => "\x{1ED9}", + 'ocircumflexgrave' => "\x{1ED3}", + 'ocircumflexhookabove' => "\x{1ED5}", + 'ocircumflextilde' => "\x{1ED7}", + 'ocyrillic' => "\x{043E}", + 'odblacute' => "\x{0151}", + 'odblgrave' => "\x{020D}", + 'odeva' => "\x{0913}", + 'odieresiscyrillic' => "\x{04E7}", + 'odotbelow' => "\x{1ECD}", + 'oekorean' => "\x{315A}", + 'ogonekcmb' => "\x{0328}", + 'ogujarati' => "\x{0A93}", + 'oharmenian' => "\x{0585}", + 'ohiragana' => "\x{304A}", + 'ohookabove' => "\x{1ECF}", + 'ohornacute' => "\x{1EDB}", + 'ohorndotbelow' => "\x{1EE3}", + 'ohorngrave' => "\x{1EDD}", + 'ohornhookabove' => "\x{1EDF}", + 'ohorntilde' => "\x{1EE1}", + 'oi' => "\x{01A3}", + 'oinvertedbreve' => "\x{020F}", + 'okatakana' => "\x{30AA}", + 'okatakanahalfwidth' => "\x{FF75}", + 'okorean' => "\x{3157}", + 'olehebrew' => "\x{05AB}", + 'omacronacute' => "\x{1E53}", + 'omacrongrave' => "\x{1E51}", + 'omdeva' => "\x{0950}", + 'omegacyrillic' => "\x{0461}", + 'omegalatinclosed' => "\x{0277}", + 'omegaroundcyrillic' => "\x{047B}", + 'omegatitlocyrillic' => "\x{047D}", + 'omgujarati' => "\x{0AD0}", + 'omonospace' => "\x{FF4F}", + 'onearabic' => "\x{0661}", + 'onebengali' => "\x{09E7}", + 'onecircle' => "\x{2460}", + 'onecircleinversesansserif' => "\x{278A}", + 'onedeva' => "\x{0967}", + 'onefitted' => "\x{F6DC}", + 'onegujarati' => "\x{0AE7}", + 'onegurmukhi' => "\x{0A67}", + 'onehackarabic' => "\x{0661}", + 'onehangzhou' => "\x{3021}", + 'oneideographicparen' => "\x{3220}", + 'oneinferior' => "\x{2081}", + 'onemonospace' => "\x{FF11}", + 'onenumeratorbengali' => "\x{09F4}", + 'oneoldstyle' => "\x{F731}", + 'oneparen' => "\x{2474}", + 'oneperiod' => "\x{2488}", + 'onepersian' => "\x{06F1}", + 'oneroman' => "\x{2170}", + 'onethai' => "\x{0E51}", + 'oogonek' => "\x{01EB}", + 'oogonekmacron' => "\x{01ED}", + 'oogurmukhi' => "\x{0A13}", + 'oomatragurmukhi' => "\x{0A4B}", + 'oopen' => "\x{0254}", + 'oparen' => "\x{24AA}", + 'option' => "\x{2325}", + 'oshortdeva' => "\x{0912}", + 'oshortvowelsigndeva' => "\x{094A}", + 'osmallhiragana' => "\x{3049}", + 'osmallkatakana' => "\x{30A9}", + 'osmallkatakanahalfwidth' => "\x{FF6B}", + 'ostrokeacute' => "\x{01FF}", + 'osuperior' => "\x{F6F0}", + 'otcyrillic' => "\x{047F}", + 'otildeacute' => "\x{1E4D}", + 'otildedieresis' => "\x{1E4F}", + 'oubopomofo' => "\x{3121}", + 'overline' => "\x{203E}", + 'overlinecenterline' => "\x{FE4A}", + 'overlinecmb' => "\x{0305}", + 'overlinedashed' => "\x{FE49}", + 'overlinedblwavy' => "\x{FE4C}", + 'overlinewavy' => "\x{FE4B}", + 'overscore' => "\x{00AF}", + 'ovowelsignbengali' => "\x{09CB}", + 'ovowelsigndeva' => "\x{094B}", + 'ovowelsigngujarati' => "\x{0ACB}", + 'paampssquare' => "\x{3380}", + 'paasentosquare' => "\x{332B}", + 'pabengali' => "\x{09AA}", + 'pacute' => "\x{1E55}", + 'padeva' => "\x{092A}", + 'pagedown' => "\x{21DF}", + 'pageup' => "\x{21DE}", + 'pagujarati' => "\x{0AAA}", + 'pagurmukhi' => "\x{0A2A}", + 'pahiragana' => "\x{3071}", + 'paiyannoithai' => "\x{0E2F}", + 'pakatakana' => "\x{30D1}", + 'palatalizationcyrilliccmb' => "\x{0484}", + 'palochkacyrillic' => "\x{04C0}", + 'pansioskorean' => "\x{317F}", + 'parallel' => "\x{2225}", + 'parenleftaltonearabic' => "\x{FD3E}", + 'parenleftbt' => "\x{F8ED}", + 'parenleftex' => "\x{F8EC}", + 'parenleftinferior' => "\x{208D}", + 'parenleftmonospace' => "\x{FF08}", + 'parenleftsmall' => "\x{FE59}", + 'parenleftsuperior' => "\x{207D}", + 'parenlefttp' => "\x{F8EB}", + 'parenleftvertical' => "\x{FE35}", + 'parenrightaltonearabic' => "\x{FD3F}", + 'parenrightbt' => "\x{F8F8}", + 'parenrightex' => "\x{F8F7}", + 'parenrightinferior' => "\x{208E}", + 'parenrightmonospace' => "\x{FF09}", + 'parenrightsmall' => "\x{FE5A}", + 'parenrightsuperior' => "\x{207E}", + 'parenrighttp' => "\x{F8F6}", + 'parenrightvertical' => "\x{FE36}", + 'paseqhebrew' => "\x{05C0}", + 'pashtahebrew' => "\x{0599}", + 'pasquare' => "\x{33A9}", + 'patah' => "\x{05B7}", + 'patah11' => "\x{05B7}", + 'patah1d' => "\x{05B7}", + 'patah2a' => "\x{05B7}", + 'patahhebrew' => "\x{05B7}", + 'patahnarrowhebrew' => "\x{05B7}", + 'patahquarterhebrew' => "\x{05B7}", + 'patahwidehebrew' => "\x{05B7}", + 'pazerhebrew' => "\x{05A1}", + 'pbopomofo' => "\x{3106}", + 'pcircle' => "\x{24DF}", + 'pdotaccent' => "\x{1E57}", + 'pe' => "\x{05E4}", + 'pecyrillic' => "\x{043F}", + 'pedagesh' => "\x{FB44}", + 'pedageshhebrew' => "\x{FB44}", + 'peezisquare' => "\x{333B}", + 'pefinaldageshhebrew' => "\x{FB43}", + 'peharabic' => "\x{067E}", + 'peharmenian' => "\x{057A}", + 'pehebrew' => "\x{05E4}", + 'pehfinalarabic' => "\x{FB57}", + 'pehinitialarabic' => "\x{FB58}", + 'pehiragana' => "\x{307A}", + 'pehmedialarabic' => "\x{FB59}", + 'pekatakana' => "\x{30DA}", + 'pemiddlehookcyrillic' => "\x{04A7}", + 'perafehebrew' => "\x{FB4E}", + 'percentarabic' => "\x{066A}", + 'percentmonospace' => "\x{FF05}", + 'percentsmall' => "\x{FE6A}", + 'periodarmenian' => "\x{0589}", + 'periodhalfwidth' => "\x{FF61}", + 'periodinferior' => "\x{F6E7}", + 'periodmonospace' => "\x{FF0E}", + 'periodsmall' => "\x{FE52}", + 'periodsuperior' => "\x{F6E8}", + 'perispomenigreekcmb' => "\x{0342}", + 'pfsquare' => "\x{338A}", + 'phabengali' => "\x{09AB}", + 'phadeva' => "\x{092B}", + 'phagujarati' => "\x{0AAB}", + 'phagurmukhi' => "\x{0A2B}", + 'phieuphacirclekorean' => "\x{327A}", + 'phieuphaparenkorean' => "\x{321A}", + 'phieuphcirclekorean' => "\x{326C}", + 'phieuphkorean' => "\x{314D}", + 'phieuphparenkorean' => "\x{320C}", + 'philatin' => "\x{0278}", + 'phinthuthai' => "\x{0E3A}", + 'phisymbolgreek' => "\x{03D5}", + 'phook' => "\x{01A5}", + 'phophanthai' => "\x{0E1E}", + 'phophungthai' => "\x{0E1C}", + 'phosamphaothai' => "\x{0E20}", + 'pieupacirclekorean' => "\x{3273}", + 'pieupaparenkorean' => "\x{3213}", + 'pieupcieuckorean' => "\x{3176}", + 'pieupcirclekorean' => "\x{3265}", + 'pieupkiyeokkorean' => "\x{3172}", + 'pieupkorean' => "\x{3142}", + 'pieupparenkorean' => "\x{3205}", + 'pieupsioskiyeokkorean' => "\x{3174}", + 'pieupsioskorean' => "\x{3144}", + 'pieupsiostikeutkorean' => "\x{3175}", + 'pieupthieuthkorean' => "\x{3177}", + 'pieuptikeutkorean' => "\x{3173}", + 'pihiragana' => "\x{3074}", + 'pikatakana' => "\x{30D4}", + 'pisymbolgreek' => "\x{03D6}", + 'piwrarmenian' => "\x{0583}", + 'plusbelowcmb' => "\x{031F}", + 'pluscircle' => "\x{2295}", + 'plusmod' => "\x{02D6}", + 'plusmonospace' => "\x{FF0B}", + 'plussmall' => "\x{FE62}", + 'plussuperior' => "\x{207A}", + 'pmonospace' => "\x{FF50}", + 'pmsquare' => "\x{33D8}", + 'pohiragana' => "\x{307D}", + 'pointingindexdownwhite' => "\x{261F}", + 'pointingindexleftwhite' => "\x{261C}", + 'pointingindexrightwhite' => "\x{261E}", + 'pointingindexupwhite' => "\x{261D}", + 'pokatakana' => "\x{30DD}", + 'poplathai' => "\x{0E1B}", + 'postalmark' => "\x{3012}", + 'postalmarkface' => "\x{3020}", + 'pparen' => "\x{24AB}", + 'precedes' => "\x{227A}", + 'primemod' => "\x{02B9}", + 'primereversed' => "\x{2035}", + 'projective' => "\x{2305}", + 'prolongedkana' => "\x{30FC}", + 'propellor' => "\x{2318}", + 'proportion' => "\x{2237}", + 'psicyrillic' => "\x{0471}", + 'psilipneumatacyrilliccmb' => "\x{0486}", + 'pssquare' => "\x{33B0}", + 'puhiragana' => "\x{3077}", + 'pukatakana' => "\x{30D7}", + 'pvsquare' => "\x{33B4}", + 'pwsquare' => "\x{33BA}", + 'qadeva' => "\x{0958}", + 'qadmahebrew' => "\x{05A8}", + 'qafarabic' => "\x{0642}", + 'qaffinalarabic' => "\x{FED6}", + 'qafinitialarabic' => "\x{FED7}", + 'qafmedialarabic' => "\x{FED8}", + 'qamats' => "\x{05B8}", + 'qamats10' => "\x{05B8}", + 'qamats1a' => "\x{05B8}", + 'qamats1c' => "\x{05B8}", + 'qamats27' => "\x{05B8}", + 'qamats29' => "\x{05B8}", + 'qamats33' => "\x{05B8}", + 'qamatsde' => "\x{05B8}", + 'qamatshebrew' => "\x{05B8}", + 'qamatsnarrowhebrew' => "\x{05B8}", + 'qamatsqatanhebrew' => "\x{05B8}", + 'qamatsqatannarrowhebrew' => "\x{05B8}", + 'qamatsqatanquarterhebrew' => "\x{05B8}", + 'qamatsqatanwidehebrew' => "\x{05B8}", + 'qamatsquarterhebrew' => "\x{05B8}", + 'qamatswidehebrew' => "\x{05B8}", + 'qarneyparahebrew' => "\x{059F}", + 'qbopomofo' => "\x{3111}", + 'qcircle' => "\x{24E0}", + 'qhook' => "\x{02A0}", + 'qmonospace' => "\x{FF51}", + 'qof' => "\x{05E7}", + 'qofdagesh' => "\x{FB47}", + 'qofdageshhebrew' => "\x{FB47}", + 'qofhatafpatah' => "\x{05E7}\x{05B2}", + 'qofhatafpatahhebrew' => "\x{05E7}\x{05B2}", + 'qofhatafsegol' => "\x{05E7}\x{05B1}", + 'qofhatafsegolhebrew' => "\x{05E7}\x{05B1}", + 'qofhebrew' => "\x{05E7}", + 'qofhiriq' => "\x{05E7}\x{05B4}", + 'qofhiriqhebrew' => "\x{05E7}\x{05B4}", + 'qofholam' => "\x{05E7}\x{05B9}", + 'qofholamhebrew' => "\x{05E7}\x{05B9}", + 'qofpatah' => "\x{05E7}\x{05B7}", + 'qofpatahhebrew' => "\x{05E7}\x{05B7}", + 'qofqamats' => "\x{05E7}\x{05B8}", + 'qofqamatshebrew' => "\x{05E7}\x{05B8}", + 'qofqubuts' => "\x{05E7}\x{05BB}", + 'qofqubutshebrew' => "\x{05E7}\x{05BB}", + 'qofsegol' => "\x{05E7}\x{05B6}", + 'qofsegolhebrew' => "\x{05E7}\x{05B6}", + 'qofsheva' => "\x{05E7}\x{05B0}", + 'qofshevahebrew' => "\x{05E7}\x{05B0}", + 'qoftsere' => "\x{05E7}\x{05B5}", + 'qoftserehebrew' => "\x{05E7}\x{05B5}", + 'qparen' => "\x{24AC}", + 'quarternote' => "\x{2669}", + 'qubuts' => "\x{05BB}", + 'qubuts18' => "\x{05BB}", + 'qubuts25' => "\x{05BB}", + 'qubuts31' => "\x{05BB}", + 'qubutshebrew' => "\x{05BB}", + 'qubutsnarrowhebrew' => "\x{05BB}", + 'qubutsquarterhebrew' => "\x{05BB}", + 'qubutswidehebrew' => "\x{05BB}", + 'questionarabic' => "\x{061F}", + 'questionarmenian' => "\x{055E}", + 'questiondownsmall' => "\x{F7BF}", + 'questiongreek' => "\x{037E}", + 'questionmonospace' => "\x{FF1F}", + 'questionsmall' => "\x{F73F}", + 'quotedblmonospace' => "\x{FF02}", + 'quotedblprime' => "\x{301E}", + 'quotedblprimereversed' => "\x{301D}", + 'quoteleftreversed' => "\x{201B}", + 'quoterightn' => "\x{0149}", + 'quotesinglemonospace' => "\x{FF07}", + 'raarmenian' => "\x{057C}", + 'rabengali' => "\x{09B0}", + 'radeva' => "\x{0930}", + 'radicalex' => "\x{F8E5}", + 'radoverssquare' => "\x{33AE}", + 'radoverssquaredsquare' => "\x{33AF}", + 'radsquare' => "\x{33AD}", + 'rafe' => "\x{05BF}", + 'rafehebrew' => "\x{05BF}", + 'ragujarati' => "\x{0AB0}", + 'ragurmukhi' => "\x{0A30}", + 'rahiragana' => "\x{3089}", + 'rakatakana' => "\x{30E9}", + 'rakatakanahalfwidth' => "\x{FF97}", + 'ralowerdiagonalbengali' => "\x{09F1}", + 'ramiddlediagonalbengali' => "\x{09F0}", + 'ramshorn' => "\x{0264}", + 'ratio' => "\x{2236}", + 'rbopomofo' => "\x{3116}", + 'rcedilla' => "\x{0157}", + 'rcircle' => "\x{24E1}", + 'rdblgrave' => "\x{0211}", + 'rdotaccent' => "\x{1E59}", + 'rdotbelow' => "\x{1E5B}", + 'rdotbelowmacron' => "\x{1E5D}", + 'referencemark' => "\x{203B}", + 'registersans' => "\x{F8E8}", + 'registerserif' => "\x{F6DA}", + 'reharabic' => "\x{0631}", + 'reharmenian' => "\x{0580}", + 'rehfinalarabic' => "\x{FEAE}", + 'rehiragana' => "\x{308C}", + 'rehyehaleflamarabic' => "\x{0631}\x{FEF3}\x{FE8E}\x{0644}", + 'rekatakana' => "\x{30EC}", + 'rekatakanahalfwidth' => "\x{FF9A}", + 'resh' => "\x{05E8}", + 'reshdageshhebrew' => "\x{FB48}", + 'reshhatafpatah' => "\x{05E8}\x{05B2}", + 'reshhatafpatahhebrew' => "\x{05E8}\x{05B2}", + 'reshhatafsegol' => "\x{05E8}\x{05B1}", + 'reshhatafsegolhebrew' => "\x{05E8}\x{05B1}", + 'reshhebrew' => "\x{05E8}", + 'reshhiriq' => "\x{05E8}\x{05B4}", + 'reshhiriqhebrew' => "\x{05E8}\x{05B4}", + 'reshholam' => "\x{05E8}\x{05B9}", + 'reshholamhebrew' => "\x{05E8}\x{05B9}", + 'reshpatah' => "\x{05E8}\x{05B7}", + 'reshpatahhebrew' => "\x{05E8}\x{05B7}", + 'reshqamats' => "\x{05E8}\x{05B8}", + 'reshqamatshebrew' => "\x{05E8}\x{05B8}", + 'reshqubuts' => "\x{05E8}\x{05BB}", + 'reshqubutshebrew' => "\x{05E8}\x{05BB}", + 'reshsegol' => "\x{05E8}\x{05B6}", + 'reshsegolhebrew' => "\x{05E8}\x{05B6}", + 'reshsheva' => "\x{05E8}\x{05B0}", + 'reshshevahebrew' => "\x{05E8}\x{05B0}", + 'reshtsere' => "\x{05E8}\x{05B5}", + 'reshtserehebrew' => "\x{05E8}\x{05B5}", + 'reversedtilde' => "\x{223D}", + 'reviahebrew' => "\x{0597}", + 'reviamugrashhebrew' => "\x{0597}", + 'rfishhook' => "\x{027E}", + 'rfishhookreversed' => "\x{027F}", + 'rhabengali' => "\x{09DD}", + 'rhadeva' => "\x{095D}", + 'rhook' => "\x{027D}", + 'rhookturned' => "\x{027B}", + 'rhookturnedsuperior' => "\x{02B5}", + 'rhosymbolgreek' => "\x{03F1}", + 'rhotichookmod' => "\x{02DE}", + 'rieulacirclekorean' => "\x{3271}", + 'rieulaparenkorean' => "\x{3211}", + 'rieulcirclekorean' => "\x{3263}", + 'rieulhieuhkorean' => "\x{3140}", + 'rieulkiyeokkorean' => "\x{313A}", + 'rieulkiyeoksioskorean' => "\x{3169}", + 'rieulkorean' => "\x{3139}", + 'rieulmieumkorean' => "\x{313B}", + 'rieulpansioskorean' => "\x{316C}", + 'rieulparenkorean' => "\x{3203}", + 'rieulphieuphkorean' => "\x{313F}", + 'rieulpieupkorean' => "\x{313C}", + 'rieulpieupsioskorean' => "\x{316B}", + 'rieulsioskorean' => "\x{313D}", + 'rieulthieuthkorean' => "\x{313E}", + 'rieultikeutkorean' => "\x{316A}", + 'rieulyeorinhieuhkorean' => "\x{316D}", + 'rightangle' => "\x{221F}", + 'righttackbelowcmb' => "\x{0319}", + 'righttriangle' => "\x{22BF}", + 'rihiragana' => "\x{308A}", + 'rikatakana' => "\x{30EA}", + 'rikatakanahalfwidth' => "\x{FF98}", + 'ringbelowcmb' => "\x{0325}", + 'ringcmb' => "\x{030A}", + 'ringhalfleft' => "\x{02BF}", + 'ringhalfleftarmenian' => "\x{0559}", + 'ringhalfleftbelowcmb' => "\x{031C}", + 'ringhalfleftcentered' => "\x{02D3}", + 'ringhalfright' => "\x{02BE}", + 'ringhalfrightbelowcmb' => "\x{0339}", + 'ringhalfrightcentered' => "\x{02D2}", + 'rinvertedbreve' => "\x{0213}", + 'rittorusquare' => "\x{3351}", + 'rlinebelow' => "\x{1E5F}", + 'rlongleg' => "\x{027C}", + 'rlonglegturned' => "\x{027A}", + 'rmonospace' => "\x{FF52}", + 'rohiragana' => "\x{308D}", + 'rokatakana' => "\x{30ED}", + 'rokatakanahalfwidth' => "\x{FF9B}", + 'roruathai' => "\x{0E23}", + 'rparen' => "\x{24AD}", + 'rrabengali' => "\x{09DC}", + 'rradeva' => "\x{0931}", + 'rragurmukhi' => "\x{0A5C}", + 'rreharabic' => "\x{0691}", + 'rrehfinalarabic' => "\x{FB8D}", + 'rrvocalicbengali' => "\x{09E0}", + 'rrvocalicdeva' => "\x{0960}", + 'rrvocalicgujarati' => "\x{0AE0}", + 'rrvocalicvowelsignbengali' => "\x{09C4}", + 'rrvocalicvowelsigndeva' => "\x{0944}", + 'rrvocalicvowelsigngujarati' => "\x{0AC4}", + 'rsuperior' => "\x{F6F1}", + 'rturned' => "\x{0279}", + 'rturnedsuperior' => "\x{02B4}", + 'ruhiragana' => "\x{308B}", + 'rukatakana' => "\x{30EB}", + 'rukatakanahalfwidth' => "\x{FF99}", + 'rupeemarkbengali' => "\x{09F2}", + 'rupeesignbengali' => "\x{09F3}", + 'rupiah' => "\x{F6DD}", + 'ruthai' => "\x{0E24}", + 'rvocalicbengali' => "\x{098B}", + 'rvocalicdeva' => "\x{090B}", + 'rvocalicgujarati' => "\x{0A8B}", + 'rvocalicvowelsignbengali' => "\x{09C3}", + 'rvocalicvowelsigndeva' => "\x{0943}", + 'rvocalicvowelsigngujarati' => "\x{0AC3}", + 'sabengali' => "\x{09B8}", + 'sacutedotaccent' => "\x{1E65}", + 'sadarabic' => "\x{0635}", + 'sadeva' => "\x{0938}", + 'sadfinalarabic' => "\x{FEBA}", + 'sadinitialarabic' => "\x{FEBB}", + 'sadmedialarabic' => "\x{FEBC}", + 'sagujarati' => "\x{0AB8}", + 'sagurmukhi' => "\x{0A38}", + 'sahiragana' => "\x{3055}", + 'sakatakana' => "\x{30B5}", + 'sakatakanahalfwidth' => "\x{FF7B}", + 'sallallahoualayhewasallamarabic' => "\x{FDFA}", + 'samekh' => "\x{05E1}", + 'samekhdagesh' => "\x{FB41}", + 'samekhdageshhebrew' => "\x{FB41}", + 'samekhhebrew' => "\x{05E1}", + 'saraaathai' => "\x{0E32}", + 'saraaethai' => "\x{0E41}", + 'saraaimaimalaithai' => "\x{0E44}", + 'saraaimaimuanthai' => "\x{0E43}", + 'saraamthai' => "\x{0E33}", + 'saraathai' => "\x{0E30}", + 'saraethai' => "\x{0E40}", + 'saraiileftthai' => "\x{F886}", + 'saraiithai' => "\x{0E35}", + 'saraileftthai' => "\x{F885}", + 'saraithai' => "\x{0E34}", + 'saraothai' => "\x{0E42}", + 'saraueeleftthai' => "\x{F888}", + 'saraueethai' => "\x{0E37}", + 'saraueleftthai' => "\x{F887}", + 'sarauethai' => "\x{0E36}", + 'sarauthai' => "\x{0E38}", + 'sarauuthai' => "\x{0E39}", + 'sbopomofo' => "\x{3119}", + 'scarondotaccent' => "\x{1E67}", + 'schwa' => "\x{0259}", + 'schwacyrillic' => "\x{04D9}", + 'schwadieresiscyrillic' => "\x{04DB}", + 'schwahook' => "\x{025A}", + 'scircle' => "\x{24E2}", + 'sdotaccent' => "\x{1E61}", + 'sdotbelow' => "\x{1E63}", + 'sdotbelowdotaccent' => "\x{1E69}", + 'seagullbelowcmb' => "\x{033C}", + 'secondtonechinese' => "\x{02CA}", + 'seenarabic' => "\x{0633}", + 'seenfinalarabic' => "\x{FEB2}", + 'seeninitialarabic' => "\x{FEB3}", + 'seenmedialarabic' => "\x{FEB4}", + 'segol' => "\x{05B6}", + 'segol13' => "\x{05B6}", + 'segol1f' => "\x{05B6}", + 'segol2c' => "\x{05B6}", + 'segolhebrew' => "\x{05B6}", + 'segolnarrowhebrew' => "\x{05B6}", + 'segolquarterhebrew' => "\x{05B6}", + 'segoltahebrew' => "\x{0592}", + 'segolwidehebrew' => "\x{05B6}", + 'seharmenian' => "\x{057D}", + 'sehiragana' => "\x{305B}", + 'sekatakana' => "\x{30BB}", + 'sekatakanahalfwidth' => "\x{FF7E}", + 'semicolonarabic' => "\x{061B}", + 'semicolonmonospace' => "\x{FF1B}", + 'semicolonsmall' => "\x{FE54}", + 'semivoicedmarkkana' => "\x{309C}", + 'semivoicedmarkkanahalfwidth' => "\x{FF9F}", + 'sentisquare' => "\x{3322}", + 'sentosquare' => "\x{3323}", + 'sevenarabic' => "\x{0667}", + 'sevenbengali' => "\x{09ED}", + 'sevencircle' => "\x{2466}", + 'sevencircleinversesansserif' => "\x{2790}", + 'sevendeva' => "\x{096D}", + 'sevengujarati' => "\x{0AED}", + 'sevengurmukhi' => "\x{0A6D}", + 'sevenhackarabic' => "\x{0667}", + 'sevenhangzhou' => "\x{3027}", + 'sevenideographicparen' => "\x{3226}", + 'seveninferior' => "\x{2087}", + 'sevenmonospace' => "\x{FF17}", + 'sevenoldstyle' => "\x{F737}", + 'sevenparen' => "\x{247A}", + 'sevenperiod' => "\x{248E}", + 'sevenpersian' => "\x{06F7}", + 'sevenroman' => "\x{2176}", + 'sevensuperior' => "\x{2077}", + 'seventeencircle' => "\x{2470}", + 'seventeenparen' => "\x{2484}", + 'seventeenperiod' => "\x{2498}", + 'seventhai' => "\x{0E57}", + 'sfthyphen' => "\x{00AD}", + 'shaarmenian' => "\x{0577}", + 'shabengali' => "\x{09B6}", + 'shacyrillic' => "\x{0448}", + 'shaddaarabic' => "\x{0651}", + 'shaddadammaarabic' => "\x{FC61}", + 'shaddadammatanarabic' => "\x{FC5E}", + 'shaddafathaarabic' => "\x{FC60}", + 'shaddafathatanarabic' => "\x{0651}\x{064B}", + 'shaddakasraarabic' => "\x{FC62}", + 'shaddakasratanarabic' => "\x{FC5F}", + 'shadedark' => "\x{2593}", + 'shadelight' => "\x{2591}", + 'shademedium' => "\x{2592}", + 'shadeva' => "\x{0936}", + 'shagujarati' => "\x{0AB6}", + 'shagurmukhi' => "\x{0A36}", + 'shalshelethebrew' => "\x{0593}", + 'shbopomofo' => "\x{3115}", + 'shchacyrillic' => "\x{0449}", + 'sheenarabic' => "\x{0634}", + 'sheenfinalarabic' => "\x{FEB6}", + 'sheeninitialarabic' => "\x{FEB7}", + 'sheenmedialarabic' => "\x{FEB8}", + 'sheicoptic' => "\x{03E3}", + 'sheqel' => "\x{20AA}", + 'sheqelhebrew' => "\x{20AA}", + 'sheva' => "\x{05B0}", + 'sheva115' => "\x{05B0}", + 'sheva15' => "\x{05B0}", + 'sheva22' => "\x{05B0}", + 'sheva2e' => "\x{05B0}", + 'shevahebrew' => "\x{05B0}", + 'shevanarrowhebrew' => "\x{05B0}", + 'shevaquarterhebrew' => "\x{05B0}", + 'shevawidehebrew' => "\x{05B0}", + 'shhacyrillic' => "\x{04BB}", + 'shimacoptic' => "\x{03ED}", + 'shin' => "\x{05E9}", + 'shindagesh' => "\x{FB49}", + 'shindageshhebrew' => "\x{FB49}", + 'shindageshshindot' => "\x{FB2C}", + 'shindageshshindothebrew' => "\x{FB2C}", + 'shindageshsindot' => "\x{FB2D}", + 'shindageshsindothebrew' => "\x{FB2D}", + 'shindothebrew' => "\x{05C1}", + 'shinhebrew' => "\x{05E9}", + 'shinshindot' => "\x{FB2A}", + 'shinshindothebrew' => "\x{FB2A}", + 'shinsindot' => "\x{FB2B}", + 'shinsindothebrew' => "\x{FB2B}", + 'shook' => "\x{0282}", + 'sigmafinal' => "\x{03C2}", + 'sigmalunatesymbolgreek' => "\x{03F2}", + 'sihiragana' => "\x{3057}", + 'sikatakana' => "\x{30B7}", + 'sikatakanahalfwidth' => "\x{FF7C}", + 'siluqhebrew' => "\x{05BD}", + 'siluqlefthebrew' => "\x{05BD}", + 'sindothebrew' => "\x{05C2}", + 'siosacirclekorean' => "\x{3274}", + 'siosaparenkorean' => "\x{3214}", + 'sioscieuckorean' => "\x{317E}", + 'sioscirclekorean' => "\x{3266}", + 'sioskiyeokkorean' => "\x{317A}", + 'sioskorean' => "\x{3145}", + 'siosnieunkorean' => "\x{317B}", + 'siosparenkorean' => "\x{3206}", + 'siospieupkorean' => "\x{317D}", + 'siostikeutkorean' => "\x{317C}", + 'sixarabic' => "\x{0666}", + 'sixbengali' => "\x{09EC}", + 'sixcircle' => "\x{2465}", + 'sixcircleinversesansserif' => "\x{278F}", + 'sixdeva' => "\x{096C}", + 'sixgujarati' => "\x{0AEC}", + 'sixgurmukhi' => "\x{0A6C}", + 'sixhackarabic' => "\x{0666}", + 'sixhangzhou' => "\x{3026}", + 'sixideographicparen' => "\x{3225}", + 'sixinferior' => "\x{2086}", + 'sixmonospace' => "\x{FF16}", + 'sixoldstyle' => "\x{F736}", + 'sixparen' => "\x{2479}", + 'sixperiod' => "\x{248D}", + 'sixpersian' => "\x{06F6}", + 'sixroman' => "\x{2175}", + 'sixsuperior' => "\x{2076}", + 'sixteencircle' => "\x{246F}", + 'sixteencurrencydenominatorbengali' => "\x{09F9}", + 'sixteenparen' => "\x{2483}", + 'sixteenperiod' => "\x{2497}", + 'sixthai' => "\x{0E56}", + 'slashmonospace' => "\x{FF0F}", + 'slong' => "\x{017F}", + 'slongdotaccent' => "\x{1E9B}", + 'smonospace' => "\x{FF53}", + 'sofpasuqhebrew' => "\x{05C3}", + 'softhyphen' => "\x{00AD}", + 'softsigncyrillic' => "\x{044C}", + 'sohiragana' => "\x{305D}", + 'sokatakana' => "\x{30BD}", + 'sokatakanahalfwidth' => "\x{FF7F}", + 'soliduslongoverlaycmb' => "\x{0338}", + 'solidusshortoverlaycmb' => "\x{0337}", + 'sorusithai' => "\x{0E29}", + 'sosalathai' => "\x{0E28}", + 'sosothai' => "\x{0E0B}", + 'sosuathai' => "\x{0E2A}", + 'spacehackarabic' => "\x{0020}", + 'spadesuitblack' => "\x{2660}", + 'spadesuitwhite' => "\x{2664}", + 'sparen' => "\x{24AE}", + 'squarebelowcmb' => "\x{033B}", + 'squarecc' => "\x{33C4}", + 'squarecm' => "\x{339D}", + 'squarediagonalcrosshatchfill' => "\x{25A9}", + 'squarehorizontalfill' => "\x{25A4}", + 'squarekg' => "\x{338F}", + 'squarekm' => "\x{339E}", + 'squarekmcapital' => "\x{33CE}", + 'squareln' => "\x{33D1}", + 'squarelog' => "\x{33D2}", + 'squaremg' => "\x{338E}", + 'squaremil' => "\x{33D5}", + 'squaremm' => "\x{339C}", + 'squaremsquared' => "\x{33A1}", + 'squareorthogonalcrosshatchfill' => "\x{25A6}", + 'squareupperlefttolowerrightfill' => "\x{25A7}", + 'squareupperrighttolowerleftfill' => "\x{25A8}", + 'squareverticalfill' => "\x{25A5}", + 'squarewhitewithsmallblack' => "\x{25A3}", + 'srsquare' => "\x{33DB}", + 'ssabengali' => "\x{09B7}", + 'ssadeva' => "\x{0937}", + 'ssagujarati' => "\x{0AB7}", + 'ssangcieuckorean' => "\x{3149}", + 'ssanghieuhkorean' => "\x{3185}", + 'ssangieungkorean' => "\x{3180}", + 'ssangkiyeokkorean' => "\x{3132}", + 'ssangnieunkorean' => "\x{3165}", + 'ssangpieupkorean' => "\x{3143}", + 'ssangsioskorean' => "\x{3146}", + 'ssangtikeutkorean' => "\x{3138}", + 'ssuperior' => "\x{F6F2}", + 'sterlingmonospace' => "\x{FFE1}", + 'strokelongoverlaycmb' => "\x{0336}", + 'strokeshortoverlaycmb' => "\x{0335}", + 'subset' => "\x{2282}", + 'subsetnotequal' => "\x{228A}", + 'subsetorequal' => "\x{2286}", + 'succeeds' => "\x{227B}", + 'suhiragana' => "\x{3059}", + 'sukatakana' => "\x{30B9}", + 'sukatakanahalfwidth' => "\x{FF7D}", + 'sukunarabic' => "\x{0652}", + 'superset' => "\x{2283}", + 'supersetnotequal' => "\x{228B}", + 'supersetorequal' => "\x{2287}", + 'svsquare' => "\x{33DC}", + 'syouwaerasquare' => "\x{337C}", + 'tabengali' => "\x{09A4}", + 'tackdown' => "\x{22A4}", + 'tackleft' => "\x{22A3}", + 'tadeva' => "\x{0924}", + 'tagujarati' => "\x{0AA4}", + 'tagurmukhi' => "\x{0A24}", + 'taharabic' => "\x{0637}", + 'tahfinalarabic' => "\x{FEC2}", + 'tahinitialarabic' => "\x{FEC3}", + 'tahiragana' => "\x{305F}", + 'tahmedialarabic' => "\x{FEC4}", + 'taisyouerasquare' => "\x{337D}", + 'takatakana' => "\x{30BF}", + 'takatakanahalfwidth' => "\x{FF80}", + 'tatweelarabic' => "\x{0640}", + 'tav' => "\x{05EA}", + 'tavdages' => "\x{FB4A}", + 'tavdagesh' => "\x{FB4A}", + 'tavdageshhebrew' => "\x{FB4A}", + 'tavhebrew' => "\x{05EA}", + 'tbopomofo' => "\x{310A}", + 'tccurl' => "\x{02A8}", + 'tcedilla' => "\x{0163}", + 'tcheharabic' => "\x{0686}", + 'tchehfinalarabic' => "\x{FB7B}", + 'tchehinitialarabic' => "\x{FB7C}", + 'tchehmedialarabic' => "\x{FB7D}", + 'tchehmeeminitialarabic' => "\x{FB7C}\x{FEE4}", + 'tcircle' => "\x{24E3}", + 'tcircumflexbelow' => "\x{1E71}", + 'tdieresis' => "\x{1E97}", + 'tdotaccent' => "\x{1E6B}", + 'tdotbelow' => "\x{1E6D}", + 'tecyrillic' => "\x{0442}", + 'tedescendercyrillic' => "\x{04AD}", + 'teharabic' => "\x{062A}", + 'tehfinalarabic' => "\x{FE96}", + 'tehhahinitialarabic' => "\x{FCA2}", + 'tehhahisolatedarabic' => "\x{FC0C}", + 'tehinitialarabic' => "\x{FE97}", + 'tehiragana' => "\x{3066}", + 'tehjeeminitialarabic' => "\x{FCA1}", + 'tehjeemisolatedarabic' => "\x{FC0B}", + 'tehmarbutaarabic' => "\x{0629}", + 'tehmarbutafinalarabic' => "\x{FE94}", + 'tehmedialarabic' => "\x{FE98}", + 'tehmeeminitialarabic' => "\x{FCA4}", + 'tehmeemisolatedarabic' => "\x{FC0E}", + 'tehnoonfinalarabic' => "\x{FC73}", + 'tekatakana' => "\x{30C6}", + 'tekatakanahalfwidth' => "\x{FF83}", + 'telephone' => "\x{2121}", + 'telephoneblack' => "\x{260E}", + 'telishagedolahebrew' => "\x{05A0}", + 'telishaqetanahebrew' => "\x{05A9}", + 'tencircle' => "\x{2469}", + 'tenideographicparen' => "\x{3229}", + 'tenparen' => "\x{247D}", + 'tenperiod' => "\x{2491}", + 'tenroman' => "\x{2179}", + 'tesh' => "\x{02A7}", + 'tet' => "\x{05D8}", + 'tetdagesh' => "\x{FB38}", + 'tetdageshhebrew' => "\x{FB38}", + 'tethebrew' => "\x{05D8}", + 'tetsecyrillic' => "\x{04B5}", + 'tevirhebrew' => "\x{059B}", + 'tevirlefthebrew' => "\x{059B}", + 'thabengali' => "\x{09A5}", + 'thadeva' => "\x{0925}", + 'thagujarati' => "\x{0AA5}", + 'thagurmukhi' => "\x{0A25}", + 'thalarabic' => "\x{0630}", + 'thalfinalarabic' => "\x{FEAC}", + 'thanthakhatlowleftthai' => "\x{F898}", + 'thanthakhatlowrightthai' => "\x{F897}", + 'thanthakhatthai' => "\x{0E4C}", + 'thanthakhatupperleftthai' => "\x{F896}", + 'theharabic' => "\x{062B}", + 'thehfinalarabic' => "\x{FE9A}", + 'thehinitialarabic' => "\x{FE9B}", + 'thehmedialarabic' => "\x{FE9C}", + 'thereexists' => "\x{2203}", + 'thetasymbolgreek' => "\x{03D1}", + 'thieuthacirclekorean' => "\x{3279}", + 'thieuthaparenkorean' => "\x{3219}", + 'thieuthcirclekorean' => "\x{326B}", + 'thieuthkorean' => "\x{314C}", + 'thieuthparenkorean' => "\x{320B}", + 'thirteencircle' => "\x{246C}", + 'thirteenparen' => "\x{2480}", + 'thirteenperiod' => "\x{2494}", + 'thonangmonthothai' => "\x{0E11}", + 'thook' => "\x{01AD}", + 'thophuthaothai' => "\x{0E12}", + 'thothahanthai' => "\x{0E17}", + 'thothanthai' => "\x{0E10}", + 'thothongthai' => "\x{0E18}", + 'thothungthai' => "\x{0E16}", + 'thousandcyrillic' => "\x{0482}", + 'thousandsseparatorarabic' => "\x{066C}", + 'thousandsseparatorpersian' => "\x{066C}", + 'threearabic' => "\x{0663}", + 'threebengali' => "\x{09E9}", + 'threecircle' => "\x{2462}", + 'threecircleinversesansserif' => "\x{278C}", + 'threedeva' => "\x{0969}", + 'threegujarati' => "\x{0AE9}", + 'threegurmukhi' => "\x{0A69}", + 'threehackarabic' => "\x{0663}", + 'threehangzhou' => "\x{3023}", + 'threeideographicparen' => "\x{3222}", + 'threeinferior' => "\x{2083}", + 'threemonospace' => "\x{FF13}", + 'threenumeratorbengali' => "\x{09F6}", + 'threeoldstyle' => "\x{F733}", + 'threeparen' => "\x{2476}", + 'threeperiod' => "\x{248A}", + 'threepersian' => "\x{06F3}", + 'threequartersemdash' => "\x{F6DE}", + 'threeroman' => "\x{2172}", + 'threethai' => "\x{0E53}", + 'thzsquare' => "\x{3394}", + 'tihiragana' => "\x{3061}", + 'tikatakana' => "\x{30C1}", + 'tikatakanahalfwidth' => "\x{FF81}", + 'tikeutacirclekorean' => "\x{3270}", + 'tikeutaparenkorean' => "\x{3210}", + 'tikeutcirclekorean' => "\x{3262}", + 'tikeutkorean' => "\x{3137}", + 'tikeutparenkorean' => "\x{3202}", + 'tildebelowcmb' => "\x{0330}", + 'tildecmb' => "\x{0303}", + 'tildedoublecmb' => "\x{0360}", + 'tildeoperator' => "\x{223C}", + 'tildeoverlaycmb' => "\x{0334}", + 'tildeverticalcmb' => "\x{033E}", + 'timescircle' => "\x{2297}", + 'tipehahebrew' => "\x{0596}", + 'tipehalefthebrew' => "\x{0596}", + 'tippigurmukhi' => "\x{0A70}", + 'titlocyrilliccmb' => "\x{0483}", + 'tiwnarmenian' => "\x{057F}", + 'tlinebelow' => "\x{1E6F}", + 'tmonospace' => "\x{FF54}", + 'toarmenian' => "\x{0569}", + 'tohiragana' => "\x{3068}", + 'tokatakana' => "\x{30C8}", + 'tokatakanahalfwidth' => "\x{FF84}", + 'tonebarextrahighmod' => "\x{02E5}", + 'tonebarextralowmod' => "\x{02E9}", + 'tonebarhighmod' => "\x{02E6}", + 'tonebarlowmod' => "\x{02E8}", + 'tonebarmidmod' => "\x{02E7}", + 'tonefive' => "\x{01BD}", + 'tonesix' => "\x{0185}", + 'tonetwo' => "\x{01A8}", + 'tonsquare' => "\x{3327}", + 'topatakthai' => "\x{0E0F}", + 'tortoiseshellbracketleft' => "\x{3014}", + 'tortoiseshellbracketleftsmall' => "\x{FE5D}", + 'tortoiseshellbracketleftvertical' => "\x{FE39}", + 'tortoiseshellbracketright' => "\x{3015}", + 'tortoiseshellbracketrightsmall' => "\x{FE5E}", + 'tortoiseshellbracketrightvertical' => "\x{FE3A}", + 'totaothai' => "\x{0E15}", + 'tpalatalhook' => "\x{01AB}", + 'tparen' => "\x{24AF}", + 'trademarksans' => "\x{F8EA}", + 'trademarkserif' => "\x{F6DB}", + 'tretroflexhook' => "\x{0288}", + 'ts' => "\x{02A6}", + 'tsadi' => "\x{05E6}", + 'tsadidagesh' => "\x{FB46}", + 'tsadidageshhebrew' => "\x{FB46}", + 'tsadihebrew' => "\x{05E6}", + 'tsecyrillic' => "\x{0446}", + 'tsere' => "\x{05B5}", + 'tsere12' => "\x{05B5}", + 'tsere1e' => "\x{05B5}", + 'tsere2b' => "\x{05B5}", + 'tserehebrew' => "\x{05B5}", + 'tserenarrowhebrew' => "\x{05B5}", + 'tserequarterhebrew' => "\x{05B5}", + 'tserewidehebrew' => "\x{05B5}", + 'tshecyrillic' => "\x{045B}", + 'tsuperior' => "\x{F6F3}", + 'ttabengali' => "\x{099F}", + 'ttadeva' => "\x{091F}", + 'ttagujarati' => "\x{0A9F}", + 'ttagurmukhi' => "\x{0A1F}", + 'tteharabic' => "\x{0679}", + 'ttehfinalarabic' => "\x{FB67}", + 'ttehinitialarabic' => "\x{FB68}", + 'ttehmedialarabic' => "\x{FB69}", + 'tthabengali' => "\x{09A0}", + 'tthadeva' => "\x{0920}", + 'tthagujarati' => "\x{0AA0}", + 'tthagurmukhi' => "\x{0A20}", + 'tturned' => "\x{0287}", + 'tuhiragana' => "\x{3064}", + 'tukatakana' => "\x{30C4}", + 'tukatakanahalfwidth' => "\x{FF82}", + 'tusmallhiragana' => "\x{3063}", + 'tusmallkatakana' => "\x{30C3}", + 'tusmallkatakanahalfwidth' => "\x{FF6F}", + 'twelvecircle' => "\x{246B}", + 'twelveparen' => "\x{247F}", + 'twelveperiod' => "\x{2493}", + 'twelveroman' => "\x{217B}", + 'twentycircle' => "\x{2473}", + 'twentyhangzhou' => "\x{5344}", + 'twentyparen' => "\x{2487}", + 'twentyperiod' => "\x{249B}", + 'twoarabic' => "\x{0662}", + 'twobengali' => "\x{09E8}", + 'twocircle' => "\x{2461}", + 'twocircleinversesansserif' => "\x{278B}", + 'twodeva' => "\x{0968}", + 'twodotleader' => "\x{2025}", + 'twodotleadervertical' => "\x{FE30}", + 'twogujarati' => "\x{0AE8}", + 'twogurmukhi' => "\x{0A68}", + 'twohackarabic' => "\x{0662}", + 'twohangzhou' => "\x{3022}", + 'twoideographicparen' => "\x{3221}", + 'twoinferior' => "\x{2082}", + 'twomonospace' => "\x{FF12}", + 'twonumeratorbengali' => "\x{09F5}", + 'twooldstyle' => "\x{F732}", + 'twoparen' => "\x{2475}", + 'twoperiod' => "\x{2489}", + 'twopersian' => "\x{06F2}", + 'tworoman' => "\x{2171}", + 'twostroke' => "\x{01BB}", + 'twothai' => "\x{0E52}", + 'ubar' => "\x{0289}", + 'ubengali' => "\x{0989}", + 'ubopomofo' => "\x{3128}", + 'ucaron' => "\x{01D4}", + 'ucircle' => "\x{24E4}", + 'ucircumflexbelow' => "\x{1E77}", + 'ucyrillic' => "\x{0443}", + 'udattadeva' => "\x{0951}", + 'udblacute' => "\x{0171}", + 'udblgrave' => "\x{0215}", + 'udeva' => "\x{0909}", + 'udieresisacute' => "\x{01D8}", + 'udieresisbelow' => "\x{1E73}", + 'udieresiscaron' => "\x{01DA}", + 'udieresiscyrillic' => "\x{04F1}", + 'udieresisgrave' => "\x{01DC}", + 'udieresismacron' => "\x{01D6}", + 'udotbelow' => "\x{1EE5}", + 'ugujarati' => "\x{0A89}", + 'ugurmukhi' => "\x{0A09}", + 'uhiragana' => "\x{3046}", + 'uhookabove' => "\x{1EE7}", + 'uhornacute' => "\x{1EE9}", + 'uhorndotbelow' => "\x{1EF1}", + 'uhorngrave' => "\x{1EEB}", + 'uhornhookabove' => "\x{1EED}", + 'uhorntilde' => "\x{1EEF}", + 'uhungarumlautcyrillic' => "\x{04F3}", + 'uinvertedbreve' => "\x{0217}", + 'ukatakana' => "\x{30A6}", + 'ukatakanahalfwidth' => "\x{FF73}", + 'ukcyrillic' => "\x{0479}", + 'ukorean' => "\x{315C}", + 'umacroncyrillic' => "\x{04EF}", + 'umacrondieresis' => "\x{1E7B}", + 'umatragurmukhi' => "\x{0A41}", + 'umonospace' => "\x{FF55}", + 'underscoremonospace' => "\x{FF3F}", + 'underscorevertical' => "\x{FE33}", + 'underscorewavy' => "\x{FE4F}", + 'uparen' => "\x{24B0}", + 'upperdothebrew' => "\x{05C4}", + 'upsilonlatin' => "\x{028A}", + 'uptackbelowcmb' => "\x{031D}", + 'uptackmod' => "\x{02D4}", + 'uragurmukhi' => "\x{0A73}", + 'ushortcyrillic' => "\x{045E}", + 'usmallhiragana' => "\x{3045}", + 'usmallkatakana' => "\x{30A5}", + 'usmallkatakanahalfwidth' => "\x{FF69}", + 'ustraightcyrillic' => "\x{04AF}", + 'ustraightstrokecyrillic' => "\x{04B1}", + 'utildeacute' => "\x{1E79}", + 'utildebelow' => "\x{1E75}", + 'uubengali' => "\x{098A}", + 'uudeva' => "\x{090A}", + 'uugujarati' => "\x{0A8A}", + 'uugurmukhi' => "\x{0A0A}", + 'uumatragurmukhi' => "\x{0A42}", + 'uuvowelsignbengali' => "\x{09C2}", + 'uuvowelsigndeva' => "\x{0942}", + 'uuvowelsigngujarati' => "\x{0AC2}", + 'uvowelsignbengali' => "\x{09C1}", + 'uvowelsigndeva' => "\x{0941}", + 'uvowelsigngujarati' => "\x{0AC1}", + 'vadeva' => "\x{0935}", + 'vagujarati' => "\x{0AB5}", + 'vagurmukhi' => "\x{0A35}", + 'vakatakana' => "\x{30F7}", + 'vav' => "\x{05D5}", + 'vavdagesh' => "\x{FB35}", + 'vavdagesh65' => "\x{FB35}", + 'vavdageshhebrew' => "\x{FB35}", + 'vavhebrew' => "\x{05D5}", + 'vavholam' => "\x{FB4B}", + 'vavholamhebrew' => "\x{FB4B}", + 'vavvavhebrew' => "\x{05F0}", + 'vavyodhebrew' => "\x{05F1}", + 'vcircle' => "\x{24E5}", + 'vdotbelow' => "\x{1E7F}", + 'vecyrillic' => "\x{0432}", + 'veharabic' => "\x{06A4}", + 'vehfinalarabic' => "\x{FB6B}", + 'vehinitialarabic' => "\x{FB6C}", + 'vehmedialarabic' => "\x{FB6D}", + 'vekatakana' => "\x{30F9}", + 'venus' => "\x{2640}", + 'verticalbar' => "\x{007C}", + 'verticallineabovecmb' => "\x{030D}", + 'verticallinebelowcmb' => "\x{0329}", + 'verticallinelowmod' => "\x{02CC}", + 'verticallinemod' => "\x{02C8}", + 'vewarmenian' => "\x{057E}", + 'vhook' => "\x{028B}", + 'vikatakana' => "\x{30F8}", + 'viramabengali' => "\x{09CD}", + 'viramadeva' => "\x{094D}", + 'viramagujarati' => "\x{0ACD}", + 'visargabengali' => "\x{0983}", + 'visargadeva' => "\x{0903}", + 'visargagujarati' => "\x{0A83}", + 'vmonospace' => "\x{FF56}", + 'voarmenian' => "\x{0578}", + 'voicediterationhiragana' => "\x{309E}", + 'voicediterationkatakana' => "\x{30FE}", + 'voicedmarkkana' => "\x{309B}", + 'voicedmarkkanahalfwidth' => "\x{FF9E}", + 'vokatakana' => "\x{30FA}", + 'vparen' => "\x{24B1}", + 'vtilde' => "\x{1E7D}", + 'vturned' => "\x{028C}", + 'vuhiragana' => "\x{3094}", + 'vukatakana' => "\x{30F4}", + 'waekorean' => "\x{3159}", + 'wahiragana' => "\x{308F}", + 'wakatakana' => "\x{30EF}", + 'wakatakanahalfwidth' => "\x{FF9C}", + 'wakorean' => "\x{3158}", + 'wasmallhiragana' => "\x{308E}", + 'wasmallkatakana' => "\x{30EE}", + 'wattosquare' => "\x{3357}", + 'wavedash' => "\x{301C}", + 'wavyunderscorevertical' => "\x{FE34}", + 'wawarabic' => "\x{0648}", + 'wawfinalarabic' => "\x{FEEE}", + 'wawhamzaabovearabic' => "\x{0624}", + 'wawhamzaabovefinalarabic' => "\x{FE86}", + 'wbsquare' => "\x{33DD}", + 'wcircle' => "\x{24E6}", + 'wdotaccent' => "\x{1E87}", + 'wdotbelow' => "\x{1E89}", + 'wehiragana' => "\x{3091}", + 'wekatakana' => "\x{30F1}", + 'wekorean' => "\x{315E}", + 'weokorean' => "\x{315D}", + 'whitebullet' => "\x{25E6}", + 'whitecircle' => "\x{25CB}", + 'whitecircleinverse' => "\x{25D9}", + 'whitecornerbracketleft' => "\x{300E}", + 'whitecornerbracketleftvertical' => "\x{FE43}", + 'whitecornerbracketright' => "\x{300F}", + 'whitecornerbracketrightvertical' => "\x{FE44}", + 'whitediamond' => "\x{25C7}", + 'whitediamondcontainingblacksmalldiamond' => "\x{25C8}", + 'whitedownpointingsmalltriangle' => "\x{25BF}", + 'whitedownpointingtriangle' => "\x{25BD}", + 'whiteleftpointingsmalltriangle' => "\x{25C3}", + 'whiteleftpointingtriangle' => "\x{25C1}", + 'whitelenticularbracketleft' => "\x{3016}", + 'whitelenticularbracketright' => "\x{3017}", + 'whiterightpointingsmalltriangle' => "\x{25B9}", + 'whiterightpointingtriangle' => "\x{25B7}", + 'whitesmallsquare' => "\x{25AB}", + 'whitesmilingface' => "\x{263A}", + 'whitesquare' => "\x{25A1}", + 'whitestar' => "\x{2606}", + 'whitetelephone' => "\x{260F}", + 'whitetortoiseshellbracketleft' => "\x{3018}", + 'whitetortoiseshellbracketright' => "\x{3019}", + 'whiteuppointingsmalltriangle' => "\x{25B5}", + 'whiteuppointingtriangle' => "\x{25B3}", + 'wihiragana' => "\x{3090}", + 'wikatakana' => "\x{30F0}", + 'wikorean' => "\x{315F}", + 'wmonospace' => "\x{FF57}", + 'wohiragana' => "\x{3092}", + 'wokatakana' => "\x{30F2}", + 'wokatakanahalfwidth' => "\x{FF66}", + 'won' => "\x{20A9}", + 'wonmonospace' => "\x{FFE6}", + 'wowaenthai' => "\x{0E27}", + 'wparen' => "\x{24B2}", + 'wring' => "\x{1E98}", + 'wsuperior' => "\x{02B7}", + 'wturned' => "\x{028D}", + 'wynn' => "\x{01BF}", + 'xabovecmb' => "\x{033D}", + 'xbopomofo' => "\x{3112}", + 'xcircle' => "\x{24E7}", + 'xdieresis' => "\x{1E8D}", + 'xdotaccent' => "\x{1E8B}", + 'xeharmenian' => "\x{056D}", + 'xmonospace' => "\x{FF58}", + 'xparen' => "\x{24B3}", + 'xsuperior' => "\x{02E3}", + 'yaadosquare' => "\x{334E}", + 'yabengali' => "\x{09AF}", + 'yadeva' => "\x{092F}", + 'yaekorean' => "\x{3152}", + 'yagujarati' => "\x{0AAF}", + 'yagurmukhi' => "\x{0A2F}", + 'yahiragana' => "\x{3084}", + 'yakatakana' => "\x{30E4}", + 'yakatakanahalfwidth' => "\x{FF94}", + 'yakorean' => "\x{3151}", + 'yamakkanthai' => "\x{0E4E}", + 'yasmallhiragana' => "\x{3083}", + 'yasmallkatakana' => "\x{30E3}", + 'yasmallkatakanahalfwidth' => "\x{FF6C}", + 'yatcyrillic' => "\x{0463}", + 'ycircle' => "\x{24E8}", + 'ydotaccent' => "\x{1E8F}", + 'ydotbelow' => "\x{1EF5}", + 'yeharabic' => "\x{064A}", + 'yehbarreearabic' => "\x{06D2}", + 'yehbarreefinalarabic' => "\x{FBAF}", + 'yehfinalarabic' => "\x{FEF2}", + 'yehhamzaabovearabic' => "\x{0626}", + 'yehhamzaabovefinalarabic' => "\x{FE8A}", + 'yehhamzaaboveinitialarabic' => "\x{FE8B}", + 'yehhamzaabovemedialarabic' => "\x{FE8C}", + 'yehinitialarabic' => "\x{FEF3}", + 'yehmedialarabic' => "\x{FEF4}", + 'yehmeeminitialarabic' => "\x{FCDD}", + 'yehmeemisolatedarabic' => "\x{FC58}", + 'yehnoonfinalarabic' => "\x{FC94}", + 'yehthreedotsbelowarabic' => "\x{06D1}", + 'yekorean' => "\x{3156}", + 'yenmonospace' => "\x{FFE5}", + 'yeokorean' => "\x{3155}", + 'yeorinhieuhkorean' => "\x{3186}", + 'yerahbenyomohebrew' => "\x{05AA}", + 'yerahbenyomolefthebrew' => "\x{05AA}", + 'yericyrillic' => "\x{044B}", + 'yerudieresiscyrillic' => "\x{04F9}", + 'yesieungkorean' => "\x{3181}", + 'yesieungpansioskorean' => "\x{3183}", + 'yesieungsioskorean' => "\x{3182}", + 'yetivhebrew' => "\x{059A}", + 'yhook' => "\x{01B4}", + 'yhookabove' => "\x{1EF7}", + 'yiarmenian' => "\x{0575}", + 'yicyrillic' => "\x{0457}", + 'yikorean' => "\x{3162}", + 'yinyang' => "\x{262F}", + 'yiwnarmenian' => "\x{0582}", + 'ymonospace' => "\x{FF59}", + 'yod' => "\x{05D9}", + 'yoddagesh' => "\x{FB39}", + 'yoddageshhebrew' => "\x{FB39}", + 'yodhebrew' => "\x{05D9}", + 'yodyodhebrew' => "\x{05F2}", + 'yodyodpatahhebrew' => "\x{FB1F}", + 'yohiragana' => "\x{3088}", + 'yoikorean' => "\x{3189}", + 'yokatakana' => "\x{30E8}", + 'yokatakanahalfwidth' => "\x{FF96}", + 'yokorean' => "\x{315B}", + 'yosmallhiragana' => "\x{3087}", + 'yosmallkatakana' => "\x{30E7}", + 'yosmallkatakanahalfwidth' => "\x{FF6E}", + 'yotgreek' => "\x{03F3}", + 'yoyaekorean' => "\x{3188}", + 'yoyakorean' => "\x{3187}", + 'yoyakthai' => "\x{0E22}", + 'yoyingthai' => "\x{0E0D}", + 'yparen' => "\x{24B4}", + 'ypogegrammeni' => "\x{037A}", + 'ypogegrammenigreekcmb' => "\x{0345}", + 'yr' => "\x{01A6}", + 'yring' => "\x{1E99}", + 'ysuperior' => "\x{02B8}", + 'ytilde' => "\x{1EF9}", + 'yturned' => "\x{028E}", + 'yuhiragana' => "\x{3086}", + 'yuikorean' => "\x{318C}", + 'yukatakana' => "\x{30E6}", + 'yukatakanahalfwidth' => "\x{FF95}", + 'yukorean' => "\x{3160}", + 'yusbigcyrillic' => "\x{046B}", + 'yusbigiotifiedcyrillic' => "\x{046D}", + 'yuslittlecyrillic' => "\x{0467}", + 'yuslittleiotifiedcyrillic' => "\x{0469}", + 'yusmallhiragana' => "\x{3085}", + 'yusmallkatakana' => "\x{30E5}", + 'yusmallkatakanahalfwidth' => "\x{FF6D}", + 'yuyekorean' => "\x{318B}", + 'yuyeokorean' => "\x{318A}", + 'yyabengali' => "\x{09DF}", + 'yyadeva' => "\x{095F}", + 'zaarmenian' => "\x{0566}", + 'zadeva' => "\x{095B}", + 'zagurmukhi' => "\x{0A5B}", + 'zaharabic' => "\x{0638}", + 'zahfinalarabic' => "\x{FEC6}", + 'zahinitialarabic' => "\x{FEC7}", + 'zahiragana' => "\x{3056}", + 'zahmedialarabic' => "\x{FEC8}", + 'zainarabic' => "\x{0632}", + 'zainfinalarabic' => "\x{FEB0}", + 'zakatakana' => "\x{30B6}", + 'zaqefgadolhebrew' => "\x{0595}", + 'zaqefqatanhebrew' => "\x{0594}", + 'zarqahebrew' => "\x{0598}", + 'zayin' => "\x{05D6}", + 'zayindagesh' => "\x{FB36}", + 'zayindageshhebrew' => "\x{FB36}", + 'zayinhebrew' => "\x{05D6}", + 'zbopomofo' => "\x{3117}", + 'zcircle' => "\x{24E9}", + 'zcircumflex' => "\x{1E91}", + 'zcurl' => "\x{0291}", + 'zdot' => "\x{017C}", + 'zdotbelow' => "\x{1E93}", + 'zecyrillic' => "\x{0437}", + 'zedescendercyrillic' => "\x{0499}", + 'zedieresiscyrillic' => "\x{04DF}", + 'zehiragana' => "\x{305C}", + 'zekatakana' => "\x{30BC}", + 'zeroarabic' => "\x{0660}", + 'zerobengali' => "\x{09E6}", + 'zerodeva' => "\x{0966}", + 'zerogujarati' => "\x{0AE6}", + 'zerogurmukhi' => "\x{0A66}", + 'zerohackarabic' => "\x{0660}", + 'zeroinferior' => "\x{2080}", + 'zeromonospace' => "\x{FF10}", + 'zerooldstyle' => "\x{F730}", + 'zeropersian' => "\x{06F0}", + 'zerosuperior' => "\x{2070}", + 'zerothai' => "\x{0E50}", + 'zerowidthjoiner' => "\x{FEFF}", + 'zerowidthnonjoiner' => "\x{200C}", + 'zerowidthspace' => "\x{200B}", + 'zhbopomofo' => "\x{3113}", + 'zhearmenian' => "\x{056A}", + 'zhebrevecyrillic' => "\x{04C2}", + 'zhecyrillic' => "\x{0436}", + 'zhedescendercyrillic' => "\x{0497}", + 'zhedieresiscyrillic' => "\x{04DD}", + 'zihiragana' => "\x{3058}", + 'zikatakana' => "\x{30B8}", + 'zinorhebrew' => "\x{05AE}", + 'zlinebelow' => "\x{1E95}", + 'zmonospace' => "\x{FF5A}", + 'zohiragana' => "\x{305E}", + 'zokatakana' => "\x{30BE}", + 'zparen' => "\x{24B5}", + 'zretroflexhook' => "\x{0290}", + 'zstroke' => "\x{01B6}", + 'zuhiragana' => "\x{305A}", + 'zukatakana' => "\x{30BA}", + ); + +# Add to this list the glyphs for new fonts (from aglfn13): + +map { $agl{$names{$_}} = pack('U',hex ($_))} (keys %names); + + +# %doubles = (map{$_ => "uni$_"} qw(0394 03A9 0162 2215 00AD 02C9 03BC 2219 00A0 0163)); + +=head2 lookup ( $usv [, $noAlt [, $noUni] ]) + +return the Adobe-recommended glyph name for a specific Unicode codepoint (integer). By default +returns C names rather than C or C names + +If C<$noAlt> is true, C and C names are returned rather than C. + +if C<$noUni> is true, returns undef if it would have to resort to C or C +style names. Essentially this represents a straight lookup in the Adobe-recommended list. + +=cut + +sub lookup +{ + my ($num, $noalt, $noUni) = @_; + my ($val) = sprintf("%04X", $num); + + if (defined $names{$val}) + { + return $names{$val} if ($noalt || $names{$val} !~ m/^(?:afii|SF)/o); + } + return undef if $noUni; + if ($num > 0xFFFF) + { return "u$val"; } + elsif ($num) + { return "uni$val"; } + else + { return ".notdef"; } +} + +=head2 parse ( $glyphname ) + +Parse an Adobe-conformant glyph name, generating a Unicode codepoint sequence equivalent to the glyph (or +glyph components, should the name represent a ligature). In scalar context, returns a reference to an +array of Unicodes (decimal). Array is empty if the glyph name is non-conformant. +In list context, the first item returned is the same array reference as above. The second item +is a reference to an array containing the extensions (if any) present on the glyph name. +The '.' that precedes each extension is not included. + +=cut + +sub parse +{ + my ($gname, @USVs, @extensions); + ($gname, @extensions) = split('\.', $_[0]); + # if name originally started with . (e.g., .null) then $gname will now be '' ... need to fix that up: + $gname = '.' . shift(@extensions) if $gname eq ''; + if (defined $gname) + { + foreach $gname (split('_', $gname)) + { + if ($gname =~ /^u[0-9a-fA-F]{4,6}$/) + { + push @USVs, hex(substr($gname, 1)); + } + elsif ($gname =~ /^uni([0-9a-fA-F]{4,4})+$/) + { + push @USVs, map {hex($_)} ($gname =~ /([0-9a-fA-F]{4,4})/g) + } + elsif (exists $agl{$gname}) + { + push @USVs, unpack ('U*', $agl{$gname}); + } + } + } + return \@USVs unless wantarray; + my @res = (\@USVs, \@extensions); + return @res; +} + +#Code used to parse Adobe's agl file and generate text for %agl initialization: +#while () { +# chomp; +# next if m/^#/; +# my ($gname, @nums) = split(/[; ]/); +# if ($#nums > 0 or !defined ($Font::TTF::PSNames::names{$nums[0]}) or $Font::TTF::PSNames::names{$nums[0]} ne $gname) +# { +# print "\t'$gname' => \""; +# map {print "\\x{$_}" } @nums; +# print "\",\n"; +# } +# } + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Post.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Post.pm new file mode 100644 index 0000000000..a3f29e2705 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Post.pm @@ -0,0 +1,329 @@ +package Font::TTF::Post; + +=head1 NAME + +Font::TTF::Post - Holds the Postscript names for each glyph + +=head1 DESCRIPTION + +Holds the postscript names for glyphs. Note that they are not held as an +array, but as indexes into two lists. The first list is the standard Postscript +name list defined by the TrueType standard. The second comes from the font +directly. + +Looking up a glyph from a Postscript name or a name from a glyph number is +achieved through methods rather than variable lookup. + +This class handles PostScript table types of 1, 2, 2.5 & 3, but not version 4. +Support for version 2.5 is as per Apple spec rather than MS. + +The way to look up Postscript names or glyphs is: + + $pname = $f->{'post'}{'VAL'}[$gnum]; + $gnum = $f->{'post'}{'STRINGS'}{$pname}; + +=head1 INSTANCE VARIABLES + +Due to different systems having different limitations, there are various class +variables available to control what post table types can be written. + +=over 4 + +=item $Font::TTF::Post::no25 + +If set tells Font::TTF::Post::out to use table type 2 instead of 2.5 in case apps +cannot handle version 2.5. + +=item VAL + +Contains an array indexed by glyph number of Postscript names. This is used when +writing out a font. + +=item STRINGS + +An associative array of Postscript names mapping to the highest glyph with that +name. These may not be in sync with VAL. + +=back + +In addition there are the standard introductory variables defined in the +standard: + + FormatType + italicAngle + underlinePosition + underlineThickness + isFixedPitch + minMemType42 + maxMemType42 + minMemType1 + maxMemType1 + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA @base_set %base_set %fields $VERSION $no25 @field_info @base_set); +require Font::TTF::Table; +use Font::TTF::Utils; + +$no25 = 1; # officially deprecated format 2.5 tables in MS spec 1.3 + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'FormatType' => 'f', + 'italicAngle' => 'f', + 'underlinePosition' => 's', + 'underlineThickness' => 's', + 'isFixedPitch' => 'L', + 'minMemType42' => 'L', + 'maxMemType42' => 'L', + 'minMemType1' => 'L', + 'maxMemType1' => 'L'); +@base_set = qw(.notdef .null nonmarkingreturn space exclam quotedbl numbersign dollar percent ampersand quotesingle + parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six + seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q + R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore grave a b c d e f g h + i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde Adieresis Aring Ccedilla + Eacute Ntilde Odieresis Udieresis aacute agrave acircumflex adieresis atilde aring ccedilla eacute + egrave ecircumflex edieresis iacute igrave icircumflex idieresis ntilde oacute ograve ocircumflex + odieresis otilde uacute ugrave ucircumflex udieresis dagger degree cent sterling section bullet + paragraph germandbls registered copyright trademark acute dieresis notequal AE Oslash infinity + plusminus lessequal greaterequal yen mu partialdiff summation product pi integral ordfeminine + ordmasculine Omega ae oslash questiondown exclamdown logicalnot radical florin approxequal + Delta guillemotleft guillemotright ellipsis nonbreakingspace Agrave Atilde Otilde OE oe endash emdash + quotedblleft quotedblright quoteleft quoteright divide lozenge ydieresis Ydieresis fraction currency + guilsinglleft guilsinglright fi fl daggerdbl periodcentered quotesinglbase quotedblbase perthousand + Acircumflex Ecircumflex Aacute Edieresis Egrave Iacute Icircumflex Idieresis Igrave Oacute Ocircumflex + apple Ograve Uacute Ucircumflex Ugrave dotlessi circumflex tilde macron breve dotaccent + ring cedilla hungarumlaut ogonek caron Lslash lslash Scaron scaron Zcaron zcaron brokenbar Eth eth + Yacute yacute Thorn thorn minus multiply onesuperior twosuperior threesuperior onehalf onequarter + threequarters franc Gbreve gbreve Idotaccent Scedilla scedilla Cacute cacute Ccaron ccaron dcroat); + +$VERSION = 0.01; # MJPH 5-AUG-1998 Re-organise data structures + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } + $i = 0; + %base_set = map {$_ => $i++} @base_set; +} + + +=head2 $t->read + +Reads the Postscript table into memory from disk + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $dat1, $i, $off, $c, $maxoff, $form, $angle, $numGlyphs); + my ($fh) = $self->{' INFILE'}; + + $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + init unless ($fields{'FormatType'}); + $fh->read($dat, 32); + TTF_Read_Fields($self, $dat, \%fields); + + if (int($self->{'FormatType'} + .5) == 1) + { + for ($i = 0; $i < 258; $i++) + { + $self->{'VAL'}[$i] = $base_set[$i]; + $self->{'STRINGS'}{$base_set[$i]} = $i unless (defined $self->{'STRINGS'}{$base_set[$i]}); + } + } elsif (int($self->{'FormatType'} * 2 + .1) == 5) + { + $fh->read($dat, 2); + $numGlyphs = unpack("n", $dat); + $fh->read($dat, $numGlyphs); + for ($i = 0; $i < $numGlyphs; $i++) + { + $off = unpack("c", substr($dat, $i, 1)); + $self->{'VAL'}[$i] = $base_set[$i + $off]; + $self->{'STRINGS'}{$base_set[$i + $off]} = $i unless (defined $self->{'STRINGS'}{$base_set[$i + $off]}); + } + } elsif (int($self->{'FormatType'} + .5) == 2) + { + my (@strings); + + $fh->read($dat, ($numGlyphs + 1) << 1); + for ($i = 0; $i < $numGlyphs; $i++) + { + $off = unpack("n", substr($dat, ($i + 1) << 1, 2)); + $maxoff = $off if (!defined $maxoff || $off > $maxoff); + } + for ($i = 0; $i < $maxoff - 257; $i++) + { + $fh->read($dat1, 1); + $off = unpack("C", $dat1); + $fh->read($dat1, $off); + $strings[$i] = $dat1; + } + for ($i = 0; $i < $numGlyphs; $i++) + { + $off = unpack("n", substr($dat, ($i + 1) << 1, 2)); + if ($off > 257) + { + $self->{'VAL'}[$i] = $strings[$off - 258]; + $self->{'STRINGS'}{$strings[$off - 258]} = $i; + } + else + { + $self->{'VAL'}[$i] = $base_set[$off]; + $self->{'STRINGS'}{$base_set[$off]} = $i unless (defined $self->{'STRINGS'}{$base_set[$off]}); + } + } + } + $self; +} + + +=head2 $t->out($fh) + +Writes out a new Postscript name table from memory or copies from disk + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i, $num); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + init unless ($fields{'FormatType'}); + + for ($i = $#{$self->{'VAL'}}; !defined $self->{'VAL'}[$i] && $i > 0; $i--) + { pop(@{$self->{'VAL'}}); } + if ($#{$self->{'VAL'}} < 0) + { $self->{'FormatType'} = 3; } + else + { + $self->{'FormatType'} = 1; + for ($i = 0; $i < $num; $i++) + { + if (!defined $base_set{$self->{'VAL'}[$i]}) + { + $self->{'FormatType'} = 2; + last; + } + elsif ($base_set{$self->{'VAL'}[$i]} != $i) + { $self->{'FormatType'} = ($no25 ? 2 : 2.5); } + } + } + + $fh->print(TTF_Out_Fields($self, \%fields, 32)); + + return $self if (int($self->{'FormatType'} + .4) == 3); + + if (int($self->{'FormatType'} + .5) == 2) + { + my (@ind); + my ($count) = 0; + + $fh->print(pack("n", $num)); + for ($i = 0; $i < $num; $i++) + { + if (defined $base_set{$self->{'VAL'}[$i]}) + { $fh->print(pack("n", $base_set{$self->{'VAL'}[$i]})); } + else + { + $fh->print(pack("n", $count + 258)); + $ind[$count++] = $i; + } + } + for ($i = 0; $i < $count; $i++) + { + $fh->print(pack("C", length($self->{'VAL'}[$ind[$i]]))); + $fh->print($self->{'VAL'}[$ind[$i]]); + } + } elsif (int($self->{'FormatType'} * 2 + .5) == 5) + { + $fh->print(pack("n", $num)); + for ($i = 0; $i < $num; $i++) + { $fh->print(pack("c", defined $base_set{$self->{'VAL'}[$i]} ? + $base_set{$self->{'VAL'}[$i]} - $i : -$i)); } + } + + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $val) + +Outputs the names as one block of XML + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $val) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self->SUPER::XML_element(@_) unless ($key eq 'STRINGS' || $key eq 'VAL'); + return unless ($key eq 'VAL'); + + $fh->print("$depth\n"); + for ($i = 0; $i <= $#{$self->{'VAL'}}; $i++) + { $fh->print("$depth$context->{'indent'}\n"); } + $fh->print("$depth\n"); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 32; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +No support for type 4 tables + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Prep.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Prep.pm new file mode 100644 index 0000000000..dae719369e --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Prep.pm @@ -0,0 +1,99 @@ +package Font::TTF::Prep; + +=head1 NAME + +Font::TTF::Prep - Preparation hinting program. Called when ppem changes + +=head1 DESCRIPTION + +This is a minimal class adding nothing beyond a table, but is a repository +for prep type information for those processes brave enough to address hinting. + +=cut + +use strict; +use vars qw(@ISA $VERSION); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +$VERSION = 0.0001; + + +=head2 $t->read + +Reads the data using C. + +=cut + +sub read +{ + $_[0]->read_dat; + $_[0]->{' read'} = 1; +} + + +=head2 $t->out_xml($context, $depth) + +Outputs Prep program as XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($dat); + + $self->read; + $dat = Font::TTF::Utils::XML_binhint($self->{' dat'}); + $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg; + $fh->print("$depth\n"); + $fh->print("$depth$context->{'indent'}$dat"); + $fh->print("$depth\n"); + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Parse all that hinting code + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'code') + { + $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'}); + return $context; + } else + { return $self->SUPER::XML_end(@_); } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Prop.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Prop.pm new file mode 100644 index 0000000000..16c4dcc723 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Prop.pm @@ -0,0 +1,179 @@ +package Font::TTF::Prop; + +=head1 NAME + +Font::TTF::Prop - Glyph Properties table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +=item default + +=item lookup + +Hash of property values keyed by glyph number + +=item lookupFormat + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Segarr; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh); + my ($version, $lookupPresent, $default); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + $fh->read($dat, 8); + ($version, $lookupPresent, $default) = TTF_Unpack("vSS", $dat); + + if ($lookupPresent) { + my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{' LENGTH'} - 8, $default); + $self->{'lookup'} = $lookup; + $self->{'format'} = $format; + } + + $self->{'version'} = $version; + $self->{'default'} = $default; + + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($default, $lookup); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $default = $self->{'default'}; + $lookup = $self->{'lookup'}; + $fh->print(TTF_Pack("vSS", $self->{'version'}, (defined $lookup ? 1 : 0), $default)); + + AAT_write_lookup($fh, $self->{'format'}, $lookup, 2, $default) if (defined $lookup); +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($lookup); + + $self->read; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\ndefault %04x # %s\n", $self->{'version'}, $self->{'default'}, meaning_($self->{'default'})); + $lookup = $self->{'lookup'}; + if (defined $lookup) { + $fh->printf("format %d\n", $self->{'format'}); + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\t%d -> %04x # %s\n", $_, $lookup->{$_}, meaning_($lookup->{$_})); + } + } +} + +sub meaning_ +{ + my ($val) = @_; + my ($res); + + my @types = ( + "Strong left-to-right", + "Strong right-to-left", + "Arabic letter", + "European number", + "European number separator", + "European number terminator", + "Arabic number", + "Common number separator", + "Block separator", + "Segment separator", + "Whitespace", + "Other neutral"); + $res = $types[$val & 0x001f] or ("Undefined [" . ($val & 0x001f) . "]"); + + $res .= ", floater" if $val & 0x8000; + $res .= ", hang left" if $val & 0x4000; + $res .= ", hang right" if $val & 0x2000; + $res .= ", attaches on right" if $val & 0x0080; + $res .= ", pair" if $val & 0x1000; + my $pairOffset = ($val & 0x0f00) >> 8; + $pairOffset = $pairOffset - 16 if $pairOffset > 7; + $res .= $pairOffset > 0 ? " +" . $pairOffset : $pairOffset < 0 ? " " . $pairOffset : ""; + + $res; +} + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Segarr.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Segarr.pm new file mode 100644 index 0000000000..514b605e13 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Segarr.pm @@ -0,0 +1,385 @@ +package Font::TTF::Segarr; + +=head1 NAME + +Font::TTF::Segarr - Segmented array + +=head1 DESCRIPTION + +Holds data either directly or indirectly as a series of arrays. This class +looks after the set of arrays and masks the individual sub-arrays, thus saving +a class, we hope. + +=head1 INSTANCE VARIABLES + +All instance variables do not start with a space. + +The segmented array is simply an array of segments + +Each segment is a more complex affair: + +=over 4 + +=item START + +In terms of the array, the address for the 0th element in this segment. + +=item LEN + +Number of elements in this segment + +=item VAL + +The array which contains the elements + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@types $VERSION); +$VERSION = 0.0001; + +@types = ('', 'C', 'n', '', 'N'); + +=head2 Font::TTF::Segarr->new($size) + +Creates a new segmented array with a given data size + +=cut + +sub new +{ + my ($class) = @_; + my ($self) = []; + + bless $self, (ref($class) || $class); +} + + +=head2 $s->fastadd_segment($start, $is_sparse, @dat) + +Creates a new segment and adds it to the array assuming no overlap between +the new segment and any others in the array. $is_sparse indicates whether the +passed in array contains Cs or not. If false no checking is done (which +is faster, but riskier). If equal to 2 then 0 is considered undef as well. + +Returns the number of segments inserted. + +=cut + +sub fastadd_segment +{ + my ($self) = shift; + my ($start) = shift; + my ($sparse) = shift; + my ($p, $i, $seg, @seg); + + + if ($sparse) + { + for ($i = 0; $i <= $#_; $i++) + { + if (!defined $seg && (($sparse != 2 && defined $_[$i]) || $_[$i] != 0)) + { $seg->{'START'} = $start + $i; $seg->{'VAL'} = []; } + + if (defined $seg && (($sparse == 2 && $_[$i] == 0) || !defined $_[$i])) + { + $seg->{'LEN'} = $start + $i - $seg->{'START'}; + push(@seg, $seg); + $seg = undef; + } elsif (defined $seg) + { push (@{$seg->{'VAL'}}, $_[$i]); } + } + if (defined $seg) + { + push(@seg, $seg); + $seg->{'LEN'} = $start + $i - $seg->{'START'}; + } + } else + { + $seg->{'START'} = $start; + $seg->{'LEN'} = $#_ + 1; + $seg->{'VAL'} = [@_]; + @seg = ($seg); + } + + for ($i = 0; $i <= $#$self; $i++) + { + if ($self->[$i]{'START'} > $start) + { + splice(@$self, $i, 0, @seg); + return wantarray ? @seg : scalar(@seg); + } + } + push(@$self, @seg); + return wantarray ? @seg : scalar(@seg); +} + + +=head2 $s->add_segment($start, $overwrite, @dat) + +Creates a new segment and adds it to the array allowing for possible overlaps +between the new segment and the existing ones. In the case of overlaps, elements +from the new segment are deleted unless $overwrite is set in which case the +elements already there are over-written. + +This method also checks the data coming in to see if it is sparse (i.e. contains +undef values). Gaps cause new segments to be created or not to over-write existing +values. + +=cut + +sub add_segment +{ + my ($self) = shift; + my ($start) = shift; + my ($over) = shift; + my ($seg, $i, $s, $offset, $j, $newi); + + return $self->fastadd_segment($start, $over, @_) if ($#$self < 0); + $offset = 0; + for ($i = 0; $i <= $#$self && $offset <= $#_; $i++) + { + $s = $self->[$i]; + if ($s->{'START'} <= $start + $offset) # only < for $offset == 0 + { + if ($s->{'START'} + $s->{'LEN'} > $start + $#_) + { + for ($j = $offset; $j <= $#_; $j++) + { + if ($over) + { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; } + else + { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; } + } + $offset = $#_ + 1; + last; + } elsif ($s->{'START'} + $s->{'LEN'} > $start + $offset) # is $offset needed here? + { + for ($j = $offset; $j < $s->{'START'} + $s->{'LEN'} - $start; $j++) + { + if ($over) + { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; } + else + { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; } + } + $offset = $s->{'START'} + $s->{'LEN'} - $start; + } + } else # new seg please + { + if ($s->{'START'} > $start + $#_ + 1) + { + $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $#_]) - 1; + $offset = $#_ + 1; + } + else + { + $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $s->{'START'} - $start]) - 1; + $offset = $s->{'START'} - $start + 1; + } + } + } + if ($offset <= $#_) + { + $seg->{'START'} = $start + $offset; + $seg->{'LEN'} = $#_ - $offset + 1; + $seg->{'VAL'} = [@_[$offset .. $#_]]; + push (@$self, $seg); + } + $self->tidy; +} + + +=head2 $s->tidy + +Merges any immediately adjacent segments + +=cut + +sub tidy +{ + my ($self) = @_; + my ($i, $sl, $s); + + for ($i = 1; $i <= $#$self; $i++) + { + $sl = $self->[$i - 1]; + $s = $self->[$i]; + if ($s->{'START'} == $sl->{'START'} + $sl->{'LEN'}) + { + $sl->{'LEN'} += $s->{'LEN'}; + push (@{$sl->{'VAL'}}, @{$s->{'VAL'}}); + splice(@$self, $i, 1); + $i--; + } + } + $self; +} + + +=head2 $s->at($addr, [$len]) + +Looks up the data held at the given address by locating the appropriate segment +etc. If $len > 1 then returns an array of values, spaces being filled with undef. + +=cut + +sub at +{ + my ($self, $addr, $len) = @_; + my ($i, $dat, $s, @res, $offset); + + $len = 1 unless defined $len; + $offset = 0; + for ($i = 0; $i <= $#$self; $i++) + { + $s = $self->[$i]; + next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset); # only fires on $offset == 0 + if ($s->{'START'} > $addr + $offset) + { + push (@res, (undef) x ($s->{'START'} > $addr + $len ? + $len - $offset : $s->{'START'} - $addr - $offset)); + $offset = $s->{'START'} - $addr; + } + last if ($s->{'START'} >= $addr + $len); + + if ($s->{'START'} + $s->{'LEN'} >= $addr + $len) + { + push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} .. + $addr + $len - $s->{'START'} - 1]); + $offset = $len; + last; + } else + { + push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} .. $s->{'LEN'} - 1]); + $offset = $s->{'START'} + $s->{'LEN'} - $addr; + } + } + push (@res, (undef) x ($len - $offset)) if ($offset < $len); + return wantarray ? @res : $res[0]; +} + + +=head2 $s->remove($addr, [$len]) + +Removes the item or items from addr returning them as an array or the first +value in a scalar context. This is very like C, including padding with +undef, but it deletes stuff as it goes. + +=cut + +sub remove +{ + my ($self, $addr, $len) = @_; + my ($i, $dat, $s, @res, $offset); + + $len = 1 unless defined $len; + $offset = 0; + for ($i = 0; $i <= $#$self; $i++) + { + $s = $self->[$i]; + next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset); + if ($s->{'START'} > $addr + $offset) + { + push (@res, (undef) x ($s->{'START'} > $addr + $len ? + $len - $offset : $s->{'START'} - $addr - $offset)); + $offset = $s->{'START'} - $addr; + } + last if ($s->{'START'} >= $addr + $len); + + unless ($s->{'START'} == $addr + $offset) + { + my ($seg) = {}; + + $seg->{'START'} = $s->{'START'}; + $seg->{'LEN'} = $addr + $offset - $s->{'START'}; + $seg->{'VAL'} = [splice(@{$s->{'VAL'}}, 0, $addr + $offset - $s->{'START'})]; + $s->{'LEN'} -= $addr + $offset - $s->{'START'}; + $s->{'START'} = $addr + $offset; + + splice(@$self, $i, 0, $seg); + $i++; + } + + if ($s->{'START'} + $s->{'LEN'} >= $addr + $len) + { + push (@res, splice(@{$s->{'VAL'}}, 0, $len - $offset)); + $s->{'LEN'} -= $len - $offset; + $s->{'START'} += $len - $offset; + $offset = $len; + last; + } else + { + push (@res, @{$s->{'VAL'}}); + $offset = $s->{'START'} + $s->{'LEN'} - $addr; + splice(@$self, $i, 0); + $i--; + } + } + push (@res, (undef) x ($len - $offset)) if ($offset < $len); + return wantarray ? @res : $res[0]; +} + + +=head2 $s->copy + +Deep copies this array + +=cut + +sub copy +{ + my ($self) = @_; + my ($res, $p); + + $res = []; + foreach $p (@$self) + { push (@$res, $self->copy_seg($p)); } + $res; +} + + +=head2 $s->copy_seg($seg) + +Creates a deep copy of a segment + +=cut + +sub copy_seg +{ + my ($self, $seg) = @_; + my ($p, $res); + + $res = {}; + $res->{'VAL'} = [@{$seg->{'VAL'}}]; + foreach $p (keys %$seg) + { $res->{$p} = $seg->{$p} unless defined $res->{$p}; } + $res; +} + + +1; + +=head1 BUGS + +No known bugs. + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Silf.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Silf.pm new file mode 100644 index 0000000000..9244c68934 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Silf.pm @@ -0,0 +1,900 @@ +package Font::TTF::Silf; + +=head1 NAME + +Font::TTF::Silf - The main Graphite table + +=head1 DESCRIPTION + +The Silf table holds the core of the Graphite rules for a font. A Silf table has +potentially multiple silf subtables, although there is usually only one. Within a silf subtable, +there are a number of passes which contain the actual finite state machines to match rules +and the constraint and action code to be executed when a rule matches. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item Version + +Silf table format version + +=item Compiler + +Lowest compiler version necessary to fully support the semantics expressed in this +Graphite description + +=item SILF + +An array of Silf subtables + +=over 4 + +=item maxGlyphID + +The maximum glyph id referenced including pseudo and non glyphs + +=item Ascent + +Extra ascent to be added to the font ascent. + +=item Descent + +Extra descent to be added to the font descent. Both values are assumed to be +positive for a descender below the base line. + +=item substPass + +Pass index into PASS of the first substitution pass. + +=item posPass + +Pass index into PASS of the first positioning pass. + +=item justPass + +Pass index into PASS of the first justification pass. + +=item bidiPass + +Pass index of the pass before which the bidirectional processing pass will be executed. +0xFF indicates that there is no bidi pass to be executed. + +=item Flags + +A bitfield of flags: + + 0 - Indicates there are line end contextual rules in one of the passes + +=item maxPreContext + +Maximum length of a context preceding a cross line boundary contextualisation. + +=item maxPostContext + +Maximum length of a context following a cross line boundary contextualsation. + +=item attrPseudo + +Glyph attribute for the actual glyph id associated with a pseudo glyph. + +=item attrBreakWeight + +Glyph attribute number of the attribute holding the default breakweight associated with a glyph. + +=item attrDirectionality + +Glyph attribute number of the attribute holding the default directionality value associated with a glyph. + +=item JUST + +The may be a number of justification levels each with their own property values. +This points to an array of hashes, one for each justification level. + +=over 4 + +=item attrStretch + +Glyph attribute number for the amount of stretch allowed before this glyph. + +=item attrShrink + +Glyph attribute number for the amount of shrink allowed before this glyph. + +=item attrStep + +Glyph attribute number specifying the minimum granularity of actual spacing associated with this glyph at this level. + +=item attrWeight + +Glyph attribute number giving the weight associated with spreading space across a run of glyphs. + +=item runto + +Which level starts the next stage. + +=back + +=item numLigComp + +Number of initial glyph attributes that represent ligature components + +=item numUserAttr + +Number of user defined slot attributes referenced. Tells the engine how much space to +allocate to a slot for user attributes. + +=item maxCompPerLig + +Maximum number of components per ligature. + +=item direction + +Supported directions for this writing system + +=item CRIT_FEATURE + +Array of critical features. + +=item scripts + +Array of script tags that indicate which set of GDL rules to execute if there is more than one in a font. + +=item lbGID + +Glyph ID of the linebreak pseudo glyph. + +=item pseudos + +Hash of Unicode values to pseduo glyph ids. + +=item classes + +This is an array of classes, each of which is an array of glyph ids in class order. + +=item PASS + +The details of rules and actions are stored in passes. This value is an array of pass subobjects one for each pass. + +=over 4 + +=item flags + +This is a bitfield: + + 0 - If true, this pass makes no change to the slot stream considered as a sequence of glyph ids. + Only slot attributes are expected to change (for example during positioning). + +=item maxRuleLoop + +How many times the engine will allow rules to be tested and run without the engine advancing through the +input slot stream. + +=item maxRuleContext + +Number of slots of input needed to run this pass. + +=item maxBackup + +Number of slots by which the following pass needs to trail this pass (i.e. the maximum this pass is allowed to back up). + +=item numRules + +Number of action code blocks, and so uncompressed rules, in this pass. + +=item numRows + +Number of rows in the finite state machine. + +=item numTransitional + +Number of rows in the finite state machine that are not final states. This specifies the number of rows in the fsm +element. + +=item numSuccess + +Number of success states. A success state may also be a transitional state. + +=item numColumns + +Number of columns in the finite state machine. + +=item colmap + +A hash, indexed by glyphid, that gives the fsm column number associated with that glyphid. If not present, then +the glyphid is not part of the fsm and will finish fsm processing if it occurs. + +=item rulemap + +An array of arrays, one for each success state. Each array holds a list of rule numbers associated with that state. + +=item minRulePreContext + +Minimum number of items in a rule's precontext. + +=item maxRulePreContext + +The maximum number of items in any rule's precontext. + +=item startStates + +Array of starting state numbers dependeing on the length of actual precontext. +There are maxRulePreContext - minRulePreContext + 1 of these. + +=item ruleSortKeys + +An array of sort keys one for each rule giving the length of the rule including its precontext. + +=item rulePreContexts + +An array of precontext lengths for each rule. + +=item fsm + +A two dimensional array such that $p->{'fsm'}[$row][$col] gives the row of the next node to try in the fsm. + +=item passConstraintLen + +Length in bytes of the passConstraint code. + +=item passConstraintCode + +A byte string holding the pass constraint code. + +=item constraintCode + +An array of byte strings holding the constraint code for each rule. + +=item actionCode + +An array of byte strings holding the action code for each rule. + +=back + +=back + +=back + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use strict; +use vars qw(@ISA); + +@ISA = qw(Font::TTF::Table); + +=head2 @opcodes + +Each array holds the name of the opcode, the number of operand bytes and a string describing the operands. +The characters in the string have the following meaning: + + c - lsb of class id + C - msb of class id + f - feature index + g - lsb of glyph attribute id + G - msb of glyph attribute id + l - lsb of a 32-bit extension to a 16-bit number + L - msb of a 32-bit number + m - glyph metric id + n - lsb of a number + N - msb of a 16-bit number + o - offset (jump) + s - slot reference + S - slot attribute id + v - variable number of following arguments + +=cut + +our @opcodes = ( ["nop", 0, ""], ["push_byte", 1, "n"], ["push_byte_u", 1, "n"], ["push_short", 2, "Nn"], + ["push_short_u", 2, "Nn"], ["push_long", 4, "LlNn"], ["add", 0, ""], ["sub", 0, ""], + ["mul", 0, ""], ["div", 0, ""], ["min", 0, ""], ["max", 0, ""], + ["neg", 0, ""], ["trunc8", 0, ""], ["trunc16", 0, ""], ["cond", 0, ""], + ["and", 0, ""], ["or", 0, ""], ["not", 0, ""], ["equal", 0, ""], # 16 + ["not_eq", 0, ""], ["less", 0, ""], ["gtr", 0, ""], ["less_eq", 0, ""], + ["gtr_eq", 0, ""], ["next", 0, ""], ["next_n", 1, "n"], ["copy_next", 0, ""], + ["put_glyph_8bit_obs", 1, "c"], ["put_subs_8bit_obs", 3, "scc"], ["put_copy", 1, "s"], ["insert", 0, ""], + ["delete", 0, ""], ["assoc", -1, "v"], ["cntxt_item", 2, "so"], ["attr_set", 1, "S"], # 32 + ["attr_add", 1, "S"], ["attr_sub", 1, "S"], ["attr_set_slot", 1, "S"], ["iattr_set_slot", 2, "Sn"], + ["push_slot_attr", 2, "Ss"], ["push_glyph_attr_obs", 2, "gs"], ["push_glyph_metric", 3, "msn"], ["push_feat", 2, "fs"], + ["push_att_to_gattr_obs", 2, "gs"], ["push_att_to_glyph_metric", 3, "msn"], ["push_islot_attr", 3, "Ssn"], ["push_iglyph_attr", 3, "gsn"], + ["pop_ret", 0, ""], ["ret_zero", 0, ""], ["ret_true", 0, ""], ["iattr_set", 2, "Sn"], # 48 + ["iattr_add", 2, "Sn"], ["iattr_sub", 2, "Sn"], ["push_proc_state", 1, "n"], ["push_version", 0, ""], + ["put_subs", 5, "sCcCc"], ["put_subs2", 4, "cscc"], ["put_subs3", 7, "scscscc"], ["put_glyph", 2, "Cc"], + ["push_glyph_attr", 3, "Ggs"], ["push_att_to_glyph_attr", 3, "Ggs"], ["bitand", 0, ""], ["bitor", 0, ""], + ["bitnot", 0, ""], ["setbits", 4, "NnNn"], ["setfeat", 2, "fs"] ); # 64 + +my ($i) = 0; +our %opnames = map {$_->[0] => $i++} @opcodes; + +=head2 read + +Reads the Silf table into the internal data structure + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $d); + my ($fh) = $self->{' INFILE'}; + my ($moff) = $self->{' OFFSET'}; + my ($numsilf, @silfo); + + $fh->read($dat, 4); + ($self->{'Version'}) = TTF_Unpack("v", $dat); + if ($self->{'Version'} >= 3) + { + $fh->read($dat, 4); + ($self->{'Compiler'}) = TTF_Unpack("v", $dat); + } + $fh->read($dat, 4); + ($numsilf) = TTF_Unpack("S", $dat); + $fh->read($dat, $numsilf * 4); + foreach my $i (0 .. $numsilf - 1) + { push (@silfo, TTF_Unpack("L", substr($dat, $i * 4, 4))); } + + foreach my $sili (0 .. $numsilf - 1) + { + my ($silf) = {}; + my (@passo, @classo, $classbase, $numJust, $numCritFeatures, $numScript, $numPasses, $numPseudo, $i); + + push (@{$self->{'SILF'}}, $silf); + $fh->seek($moff + $silfo[$sili], 0); + if ($self->{'Version'} >= 3) + { + $fh->read($dat, 8); + ($silf->{'Version'}) = TTF_Unpack("v", $dat); + } + $fh->read($dat, 20); + ($silf->{'maxGlyphID'}, $silf->{'Ascent'}, $silf->{'Descent'}, + $numPasses, $silf->{'substPass'}, $silf->{'posPass'}, $silf->{'justPass'}, $silf->{'bidiPass'}, + $silf->{'Flags'}, $silf->{'maxPreContext'}, $silf->{'maxPostContext'}, $silf->{'attrPseudo'}, + $silf->{'attrBreakWeight'}, $silf->{'attrDirectionality'}, $silf->{'attrMirror'}, $silf->{'passBits'}, $numJust) = + TTF_Unpack("SssCCCCCCCCCCCCCC", $dat); + if ($numJust) + { + foreach my $j (0 .. $silf->{'numJust'} - 1) + { + my ($just) = {}; + push (@{$silf->{'JUST'}}, $just); + $fh->read($dat, 8); + ($just->{'attrStretch'}, $just->{'attrShrink'}, $just->{'attrStep'}, $just->{'attrWeight'}, + $just->{'runto'}) = TTF_Unpack("CCCCC", $dat); + } + } + $fh->read($dat, 10); + ($silf->{'numLigComp'}, $silf->{'numUserAttr'}, $silf->{'maxCompPerLig'}, $silf->{'direction'}, + $silf->{'attCollisions'}, $d, $d, $d, $numCritFeatures) = TTF_Unpack("SCCCCCCCC", $dat); + if ($numCritFeatures) + { + $fh->read($dat, $numCritFeatures * 2); + $silf->{'CRIT_FEATURE'} = [TTF_Unpack("S$numCritFeatures", $dat)]; + } + $fh->read($dat, 2); + ($d, $numScript) = TTF_Unpack("CC", $dat); + if ($numScript) + { + $fh->read($dat, $numScript * 4); + foreach (0 .. $numScript - 1) + { push (@{$silf->{'scripts'}}, unpack('a4', substr($dat, $_ * 4, 4))); } + } + $fh->read($dat, 2); + ($silf->{'lbGID'}) = TTF_Unpack("S", $dat); + $fh->read($dat, $numPasses * 4 + 4); + @passo = unpack("N*", $dat); + $fh->read($dat, 8); + ($numPseudo) = TTF_Unpack("S", $dat); + if ($numPseudo) + { + $fh->read($dat, $numPseudo * 6); + foreach (0 .. $numPseudo - 1) + { + my ($uni, $gid) = TTF_Unpack("LS", substr($dat, $_ * 6, 6)); + $silf->{'pseudos'}{$uni} = $gid; + } + } + $classbase = $fh->tell(); + $fh->read($dat, 4); + my ($numClasses, $numLinearClasses) = TTF_Unpack("SS", $dat); + $silf->{'numLinearClasses'} = $numLinearClasses; + $fh->read($dat, ($numClasses + 1) * ($self->{'Version'} >= 4 ? 4 : 2)); + @classo = unpack($self->{'Version'} >= 4 ? "N*" : "n*", $dat); + $fh->read($dat, $classo[-1] - $classo[0]); + for ($i = 0; $i < $numLinearClasses; $i++) + { + push (@{$silf->{'classes'}}, [unpack("n*", substr($dat, $classo[$i] - $classo[0], + $classo[$i+1] - $classo[$i]))]) + } + for ($i = $numLinearClasses; $i < $numClasses; $i++) + { + my (@res); + my (@c) = unpack("n*", substr($dat, $classo[$i] - $classo[0] + 8, $classo[$i+1] - $classo[$i] - 8)); + for (my $j = 0; $j < @c; $j += 2) + { $res[$c[$j+1]] = $c[$j]; } + push (@{$silf->{'classes'}}, \@res); + } + foreach (0 .. $numPasses - 1) + { $self->read_pass($fh, $passo[$_], $moff + $silfo[$sili], $silf, $_); } + } + return $self; +} + +sub chopcode +{ + my ($dest, $dat, $offsets, $isconstraint) = @_; + my ($last) = $offsets->[-1]; + my ($i); + + for ($i = $#{$offsets} - 1; $i >= 0; $i--) + { + if ((!$isconstraint || $offsets->[$i]) && $offsets->[$i] != $last) + { + unshift(@{$dest}, substr($dat, $offsets->[$i], $last - $offsets->[$i])); + $last = $offsets->[$i]; + } + else + { unshift(@{$dest}, ""); } + } +} + + +sub read_pass +{ + my ($self, $fh, $offset, $base, $silf, $id) = @_; + my ($pass) = {'id' => $id}; + my ($d, $dat, $i, @orulemap, @oconstraints, @oactions, $numRanges); + + $fh->seek($offset + $base, 0); + # printf "pass base = %04X\n", $offset; + push (@{$silf->{'PASS'}}, $pass); + $fh->read($dat, 40); + ($pass->{'flags'}, $pass->{'maxRuleLoop'}, $pass->{'maxRuleContext'}, $pass->{'maxBackup'}, + $pass->{'numRules'}, $d, $d, $d, $d, $d, $pass->{'numRows'}, $pass->{'numTransitional'}, + $pass->{'numSuccess'}, $pass->{'numColumns'}, $numRanges) = + TTF_Unpack("CCCCSSLLLLSSSSS", $dat); + $fh->read($dat, $numRanges * 6); + foreach $i (0 .. $numRanges - 1) + { + my ($first, $last, $col) = TTF_Unpack('SSS', substr($dat, $i * 6, 6)); + foreach ($first .. $last) + { $pass->{'colmap'}{$_} = $col; } + } + $fh->read($dat, $pass->{'numSuccess'} * 2 + 2); + @orulemap = unpack("n*", $dat); + $fh->read($dat, $orulemap[-1] * 2); + foreach (0 .. $pass->{'numSuccess'} - 1) + { push (@{$pass->{'rulemap'}}, [unpack("n*", substr($dat, $orulemap[$_] * 2, ($orulemap[$_+1] - $orulemap[$_]) * 2))]); } + $fh->read($dat, 2); + ($pass->{'minRulePreContext'}, $pass->{'maxRulePreContext'}) = TTF_Unpack("CC", $dat); + $fh->read($dat, ($pass->{'maxRulePreContext'} - $pass->{'minRulePreContext'} + 1) * 2); + $pass->{'startStates'} = [unpack('n*', $dat)]; + $fh->read($dat, $pass->{'numRules'} * 2); + $pass->{'ruleSortKeys'} = [unpack('n*', $dat)]; + $fh->read($dat, $pass->{'numRules'}); + $pass->{'rulePreContexts'} = [unpack('C*', $dat)]; + $fh->read($dat, 3); + ($pass->{'collisionThreshold'}, $pass->{'passConstraintLen'}) = TTF_Unpack("CS", $dat); + $fh->read($dat, ($pass->{'numRules'} + 1) * 2); + @oconstraints = unpack('n*', $dat); + $fh->read($dat, ($pass->{'numRules'} + 1) * 2); + @oactions = unpack('n*', $dat); + foreach (0 .. $pass->{'numTransitional'} - 1) + { + $fh->read($dat, $pass->{'numColumns'} * 2); + push (@{$pass->{'fsm'}}, [unpack('n*', $dat)]); + } + $fh->read($dat, 1); + if ($pass->{'passConstraintLen'}) + { $fh->read($pass->{'passConstraintCode'}, $pass->{'passConstraintLen'}); } + $fh->read($dat, $oconstraints[-1]); + $pass->{'constraintCode'} = []; + chopcode($pass->{'constraintCode'}, $dat, \@oconstraints, 1); + $fh->read($dat, $oactions[-1]); + $pass->{'actionCode'} = []; + chopcode($pass->{'actionCode'}, $dat, \@oactions, 0); + return $pass; +} + +sub chopranges +{ + my ($map, $numg) = @_; + my ($dat, $numRanges); + my (@keys) = sort {$a <=> $b} keys %{$map}; + my ($first, $last, $col, $g); + + $first = -1; + $last = -1; + $col = -1; + foreach $g (@keys) + { + next unless ($g > 0 or $g eq '0'); + if ($g != $last + 1 || $map->{$g} != $col) + { + if ($col != -1) + { + $dat .= pack("nnn", $first, $last, $col); + $numRanges++; + } + $first = $last = $g; + $col = $map->{$g}; + } + else + { $last++; } + } + if ($col != -1) + { + $dat .= pack("nnn", $first, $last, $col); + $numRanges++; + } + return ($numRanges, $dat); +} + +sub unpack_code +{ + my ($self, $str) = @_; + my (@res, $i, $j); + my ($l) = length($str); + + for ($i = 0; $i < $l; ) + { + my ($a) = unpack('C', substr($str, $i, 1)); + my ($o) = $opcodes[$a]; + my (@args); + my (@types) = split('', $o->[2]); + ++$i; + for ($j = 0; $j < @types; ++$j) + { + my ($t) = $types[$j]; + if ($t eq 'v') + { + my ($n) = unpack('C', substr($str, $i, 1)); + push (@args, unpack('C*', substr($str, $i + 1, $n))); + $i += $n + 1; + } + elsif ($t eq 'L' or $t eq 'N' or $t eq 'G' or $t eq 'C') + { + push (@args, unpack('n', substr($str, $i, 2))); + $i += 2; + $j++; + } + else + { + push (@args, unpack($t eq 's' ? 'c' : 'C', substr($str, $i, 1))); + $i++; + } + } + push (@res, [$o->[0], @args]); + } + return @res; +} + +sub pack_code +{ + my ($self, $cmds) = @_; + my ($res); + + foreach my $c (@{$cmds}) + { + my ($ind) = $opnames{$c->[0]}; + my ($i) = 1; + $res .= pack('C', $ind); + # my (@types) = unpack('C*', $opcodes[$ind][2]); + my (@types) = split('', $opcodes[$ind][2]); + for (my $j = 0; $j < @types; $j++) + { + my ($t) = $types[$j]; + if ($t eq 'v') + { + my ($n) = scalar @{$c} - 1; + $res .= pack('C*', $n, @{$c}[1..$#{$c}]); + $i += $n; + } + elsif ($t eq 'C' or $t eq 'G' or $t eq 'L' or $t eq 'N') + { + $res .= pack('n', $c->[$i]); + $j++; + } + else + { $res .= pack($t eq 's' ? 'c' : 'C', $c->[$i]); } + $i++; + } + } + return $res; +} + +sub packcode +{ + my ($code, $isconstraint) = @_; + my ($dat, $c, $res); + + $c = 1; + $dat = "\000"; + foreach (@{$code}) + { + if ($_) + { + push(@{$res}, $c); + $dat .= $_; + $c += length($_); + } + else + { push(@{$res}, $isconstraint ? 0 : $c); } + } + push(@{$res}, $c); + return ($res, $dat); +} + +sub out_pass +{ + my ($self, $fh, $pass, $silf, $subbase) = @_; + my (@orulemap, $dat, $actiondat, $numRanges, $c); + my (@offsets, $res, $pbase); + + $pbase = $fh->tell(); + # printf "pass base = %04X, ", $pbase - $subbase; + $fh->print(TTF_Pack("CCCCSSLLLLSSSS", $pass->{'flags'}, $pass->{'maxRuleLoop'}, $pass->{'maxRuleContext'}, + $pass->{'maxBackup'}, $pass->{'numRules'}, 24, 0, 0, 0, 0, $pass->{'numRows'}, + $pass->{'numTransitional'}, $pass->{'numSuccess'}, $pass->{'numColumns'})); + ($numRanges, $dat) = chopranges($pass->{'colmap'}); +# print "numranges = $numRanges\n"; + $fh->print(TTF_Pack("SSSS", TTF_bininfo($numRanges, 6))); + $fh->print($dat); + $dat = ""; + $c = 0; +# print "transitions = $pass->{'numTransitional'}, success = $pass->{'numSuccess'}, rows = $pass->{'numRows'}\n"; + my ($sucbase) = $pass->{'numRows'} - $pass->{'numSuccess'}; + foreach (0 .. ($pass->{'numSuccess'} - 1)) + { + push(@orulemap, $c); + if (defined $pass->{'rulemap'}[$_]) + { + $dat .= pack("n*", @{$pass->{'rulemap'}[$_]}); + $c += @{$pass->{'rulemap'}[$_]}; + } + else + { + print "No rules for " . ($sucbase + $_); + if ($sucbase + $_ < $pass->{'numTransitional'}) + { print ": (" . join(",", @{$pass->{'fsm'}[$sucbase + $_]}) . ")"; } + print "\n"; + } + } + push (@orulemap, $c); + $fh->print(pack("n*", @orulemap)); + $fh->print($dat); + $fh->print(TTF_Pack("CC", $pass->{'minRulePreContext'}, $pass->{'maxRulePreContext'})); + $fh->print(pack("n*", @{$pass->{'startStates'}})); + $fh->print(pack("n*", @{$pass->{'ruleSortKeys'}})); + $fh->print(pack("C*", @{$pass->{'rulePreContexts'}})); + $fh->print(TTF_Pack("CS", 0, $pass->{'passConstraintLen'})); + my ($oconstraints, $oactions); + ($oconstraints, $dat) = packcode($pass->{'constraintCode'}, 1); + ($oactions, $actiondat) = packcode($pass->{'actionCode'}, 0); +# printf "constraint offsets @ %X\n", $fh->tell(); + $fh->print(pack("n*", @{$oconstraints})); +# printf "action offsets @ %X\n", $fh->tell(); + $fh->print(pack("n*", @{$oactions})); +# printf "fsm @ %X\n", $fh->tell(); + foreach (@{$pass->{'fsm'}}) + { $fh->print(pack("n*", @{$_})); } +# printf "end of fsm @ %X\n", $fh->tell(); + $fh->print(pack("C", $pass->{'collisionThreshold'})); + push(@offsets, $fh->tell() - $subbase); + $fh->print($pass->{'passConstraintCode'}); + push(@offsets, $fh->tell() - $subbase); + $fh->print($dat); + push(@offsets, $fh->tell() - $subbase); + $fh->print($actiondat); + push(@offsets, 0); + print join(", ", @offsets) . "\n"; + $res = $fh->tell(); + $fh->seek($pbase + 8, 0); + $fh->print(pack("N*", @offsets)); + $fh->seek($res, 0); +# printf "end = %04X\n", $res - $subbase; + return $res; +} + +=head2 out + +Outputs a Silf data structure to a font file in binary format + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($silf, $base, $subbase, $silfc, $end); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $base = $fh->tell(); + if ($self->{'Version'} >= 3) + { $fh->print(TTF_Pack("vvSS", $self->{'Version'}, $self->{'Compiler'}, $#{$self->{'SILF'}} + 1, 0)); } + else + { $fh->print(TTF_Pack("vSS", $self->{'Version'}, $#{$self->{'SILF'}} + 1, 0)); } + $fh->print(pack('N*', (0) x (@{$self->{'SILF'}}))); + foreach $silf (@{$self->{'SILF'}}) + { + my ($subbase) = $fh->tell(); + my ($numlin, $i, @opasses, $oPasses, $oPseudo, $ooPasses); + if ($self->{'Version'} >= 3) + { + $fh->seek($base + 12 + $silfc * 4, 0); + $fh->print(pack('N', $subbase - $base)); + $fh->seek($subbase, 0); + $fh->print(TTF_Pack("vSS", $silf->{'Version'}, $ooPasses, $oPseudo)); + } + else + { + $fh->seek($base + 8 + $silfc * 4, 0); + $fh->print(pack('N', $subbase - $base)); + $fh->seek($subbase, 0); + } + $fh->print(TTF_Pack("SssCCCCCCCCCCCCCC", + $silf->{'maxGlyphID'}, $silf->{'Ascent'}, $silf->{'Descent'}, + scalar @{$silf->{'PASS'}}, $silf->{'substPass'}, $silf->{'posPass'}, $silf->{'justPass'}, $silf->{'bidiPass'}, + $silf->{'Flags'}, $silf->{'maxPreContext'}, $silf->{'maxPostContext'}, $silf->{'attrPseudo'}, + $silf->{'attrBreakWeight'}, $silf->{'attrDirectionality'}, $silf->{'attrMirror'}, $silf->{'passBits'}, $#{$silf->{'JUST'}} + 1)); + foreach (@{$silf->{'JUST'}}) + { $fh->print(TTF_Pack("CCCCCCCC", $_->{'attrStretch'}, $_->{'attrShrink'}, $_->{'attrStep'}, + $_->{'attrWeight'}, $_->{'runto'}, 0, 0, 0)); } + + $fh->print(TTF_Pack("SCCCCCCCC", $silf->{'numLigComp'}, $silf->{'numUserAttr'}, $silf->{'maxCompPerLig'}, + $silf->{'direction'}, $silf->{'attCollisions'}, 0, 0, 0, $#{$silf->{'CRIT_FEATURE'}} + 1)); + $fh->print(pack("n*", @{$silf->{'CRIT_FEATURE'}})); + $fh->print(TTF_Pack("CC", 0, $#{$silf->{'scripts'}} + 1)); + foreach (@{$self->{'scripts'}}) + { $fh->print(pack("a4", $_)); } + $fh->print(TTF_Pack("S", $silf->{'lbGID'})); + $ooPasses = $fh->tell(); + if ($silf->{'PASS'}) { $fh->print(pack("N*", (0) x (@{$silf->{'PASS'}} + 1)));} + $oPseudo = $fh->tell() - $subbase; + my (@pskeys) = keys %{$silf->{'pseudos'}}; + $fh->print(TTF_Pack("SSSS", TTF_bininfo(scalar @pskeys, 6))); + foreach my $k (sort {$a <=> $b} @pskeys) + { $fh->print(TTF_Pack("Ls", $k, $silf->{'pseudos'}{$k})); } + $numlin = $silf->{'numLinearClasses'}; + $fh->print(TTF_Pack("SS", scalar @{$silf->{'classes'}}, $numlin)); + my (@coffsets); + # printf "%X, ", $fh->tell() - $base; + my ($cbase) = (scalar @{$silf->{'classes'}} + 1) * ($self->{'Version'} >= 4 ? 4 : 2) + 4; + for ($i = 0; $i < $numlin; $i++) + { + push (@coffsets, $cbase); + $cbase += 2 * scalar @{$silf->{'classes'}[$i]}; + } + my (@nonlinclasses); + for ($i = $numlin; $i < @{$silf->{'classes'}}; $i++) + { + my (@c, $d, @d); + my $c = $silf->{'classes'}[$i]; + push (@coffsets, $cbase); + @c = sort {$c->[$a] <=> $c->[$b]} (0 .. $#{$c}); + foreach $d (@c) + { push (@d, $c->[$d], $d); } + push (@nonlinclasses, [@d]); + my ($len) = scalar @d; + $cbase += 8 + 2 * $len; + } + push (@coffsets, $cbase); + $fh->print(pack(($self->{'Version'} >= 4 ? 'N*' : 'n*'), @coffsets)); + for ($i = 0; $i < $numlin; $i++) + { $fh->print(pack("n*", @{$silf->{'classes'}[$i]})); } + # printf "%X, ", $fh->tell() - $base; + for ($i = $numlin; $i < @{$silf->{'classes'}}; $i++) + { + + my ($num) = scalar @{$nonlinclasses[$i-$numlin]}; + my (@bin) = TTF_bininfo($num/2, 1); + $fh->print(TTF_Pack("SSSS", @bin)); + $fh->print(pack("n*", @{$nonlinclasses[$i-$numlin]})); + } + $oPasses = $fh->tell() - $subbase; +# printf "original pass = %04X\n", $oPasses; + push (@opasses, $oPasses); + foreach (@{$silf->{'PASS'}}) + { push(@opasses, $self->out_pass($fh, $_, $silf, $subbase) - $subbase); } + $end = $fh->tell(); + $fh->seek($ooPasses, 0); + $fh->print(pack("N*", @opasses)); + if ($self->{'Version'} >= 3) + { + $fh->seek($subbase + 4, 0); + $fh->print(TTF_Pack("SS", $ooPasses - $subbase, $oPseudo)); + } + $fh->seek($end, 0); + $silfc++; + } +} + +sub XML_element +{ + my ($self, $context, $depth, $k, $val, $ind) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self if ($k eq 'LOC'); + + if ($k eq 'classes') + { + $fh->print("$depth\n"); + foreach $i (0 .. $#{$val}) + { + $fh->printf("$depth \n", $i); + $fh->printf("$depth " . join(" ", map{sprintf("%d", $_)} @{$val->[$i]})); + $fh->print("\n$depth \n"); + } + $fh->print("$depth\n"); + } + elsif ($k eq 'fsm') + { + $fh->print("$depth\n"); + my ($i) = 0; + foreach (@{$val}) + { $fh->print("$depth " . join(" ", @{$_}) . "\n"); $i++; } + $fh->print("$depth\n"); + } + elsif ($k eq 'colmap') + { + my ($i); + $fh->print("$depth"); + foreach my $k (sort {$a <=> $b} keys %{$val}) + { + if ($i++ % 8 == 0) + { $fh->print("\n$depth "); } + $fh->printf(" %d=%d", $k, $val->{$k}); + } + $fh->print("\n$depth\n"); + } + elsif ($k eq 'constraintCode' or $k eq 'actionCode') + { + $fh->print("$depth<$k>\n"); + foreach my $i (0 .. $#{$val}) + { + my (@rules) = $self->unpack_code($val->[$i]); + next unless (@rules); + $fh->print("$depth [$i])) . "'>\n"); + foreach my $r (@rules) + { $fh->print("$depth $r->[0]: ". join(", ", @{$r}[1..$#{$r}]) . "\n"); } + $fh->print("$depth \n"); + } + $fh->print("$depth\n"); + } + else + { return $self->SUPER::XML_element($context, $depth, $k, $val, $ind); } + + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Sill.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Sill.pm new file mode 100644 index 0000000000..1977709d68 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Sill.pm @@ -0,0 +1,143 @@ +package Font::TTF::Sill; + +=head1 NAME + +Font::TTF::Sill - Graphite language mapping table + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over 4 + +=item version + +Table version number. + +=item langs + +Contains a hash where the key is the language id and the value is an array of +language records + +=back + +=head2 Language Records + +Each language record is itself an array of two values [fid, val]. fid is the +feature id and is held as a long. + +=cut + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +sub read +{ + my ($self) = @_; + my ($num, $i, $j); + + return $self if ($self->{' read'}); + $self->SUPER::read_dat or return $self; + + ($self->{'version'}, $num) = TTF_Unpack("vS", $self->{' dat'}); + + foreach $i (1 .. $num) # ignore bogus entry at end + { + my ($lid, $numf, $offset) = unpack("A4nn", substr($self->{' dat'}, $i * 8 + 4)); # 12 - 8 = 4 since i starts at 1. A4 strips nulls + my (@settings); + + foreach $j (1 .. $numf) + { + my ($fid, $val) = TTF_Unpack("Ls", substr($self->{' dat'}, $offset + $j * 8 - 8)); + push (@settings, [$fid, $val]); + } + $self->{'langs'}{$lid} = [@settings]; + } + delete $self->{' dat'}; + $self->{' read'} = 1; + $self; +} + +sub out +{ + my ($self, $fh) = @_; + my ($num, $range, $select, $shift) = TTF_bininfo(scalar keys %{$self->{'langs'}}, 1); + my ($offset) = $num * 8 + 20; #header = 12, dummy = 8 + my ($k, $s); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $fh->print(TTF_Pack("vSSSS", $self->{'version'}, $num, $range, $select, $shift)); + foreach $k ((sort keys %{$self->{'langs'}}), '+1') + { + my ($numf) = scalar @{$self->{'langs'}{$k}} unless ($k eq '+1'); + $fh->print(pack("a4nn", $k, $numf, $offset)); + $offset += $numf * 8; + } + + foreach $k (sort keys %{$self->{'langs'}}) + { + foreach $s (@{$self->{'langs'}{$k}}) + { $fh->print(TTF_Pack("LsS", @{$s}, 0)); } + } + $self; +} + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $dat) = @_; + my ($fh) = $context->{'fh'}; + my ($k, $s); + + return $self->SUPER::XML_element(@_) unless ($key eq 'langs'); + foreach $k (sort keys %{$self->{'langs'}}) + { + $fh->printf("%s\n", $depth, $k); + foreach $s (@{$self->{'langs'}{$k}}) + { + my ($fid) = $s->[0]; + if ($fid > 0x00FFFFFF) + { $fid = unpack("A4", pack ("N", $fid)); } + else + { $fid = sprintf("%d", $fid); } + $fh->printf("%s%s\n", + $depth, $context->{'indent'}, $fid, $s->[1]); + } + $fh->printf("%s\n", $depth); + } + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Table.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Table.pm new file mode 100644 index 0000000000..5367c6e54f --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Table.pm @@ -0,0 +1,464 @@ +package Font::TTF::Table; + +=head1 NAME + +Font::TTF::Table - Superclass for tables and used for tables we don't have a class for + +=head1 DESCRIPTION + +Looks after the purely table aspects of a TTF table, such as whether the table +has been read before, locating the file pointer, etc. Also copies tables from +input to output. + +=head1 INSTANCE VARIABLES + +Instance variables start with a space + +=over 4 + +=item read + +Flag which indicates that the table has already been read from file. + +=item dat + +Allows the creation of unspecific tables. Data is simply output to any font +file being created. + +=item nocompress + +If set, overrides the font default for WOFF table compression. Is a scalar integer specifying a +table size threshold below which this table will not be compressed. Set to -1 to never +compress; 0 to always compress. + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item LENGTH + +Length in the input directory + +=item ZLENGTH + +Compressed length of the table if a WOFF font. 0 < ZLENGTH < LENGTH implies table is compressed. + +=item CSUM + +Checksum read from the input file's directory + +=item PARENT + +The L that table is part of + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw($VERSION); +use Font::TTF::Utils; +use IO::String; +$VERSION = 0.0001; + +my $havezlib = eval {require Compress::Zlib}; + +=head2 Font::TTF::Table->new(%parms) + +Creates a new table or subclass. Table instance variables are passed in +at this point as an associative array. + +=cut + +sub new +{ + my ($class, %parms) = @_; + my ($self) = {}; + my ($p); + + $class = ref($class) || $class; + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +=head2 $t->read + +Reads the table from the input file. Acts as a superclass to all true tables. +This method marks the table as read and then just sets the input file pointer +but does not read any data. If the table has already been read, then returns +C else returns C<$self> + +For WOFF-compressed tables, the table is first decompressed and a +replacement file handle is created for reading the decompressed data. In this +case ORIGINALOFFSET will preserve the original value of OFFSET for +applications that care. + +=cut + +sub read +{ + my ($self) = @_; + + return $self->read_dat if (ref($self) eq "Font::TTF::Table"); + return undef if $self->{' read'}; + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Uncompress it to memory and create new fh + die ("Cannot uncompress WOFF data: Compress::Zlib not present.\n") unless $havezlib; + $self->{' ORIGINALOFFSET'} = $self->{' OFFSET'}; # Preserve this for those who care + my $dat; + $self->{' INFILE'}->read($dat, $self->{' ZLENGTH'}); + $dat = Compress::Zlib::uncompress($dat); + warn "$self->{' NAME'} table decompressed to wrong length" if $self->{' LENGTH'} != bytes::length($dat); + $self->{' INFILE'} = IO::String->new($dat); + binmode $self->{' INFILE'}; + $self->{' OFFSET'} = 0; + } + $self->{' read'} = 1; + $self; +} + + +=head2 $t->read_dat + +Reads the table into the C instance variable for those tables which don't +know any better + +=cut + +sub read_dat +{ + my ($self) = @_; + +# can't just $self->read here otherwise those tables which start their read sub with +# $self->read_dat are going to permanently loop + return undef if ($self->{' read'}); +# $self->{' read'} = 1; # Let read do this, now out will call us for subclasses + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Uncompress it directly to ' dat' + die ("Cannot uncompress WOFF data: Compress::Zlib not present.\n") unless $havezlib; + my $dat; + $self->{' INFILE'}->read($dat, $self->{' ZLENGTH'}); + $dat = Compress::Zlib::uncompress($dat); + warn "$self->{' NAME'} table decompressed to wrong length" if $self->{' LENGTH'} != bytes::length($dat); + $self->{' dat'} = $dat; + } + else + { + $self->{' INFILE'}->read($self->{' dat'}, $self->{' LENGTH'}); + } + $self; +} + +=head2 $t->out($fh) + +Writes out the table to the font file. If there is anything in the +C instance variable then this is output, otherwise the data is copied +from the input file to the output + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($dat, $i, $len, $count); + + if (defined $self->{' dat'}) + { + $fh->print($self->{' dat'}); + return $self; + } + + return undef unless defined $self->{' INFILE'}; + + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Have to uncompress first + $self->read_dat; + $fh->print($self->{' dat'}); + return $self; + } + + # We don't really have to keep the following code... we could have + # just always done a full read_dat() on the table. But the following + # is more memory-friendly so I've kept it for the more common case + # of non-compressed tables. + + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + $len = $self->{' LENGTH'}; + while ($len > 0) + { + $count = ($len > 4096) ? 4096 : $len; + $self->{' INFILE'}->read($dat, $count); + $fh->print($dat); + $len -= $count; + } + $self; +} + + +=head2 $t->out_xml($context) + +Outputs this table in XML format. The table is first read (if not already read) and then if +there is no subclass, then the data is dumped as hex data + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($k); + + if (ref($self) eq __PACKAGE__) + { + $self->read_dat; + Font::TTF::Utils::XML_hexdump($context, $depth, $self->{' dat'}); + } + else + { + $self->read; + foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self}) + { + $self->XML_element($context, $depth, $k, $self->{$k}); + } + } + $self; +} + + +=head2 $t->XML_element + +Output a particular element based on its contents. + +=cut + +sub XML_element +{ + my ($self, $context, $depth, $k, $dat, $ind) = @_; + my ($fh) = $context->{'fh'}; + my ($ndepth, $d); + + return unless defined $dat; + + if (!ref($dat)) + { + $fh->printf("%s<%s>%s\n", $depth, $k, $dat, $k); + return $self; + } + + if ($ind) + { $fh->printf("%s<%s i='%d'>\n", $depth, $k, $ind); } + else + { $fh->printf("%s<%s>\n", $depth, $k); } + $ndepth = $depth . $context->{'indent'}; + + if (ref($dat) eq 'SCALAR') + { $self->XML_element($context, $ndepth, 'scalar', $$dat); } + elsif (ref($dat) eq 'ARRAY') + { + my ($c) = 1; + foreach $d (@{$dat}) + { $self->XML_element($context, $ndepth, 'elem', $d, $c++); } + } + elsif (ref($dat) eq 'HASH') + { + foreach $d (sort grep {$_ !~ m/^\s/o} keys %{$dat}) + { $self->XML_element($context, $ndepth, $d, $dat->{$d}); } + } + else + { + $context->{'name'} = ref($dat); + $context->{'name'} =~ s/^.*://o; + $dat->out_xml($context, $ndepth); + } + + $fh->printf("%s\n", $depth, $k); + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Handles the default type of for those tables which aren't subclassed + +=cut + +sub XML_end +{ + my ($self, $context, $tag, %attrs) = @_; + my ($dat, $addr); + + return undef unless ($tag eq 'data'); + $dat = $context->{'text'}; + $dat =~ s/([0-9a-f]{2})\s*/hex($1)/oig; + if (defined $attrs{'addr'}) + { $addr = hex($attrs{'addr'}); } + else + { $addr = length($self->{' dat'}); } + substr($self->{' dat'}, $addr, length($dat)) = $dat; + return $context; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 0; +} + +=head2 $t->dirty($val) + +This sets the dirty flag to the given value or 1 if no given value. It returns the +value of the flag + +=cut + +sub dirty +{ + my ($self, $val) = @_; + my ($res) = $self->{' isDirty'}; + + $self->{' isDirty'} = defined $val ? $val : 1; + $res; +} + +=head2 $t->update + +Each table knows how to update itself. This consists of doing whatever work +is required to ensure that the memory version of the table is consistent +and that other parameters in other tables have been updated accordingly. +I.e. by the end of sending C to all the tables, the memory version +of the font should be entirely consistent. + +Some tables which do no work indicate to themselves the need to update +themselves by setting isDirty above 1. This method resets that accordingly. + +=cut + +sub update +{ + my ($self) = @_; + + if ($self->{' isDirty'}) + { + $self->read; + $self->{' isDirty'} = 0; + return $self; + } + else + { return undef; } +} + + +=head2 $t->empty + +Clears a table of all data to the level of not having been read + +=cut + +sub empty +{ + my ($self) = @_; + my (%keep); + + foreach (qw(INFILE LENGTH OFFSET CSUM PARENT)) + { $keep{" $_"} = 1; } + + map {delete $self->{$_} unless $keep{$_}} keys %$self; + $self; +} + + +=head2 $t->release + +Releases ALL of the memory used by this table, and all of its component/child +objects. This method is called automatically by +'Font::TTF::Font-Erelease' (so you don't have to call it yourself). + +B, that it is important that this method get called at some point prior +to the actual destruction of the object. Internally, we track things in a +structure that can result in circular references, and without calling +'C' these will not properly get cleaned up by Perl. Once this +method has been called, though, don't expect to be able to do anything with the +C object; it'll have B internal state whatsoever. + +B As part of the brute-force cleanup done here, this method +will throw a warning message whenever unexpected key values are found within +the C object. This is done to help ensure that any +unexpected and unfreed values are brought to your attention so that you can bug +us to keep the module updated properly; otherwise the potential for memory +leaks due to dangling circular references will exist. + +=cut + +sub release +{ + my ($self) = @_; + +# delete stuff that we know we can, here + + my @tofree = map { delete $self->{$_} } keys %{$self}; + + while (my $item = shift @tofree) + { + my $ref = ref($item); + if (UNIVERSAL::can($item, 'release')) + { $item->release(); } + elsif ($ref eq 'ARRAY') + { push( @tofree, @{$item} ); } + elsif (UNIVERSAL::isa($ref, 'HASH')) + { release($item); } + } + +# check that everything has gone - it better had! + foreach my $key (keys %{$self}) + { warn ref($self) . " still has '$key' key left after release.\n"; } +} + + +sub __dumpvar__ +{ + my ($self, $key) = @_; + + return ($key eq ' PARENT' ? '...parent...' : $self->{$key}); +} + +1; + +=head1 BUGS + +No known bugs + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Ttc.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Ttc.pm new file mode 100644 index 0000000000..116221adb9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Ttc.pm @@ -0,0 +1,176 @@ +package Font::TTF::Ttc; + +=head1 NAME + +Font::TTF::Ttc - Truetype Collection class + +=head1 DESCRIPTION + +A TrueType collection is a collection of TrueType fonts in one file in which +tables may be shared between different directories. In order to support this, +the TTC introduces the concept of a table being shared by different TrueType +fonts. This begs the question of what should happen to the ' PARENT' property +of a particular table. It is made to point to the first directory object which +refers to it. It is therefore up to the application to sort out any confusion. +Confusion only occurs if shared tables require access to non-shared tables. +This should not happen since the shared tables are dealing with glyph +information only and the private tables are dealing with encoding and glyph +identification. Thus the general direction is from identification to glyph and +not the other way around (at least not without knowledge of the particular +context). + +=head1 INSTANCE VARIABLES + +The following instance variables are preceded by a space + +=over 4 + +=item fname (P) + +Filename for this TrueType Collection + +=item INFILE (P) + +The filehandle of this collection + +=back + +The following instance variable does not start with a space + +=over 4 + +=item directs + +An array of directories (Font::TTF::Font objects) for each sub-font in the directory + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw($VERSION); + +use IO::File; + +$VERSION = 0.0001; + +=head2 Font::TTF::Ttc->open($fname) + +Opens and reads the given filename as a TrueType Collection. Reading a collection +involves reading each of the directories which go to make up the collection. + +=cut + +sub open +{ + my ($class, $fname) = @_; + my ($self) = {}; + my ($fh); + + unless (ref($fname)) + { + $fh = IO::File->new($fname) or return undef; + binmode $fh; + } else + { $fh = $fname; } + + bless $self, $class; + $self->{' INFILE'} = $fh; + $self->{' fname'} = $fname; + $fh->seek(0, 0); + $self->read; +} + + +=head2 $c->read + +Reads a Collection by reading all the directories in the collection + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($dat, $ttc, $ver, $num, $i, $loc); + + $fh->read($dat, 12); + ($ttc, $ver, $num) = unpack("A4N2", $dat); + + return undef unless $ttc eq "ttcf"; + $fh->read($dat, $num << 2); + for ($i = 0; $i < $num; $i++) + { + $loc = unpack("N", substr($dat, $i << 2, 4)); + $self->{'directs'}[$i] = Font::TTF::Font->new('INFILE' => $fh, + 'PARENT' => $self, + 'OFFSET' => $loc) || return undef; + } + for ($i = 0; $i < $num; $i++) + { $self->{'directs'}[$i]->read; } + $self; +} + + +=head2 $c->find($direct, $name, $check, $off, $len) + +Hunts around to see if a table with the given characteristics of name, checksum, +offset and length has been associated with a directory earlier in the list. +Actually on checks the offset since no two tables can share the same offset in +a TrueType font, collection or otherwise. + +=cut + +sub find +{ + my ($self, $direct, $name, $check, $off, $len) = @_; + my ($d); + + foreach $d (@{$self->{'directs'}}) + { + return undef if $d eq $direct; + next unless defined $d->{$name}; + return $d->{$name} if ($d->{$name}{' OFFSET'} == $off); + } + undef; # wierd that the font passed is not in the list! +} + + +=head2 $c->DESTROY + +Closees any opened files by us + +=cut + +sub DESTROY +{ + my ($self) = @_; + close ($self->{' INFILE'}) if $self->{' INFILE'}; + undef; +} + +1; + +=head1 BUGS + +No known bugs, but then not ever executed! + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Ttopen.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Ttopen.pm new file mode 100644 index 0000000000..15e0c1460b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Ttopen.pm @@ -0,0 +1,1345 @@ +package Font::TTF::Ttopen; + +=head1 NAME + +Font::TTF::Ttopen - Opentype superclass for standard Opentype lookup based tables +(GSUB and GPOS) + +=head1 DESCRIPTION + +Handles all the script, lang, feature, lookup stuff for a +L/L table leaving the class specifics to the +subclass + +=head1 INSTANCE VARIABLES + +The instance variables of an opentype table form a complex sub-module hierarchy. + +=over 4 + +=item Version + +This contains the version of the table as a floating point number + +=item SCRIPTS + +The scripts list is a hash of script tags. Each script tag (of the form +$t->{'SCRIPTS'}{$tag}) has information below it. + +=over 8 + +=item OFFSET + +This variable is preceded by a space and gives the offset from the start of the +table (not the table section) to the script table for this script + +=item REFTAG + +This variable is preceded by a space and gives a corresponding script tag to this +one such that the offsets in the file are the same. When writing, it is up to the +caller to ensure that the REFTAGs are set correctly, since these will be used to +assume that the scripts are identical. Note that REFTAG must refer to a script which +has no REFTAG of its own. + +=item DEFAULT + +This corresponds to the default language for this script, if there is one, and +contains the same information as an itemised language + +=item LANG_TAGS + +This contains an array of language tag strings (each 4 bytes) corresponding to +the languages listed by this script + +=item $lang + +Each language is a hash containing its information: + +=over 12 + +=item OFFSET + +This variable is preceded by a a space and gives the offset from the start of +the whole table to the language table for this language + +=item REFTAG + +This variable is preceded by a space and has the same function as for the script +REFTAG, only for the languages within a script. + +=item RE-ORDER + +This indicates re-ordering information, and has not been set. The value should +always be 0. + +=item DEFAULT + +This holds the index of the default feature, if there is one, or -1 otherwise. + +=item FEATURES + +This is an array of feature tags for all the features enabled for this language + +=back + +=back + +=item FEATURES + +The features section of instance variables corresponds to the feature table in +the opentype table. + +=over 8 + +=item FEAT_TAGS + +This array gives the ordered list of feature tags for this table. It is used during +reading and writing for converting between feature index and feature tag. + +=back + +The rest of the FEATURES variable is itself a hash based on the feature tag for +each feature. Each feature has the following structure: + +=over 8 + +=item OFFSET + +This attribute is preceded by a space and gives the offset relative to the start of the whole +table of this particular feature. + +=item PARMS + +If FeatureParams are defined for this feature, this contains a reference to the corresponding FeatureParams object. Otherwise set to null. + +=item LOOKUPS + +This is an array containing indices to lookups in the LOOKUP instance variable of the table + +=item INDEX + +This gives the feature index for this feature and is used during reading and writing for +converting between feature tag and feature index. + +=back + +=item LOOKUP + +This variable is an array of lookups in order and is indexed via the features of a language of a +script. Each lookup contains subtables and other information: + +=over 8 + +=item OFFSET + +This name is preceded by a space and contains the offset from the start of the table to this +particular lookup + +=item TYPE + +This is a subclass specific type for a lookup. It stipulates the type of lookup and hence subtables +within the lookup + +=item FLAG + +Holds the lookup flag bits + +=item FILTER + +Holds the MarkFilteringSet (that is, the index into GDEF->MARKSETS) for the lookup. + +=item SUB + +This holds an array of subtables which are subclass specific. Each subtable must have +an OFFSET. The other variables described here are an abstraction used in both the +GSUB and GPOS tables which are the target subclasses of this class. + +=over 12 + +=item OFFSET + +This is preceded by a space and gives the offset relative to the start of the table for this +subtable + +=item FORMAT + +Gives the sub-table sub format for this GSUB subtable. It is assumed that this +value is correct when it comes time to write the subtable. + +=item COVERAGE + +Most lookups consist of a coverage table corresponding to the first +glyph to match. The offset of this coverage table is stored here and the coverage +table looked up against the GSUB table proper. There are two lookups +without this initial coverage table which is used to index into the RULES array. +These lookups have one element in the RULES array which is used for the whole +match. + +=item RULES + +The rules are a complex array. In most cases, each element of the array +corresponds to an element in the coverage table (governed by the coverage index). +In a few caess, such as when there is +no coverage table, then there is considered to be only one element in the rules +array. Each element of the array is itself an array corresponding to the +possibly multiple string matches which may follow the initial glyph. Each +element of this array is a hash with fixed keys corresponding to information +needed to match a glyph string or act upon it. Thus the RULES element is an +array of arrays of hashes which contain the following keys: + +=over 16 + +=item MATCH + +This contains a sequence of elements held as an array. The elements may be +glyph ids (gid), class ids (cids), or offsets to coverage tables. Each element +corresponds to one glyph in the glyph string. See MATCH_TYPE for details of +how the different element types are marked. + +=item PRE + +This array holds the sequence of elements preceding the first match element +and has the same form as the MATCH array. + +=item POST + +This array holds the sequence of elements to be tested for following the match +string and is of the same form as the MATCH array. + +=item ACTION + +This array holds information regarding what should be done if a match is found. +The array may either hold glyph ids (which are used to replace or insert or +whatever glyphs in the glyph string) or 2 element arrays consisting of: + +=over 20 + +=item OFFSET + +Offset from the start of the matched string that the lookup should start at +when processing the substring. + +=item LOOKUP_INDEX + +The index to a lookup to be acted upon on the match string. + +=back + +=back + +=item CLASS + +For those lookups which use class categories rather than glyph ids for matching +this is the offset to the class definition used to categories glyphs in the +match string. + +=item PRE_CLASS + +This is the offset to the class definition for the before match glyphs + +=item POST_CLASS + +This is the offset to the class definition for the after match glyphs. + +=item ACTION_TYPE + +This string holds the type of information held in the ACTION variable of a RULE. +It is subclass specific. + +=item MATCH_TYPE + +This holds the type of information in the MATCH array of a RULE. This is subclass +specific. + +=item ADJUST + +This corresponds to a single action for all items in a coverage table. The meaning +is subclass specific. + +=item CACHE + +This key starts with a space + +A hash of other tables (such as coverage tables, classes, anchors, device tables) +based on the offset given in the subtable to that other information. +Note that the documentation is particularly +unhelpful here in that such tables are given as offsets relative to the +beginning of the subtable not the whole GSUB table. This includes those items which +are stored relative to another base within the subtable. + +=back + +=back + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use Font::TTF::Coverage; + +use strict; +use vars qw(@ISA %FeatParams); + +@ISA = qw(Font::TTF::Table); + +%FeatParams = ( + 'ss' => 'Font::TTF::Features::Sset', + 'cv' => 'Font::TTF::Features::Cvar', + 'si' => 'Font::TTF::Features::Size', + ); + +=head2 $t->read + +Reads the table passing control to the subclass to handle the subtable specifics + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $i, $l, $oScript, $oFeat, $oLook, $tag, $nScript, $off, $dLang, $nLang, $lTag); + my ($nFeat, $oParms, $FType, $nLook, $nSub, $j, $temp, $t); + my ($fh) = $self->{' INFILE'}; + my ($moff) = $self->{' OFFSET'}; + + $fh->read($dat, 10); + ($self->{'Version'}, $oScript, $oFeat, $oLook) = TTF_Unpack("vSSS", $dat); + +# read features first so that in the script/lang hierarchy we can use feature tags + + $fh->seek($moff + $oFeat, 0); + $fh->read($dat, 2); + $nFeat = unpack("n", $dat); + $self->{'FEATURES'} = {}; + $l = $self->{'FEATURES'}; + $fh->read($dat, 6 * $nFeat); + for ($i = 0; $i < $nFeat; $i++) + { + ($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6)); + while (defined $l->{$tag}) + { + if ($tag =~ m/(.*?)\s_(\d+)$/o) + { $tag = $1 . " _" . ($2 + 1); } + else + { $tag .= " _0"; } + } + $l->{$tag}{' OFFSET'} = $off + $oFeat; + $l->{$tag}{'INDEX'} = $i; + push (@{$l->{'FEAT_TAGS'}}, $tag); + } + + foreach $tag (grep {m/^.{4}(?:\s_\d+)?$/o} keys %$l) + { + $oFeat=$moff + $l->{$tag}{' OFFSET'}; + $fh->seek($oFeat, 0); + $fh->read($dat, 4); + ($oParms, $nLook) = unpack("n2", $dat); + $fh->read($dat, $nLook * 2); + $l->{$tag}{'LOOKUPS'} = [unpack("n*", $dat)]; + $l->{$tag}{'PARMS'}=""; + if ($oParms > 0) + { + $FType=$FeatParams{substr($tag,0,2)}; + if ($FType) + { + $t=$FType; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $l->{$tag}{'PARMS'} = $FType->new( INFILE => $fh, + OFFSET => $oFeat+$oParms); + $l->{$tag}{'PARMS'}->read; + } + } + + } + +# Now the script/lang hierarchy + + $fh->seek($moff + $oScript, 0); + $fh->read($dat, 2); + $nScript = unpack("n", $dat); + $self->{'SCRIPTS'} = {}; + $l = $self->{'SCRIPTS'}; + $fh->read($dat, 6 * $nScript); + for ($i = 0; $i < $nScript; $i++) + { + ($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6)); + $off += $oScript; + foreach (keys %$l) + { $l->{$tag}{' REFTAG'} = $_ if ($l->{$_}{' OFFSET'} == $off + && !defined $l->{$_}{' REFTAG'}); } + $l->{$tag}{' OFFSET'} = $off; + } + + foreach $tag (keys %$l) + { + next if ($l->{$tag}{' REFTAG'}); + $fh->seek($moff + $l->{$tag}{' OFFSET'}, 0); + $fh->read($dat, 4); + ($dLang, $nLang) = unpack("n2", $dat); + $l->{$tag}{'DEFAULT'}{' OFFSET'} = + $dLang + $l->{$tag}{' OFFSET'} if $dLang; + $fh->read($dat, 6 * $nLang); + for ($i = 0; $i < $nLang; $i++) + { + ($lTag, $off) = unpack("a4n", substr($dat, $i * 6, 6)); + $off += $l->{$tag}{' OFFSET'}; + $l->{$tag}{$lTag}{' OFFSET'} = $off; + foreach (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT') + { $l->{$tag}{$lTag}{' REFTAG'} = $_ if ($l->{$tag}{$_}{' OFFSET'} == $off + && !$l->{$tag}{$_}{' REFTAG'}); } + push (@{$l->{$tag}{'LANG_TAGS'}}, $lTag); + } + foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT') + { + next unless defined $l->{$tag}{$lTag}; + next if ($l->{$tag}{$lTag}{' REFTAG'}); + $fh->seek($moff + $l->{$tag}{$lTag}{' OFFSET'}, 0); + $fh->read($dat, 6); + ($l->{$tag}{$lTag}{'RE-ORDER'}, $l->{$tag}{$lTag}{'DEFAULT'}, $nFeat) + = unpack("n3", $dat); + $fh->read($dat, $nFeat * 2); + $l->{$tag}{$lTag}{'FEATURES'} = [map {$self->{'FEATURES'}{'FEAT_TAGS'}[$_]} unpack("n*", $dat)]; + } + foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT') + { + # Make copies of referenced languages for each reference. + next unless $l->{$tag}{$lTag}{' REFTAG'}; + $temp = $l->{$tag}{$lTag}{' REFTAG'}; + $l->{$tag}{$lTag} = ©($l->{$tag}{$temp}); + $l->{$tag}{$lTag}{' REFTAG'} = $temp; + } + } + foreach $tag (keys %$l) + { + next unless $l->{$tag}{' REFTAG'}; + $temp = $l->{$tag}{' REFTAG'}; + $l->{$tag} = ©($l->{$temp}); + $l->{$tag}{' REFTAG'} = $temp; + } + +# And finally the lookups + + $fh->seek($moff + $oLook, 0); + $fh->read($dat, 2); + $nLook = unpack("n", $dat); + $fh->read($dat, $nLook * 2); + $i = 0; + map { $self->{'LOOKUP'}[$i++]{' OFFSET'} = $_; } unpack("n*", $dat); + + for ($i = 0; $i < $nLook; $i++) + { + $l = $self->{'LOOKUP'}[$i]; + $fh->seek($l->{' OFFSET'} + $moff + $oLook, 0); + $fh->read($dat, 6); + ($l->{'TYPE'}, $l->{'FLAG'}, $nSub) = unpack("n3", $dat); + $fh->read($dat, $nSub * 2); + my @offsets = unpack("n*", $dat); + if ($l->{'FLAG'} & 0x0010) + { + $fh->read($dat, 2); + $l->{'FILTER'} = unpack("n", $dat); + } + my $isExtension = ($l->{'TYPE'} == $self->extension()); + for ($j = 0; $j < $nSub; $j++) + { + $l->{'SUB'}[$j]{' OFFSET'} = $offsets[$j]; + $fh->seek($moff + $oLook + $l->{' OFFSET'} + $l->{'SUB'}[$j]{' OFFSET'}, 0); + if ($isExtension) + { + $fh->read($dat, 8); + my $longOff; + (undef, $l->{'TYPE'}, $longOff) = unpack("nnN", $dat); + $l->{'SUB'}[$j]{' OFFSET'} += $longOff; + $fh->seek($moff + $oLook + $l->{' OFFSET'} + $l->{'SUB'}[$j]{' OFFSET'}, 0); + } + $self->read_sub($fh, $l, $j); + } + } + return $self; +} + +=head2 $t->read_sub($fh, $lookup, $index) + +This stub is to allow subclasses to read subtables of lookups in a table specific manner. A +reference to the lookup is passed in along with the subtable index. The file is located at the +start of the subtable to be read + +=cut + +sub read_sub +{ } + + +=head2 $t->extension() + +Returns the lookup number for the extension table that allows access to 32-bit offsets. + +=cut + +sub extension +{ } + + +=head2 $t->out($fh) + +Writes this Opentype table to the output calling $t->out_sub for each sub table +at the appropriate point in the output. The assumption is that on entry the +number of scripts, languages, features, lookups, etc. are all resolved and +the relationships fixed. This includes a LANG_TAGS list for a script, and that all +scripts and languages in their respective dictionaries either have a REFTAG or contain +real data. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i, $j, $base, $off, $tag, $t, $l, $lTag, $oScript, @script, @tags); + my ($end, $nTags, @offs, $oFeat, $oFtable, $oParms, $FType, $oLook, $nSub, $nSubs, $big, $out); + + return $self->SUPER::out($fh) unless $self->{' read'}; + +# First sort the features + $i = 0; + $self->{'FEATURES'}{'FEAT_TAGS'} = [sort grep {m/^.{4}(?:\s_\d+)?$/o} %{$self->{'FEATURES'}}] + if (!defined $self->{'FEATURES'}{'FEAT_TAGS'}); + foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}}) + { $self->{'FEATURES'}{$t}{'INDEX'} = $i++; } + + $base = $fh->tell(); + $fh->print(TTF_Pack("v", $self->{'Version'})); + $fh->print(pack("n3", 10, 0, 0)); + $oScript = $fh->tell() - $base; + @script = sort grep {length($_) == 4} keys %{$self->{'SCRIPTS'}}; + $fh->print(pack("n", $#script + 1)); + foreach $t (@script) + { $fh->print(pack("a4n", $t, 0)); } + + $end = $fh->tell(); + foreach $t (@script) + { + $fh->seek($end, 0); + $tag = $self->{'SCRIPTS'}{$t}; + next if ($tag->{' REFTAG'}); + $tag->{' OFFSET'} = tell($fh) - $base - $oScript; + $fh->print(pack("n2", 0, $#{$tag->{'LANG_TAGS'}} + 1)); + foreach $lTag (sort @{$tag->{'LANG_TAGS'}}) + { $fh->print(pack("a4n", $lTag, 0)); } + foreach $lTag (@{$tag->{'LANG_TAGS'}}, 'DEFAULT') + { + my ($def); + $l = $tag->{$lTag}; + next if (!defined $l || (defined $l->{' REFTAG'} && $l->{' REFTAG'} ne '')); + $l->{' OFFSET'} = $fh->tell() - $base - $oScript - $tag->{' OFFSET'}; + if (defined $l->{'DEFAULT'}) +# { $def = $self->{'FEATURES'}{$l->{'FEATURES'}[$l->{'DEFAULT'}]}{'INDEX'}; } + { $def = $l->{'DEFAULT'}; } + else + { $def = -1; } + $fh->print(pack("n*", $l->{'RE_ORDER'} || 0, $def, $#{$l->{'FEATURES'}} + 1, + map {$self->{'FEATURES'}{$_}{'INDEX'} || 0} @{$l->{'FEATURES'}})); + } + $end = $fh->tell(); + if ($tag->{'DEFAULT'}{' REFTAG'} || defined $tag->{'DEFAULT'}{'FEATURES'}) + { + $fh->seek($base + $oScript + $tag->{' OFFSET'}, 0); + if (defined $tag->{'DEFAULT'}{' REFTAG'}) + { + my ($ttag); + for ($ttag = $tag->{'DEFAULT'}{' REFTAG'}; defined $tag->{$ttag}{' REFTAG'}; $ttag = $tag->{$ttag}{' REFTAG'}) + { } + $off = $tag->{$ttag}{' OFFSET'}; + } + else + { $off = $tag->{'DEFAULT'}{' OFFSET'}; } + $fh->print(pack("n", $off)); + } + $fh->seek($base + $oScript + $tag->{' OFFSET'} + 4, 0); + foreach (sort @{$tag->{'LANG_TAGS'}}) + { + if (defined $tag->{$_}{' REFTAG'}) + { + my ($ttag); + for ($ttag = $tag->{$_}{' REFTAG'}; defined $tag->{$ttag}{' REFTAG'}; $ttag = $tag->{$ttag}{' REFTAG'}) + { } + $off = $tag->{$ttag}{' OFFSET'}; + } + else + { $off = $tag->{$_}{' OFFSET'}; } + $fh->print(pack("a4n", $_, $off)); + } + } + $fh->seek($base + $oScript + 2, 0); + foreach $t (@script) + { + $tag = $self->{'SCRIPTS'}{$t}; + $off = $tag->{' REFTAG'} ? $tag->{$tag->{' REFTAG'}}{' OFFSET'} : $tag->{' OFFSET'}; + $fh->print(pack("a4n", $t, $off)); + } + + $fh->seek($end, 0); + $oFeat = $end - $base; + $nTags = $#{$self->{'FEATURES'}{'FEAT_TAGS'}} + 1; + $fh->print(pack("n", $nTags)); + $fh->print(pack("a4n", " ", 0) x $nTags); + + foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}}) + { + $tag = $self->{'FEATURES'}{$t}; + $oFtable = tell($fh) - $base - $oFeat; + $tag->{' OFFSET'} = $oFtable; + $fh->print(pack("n*", 0, $#{$tag->{'LOOKUPS'}} + 1, @{$tag->{'LOOKUPS'}})); + if ($tag->{'PARMS'}) + { + $end = $fh->tell(); + $oParms = $end - $oFtable - $base - $oFeat; + $fh->seek($oFtable + $base + $oFeat,0); + $fh->print(pack("n",$oParms)); + $fh->seek($end,0); + $tag->{'PARMS'}->out($fh); + } + } + $end = $fh->tell(); + $fh->seek($oFeat + $base + 2, 0); + foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}}) + { $fh->print(pack("a4n", $t, $self->{'FEATURES'}{$t}{' OFFSET'})); } + + undef $big; + $fh->seek($end, 0); + $oLook = $end - $base; + + # LookupListTable (including room for offsets to LookupTables) + $nTags = $#{$self->{'LOOKUP'}} + 1; + $fh->print(pack("n", $nTags)); + $fh->print(pack("n", 0) x $nTags); + $end = $fh->tell(); # end of LookupListTable = start of Lookups + foreach $tag (@{$self->{'LOOKUP'}}) + { $nSubs += $self->num_sub($tag); } + for ($i = 0; $i < $nTags; $i++) + { + $fh->seek($end, 0); + $tag = $self->{'LOOKUP'}[$i]; + $off = $end - $base - $oLook; # BH 2004-03-04 + # Is there room, from the start of this i'th lookup, for this and the remaining + # lookups to be wrapped in extension lookups? + if (!defined $big && $off + ($nTags - $i) * 6 + $nSubs * 10 > 65535) # BH 2004-03-04 + { + # Not enough room -- need to start an extension! + my ($k, $ext); + $ext = $self->extension(); + # Must turn previous lookup into the first extension + $i--; + $tag = $self->{'LOOKUP'}[$i]; + $end = $tag->{' OFFSET'} + $base + $oLook; + $fh->seek($end, 0); + $big = $i; + # For this and the remaining lookups, build extensions lookups + for ($j = $i; $j < $nTags; $j++) + { + $tag = $self->{'LOOKUP'}[$j]; + $nSub = $self->num_sub($tag); + $tag->{' OFFSET'} = $fh->tell() - $base - $oLook; # offset to this extension lookup + # LookupTable (including actual offsets to subtables) + $fh->print(pack("nnn", $ext, $tag->{'FLAG'}, $nSub)); + $fh->print(pack("n*", map {6 + $nSub * 2 + $_ * 8 + ($tag->{'FLAG'} & 0x0010 ? 2 : 0) } (0 .. $nSub-1))); + $fh->print(pack("n", $tag->{'FILTER'})) if $tag->{'FLAG'} & 0x0010; + $tag->{' EXT_OFFSET'} = $fh->tell(); # = first extension lookup subtable + for ($k = 0; $k < $nSub; $k++) + { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, 0)); } + } + + $tag = $self->{'LOOKUP'}[$i]; + # Leave file positioned after all the extension lookups -- where the referenced lookups will start. + } + $tag->{' OFFSET'} = $off unless defined $big; # BH 2004-03-04 + $nSub = $self->num_sub($tag); + if (!defined $big) + { + # LookupTable (including room for subtable offsets) + $fh->print(pack("nnn", $tag->{'TYPE'}, $tag->{'FLAG'}, $nSub)); + $fh->print(pack("n", 0) x $nSub); + $fh->print(pack("n", $tag->{'FILTER'})) if $tag->{'FLAG'} & 0x0010; + } + else + { $end = $tag->{' EXT_OFFSET'}; } # Extension offsets computed relative to start of first Extension subtable -- corrected later + my (@offs, $out, @refs); + for ($j = 0; $j < $nSub; $j++) + { + my ($ctables) = {}; + my ($base) = length($out); + push(@offs, tell($fh) - $end + $base); + $out .= $self->out_sub($fh, $tag, $j, $ctables, $base); + push (@refs, [$ctables, $base]); + } + out_final($fh, $out, \@refs); + $end = $fh->tell(); + if (!defined $big) + { + $fh->seek($tag->{' OFFSET'} + $base + $oLook + 6, 0); + $fh->print(pack("n*", @offs)); + } + else + { + $fh->seek($tag->{' EXT_OFFSET'}, 0); + for ($j = 0; $j < $nSub; $j++) + { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, $offs[$j] - $j * 8)); } + } + } + $fh->seek($oLook + $base + 2, 0); + $fh->print(pack("n*", map {$self->{'LOOKUP'}[$_]{' OFFSET'}} (0 .. $nTags - 1))); + $fh->seek($base + 6, 0); + $fh->print(pack('n2', $oFeat, $oLook)); + $fh->seek($end, 0); + $self; +} + + +=head2 $t->num_sub($lookup) + +Asks the subclass to count the number of subtables for a particular lookup and to +return that value. Used in out(). + +=cut + +sub num_sub +{ + my ($self, $lookup) = @_; + + return $#{$lookup->{'SUB'}} + 1; +} + + +=head2 $t->out_sub($fh, $lookup, $index) + +This stub is to allow subclasses to output subtables of lookups in a table specific manner. A +reference to the lookup is passed in along with the subtable index. The file is located at the +start of the subtable to be output + +=cut + +sub out_sub +{ } + +=head2 $t->dirty + +Setting GPOS or GSUB dirty means that OS/2 may need updating, so set it dirty. + +=cut + +sub dirty +{ + my ($self, $val) = @_; + my $res = $self->SUPER::dirty ($val); + $self->{' PARENT'}{'OS/2'}->read->dirty($val) if exists $self->{' PARENT'}{'OS/2'}; + $res; +} + +=head2 $t->maxContext + +Returns the length of the longest opentype rule in this table. + +=cut + +sub maxContext +{ + my ($self) = @_; + + # Make sure table is read + $self->read; + + # Calculate my contribution to OS/2 usMaxContext + + my ($maxcontext, $l, $s, $r, $m); + + for $l (@{$self->{'LOOKUP'}}) # Examine each lookup + { + for $s (@{$l->{'SUB'}}) # Multiple possible subtables for this lookup + { + for $r (@{$s->{'RULES'}}) # One ruleset for each covered glyph + { + for $m (@{$r}) # Multiple possible matches for this covered glyph + { + my $lgt; + $lgt++ if exists $s->{'COVERAGE'}; # Count 1 for the coverage table if it exists + for (qw(MATCH POST)) # only Input and Lookahead sequences count (Lookbehind doesn't) -- see OT spec. + { + $lgt += @{$m->{$_}} if exists $m->{$_}; + } + $maxcontext = $lgt if $lgt > $maxcontext; + } + } + + } + } + + $maxcontext; +} + + +=head2 $t->update + +Perform various housekeeping items: + +For all lookups, set/clear 0x0010 bit of flag words based on 'FILTER' value. + +Sort COVERAGE table and RULES for all lookups. + +Unless $t->{' PARENT'}{' noharmony'} is true, update will make sure that GPOS and GSUB include +the same scripts and languages. Any added scripts and languages will have empty feature sets. + +=cut + +# Assumes we are called on both GSUB and GPOS. So simply ADDS scripts and languages to $self that it finds +# in the other table. + +sub update +{ + my ($self) = @_; + + return undef unless ($self->SUPER::update); + + if (defined ($self->{'LOOKUP'})) + { + + # make flag word agree with mark filter setting: + for my $l (@{$self->{'LOOKUP'}}) + { + if (defined $l->{'FILTER'}) + { $l->{'FLAG'} |= 0x0010; } + else + { $l->{'FLAG'} &= ~0x0010; } + } + + unless ($Font::TTF::Coverage::dontsort) + { + # Sort coverage tables and rules of all lookups by glyphID + # The lookup types that need to be sorted are: + # GSUB: 1.2 2 3 4 5.1 6.1 8 (However GSUB type 8 lookups are not yet supported by Font::TTF) + # GPOS: 1.2 2.1 3 4 5 6 7.1 8.1 + + for my $l (@{$self->{'LOOKUP'}}) + { + next unless defined $l->{'SUB'}; + for my $sub (@{$l->{'SUB'}}) + { + if (defined $sub->{'COVERAGE'} and $sub->{'COVERAGE'}{'cover'} and !$sub->{'COVERAGE'}{'dontsort'}) + { + # OK! Found a lookup with coverage table: + my @map = $sub->{'COVERAGE'}->sort(); + if (defined $sub->{'RULES'} and ($sub->{'MATCH_TYPE'} =~ /g/ or $sub->{'ACTION_TYPE'} =~ /[gvea]/)) + { + # And also a RULES table which now needs to be re-sorted + my $newrules = []; + foreach (0 .. $#map) + { push @{$newrules}, $sub->{'RULES'}[$map[$_]]; } + $sub->{'RULES'} = $newrules; + } + } + + # Special case for Mark positioning -- need to also sort the MarkArray + if (exists($sub->{'MARKS'}) and ref($sub->{'MATCH'}[0]) =~ /Cover/ and $sub->{'MATCH'}[0]{'cover'} and !$sub->{'MATCH'}[0]{'dontsort'}) + { + my @map = $sub->{'MATCH'}[0]->sort(); + my $newmarks = []; + foreach (0 .. $#map) + { push @{$newmarks}, $sub->{'MARKS'}[$map[$_]]; } + $sub->{'MARKS'} = $newmarks; + } + } + } + } + } + + # Enforce script/lang congruence unless asked not to: + return $self if $self->{' PARENT'}{' noharmony'}; + + # Find my sibling (GSUB or GPOS, depending on which I am) + my $sibling = ref($self) eq 'Font::TTF::GSUB' ? 'GPOS' : ref($self) eq 'Font::TTF::GPOS' ? 'GSUB' : undef; + return $self unless $sibling && defined $self->{' PARENT'}{$sibling}; + $sibling = $self->{' PARENT'}{$sibling}; + + # Look through scripts defined in sibling: + for my $sTag (grep {length($_) == 4} keys %{$sibling->{'SCRIPTS'}}) + { + my $sibScript = $sibling->{'SCRIPTS'}{$sTag}; + $sibScript = $sibling->{$sibScript->{' REFTAG'}} if exists $sibScript->{' REFTAG'} && $sibScript->{' REFTAG'} ne ''; + + $self->{'SCRIPTS'}{$sTag} = {} unless defined $self->{'SCRIPTS'}{$sTag}; # Create script if not present in $self + + my $myScript = $self->{'SCRIPTS'}{$sTag}; + $myScript = $self->{$myScript->{' REFTAG'}} if exists $myScript->{' REFTAG'} && $myScript->{' REFTAG'} ne ''; + + foreach my $lTag (@{$sibScript->{'LANG_TAGS'}}) + { + # Ok, found a script/lang that is in our sibling. + next if exists $myScript->{$lTag}; # Already in $self + + # Need to create this lang: + push @{$myScript->{'LANG_TAGS'}}, $lTag; + $myScript->{$lTag} = { 'FEATURES' => [] }; + } + + if (defined $sibScript->{'DEFAULT'} && !defined $myScript->{'DEFAULT'}) + { + # Create default lang for this script. + $myScript->{'DEFAULT'} = { 'FEATURES' => [] }; + } + } + $self; +} + +=head1 Internal Functions & Methods + +Most of these methods are used by subclasses for handling such things as coverage +tables. + +=head2 copy($ref) + +Internal function to copy the top level of a dictionary to create a new dictionary. +Only the top level is copied. + +=cut + +sub copy +{ + my ($ref) = @_; + my ($res) = {}; + + foreach (keys %$ref) + { $res->{$_} = $ref->{$_}; } + $res; +} + + +=head2 $t->read_cover($cover_offset, $lookup_loc, $lookup, $fh, $is_cover) + +Reads a coverage table and stores the results in $lookup->{' CACHE'}, that is, if +it has not been read already. + +=cut + +sub read_cover +{ + my ($self, $offset, $base, $lookup, $fh, $is_cover) = @_; + my ($loc) = $fh->tell(); + my ($cover, $str); + + return undef unless $offset; + $str = sprintf("%X", $base + $offset); + return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str}; + $fh->seek($base + $offset, 0); + $cover = Font::TTF::Coverage->new($is_cover)->read($fh); + $fh->seek($loc, 0); + $lookup->{' CACHE'}{$str} = $cover; + return $cover; +} + + +=head2 ref_cache($obj, $cache, $offset [, $template]) + +Internal function to keep track of the local positioning of subobjects such as +coverage and class definition tables, and their offsets. +What happens is that the cache is a hash of +sub objects indexed by the reference (using a string mashing of the +reference name which is valid for the duration of the reference) and holds a +list of locations in the output string which should be filled in with the +offset to the sub object when the final string is output in out_final. + +Uses tricks for Tie::Refhash + +=cut + +sub ref_cache +{ + my ($obj, $cache, $offset, $template) = @_; + + return 0 unless defined $obj; + $template ||= 'n'; + unless (defined $cache->{"$obj"}) + { push (@{$cache->{''}}, $obj); } + push (@{$cache->{"$obj"}}, [$offset, $template]); + return 0; +} + + +=head2 out_final($fh, $out, $cache_list, $state) + +Internal function to actually output everything to the file handle given that +now we know the offset to the first sub object to be output and which sub objects +are to be output and what locations need to be updated, we can now +generate everything. $cache_list is an array of two element arrays. The first element +is a cache object, the second is an offset to be subtracted from each reference +to that object made in the cache. + +If $state is 1, then the output is not sent to the filehandle and the return value +is the string to be output. If $state is absent or 0 then output is not limited +by storing in a string first and the return value is ""; + +=cut + +sub out_final +{ + my ($fh, $out, $cache_list, $state) = @_; + my ($len) = length($out || ''); + my ($base_loc) = $state ? 0 : $fh->tell(); + my ($loc, $t, $r, $s, $master_cache, $offs, $str, %vecs); + + $fh->print($out || '') unless $state; # first output the current attempt + foreach $r (@$cache_list) + { + $offs = $r->[1]; + foreach $t (@{$r->[0]{''}}) + { + $str = "$t"; + if (!defined $master_cache->{$str}) + { + my ($vec) = $t->signature(); + if ($vecs{$vec}) + { $master_cache->{$str} = $master_cache->{$vecs{$vec}}; } + else + { + $vecs{$vec} = $str; + $master_cache->{$str} = ($state ? length($out) : $fh->tell()) + - $base_loc; + if ($state) + { $out .= $t->out($fh, 1); } + else + { $t->out($fh, 0); } + } + } + foreach (@{$r->[0]{$str}}) + { + $s = pack($_->[1], $master_cache->{$str} - $offs); + substr($out, $_->[0], length($s)) = $s; + } + } + } + if ($state) + { return $out; } + else + { + $loc = $fh->tell(); + $fh->seek($base_loc, 0); + $fh->print($out || ''); # the corrected version + $fh->seek($loc, 0); + } +} + + +=head2 $self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc) + +Internal method to read context (simple and chaining context) lookup subtables for +the GSUB and GPOS table types. The assumed values for $type correspond to those +for GSUB, so GPOS should adjust the values upon calling. + +=cut + +sub read_context +{ + my ($self, $lookup, $fh, $type, $fmt, $cover, $count, $loc) = @_; + my ($dat, $i, $s, $t, @subst, @srec, $mcount, $scount); + + if ($type == 5 && $fmt < 3) + { + if ($fmt == 2) + { + $fh->read($dat, 2); + $lookup->{'CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0); + $count = TTF_Unpack('S', $dat); + } + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { + if ($s == 0) + { + push (@{$lookup->{'RULES'}}, []); + next; + } + @subst = (); + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + foreach $t (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s + $t, 0); + @srec = (); + $fh->read($dat, 4); + ($mcount, $scount) = TTF_Unpack('S2', $dat); + $mcount--; + $fh->read($dat, ($mcount << 1) + ($scount << 2)); + for ($i = 0; $i < $scount; $i++) + { push (@srec, [TTF_Unpack('S2', substr($dat, + ($mcount << 1) + ($i << 2), 4))]); } + push (@subst, {'ACTION' => [@srec], + 'MATCH' => [TTF_Unpack('S*', + substr($dat, 0, $mcount << 1))]}); + } + push (@{$lookup->{'RULES'}}, [@subst]); + } + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g'); + } elsif ($type == 5 && $fmt == 3) + { + $fh->read($dat, ($cover << 1) + ($count << 2)); + @subst = (); @srec = (); + for ($i = 0; $i < $cover; $i++) + { push (@subst, $self->read_cover(TTF_Unpack('S', substr($dat, $i << 1, 2)), + $loc, $lookup, $fh, 1)); } + for ($i = 0; $i < $count; $i++) + { push (@srec, [TTF_Unpack('S2', substr($dat, ($count << 1) + ($i << 2), 4))]); } + $lookup->{'RULES'} = [[{'ACTION' => [@srec], 'MATCH' => [@subst]}]]; + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = 'o'; + } elsif ($type == 6 && $fmt < 3) + { + if ($fmt == 2) + { + $fh->read($dat, 6); + $lookup->{'PRE_CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0) if $count; + ($i, $mcount, $count) = TTF_Unpack('S3', $dat); # messy: 2 classes & count + $lookup->{'CLASS'} = $self->read_cover($i, $loc, $lookup, $fh, 0) if $i; + $lookup->{'POST_CLASS'} = $self->read_cover($mcount, $loc, $lookup, $fh, 0) if $mcount; + } + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { + if ($s == 0) + { + push (@{$lookup->{'RULES'}}, []); + next; + } + @subst = (); + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + foreach $i (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s + $i, 0); + @srec = (); + $t = {}; + $fh->read($dat, 2); + $mcount = TTF_Unpack('S', $dat); + if ($mcount > 0) + { + $fh->read($dat, $mcount << 1); + $t->{'PRE'} = [TTF_Unpack('S*', $dat)]; + } + $fh->read($dat, 2); + $mcount = TTF_Unpack('S', $dat); + if ($mcount > 1) + { + $fh->read($dat, ($mcount - 1) << 1); + $t->{'MATCH'} = [TTF_Unpack('S*', $dat)]; + } + $fh->read($dat, 2); + $mcount = TTF_Unpack('S', $dat); + if ($mcount > 0) + { + $fh->read($dat, $mcount << 1); + $t->{'POST'} = [TTF_Unpack('S*', $dat)]; + } + $fh->read($dat, 2); + $scount = TTF_Unpack('S', $dat); + $fh->read($dat, $scount << 2); + for ($i = 0; $i < $scount; $i++) + { push (@srec, [TTF_Unpack('S2', substr($dat, $i << 2))]); } + $t->{'ACTION'} = [@srec]; + push (@subst, $t); + } + push (@{$lookup->{'RULES'}}, [@subst]); + } + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g'); + } elsif ($type == 6 && $fmt == 3) + { + $t = {}; + unless ($cover == 0) + { + @subst = (); + $fh->read($dat, $cover << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'PRE'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'MATCH'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'POST'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + @subst = (); + $fh->read($dat, $count << 2); + for ($i = 0; $i < $count; $i++) + { push (@subst, [TTF_Unpack('S2', substr($dat, $i << 2, 4))]); } + $t->{'ACTION'} = [@subst]; + $lookup->{'RULES'} = [[$t]]; + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = 'o'; + } + $lookup; +} + + +=head2 $self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num) + +Provides shared behaviour between GSUB and GPOS tables during output for context +(chained and simple) rules. In addition, support is provided here for type 4 GSUB +tables, which are not used in GPOS. The value for $type corresponds to the type +in a GSUB table so calling from GPOS should adjust the value accordingly. + +=cut + +sub out_context +{ + my ($self, $lookup, $fh, $type, $fmt, $ctables, $out, $num, $base) = @_; + my ($offc, $offd, $i, $j, $r, $t, $numd); + + $out ||= ''; + if (($type == 4 || $type == 5 || $type == 6) && ($fmt == 1 || $fmt == 2)) + { + my ($base_off); + + if ($fmt == 1) + { + $out = pack("nnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $num); + $base_off = 6; + } elsif ($type == 5) + { + $out = pack("nnnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 4 + $base), $num); + $base_off = 8; + } elsif ($type == 6) + { + $out = pack("n6", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'PRE_CLASS'}, $ctables, 4 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 6 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'POST_CLASS'}, $ctables, 8 + $base), + $num); + $base_off = 12; + } + + $out .= pack('n*', (0) x $num); + $offc = length($out); + for ($i = 0; $i < $num; $i++) + { + $r = $lookup->{'RULES'}[$i]; + next unless exists $r->[0]{'ACTION'}; + $numd = $#{$r} + 1; + substr($out, ($i << 1) + $base_off, 2) = pack('n', $offc); + $out .= pack('n*', $numd, (0) x $numd); + $offd = length($out) - $offc; + for ($j = 0; $j < $numd; $j++) + { + substr($out, $offc + 2 + ($j << 1), 2) = pack('n', $offd); + if ($type == 4) + { + $out .= pack('n*', $r->[$j]{'ACTION'}[0], $#{$r->[$j]{'MATCH'}} + 2, + @{$r->[$j]{'MATCH'}}); + } elsif ($type == 5) + { + $out .= pack('n*', $#{$r->[$j]{'MATCH'}} + 2, + $#{$r->[$j]{'ACTION'}} + 1, + @{$r->[$j]{'MATCH'}}); + foreach $t (@{$r->[$j]{'ACTION'}}) + { $out .= pack('n2', @$t); } + } elsif ($type == 6) + { + $out .= pack('n*', $#{$r->[$j]{'PRE'}} + 1, @{$r->[$j]{'PRE'}}, + $#{$r->[$j]{'MATCH'}} + 2, @{$r->[$j]{'MATCH'}}, + $#{$r->[$j]{'POST'}} + 1, @{$r->[$j]{'POST'}}, + $#{$r->[$j]{'ACTION'}} + 1); + foreach $t (@{$r->[$j]{'ACTION'}}) + { $out .= pack('n2', @$t); } + } + $offd = length($out) - $offc; + } + $offc = length($out); + } + } elsif ($type == 5 && $fmt == 3) + { + $out .= pack('n3', $fmt, $#{$lookup->{'RULES'}[0][0]{'MATCH'}} + 1, + $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1); + foreach $t (@{$lookup->{'RULES'}[0][0]{'MATCH'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + foreach $t (@{$lookup->{'RULES'}[0][0]{'ACTION'}}) + { $out .= pack('n2', @$t); } + } elsif ($type == 6 && $fmt == 3) + { + $r = $lookup->{'RULES'}[0][0]; + no strict 'refs'; # temp fix - more code needed (probably "if" statements in the event 'PRE' or 'POST' are empty) + $out .= pack('n2', $fmt, defined $r->{'PRE'} ? scalar @{$r->{'PRE'}} : 0); + foreach $t (@{$r->{'PRE'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'MATCH'} ? scalar @{$r->{'MATCH'}} : 0); + foreach $t (@{$r->{'MATCH'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'POST'} ? scalar @{$r->{'POST'}} : 0); + foreach $t (@{$r->{'POST'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'ACTION'} ? scalar @{$r->{'ACTION'}} : 0); + foreach $t (@{$r->{'ACTION'}}) + { $out .= pack('n2', @$t); } + } + $out; +} + +1; + + +=head1 BUGS + +=over 4 + +=item * + +No way to share cachable items (coverage tables, classes, anchors, device tables) +across different lookups. The items are always output after the lookup and +repeated if necessary. Within lookup sharing is possible. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Useall.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Useall.pm new file mode 100644 index 0000000000..c140eb97bc --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Useall.pm @@ -0,0 +1,102 @@ +=head1 NAME + +Font::TTF::Useall - shortcut to 'use' all the Font::TTF modules + +=head1 SYNOPSIS + + use Font::TTF::Useall; + +=head1 DESCRIPTION + +Useful for debugging, this module simply does a 'use' on all the other +modules that are part of Font::TTF. + +=cut + +use Font::TTF::Ttc; +use Font::TTF::PSNames; +use Font::TTF::OTTags; +use Font::TTF::EBDT; +use Font::TTF::EBLC; +use Font::TTF::DSIG; +use Font::TTF::Sill; +use Font::TTF::Silf; +use Font::TTF::Cvt_; +use Font::TTF::Fpgm; +use Font::TTF::Glyf; +use Font::TTF::Hdmx; +use Font::TTF::Kern; +use Font::TTF::Loca; +use Font::TTF::LTSH; +use Font::TTF::Name; +use Font::TTF::OS_2; +use Font::TTF::PCLT; +use Font::TTF::Post; +use Font::TTF::Prep; +use Font::TTF::Vmtx; +use Font::TTF::AATKern; +use Font::TTF::AATutils; +use Font::TTF::Anchor; +use Font::TTF::Bsln; +use Font::TTF::Delta; +use Font::TTF::Fdsc; +use Font::TTF::Feat; +use Font::TTF::GrFeat; +use Font::TTF::Fmtx; +use Font::TTF::GPOS; +use Font::TTF::Mort; +use Font::TTF::Prop; +use Font::TTF::GDEF; +use Font::TTF::Coverage; +use Font::TTF::GSUB; +use Font::TTF::Hhea; +use Font::TTF::Table; +use Font::TTF::Ttopen; +use Font::TTF::Glyph; +use Font::TTF::Head; +use Font::TTF::Hmtx; +use Font::TTF::Vhea; +use Font::TTF::Cmap; +use Font::TTF::Utils; +use Font::TTF::Maxp; +use Font::TTF::Font; +use Font::TTF::Kern::ClassArray; +use Font::TTF::Kern::CompactClassArray; +use Font::TTF::Kern::OrderedList; +use Font::TTF::Kern::StateTable; +use Font::TTF::Kern::Subtable; +use Font::TTF::Mort::Chain; +use Font::TTF::Mort::Contextual; +use Font::TTF::Mort::Insertion; +use Font::TTF::Mort::Ligature; +use Font::TTF::Mort::Noncontextual; +use Font::TTF::Mort::Rearrangement; +use Font::TTF::Mort::Subtable; +use Font::TTF::Features::Cvar; +use Font::TTF::Features::Size; +use Font::TTF::Features::Sset; +use Font::TTF::Woff; +use Font::TTF::Woff::MetaData; +use Font::TTF::Woff::PrivateData; +use Font::TTF::Glat; +use Font::TTF::Gloc; +use Font::TTF::Dumper; + + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Utils.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Utils.pm new file mode 100644 index 0000000000..2beb1b3a9f --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Utils.pm @@ -0,0 +1,639 @@ +package Font::TTF::Utils; + +=head1 NAME + +Font::TTF::Utils - Utility functions to save fingers + +=head1 DESCRIPTION + +Lots of useful functions to save my fingers, especially for trivial tables + +=head1 FUNCTIONS + +The following functions are exported + +=cut + +use strict; +use vars qw(@ISA @EXPORT $VERSION @EXPORT_OK); +require Exporter; + +@ISA = qw(Exporter); +@EXPORT = qw(TTF_Init_Fields TTF_Read_Fields TTF_Out_Fields TTF_Pack + TTF_Unpack TTF_word_utf8 TTF_utf8_word TTF_bininfo); +@EXPORT_OK = (@EXPORT, qw(XML_hexdump)); +$VERSION = 0.0001; + +=head2 ($val, $pos) = TTF_Init_Fields ($str, $pos) + +Given a field description from the C section, creates an absolute entry +in the fields associative array for the class + +=cut + +sub TTF_Init_Fields +{ + my ($str, $pos, $inval) = @_; + my ($key, $val, $res, $len, $rel); + + $str =~ s/\r?\n$//o; + if ($inval) + { ($key, $val) = ($str, $inval); } + else + { ($key, $val) = split(',\s*', $str); } + return (undef, undef, 0) unless (defined $key && $key ne ""); + if ($val =~ m/^(\+?)(\d*)(\D+)(\d*)/oi) + { + $rel = $1; + if ($rel eq "+") + { $pos += $2; } + elsif ($2 ne "") + { $pos = $2; } + $val = $3; + $len = $4; + } + $len = "" unless defined $len; + $pos = 0 if !defined $pos || $pos eq ""; + $res = "$pos:$val:$len"; + if ($val eq "f" || $val eq 'v' || $val =~ m/^[l]/oi) + { $pos += 4 * ($len ne "" ? $len : 1); } + elsif ($val eq "F" || $val =~ m/^[s]/oi) + { $pos += 2 * ($len ne "" ? $len : 1); } + else + { $pos += 1 * ($len ne "" ? $len : 1); } + + ($key, $res, $pos); +} + + +=head2 TTF_Read_Fields($obj, $dat, $fields) + +Given a block of data large enough to account for all the fields in a table, +processes the data block to convert to the values in the objects instance +variables by name based on the list in the C block which has been run +through C + +=cut + +sub TTF_Read_Fields +{ + my ($self, $dat, $fields) = @_; + my ($pos, $type, $res, $f, $arrlen, $arr, $frac); + + foreach $f (keys %{$fields}) + { + ($pos, $type, $arrlen) = split(':', $fields->{$f}); + $pos = 0 if $pos eq ""; + if ($arrlen ne "") + { $self->{$f} = [TTF_Unpack("$type$arrlen", substr($dat, $pos))]; } + else + { $self->{$f} = TTF_Unpack("$type", substr($dat, $pos)); } + } + $self; +} + + +=head2 TTF_Unpack($fmt, $dat) + +A TrueType types equivalent of Perls C function. Thus $fmt consists of +type followed by an optional number of elements to read including *. The type +may be one of: + + c BYTE + C CHAR + f FIXED + F F2DOT14 + l LONG + L ULONG + s SHORT + S USHORT + v Version number (FIXED) + +Note that C, C and C are not data types but units. + +Returns array of scalar (first element) depending on context + +=cut + +sub TTF_Unpack +{ + my ($fmt, $dat) = @_; + my ($res, $frac, $i, $arrlen, $type, @res); + + while ($fmt =~ s/^([cflsv])(\d+|\*)?//oi) + { + $type = $1; + $arrlen = $2; + $arrlen = 1 if !defined $arrlen || $arrlen eq ""; + $arrlen = -1 if $arrlen eq "*"; + + for ($i = 0; ($arrlen == -1 && $dat ne "") || $i < $arrlen; $i++) + { + if ($type eq "f") + { + ($res, $frac) = unpack("nn", $dat); + substr($dat, 0, 4) = ""; + $res -= 65536 if $res > 32767; + $res += $frac / 65536.; + } + elsif ($type eq "v") + { + ($res, $frac) = unpack("nn", $dat); + substr($dat, 0, 4) = ""; + $res = sprintf("%d.%04X", $res, $frac); + } + elsif ($type eq "F") + { + $res = unpack("n", $dat); + substr($dat, 0, 2) = ""; +# $res -= 65536 if $res >= 32768; + $frac = $res & 0x3fff; + $res >>= 14; + $res -= 4 if $res > 1; +# $frac -= 16384 if $frac > 8191; + $res += $frac / 16384.; + } + elsif ($type =~ m/^[l]/oi) + { + $res = unpack("N", $dat); + substr($dat, 0, 4) = ""; + $res -= (1 << 32) if ($type eq "l" && $res >= 1 << 31); + } + elsif ($type =~ m/^[s]/oi) + { + $res = unpack("n", $dat); + substr($dat, 0, 2) = ""; + $res -= 65536 if ($type eq "s" && $res >= 32768); + } + elsif ($type eq "c") + { + $res = unpack("c", $dat); + substr($dat, 0, 1) = ""; + } + else + { + $res = unpack("C", $dat); + substr($dat, 0, 1) = ""; + } + push (@res, $res); + } + } + return wantarray ? @res : $res[0]; +} + + +=head2 $dat = TTF_Out_Fields($obj, $fields, $len) + +Given the fields table from C writes out the instance variables from +the object to the filehandle in TTF binary form. + +=cut + +sub TTF_Out_Fields +{ + my ($obj, $fields, $len) = @_; + my ($dat) = "\000" x $len; + my ($f, $pos, $type, $res, $arr, $arrlen, $frac); + + foreach $f (keys %{$fields}) + { + ($pos, $type, $arrlen) = split(':', $fields->{$f}); + if ($arrlen ne "") + { $res = TTF_Pack("$type$arrlen", @{$obj->{$f}}); } + else + { $res = TTF_Pack("$type", $obj->{$f}); } + substr($dat, $pos, length($res)) = $res; + } + $dat; +} + + +=head2 $dat = TTF_Pack($fmt, @data) + +The TrueType equivalent to Perl's C function. See details of C +for how to work the $fmt string. + +=cut + +sub TTF_Pack +{ + my ($fmt, @obj) = @_; + my ($type, $i, $arrlen, $dat, $res, $frac); + + $dat = ''; + while ($fmt =~ s/^([flscv])(\d+|\*)?//oi) + { + $type = $1; + $arrlen = $2 || ""; + $arrlen = $#obj + 1 if $arrlen eq "*"; + $arrlen = 1 if $arrlen eq ""; + + for ($i = 0; $i < $arrlen; $i++) + { + $res = shift(@obj) || 0; + if ($type eq "f") + { + $frac = int(($res - int($res)) * 65536); + $res = (int($res) << 16) + $frac; + $dat .= pack("N", $res); + } + elsif ($type eq "v") + { + if ($res =~ s/\.([0-9a-f]+)$//oi) + { + $frac = $1; + $frac .= "0" x (4 - length($frac)); + } + else + { $frac = 0; } + $dat .= pack('nn', $res, hex($frac)); + } + elsif ($type eq "F") + { + $frac = int(($res - int($res)) * 16384); + $res = (int($res) << 14) + $frac; + $dat .= pack("n", $res); + } + elsif ($type =~ m/^[l]/oi) + { + $res += 1 << 32 if ($type eq 'L' && $res < 0); + $dat .= pack("N", $res); + } + elsif ($type =~ m/^[s]/oi) + { + $res += 1 << 16 if ($type eq 'S' && $res < 0); + $dat .= pack("n", $res); + } + elsif ($type eq "c") + { $dat .= pack("c", $res); } + else + { $dat .= pack("C", $res); } + } + } + $dat; +} + + +=head2 ($num, $range, $select, $shift) = TTF_bininfo($num) + +Calculates binary search information from a number of elements + +=cut + +sub TTF_bininfo +{ + my ($num, $block) = @_; + my ($range, $select, $shift); + + $range = 1; + for ($select = 0; $range <= $num; $select++) + { $range *= 2; } + $select--; $range /= 2; + $range *= $block; + + $shift = $num * $block - $range; + ($num, $range, $select, $shift); +} + + +=head2 TTF_word_utf8($str) + +Returns the UTF8 form of the 16 bit string, assumed to be in big endian order, +including surrogate handling + +=cut + +sub TTF_word_utf8 +{ + my ($str) = @_; + my ($res, $i); + my (@dat) = unpack("n*", $str); + + return pack("U*", @dat) if ($] >= 5.006); + for ($i = 0; $i <= $#dat; $i++) + { + my ($dat) = $dat[$i]; + if ($dat < 0x80) # Thanks to Gisle Aas for some of his old code + { $res .= chr($dat); } + elsif ($dat < 0x800) + { $res .= chr(0xC0 | ($dat >> 6)) . chr(0x80 | ($dat & 0x3F)); } + elsif ($dat >= 0xD800 && $dat < 0xDC00) + { + my ($dat1) = $dat[++$i]; + my ($top) = (($dat & 0x3C0) >> 6) + 1; + $res .= chr(0xF0 | ($top >> 2)) + . chr(0x80 | (($top & 1) << 4) | (($dat & 0x3C) >> 2)) + . chr(0x80 | (($dat & 0x3) << 4) | (($dat1 & 0x3C0) >> 6)) + . chr(0x80 | ($dat1 & 0x3F)); + } else + { $res .= chr(0xE0 | ($dat >> 12)) . chr(0x80 | (($dat >> 6) & 0x3F)) + . chr(0x80 | ($dat & 0x3F)); } + } + $res; +} + + +=head2 TTF_utf8_word($str) + +Returns the 16-bit form in big endian order of the UTF 8 string, including +surrogate handling to Unicode. + +=cut + +sub TTF_utf8_word +{ + my ($str) = @_; + my ($res); + + return pack("n*", unpack("U*", $str)) if ($^V ge v5.6.0); + $str = "$str"; # copy $str + while (length($str)) # Thanks to Gisle Aas for some of his old code + { + $str =~ s/^[\x80-\xBF]+//o; + if ($str =~ s/^([\x00-\x7F]+)//o) + { $res .= pack("n*", unpack("C*", $1)); } + elsif ($str =~ s/^([\xC0-\xDF])([\x80-\xBF])//o) + { $res .= pack("n", ((ord($1) & 0x1F) << 6) | (ord($2) & 0x3F)); } + elsif ($str =~ s/^([\0xE0-\xEF])([\x80-\xBF])([\x80-\xBF])//o) + { $res .= pack("n", ((ord($1) & 0x0F) << 12) + | ((ord($2) & 0x3F) << 6) + | (ord($3) & 0x3F)); } + elsif ($str =~ s/^([\xF0-\xF7])([\x80-\xBF])([\x80-\xBF])([\x80-\xBF])//o) + { + my ($b1, $b2, $b3, $b4) = (ord($1), ord($2), ord($3), ord($4)); + $res .= pack("n", ((($b1 & 0x07) << 8) | (($b2 & 0x3F) << 2) + | (($b3 & 0x30) >> 4)) + 0xD600); # account for offset + $res .= pack("n", ((($b3 & 0x0F) << 6) | ($b4 & 0x3F)) + 0xDC00); + } + elsif ($str =~ s/^[\xF8-\xFF][\x80-\xBF]*//o) + { } + } + $res; +} + + +=head2 XML_hexdump($context, $dat) + +Dumps out the given data as a sequence of blocks each 16 bytes wide + +=cut + +sub XML_hexdump +{ + my ($context, $depth, $dat) = @_; + my ($fh) = $context->{'fh'}; + my ($i, $len, $out); + + $len = length($dat); + for ($i = 0; $i < $len; $i += 16) + { + $out = join(' ', map {sprintf("%02X", ord($_))} (split('', substr($dat, $i, 16)))); + $fh->printf("%s%s\n", $depth, $i, $out); + } +} + + +=head2 XML_outhints + +Converts a binary string of hinting code into a textual representation + +=cut + +{ + my (@hints) = ( + ['SVTCA[0]'], ['SVTCA[1]'], ['SPVTCA[0]'], ['SPVTCA[1]'], ['SFVTCA[0]'], ['SFVTCA[1]'], ['SPVTL[0]'], ['SPVTL[1]'], + ['SFVTL[0]'], ['SFVTL[1]'], ['SPVFS'], ['SFVFS'], ['GPV'], ['GFV'], ['SVFTPV'], ['ISECT'], +# 10 + ['SRP0'], ['SRP1'], ['SRP2'], ['SZP0'], ['SZP1'], ['SZP2'], ['SZPS'], ['SLOOP'], + ['RTG'], ['RTHG'], ['SMD'], ['ELSE'], ['JMPR'], ['SCVTCI'], ['SSWCI'], ['SSW'], +# 20 + ['DUP'], ['POP'], ['CLEAR'], ['SWAP'], ['DEPTH'], ['CINDEX'], ['MINDEX'], ['ALIGNPTS'], + [], ['UTP'], ['LOOPCALL'], ['CALL'], ['FDEF'], ['ENDF'], ['MDAP[0]'], ['MDAP[1]'], +# 30 + ['IUP[0]'], ['IUP[1]'], ['SHP[0]'], ['SHP[1]'], ['SHC[0]'], ['SHC[1]'], ['SHZ[0]'], ['SHZ[1]'], + ['SHPIX'], ['IP'], ['MSIRP[0]'], ['MSIRP[1]'], ['ALIGNRP'], ['RTDG'], ['MIAP[0]'], ['MIAP[1]'], +# 40 + ['NPUSHB', -1, 1], ['NPUSHW', -1, 2], ['WS', 0, 0], ['RS', 0, 0], ['WCVTP', 0, 0], ['RCVT', 0, 0], ['GC[0]'], ['GC[1]'], + ['SCFS'], ['MD[0]'], ['MD[1]'], ['MPPEM'], ['MPS'], ['FLIPON'], ['FLIPOFF'], ['DEBUG'], +# 50 + ['LT'], ['LTEQ'], ['GT'], ['GTEQ'], ['EQ'], ['NEQ'], ['ODD'], ['EVEN'], + ['IF'], ['EIF'], ['AND'], ['OR'], ['NOT'], ['DELTAP1'], ['SDB'], ['SDS'], +# 60 + ['ADD'], ['SUB'], ['DIV'], ['MULT'], ['ABS'], ['NEG'], ['FLOOR'], ['CEILING'], + ['ROUND[0]'], ['ROUND[1]'], ['ROUND[2]'], ['ROUND[3]'], ['NROUND[0]'], ['NROUND[1]'], ['NROUND[2]'], ['NROUND[3]'], +# 70 + ['WCVTF'], ['DELTAP2'], ['DELTAP3'], ['DELTAC1'], ['DELTAC2'], ['DELTAC3'], ['SROUND'], ['S45ROUND'], + ['JROT'], ['JROF'], ['ROFF'], [], ['RUTG'], ['RDTG'], ['SANGW'], [], +# 80 + ['FLIPPT'], ['FLIPRGON'], ['FLIPRGOFF'], [], [], ['SCANCTRL'], ['SDPVTL[0]'], ['SDPVTL[1]'], + ['GETINFO'], ['IDEF'], ['ROLL'], ['MAX'], ['MIN'], ['SCANTYPE'], ['INSTCTRL'], [], +# 90 + [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], +# A0 + [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], +# B0 + ['PUSHB1', 1, 1], ['PUSHB2', 2, 1], ['PUSHB3', 3, 1], ['PUSHB4', 4, 1], ['PUSHB5', 5, 1], ['PUSHB6', 6, 1], ['PUSHB7', 7, 1], ['PUSHB8', 8, 1], + ['PUSHW1', 1, 2], ['PUSHW2', 2, 2], ['PUSHW3', 3, 2], ['PUSHW4', 4, 2], ['PUSHW5', 5, 2], ['PUSHW6', 6, 2], ['PUSHW7', 7, 2], ['PUSHW8', 8, 2], +# C0 + ['MDRP[0]'], ['MDRP[1]'], ['MDRP[2]'], ['MDRP[3]'], ['MDRP[4]'], ['MDRP[5]'], ['MDRP[6]'], ['MDRP[7]'], + ['MDRP[8]'], ['MDRP[9]'], ['MDRP[A]'], ['MDRP[B]'], ['MDRP[C]'], ['MDRP[D]'], ['MDRP[E]'], ['MDRP[F]'], +# D0 + ['MDRP[10]'], ['MDRP[11]'], ['MDRP[12]'], ['MDRP[13]'], ['MDRP[14]'], ['MDRP[15]'], ['MDRP[16]'], ['MDRP[17]'], + ['MDRP[18]'], ['MDRP[19]'], ['MDRP[1A]'], ['MDRP[1B]'], ['MDRP[1C]'], ['MDRP[1D]'], ['MDRP[1E]'], ['MDRP[1F]'], +# E0 + ['MIRP[0]'], ['MIRP[1]'], ['MIRP[2]'], ['MIRP[3]'], ['MIRP[4]'], ['MIRP[5]'], ['MIRP[6]'], ['MIRP[7]'], + ['MIRP[8]'], ['MIRP[9]'], ['MIRP[A]'], ['MIRP[B]'], ['MIRP[C]'], ['MIRP[D]'], ['MIRP[E]'], ['MIRP[F]'], +# F0 + ['MIRP[10]'], ['MIRP[11]'], ['MIRP[12]'], ['MIRP[13]'], ['MIRP[14]'], ['MIRP[15]'], ['MIRP[16]'], ['MIRP[17]'], + ['MIRP[18]'], ['MIRP[19]'], ['MIRP[1A]'], ['MIRP[1B]'], ['MIRP[1C]'], ['MIRP[1D]'], ['MIRP[1E]'], ['MIRP[1F]']); + + my ($i); + my (%hints) = map { $_->[0] => $i++ if (defined $_->[0]); } @hints; + + sub XML_binhint + { + my ($dat) = @_; + my ($len) = length($dat); + my ($res, $i, $text, $size, $num); + + for ($i = 0; $i < $len; $i++) + { + ($text, $num, $size) = @{$hints[ord(substr($dat, $i, 1))]}; + $num = 0 unless (defined $num); + $text = sprintf("UNK[%02X]", ord(substr($dat, $i, 1))) unless defined $text; + $res .= $text; + if ($num != 0) + { + if ($num < 0) + { + $i++; + my ($nnum) = unpack($num == -1 ? 'C' : 'n', substr($dat, $i, -$num)); + $i += -$num - 1; + $num = $nnum; + } + $res .= "\t" . join(' ', unpack($size == 1 ? 'C*' : 'n*', substr($dat, $i + 1, $num * $size))); + $i += $num * $size; + } + $res .= "\n"; + } + $res; + } + + sub XML_hintbin + { + my ($dat) = @_; + my ($l, $res, @words, $num); + + foreach $l (split(/\s*\n\s*/, $dat)) + { + @words = split(/\s*/, $l); + next unless (defined $hints{$words[0]}); + $num = $hints{$words[0]}; + $res .= pack('C', $num); + if ($hints[$num][1] < 0) + { + $res .= pack($hints[$num][1] == -1 ? 'C' : 'n', $#words); + $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $#words]); + } + elsif ($hints[$num][1] > 0) + { + $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $hints[$num][1]]); + } + } + $res; + } +} + + +=head2 make_circle($f, $cmap, [$dia, $sb, $opts]) + +Adds a dotted circle to a font. This function is very configurable. The +parameters passed in are: + +=over 4 + +=item $f + +Font to work with. This is required. + +=item $cmap + +A cmap table (not the 'val' sub-element of a cmap) to add the glyph too. Optional. + +=item $dia + +Optional diameter for the main circle. Defaults to 80% em + +=item $sb + +Side bearing. The left and right side-bearings are always the same. This value +defaults to 10% em. + +=back + +There are various options to control all sorts of interesting aspects of the circle + +=over 4 + +=item numDots + +Number of dots in the circle + +=item numPoints + +Number of curve points to use to create each dot + +=item uid + +Unicode reference to store this glyph under in the cmap. Defaults to 0x25CC + +=item pname + +Postscript name to give the glyph. Defaults to uni25CC. + +=item -dRadius + +Radius of each dot. + +=back + +=cut + +sub make_circle +{ + my ($font, $cmap, $dia, $sb, %opts) = @_; + my ($upem) = $font->{'head'}{'unitsPerEm'}; + my ($glyph) = Font::TTF::Glyph->new('PARENT' => $font, 'read' => 2, 'isDirty' => 1); + my ($PI) = 3.1415926535; + my ($R, $r, $xorg, $yorg); + my ($i, $j, $numg, $maxp); + my ($numc) = $opts{'-numDots'} || 16; + my ($nump) = ($opts{'-numPoints'} * 2) || 8; + my ($uid) = $opts{'-uid'} || 0x25CC; + my ($pname) = $opts{'-pname'} || 'uni25CC'; + + $dia ||= $upem * .8; # .95 to fit exactly + $sb ||= $upem * .1; + $R = $dia / 2; + $r = $opts{'-dRadius'} || ($R * .1); + ($xorg, $yorg) = ($R + $r, $R); + + $xorg += $sb; + $font->{'post'}->read; + $font->{'glyf'}->read; + for ($i = 0; $i < $numc; $i++) + { + my ($pxorg, $pyorg) = ($xorg + $R * cos(2 * $PI * $i / $numc), + $yorg + $R * sin(2 * $PI * $i / $numc)); + for ($j = 0; $j < $nump; $j++) + { + push (@{$glyph->{'x'}}, int ($pxorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * cos(2 * $PI * $j / $nump))); + push (@{$glyph->{'y'}}, int ($pyorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * sin(2 * $PI * $j / $nump))); + push (@{$glyph->{'flags'}}, $j & 1 ? 0 : 1); + } + push (@{$glyph->{'endPoints'}}, $#{$glyph->{'x'}}); + } + $glyph->{'numberOfContours'} = $#{$glyph->{'endPoints'}} + 1; + $glyph->{'numPoints'} = $#{$glyph->{'x'}} + 1; + $glyph->update; + $numg = $font->{'maxp'}{'numGlyphs'}; + $font->{'maxp'}{'numGlyphs'}++; + + $font->{'hmtx'}{'advance'}[$numg] = int($xorg + $R + $r + $sb + .5); + $font->{'hmtx'}{'lsb'}[$numg] = int($xorg - $R - $r + .5); + $font->{'loca'}{'glyphs'}[$numg] = $glyph; + $cmap->{'val'}{$uid} = $numg if ($cmap); + $font->{'post'}{'VAL'}[$numg] = $pname; + delete $font->{'hdmx'}; + delete $font->{'VDMX'}; + delete $font->{'LTSH'}; + + $font->tables_do(sub {$_[0]->dirty;}); + $font->update; + return ($numg - 1); +} + + +1; + +=head1 BUGS + +No known bugs + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Vhea.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Vhea.pm new file mode 100644 index 0000000000..f4f630a04b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Vhea.pm @@ -0,0 +1,181 @@ +package Font::TTF::Vhea; + +=head1 NAME + +Font::TTF::Vhea - Vertical Header table + +=head1 DESCRIPTION + +This is a simple table with just standards specified instance variables + +=head1 INSTANCE VARIABLES + + version + Ascender + Descender + LineGap + advanceHeightMax + minTopSideBearing + minBottomSideBearing + yMaxExtent + caretSlopeRise + caretSlopeRun + metricDataFormat + numberOfVMetrics + + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'Ascender' => 's', + 'Descender' => 's', + 'LineGap' => 's', + 'advanceHeightMax' => 'S', + 'minTopSideBearing' => 's', + 'minBottomSideBearing' => 's', + 'yMaxExtent' => 's', + 'caretSlopeRise' => 's', + 'caretSlopeRun' => 's', + 'metricDataFormat' => '+10s', + 'numberOfVMetrics' => 's'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory as instance variables + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + init unless defined $fields{'Ascender'}; + $self->{' INFILE'}->read($dat, 36); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $self->{'numberOfVMetrics'} = $self->{' PARENT'}{'vmtx'}->numMetrics || $self->{'numberOfVMetrics'}; + $fh->print(TTF_Out_Fields($self, \%fields, 36)); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 36; +} + + +=head2 $t->update + +Updates various parameters in the hhea table from the hmtx table, assuming +the C table is dirty. + +=cut + +sub update +{ + my ($self) = @_; + my ($vmtx) = $self->{' PARENT'}{'vmtx'}; + my ($glyphs); + my ($num); + my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext); + + return undef unless ($self->SUPER::update); + return undef unless (defined $vmtx && defined $self->{' PARENT'}{'loca'}); + $vmtx->read->update; + $self->{' PARENT'}{'loca'}->read->update; + $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'}; + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + for ($i = 0; $i < $num; $i++) + { + $aw = $vmtx->{'advance'}[$i]; + $lsb = $vmtx->{'top'}[$i]; + if (defined $glyphs->[$i]) + { $ext = $lsb + $glyphs->[$i]->read->{'yMax'} - $glyphs->[$i]{'yMin'}; } + else + { $ext = $aw; } + $maw = $aw if ($aw > $maw); + $mlsb = $lsb if ($lsb < $mlsb or $i == 0); + $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0); + $mext = $ext if ($ext > $mext); + } + $self->{'advanceHeightMax'} = $maw; + $self->{'minTopSideBearing'} = $mlsb; + $self->{'minBottomSideBearing'} = $mrsb; + $self->{'yMaxExtent'} = $mext; + $self->{'numberOfVMetrics'} = $vmtx->numMetrics; + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Vmtx.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Vmtx.pm new file mode 100644 index 0000000000..9d53290cbd --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Vmtx.pm @@ -0,0 +1,96 @@ +package Font::TTF::Vmtx; + +=head1 NAME + +Font::TTF::Vmtx - Vertical Metrics + +=head1 DESCRIPTION + +Contains the advance height and top side bearing for each glyph. Given the +compressability of the data onto disk, this table uses information from +other tables, and thus must do part of its output during the output of +other tables + +=head1 INSTANCE VARIABLES + +The vertical metrics are kept in two arrays by glyph id. The variable names +do not start with a space + +=over 4 + +=item advance + +An array containing the advance height for each glyph + +=item top + +An array containing the top side bearing for each glyph + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Hmtx; + +@ISA = qw(Font::TTF::Hmtx); + + +=head2 $t->read + +Reads the vertical metrics from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($numh, $numg); + + $numh = $self->{' PARENT'}{'vhea'}->read->{'numberOfVMetrics'}; + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + $self->_read($numg, $numh, "advance", "top"); +} + + +=head2 $t->out($fh) + +Writes the metrics to a TTF file. Assumes that the C has updated the +numVMetrics from here + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($numh) = $self->{' PARENT'}{'vhea'}{'numberOfVMetrics'}; + $self->_out($fh, $numg, $numh, "advance", "top"); +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Win32.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Win32.pm new file mode 100644 index 0000000000..fcbf3ade49 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Win32.pm @@ -0,0 +1,49 @@ +package Font::TTF::Win32; + +# use strict; +# use vars qw($HKEY_LOCAL_MACHINE); + +use Win32::Registry; +use Win32; +use File::Spec; +use Font::TTF::Font; + + +sub findfonts +{ + my ($sub) = @_; + my ($font_key) = 'SOFTWARE\Microsoft\Windows' . (Win32::IsWinNT() ? ' NT' : '') . '\CurrentVersion\Fonts'; + my ($regFont, $list, $l, $font, $file); + +# get entry from registry for a font of this name + $::HKEY_LOCAL_MACHINE->Open($font_key, $regFont); + $regFont->GetValues($list); + + foreach $l (sort keys %{$list}) + { + my ($fname) = $list->{$l}[0]; + next unless ($fname =~ s/\(TrueType\)$//o); + $file = File::Spec->rel2abs($list->{$l}[2], "$ENV{'windir'}/fonts"); + $font = Font::TTF::Font->open($file) || next; + &{$sub}($font, $fname); + $font->release; + } +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff.pm new file mode 100644 index 0000000000..0e151c2621 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff.pm @@ -0,0 +1,61 @@ +package Font::TTF::Woff; + +=head1 NAME + +Font::TTF::WOFF - holds Web Open Font File (WOFF) data for the font + +=head1 DESCRIPTION + +This contains the WOFF packaging data. + +=head1 INSTANCE VARIABLES + +This object supports the following instance variables (which, because they +reflect the structure of the table, do not begin with a space): + +=over + +=item majorVersion + +=item minorVersion + +The two version integers come directly from the WOFF font header. + +=item metaData + +Contains a reference to Font::TTF::Woff::Meta structure, if the font has WOFF metadata. + +=item privateData + +Contains a reference to a Font::TTF::Woff::Private structure, if the font has a WOFF private data block + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff/MetaData.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff/MetaData.pm new file mode 100644 index 0000000000..5202e07e44 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff/MetaData.pm @@ -0,0 +1,31 @@ +package Font::TTF::Woff::MetaData; + +=head1 NAME + +Font::TTF::Woff::MetaData - WOFF metadata + +=head1 DESCRIPTION + +Currently a stub, thus read() results in read_dat() + +=cut + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff/PrivateData.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff/PrivateData.pm new file mode 100644 index 0000000000..ccebdc6521 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/Woff/PrivateData.pm @@ -0,0 +1,32 @@ +package Font::TTF::Woff::PrivateData; + +=head1 NAME + +Font::TTF::Woff::PrivateData - WOFF Private data + +=head1 DESCRIPTION + +Currently a stub, thus read() results in read_dat() + +=cut + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/XMLparse.pm b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/XMLparse.pm new file mode 100644 index 0000000000..f3ff38e3a6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/Font/TTF/XMLparse.pm @@ -0,0 +1,192 @@ +package Font::TTF::XMLparse; + +=head1 NAME + +Font::TTF::XMLparse - provides support for XML parsing. Requires Expat module XML::Parser::Expat + +=head1 SYNOPSIS + + use Font::TTF::Font; + use Font::TTF::XMLparse; + + $f = Font::TTF::Font->new; + read_xml($f, $ARGV[0]); + $f->out($ARGV[1]); + +=head1 DESCRIPTION + +This module contains the support routines for parsing XML and generating the +Truetype font structures as a result. The module has been separated from the rest +of the package in order to reduce the dependency that this would bring, of the +whole package on XML::Parser. This way, people without the XML::Parser can still +use the rest of the package. + +The package interacts with another package through the use of a context containing +and element 'receiver' which is an object which can possibly receive one of the +following messages: + +=over 4 + +=item XML_start + +This message is called when an open tag occurs. It is called with the context, +tag name and the attributes. The return value has no meaning. + +=item XML_end + +This messages is called when a close tag occurs. It is called with the context, +tag name and attributes (held over from when the tag was opened). There are 3 +possible return values from such a message: + +=over 8 + +=item undef + +This is the default return value indicating that default processing should +occur in which either the current element on the tree, or the text of this element +should be stored in the parent object. + +=item $context + +This magic value marks that the element should be deleted from the parent. +Nothing is stored in the parent. (This rather than '' is used to allow 0 returns.) + +=item anything + +Anything else is taken as the element content to be stored in the parent. + +=back + +In addition, the context hash passed to these messages contains the following +keys: + +=over 4 + +=item xml + +This is the expat xml object. The context is also available as +$context->{'xml'}{' mycontext'}. But that is a long winded way of not saying much! + +=item font + +This is the base object that was passed in for XML parsing. + +=item receiver + +This holds the current receiver of parsing events. It may be set in associated +application to adjust which objects should receive messages when. It is also stored +in the parsing stack to ensure that where an object changes it during XML_start, that +that same object that received XML_start will receive the corresponding XML_end + +=item stack + +This is the parsing stack, used internally to hold the current receiver and attributes +for each element open, as a complete hierarchy back to the root element. + +=item tree + +This element contains the storage tree corresponding to the parent of each element +in the stack. The default action is to push undef onto this stack during XML_start +and then to resolve this, either in the associated application (by changing +$context->{'tree'}[-1]) or during XML_end of a child element, by which time we know +whether we are dealing with an array or a hash or what. + +=item text + +Character processing is to insert all the characters into the text element of the +context for available use later. + +=back + +=back + +=head1 METHODS + +=cut + +use XML::Parser::Expat; +require Exporter; + +use strict; +use vars qw(@ISA @EXPORT); + +@ISA = qw(Exporter); +@EXPORT = qw(read_xml); + +sub read_xml +{ + my ($font, $fname) = @_; + + my ($xml) = XML::Parser::Expat->new; + my ($context) = {'xml' => $xml, 'font' => $font}; + + $xml->setHandlers('Start' => sub { + my ($x, $tag, %attrs) = @_; + my ($context) = $x->{' mycontext'}; + my ($fn) = $context->{'receiver'}->can('XML_start'); + + push(@{$context->{'tree'}}, undef); + push(@{$context->{'stack'}}, [$context->{'receiver'}, {%attrs}]); + &{$fn}($context->{'receiver'}, $context, $tag, %attrs) if defined $fn; + }, + 'End' => sub { + my ($x, $tag) = @_; + my ($context) = $x->{' mycontext'}; + my ($fn) = $context->{'receiver'}->can('XML_end'); + my ($stackinfo) = pop(@{$context->{'stack'}}); + my ($current, $res); + + $context->{'receiver'} = $stackinfo->[0]; + $context->{'text'} =~ s/^\s*(.*?)\s*$/$1/o; + $res = &{$fn}($context->{'receiver'}, $context, $tag, %{$stackinfo->[1]}) if defined $fn; + $current = pop(@{$context->{'tree'}}); + $current = $context->{'text'} unless (defined $current); + $context->{'text'} = ''; + + if (defined $res) + { + return if ($res eq $context); + $current = $res; + } + return unless $#{$context->{'tree'}} >= 0; + if ($tag eq 'elem') + { + $context->{'tree'}[-1] = [] unless defined $context->{'tree'}[-1]; + push (@{$context->{'tree'}[-1]}, $current); + } else + { + $context->{'tree'}[-1] = {} unless defined $context->{'tree'}[-1]; + $context->{'tree'}[-1]{$tag} = $current; + } + }, + 'Char' => sub { + my ($x, $str) = @_; + $x->{' mycontext'}{'text'} .= $str; + }); + + $xml->{' mycontext'} = $context; + + $context->{'receiver'} = $font; + if (ref $fname) + { return $xml->parse($fname); } + else + { return $xml->parsefile($fname); } +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/auto/Font/TTF/.exists b/.cpan/build/Font-TTF-1.06-0/blib/lib/auto/Font/TTF/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/lib/ttfmod.pl b/.cpan/build/Font-TTF-1.06-0/blib/lib/ttfmod.pl new file mode 100644 index 0000000000..c578a1a440 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/lib/ttfmod.pl @@ -0,0 +1,187 @@ +# Title: TTFMOD.PL +# Author: M. Hosken +# Description: Read TTF file calling user functions for each table +# and output transformed tables to new TTF file. +# Useage: TTFMOD provides the complete control loop for processing +# the TTF files. All that the caller need supply is an +# associative array of functions to call keyed by the TTF +# table name and the two filenames. +# +# &ttfmod($infile, $outfile, *fns [, @must]); +# +# *fns is an associative array keyed by table name with +# values of the name of the subroutine in package main to +# be called to transfer the table from INFILE to OUTFILE. +# The subroutine is called with the following parameters and +# expected return values: +# +# ($len, $csum) = &sub(*INFILE, *OUTFILE, $len); +# +# INFILE and OUTFILE are the input and output streams, $len +# is the length of the table according to the directory. +# The return values are $len = new length of table to be +# given in the table directory. $csum = new value of table +# checksum. A way to test that this is correct is to +# checksum the whole file (e.g. using CSUM.BAT) and to +# ensure that the value is 0xB1B0AFBA according to a 32 bit +# checksum calculated bigendien. +# +# @must consists of a list of tables which must exist in the +# final output file, either by being there alread or by being +# inserted. +# +# Modifications: +# MJPH 1.00 22-SEP-1994 Original +# MJPH 1.1 18-MAR-1998 Added @must to ttfmod() +# MJPH 1.1.1 25-MAR-1998 Added $csum to copytab (to make reusable) + +package ttfmod; + +sub main'ttfmod { + local($infile, $outfile, *fns, @must) = @_; + + # open files as binary. Notice OUTFILE is opened for update not just write + open(INFILE, "$infile") || die "Unable top open \"$infile\" for reading"; + binmode INFILE; + open(OUTFILE, "+>$outfile") || die "Unable to open \"$outfile\" for writing"; + binmode OUTFILE; + + seek(INFILE, 0, 0); + read(INFILE, $dir_head, 12) || die "Reading table header"; + ($dir_num) = unpack("x4n", $dir_head); + print OUTFILE $dir_head; + # read and unpack table directory + for ($i = 0; $i < $dir_num; $i++) + { + read(INFILE, $dir_val, 16) || die "Reading table entry"; + $dir{unpack("a4", $dir_val)} = join(":", $i, unpack("x4NNN", $dir_val)); + print OUTFILE $dir_val; + printf STDERR "%s %08x\n", unpack("a4", $dir_val), unpack("x8N", $dir_val) + if (defined $main'opt_z); + } + foreach $n (@must) + { + next if defined $dir{$n}; + $dir{$n} = "$i:0:-1:0"; + $i++; $dir_num++; + print OUTFILE pack("a4NNN", $n, 0, -1, 0); + } + substr($dir_head, 4, 2) = pack("n", $dir_num); + $csum = unpack("%32N*", $dir_head); + $off = tell(OUTFILE); + seek(OUTFILE, 0, 0); + print OUTFILE $dir_head; + seek (OUTFILE, $off, 0); + # process tables in order they occur in the file + @dirlist = sort byoffset keys(%dir); + foreach $tab (@dirlist) + { + @tab_split = split(':', $dir{$tab}); + seek(INFILE, $tab_split[2], 0); # offset + $tab_split[2] = tell(OUTFILE); + if (defined $fns{$tab}) + { + $temp = "main'$fns{$tab}"; + ($dir_len, $sum) = &$temp(*INFILE, *OUTFILE, $tab_split[3]); + } + else + { + ($dir_len, $sum) = ©tab(*INFILE, *OUTFILE, $tab_split[3]); + } + $tab_split[3] = $dir_len; # len + $tab_split[1] = $sum; # checksum + $out_dir{$tab} = join(":", @tab_split); + } + # now output directory in same order as original directory + @dirlist = sort byindex keys(%out_dir); + foreach $tab (@dirlist) + { + @tab_split = split(':', $out_dir{$tab}); + seek (OUTFILE, 12 + $tab_split[0] * 16, 0); # directory index + print OUTFILE pack("A4N3", $tab, @tab_split[1..3]); + foreach $i (1..3, 1) # checksum directory values with csum twice + { + $csum += $tab_split[$i]; + # this line ensures $csum stays within 32 bit bounds, clipping as necessary + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + } + # checksum the tag + $csum += unpack("N", $tab); + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + } + # handle main checksum + @tab_split = split(':', $out_dir{"head"}); + seek(OUTFILE, $tab_split[2], 0); + read(OUTFILE, $head_head, 12); # read first bit of "head" table + @head_split = unpack("N3", $head_head); + $tab_split[1] -= $head_split[2]; # subtract old checksum + $csum -= $head_split[2] * 2; # twice because had double effect + # already + if ($csum < 0 ) { $csum += 0xffffffff; $csum++; } + $head_split[2] = 0xB1B0AFBA - $csum; # calculate new checksum + seek (OUTFILE, 12 + $tab_split[0] * 16, 0); + print OUTFILE pack("A4N3", "head", @tab_split[1..3]); + seek (OUTFILE, $tab_split[2], 0); # rewrite first bit of "head" table + print OUTFILE pack("N3", @head_split); + + # finish up + close(OUTFILE); + close(INFILE); + } + +# support function for sorting by table offset +sub byoffset { + @t1 = split(':', $dir{$a}); + @t2 = split(':', $dir{$b}); + return 1 if ($t1[2] == -1); # put inserted tables at the end + return -1 if ($t2[2] == -1); + return $t1[2] <=> $t2[2]; + } + +# support function for sorting by directory entry order +sub byindex { + $t1 = split(':', $dir{$a}, 1); + $t2 = split(':', $dir{$b}, 1); + return $t1 <=> $t2; + } + +# default table action: copies a table from input to output, recalculating +# the checksum (just to be absolutely sure). +sub copytab { + local(*INFILE, *OUTFILE, $len, $csum) = @_; + + while ($len > 0) + { + $count = ($len > 8192) ? 8192 : $len; # 8K buffering + read(INFILE, $buf, $count) == $count || die "Copying"; + $buf .= "\0" x (4 - ($count & 3)) if ($count & 3); # pad to long + print OUTFILE $buf; + $csum += unpack("%32N*", $buf); + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + $len -= $count; + } + ($_[2], $csum); + } + +# test routine to copy file from input to output, no changes +package main; + +if ($test_package) + { + &ttfmod($ARGV[0], $ARGV[1], *dummy); + } +else + { 1; } + +=head1 AUTHOR + +Martin Hosken L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This script is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/blib/man1/.exists b/.cpan/build/Font-TTF-1.06-0/blib/man1/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/man3/.exists b/.cpan/build/Font-TTF-1.06-0/blib/man3/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF.3pm" new file mode 100644 index 0000000000..c6c1de58e8 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF.3pm" @@ -0,0 +1,104 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF 3pm" +.TH Font::TTF 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF \- Perl module for TrueType Font hacking +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This module allows you to do almost anything to a TrueType/OpenType Font +including modify and inspect nearly all tables. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +(see \s-1CONTRIBUTORS\s0 for other authors). +.PP +Repository available at +.SH "HISTORY" +.IX Header "HISTORY" +See \fIChanges\fR file for a change log. +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 +.PP +The fonts in the test suite are released under the Open Font License 1.1, see \fIt/OFL.txt\fR. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Font::TTF::Font diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242AATKern.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242AATKern.3pm" new file mode 100644 index 0000000000..986f0a011f --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242AATKern.3pm" @@ -0,0 +1,106 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::AATKern 3pm" +.TH Font::TTF::AATKern 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::AATKern \- AAT Kern table +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242AATutils.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242AATutils.3pm" new file mode 100644 index 0000000000..91f9c2bf2b --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242AATutils.3pm" @@ -0,0 +1,109 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::AATutils 3pm" +.TH Font::TTF::AATutils 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::AATutils \- Utility functions for AAT tables +.ie n .SS "($classes, $states) = AAT_read_subtable($fh, $baseOffset, $subtableStart, $limits)" +.el .SS "($classes, \f(CW$states\fP) = AAT_read_subtable($fh, \f(CW$baseOffset\fP, \f(CW$subtableStart\fP, \f(CW$limits\fP)" +.IX Subsection "($classes, $states) = AAT_read_subtable($fh, $baseOffset, $subtableStart, $limits)" +.ie n .SS "$length = AAT_write_state_table($fh, $classes, $states, $numExtraTables, $packEntry)" +.el .SS "\f(CW$length\fP = AAT_write_state_table($fh, \f(CW$classes\fP, \f(CW$states\fP, \f(CW$numExtraTables\fP, \f(CW$packEntry\fP)" +.IX Subsection "$length = AAT_write_state_table($fh, $classes, $states, $numExtraTables, $packEntry)" +\&\f(CW$packEntry\fR is a subroutine for packing an entry into binary form, called as +.PP +\&\f(CW$dat\fR = \f(CW$packEntr\fRy($entry, \f(CW$entryTable\fR, \f(CW$numEntries\fR) +.PP +where the entry is a comma-separated list of nextStateOffset, flags, actions +.ie n .SS "($classes, $states, $entries) = AAT_read_state_table($fh, $numActionWords)" +.el .SS "($classes, \f(CW$states\fP, \f(CW$entries\fP) = AAT_read_state_table($fh, \f(CW$numActionWords\fP)" +.IX Subsection "($classes, $states, $entries) = AAT_read_state_table($fh, $numActionWords)" +.ie n .SS "($format, $lookup) = AAT_read_lookup($fh, $valueSize, $length, $default)" +.el .SS "($format, \f(CW$lookup\fP) = AAT_read_lookup($fh, \f(CW$valueSize\fP, \f(CW$length\fP, \f(CW$default\fP)" +.IX Subsection "($format, $lookup) = AAT_read_lookup($fh, $valueSize, $length, $default)" +.ie n .SS "AAT_write_lookup($fh, $format, $lookup, $valueSize, $default)" +.el .SS "AAT_write_lookup($fh, \f(CW$format\fP, \f(CW$lookup\fP, \f(CW$valueSize\fP, \f(CW$default\fP)" +.IX Subsection "AAT_write_lookup($fh, $format, $lookup, $valueSize, $default)" +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Anchor.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Anchor.3pm" new file mode 100644 index 0000000000..a96a5c1bac --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Anchor.3pm" @@ -0,0 +1,136 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Anchor 3pm" +.TH Font::TTF::Anchor 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Anchor \- Anchor points for GPOS tables +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The Anchor defines an anchor point on a glyph providing various information +depending on how much is available, including such information as the co-ordinates, +a curve point and even device specific modifiers. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "x" 4 +.IX Item "x" +XCoordinate of the anchor point +.IP "y" 4 +.IX Item "y" +YCoordinate of the anchor point +.IP "p" 4 +.IX Item "p" +Curve point on the glyph to use as the anchor point +.IP "xdev" 4 +.IX Item "xdev" +Device table (delta) for the xcoordinate +.IP "ydev" 4 +.IX Item "ydev" +Device table (delta) for the ycoordinate +.IP "xid" 4 +.IX Item "xid" +XIdAnchor for multiple master horizontal metric id +.IP "yid" 4 +.IX Item "yid" +YIdAnchor for multiple master vertical metric id +.SH "METHODS" +.IX Header "METHODS" +.SS "new" +.IX Subsection "new" +Creates a new Anchor +.SS "read($fh)" +.IX Subsection "read($fh)" +Reads the anchor from the given file handle at that point. The file handle is left +at an arbitrary read point, usually the end of something! +.ie n .SS "out($fh, $style)" +.el .SS "out($fh, \f(CW$style\fP)" +.IX Subsection "out($fh, $style)" +Outputs the Anchor to the given file handle at this point also addressing issues +of deltas. If \f(CW$style\fR is set, then no output is sent to the file handle. The return +value is the output string. +.ie n .SS "$a\->out_xml($context)" +.el .SS "\f(CW$a\fP\->out_xml($context)" +.IX Subsection "$a->out_xml($context)" +Outputs the anchor in \s-1XML\s0 +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Bsln.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Bsln.3pm" new file mode 100644 index 0000000000..40dbd5e480 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Bsln.3pm" @@ -0,0 +1,128 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Bsln 3pm" +.TH Font::TTF::Bsln 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Bsln \- Baseline table in a font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "version" 4 +.IX Item "version" +.PD 0 +.IP "xformat" 4 +.IX Item "xformat" +.IP "defaultBaseline" 4 +.IX Item "defaultBaseline" +.IP "deltas" 4 +.IX Item "deltas" +.IP "stdGlyph" 4 +.IX Item "stdGlyph" +.IP "ctlPoints" 4 +.IX Item "ctlPoints" +.IP "lookupFormat" 4 +.IX Item "lookupFormat" +.IP "lookup" 4 +.IX Item "lookup" +.PD +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Cmap.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Cmap.3pm" new file mode 100644 index 0000000000..4029e37049 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Cmap.3pm" @@ -0,0 +1,203 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Cmap 3pm" +.TH Font::TTF::Cmap 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Cmap \- Character map table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Looks after the character map. For ease of use, the actual cmap is held in +a hash against codepoint. Thus for a given table: +.PP +.Vb 1 +\& $gid = $font\->{\*(Aqcmap\*(Aq}{\*(AqTables\*(Aq}[0]{\*(Aqval\*(Aq}{$code}; +.Ve +.PP +Note that \f(CW$code\fR should be a true value (0x1234) rather than a string representation. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The instance variables listed here are not preceded by a space due to their +emulating structural information in the font. +.IP "Num" 4 +.IX Item "Num" +Number of subtables in this table +.IP "Tables" 4 +.IX Item "Tables" +An array of subtables ([0..Num\-1]) +.Sp +Each subtable also has its own instance variables which are, again, not +preceded by a space. +.RS 4 +.IP "Platform" 4 +.IX Item "Platform" +The platform number for this subtable +.IP "Encoding" 4 +.IX Item "Encoding" +The encoding number for this subtable +.IP "Format" 4 +.IX Item "Format" +Gives the stored format of this subtable +.IP "Ver" 4 +.IX Item "Ver" +Gives the version (or language) information for this subtable +.IP "val" 4 +.IX Item "val" +A hash keyed by the codepoint value (not a string) storing the glyph id +.RE +.RS 4 +.RE +.PP +The following cmap options are controlled by instance variables that start with a space: +.IP "allowholes" 4 +.IX Item "allowholes" +By default, when generating format 4 cmap subtables character codes that point to glyph zero +(normally called .notdef) are not included in the subtable. In some cases including some of these +character codes can result in a smaller format 4 subtable. To enable this behavior, set allowholes +to non-zero. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the cmap into memory. Format 4 subtables read the whole subtable and +fill in the segmented array accordingly. +.ie n .SS "$t\->ms_lookup($uni)" +.el .SS "\f(CW$t\fP\->ms_lookup($uni)" +.IX Subsection "$t->ms_lookup($uni)" +Finds a Unicode table, giving preference to the \s-1MS\s0 one, and looks up the given +Unicode codepoint in it to find the glyph id. +.ie n .SS "$t\->find_ms" +.el .SS "\f(CW$t\fP\->find_ms" +.IX Subsection "$t->find_ms" +Finds the a Unicode table, giving preference to the Microsoft one, and sets the \f(CW\*(C`mstable\*(C'\fR instance variable +to it if found. Returns the table it finds. +.ie n .SS "$t\->ms_enc" +.el .SS "\f(CW$t\fP\->ms_enc" +.IX Subsection "$t->ms_enc" +Returns the encoding of the microsoft table (0 => symbol, etc.). Returns undef if there is +no Microsoft cmap. +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes out a cmap table to a filehandle. If it has not been read, then +just copies from input file to output +.ie n .SS "$t\->XML_element($context, $depth, $name, $val)" +.el .SS "\f(CW$t\fP\->XML_element($context, \f(CW$depth\fP, \f(CW$name\fP, \f(CW$val\fP)" +.IX Subsection "$t->XML_element($context, $depth, $name, $val)" +Outputs the elements of the cmap in \s-1XML.\s0 We only need to process val here +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be in bytes. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Tidies the cmap table. +.PP +Removes \s-1MS\s0 Fmt12 cmap if it is no longer needed. +.PP +Removes from all cmaps any codepoint that map to GID=0. Note that such entries will +be re-introduced as necessary depending on the cmap format. +.ie n .SS "@map = $t\->reverse(%opt)" +.el .SS "\f(CW@map\fP = \f(CW$t\fP\->reverse(%opt)" +.IX Subsection "@map = $t->reverse(%opt)" +Returns a reverse map of the Unicode cmap. I.e. given a glyph gives the Unicode value for it. Options are: +.IP "tnum" 4 +.IX Item "tnum" +Table number to use rather than the default Unicode table +.IP "array" 4 +.IX Item "array" +Returns each element of reverse as an array since a glyph may be mapped by more +than one Unicode value. The arrays are unsorted. Otherwise store any one unicode value for a glyph. +.SS "is_unicode($index)" +.IX Subsection "is_unicode($index)" +Returns whether the table of a given index is known to be a unicode table +(as specified in the specifications) +.SH "BUGS" +.IX Header "BUGS" +.IP "\(bu" 4 +Format 14 (Unicode Variation Sequences) cmaps are not supported. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Coverage.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Coverage.3pm" new file mode 100644 index 0000000000..5e7e0f4667 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Coverage.3pm" @@ -0,0 +1,147 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Coverage 3pm" +.TH Font::TTF::Coverage 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Coverage \- Opentype coverage and class definition objects +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Coverage tables and class definition objects are virtually identical concepts +in OpenType. Their difference comes purely in their storage. Therefore we can +say that a coverage table is a class definition in which the class definition +for each glyph is the corresponding index in the coverage table. The resulting +data structure is that a Coverage table has the following fields: +.IP "cover" 4 +.IX Item "cover" +A boolean to indicate whether this table is a coverage table (\s-1TRUE\s0) or a +class definition (\s-1FALSE\s0) +.IP "val" 4 +.IX Item "val" +A hash of glyph ids against values (either coverage index or class value) +.IP "fmt" 4 +.IX Item "fmt" +The storage format used is given here, but is recalculated when the table +is written out. +.IP "count" 4 +.IX Item "count" +A count of the elements in a coverage table for use with add. Each subsequent +addition is added with the current count and increments the count. +.IP "max" 4 +.IX Item "max" +Maximum class value in a class table. +.SH "METHODS" +.IX Header "METHODS" +.SS "new($isCover [, vals])" +.IX Subsection "new($isCover [, vals])" +Creates a new coverage table or class definition table, depending upon the +value of \f(CW$isCover\fR. if \f(CW$isCover\fR then vals may be a list of glyphs to include in order. +If no \f(CW$isCover\fR, then vals is a hash of glyphs against class values. +.SS "read($fh)" +.IX Subsection "read($fh)" +Reads the coverage/class table from the given file handle +.ie n .SS "out($fh, $state)" +.el .SS "out($fh, \f(CW$state\fP)" +.IX Subsection "out($fh, $state)" +Writes the coverage/class table to the given file handle. If \f(CW$state\fR is 1 then +the output string is returned rather than being output to a filehandle. +.ie n .SS "$c\->add($glyphid[, $class])" +.el .SS "\f(CW$c\fP\->add($glyphid[, \f(CW$class\fP])" +.IX Subsection "$c->add($glyphid[, $class])" +Adds a glyph id to the coverage or class table. +Returns the index or class number of the glyphid added. +.ie n .SS "$c\->signature" +.el .SS "\f(CW$c\fP\->signature" +.IX Subsection "$c->signature" +Returns a vector of all the glyph ids covered by this coverage table or class +.ie n .SS "@map=$c\->sort" +.el .SS "\f(CW@map\fP=$c\->sort" +.IX Subsection "@map=$c->sort" +Sorts the coverage table so that indexes are in ascending order of glyphid. +Returns a map such that \f(CW$map\fR[$new_index]=$old_index. +.ie n .SS "$c\->out_xml($context)" +.el .SS "\f(CW$c\fP\->out_xml($context)" +.IX Subsection "$c->out_xml($context)" +Outputs this coverage/class in \s-1XML\s0 +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Cvt_.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Cvt_.3pm" new file mode 100644 index 0000000000..ab3c674fbb --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Cvt_.3pm" @@ -0,0 +1,116 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Cvt_ 3pm" +.TH Font::TTF::Cvt_ 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Cvt_ \- Control Value Table in a TrueType font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a minimal class adding nothing beyond a table, but is a repository +for cvt type information for those processes brave enough to address hinting. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "val" 4 +.IX Item "val" +This is an array of \s-1CVT\s0 values. Thus access to the \s-1CVT\s0 is via: +.Sp +.Vb 1 +\& $f\->{\*(Aqcvt_\*(Aq}{\*(Aqval\*(Aq}[$num]; +.Ve +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the \s-1CVT\s0 table into both the tables \f(CW\*(Aq dat\*(Aq\fR variable and the \f(CW\*(C`val\*(C'\fR +array. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Updates the \s-1RAM\s0 file copy \f(CW\*(Aq dat\*(Aq\fR to be the same as the array. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242DSIG.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242DSIG.3pm" new file mode 100644 index 0000000000..b080819be9 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242DSIG.3pm" @@ -0,0 +1,87 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::DSIG 3pm" +.TH Font::TTF::DSIG 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Delta.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Delta.3pm" new file mode 100644 index 0000000000..6cbf373c15 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Delta.3pm" @@ -0,0 +1,129 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Delta 3pm" +.TH Font::TTF::Delta 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Delta \- Opentype Device tables +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Each device table corresponds to a set of deltas for a particular point over +a range of ppem values. +.IP "first" 4 +.IX Item "first" +The first ppem value in the range +.IP "last" 4 +.IX Item "last" +The last ppem value in the range +.IP "val" 4 +.IX Item "val" +This is an array of deltas corresponding to each ppem in the range between +first and last inclusive. +.IP "fmt" 4 +.IX Item "fmt" +This is the fmt used (log2 of number bits per value) when the device table was +read. It is recalculated on output. +.SH "METHODS" +.IX Header "METHODS" +.SS "new" +.IX Subsection "new" +Creates a new device table +.SS "read" +.IX Subsection "read" +Reads a device table from the given \s-1IO\s0 object at the current location +.ie n .SS "out($fh, $style)" +.el .SS "out($fh, \f(CW$style\fP)" +.IX Subsection "out($fh, $style)" +Outputs a device table to the given \s-1IO\s0 object at the current location, or just +returns the data to be output if \f(CW$style\fR != 0 +.ie n .SS "$d\->\fBsignature()\fP" +.el .SS "\f(CW$d\fP\->\fBsignature()\fP" +.IX Subsection "$d->signature()" +Returns a content based identifying string for this delta for +compression purposes +.ie n .SS "$d\->out_xml($context)" +.el .SS "\f(CW$d\fP\->out_xml($context)" +.IX Subsection "$d->out_xml($context)" +Outputs a delta in \s-1XML\s0 +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Dumper.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Dumper.3pm" new file mode 100644 index 0000000000..c18ab8740f --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Dumper.3pm" @@ -0,0 +1,121 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Dumper 3pm" +.TH Font::TTF::Dumper 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Dumper \- Debug dump of a font datastructure, avoiding recursion on ' PARENT' +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use Font::TTF::Dumper; +\& +\& # Print a table from the font structure: +\& print ttfdump($font\->{$tag}); +\& +\& # Print font table with name +\& print ttfdump($font\->{\*(Aqhead\*(Aq}, \*(Aqhead\*(Aq); +\& +\& # Print font table with name and other options +\& print ttfdump($font\->{\*(Aqhead\*(Aq}, \*(Aqhead\*(Aq, %opts); +\& +\& # Print one glyph\*(Aqs data: +\& print ttfdump($font\->{\*(Aqloca\*(Aq}\->read\->{\*(Aqglyphs\*(Aq}[$gid], "glyph_$gid"); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Font::TTF data structures are trees created from hashes and arrays. When trying to figure +out how the structures work, sometimes it is helpful to use Data::Dumper on them. However, +many of the object structures have ' \s-1PARENT\s0' links that refer back to the object's parent, +which means that Data::Dumper ends up dumping the whole font no matter what. +.PP +The main purpose of this module is to invoke Data::Dumper with a +filter that skips over the ' \s-1PARENT\s0' element of any hash. +.PP +To reduce output further, this module also skips over ' \s-1CACHE\s0' elements and any +hash element whose value is a Font::TTF::Glyph or Font::TTF::Font object. +(Really should make this configurable.) +.PP +If \f(CW$opts\fR{'d'}, then set Deepcopy mode to minimize use of crossreferencing. +.SH "AUTHOR" +.IX Header "AUTHOR" +Bob Hallissy . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242EBDT.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242EBDT.3pm" new file mode 100644 index 0000000000..88c5326811 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242EBDT.3pm" @@ -0,0 +1,149 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::EBDT 3pm" +.TH Font::TTF::EBDT 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::EBDT \- Embeeded Bitmap Data Table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Contains the metrics and bitmap image data. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +Only has 'bitmap' instance variable. It is an array of assosiative +array keyed by glyph-id. The element is an object which consists +of metric information and image data. +.IP "bitmap object" 4 +.IX Item "bitmap object" +.RS 4 +.PD 0 +.IP "format" 8 +.IX Item "format" +.PD +Only 7 is supported. +.IP "height" 8 +.IX Item "height" +.PD 0 +.IP "width" 8 +.IX Item "width" +.IP "horiBearingX" 8 +.IX Item "horiBearingX" +.IP "horiBearingY" 8 +.IX Item "horiBearingY" +.IP "horiAdvance" 8 +.IX Item "horiAdvance" +.IP "vertBearingX" 8 +.IX Item "vertBearingX" +.IP "vertBearingY" 8 +.IX Item "vertBearingY" +.IP "vertAdvance" 8 +.IX Item "vertAdvance" +.IP "imageData" 8 +.IX Item "imageData" +.RE +.RS 4 +.RE +.PD +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the embedded bitmap data from the \s-1TTF\s0 file into memory. +This routine should be called _after_ {'\s-1EBLC\s0'}\->read. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Update \s-1EBLC\s0 information using \s-1EBDT\s0 data. +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Outputs the bitmap data of embedded bitmap for this font. +.SH "BUGS" +.IX Header "BUGS" +Only Format 7 is implemented. \s-1XML\s0 output is not supported (yet). +.SH "AUTHOR" +.IX Header "AUTHOR" +\&\s-1NIIBE\s0 Yutaka . +This was written at the CodeFest Akihabara 2006 hosted by \s-1FSIJ.\s0 +.PP +?? patch sent with licensing requirements or not? +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242EBLC.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242EBLC.3pm" new file mode 100644 index 0000000000..eaf0a0f892 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242EBLC.3pm" @@ -0,0 +1,154 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::EBLC 3pm" +.TH Font::TTF::EBLC 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::EBLC \- Embeeded Bitmap Location Table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Contains the sizes and glyph ranges of bitmaps, and the offsets to +glyph bitmap data in indexSubTables for \s-1EBDT.\s0 +.PP +Possibly contains glyph metrics information. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The information specified '\fB(R)\fRead only' is read only, those +are calculated from \s-1EBDT,\s0 when it is 'update'\-ed. +.IP "bitmapSizeTable" 4 +.IX Item "bitmapSizeTable" +An array of tables of following information +.RS 4 +.IP "indexSubTableArrayOffset (R)" 8 +.IX Item "indexSubTableArrayOffset (R)" +.PD 0 +.IP "indexTablesSize (R)" 8 +.IX Item "indexTablesSize (R)" +.IP "numberOfIndexSubTables (R)" 8 +.IX Item "numberOfIndexSubTables (R)" +.IP "colorRef" 8 +.IX Item "colorRef" +.IP "hori" 8 +.IX Item "hori" +.IP "vert" 8 +.IX Item "vert" +.IP "startGlyphIndex (R)" 8 +.IX Item "startGlyphIndex (R)" +.IP "endGlyphIndex (R)" 8 +.IX Item "endGlyphIndex (R)" +.IP "ppemX" 8 +.IX Item "ppemX" +.IP "ppemY" 8 +.IX Item "ppemY" +.IP "bitDepth" 8 +.IX Item "bitDepth" +.IP "flags" 8 +.IX Item "flags" +.RE +.RS 4 +.RE +.IP "indexSubTableArray (R)" 4 +.IX Item "indexSubTableArray (R)" +.PD +An array which contains range information. +.IP "indexSubTable (R)" 4 +.IX Item "indexSubTable (R)" +An array which contains offsets of \s-1EBDT\s0 table. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the location information of embedded bitmap from the \s-1TTF\s0 file into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Outputs the location information of embedded bitmap for this font. +.SH "BUGS" +.IX Header "BUGS" +Only indexFormat ==1 is implemented. \s-1XML\s0 output is not supported (yet). +.SH "AUTHOR" +.IX Header "AUTHOR" +\&\s-1NIIBE\s0 Yutaka . +This was written at the CodeFest Akihabara 2006 hosted by \s-1FSIJ.\s0 +.PP +Patch sent with licensing requirements?? +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fdsc.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fdsc.3pm" new file mode 100644 index 0000000000..ce72d1d42b --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fdsc.3pm" @@ -0,0 +1,117 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Fdsc 3pm" +.TH Font::TTF::Fdsc 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Fdsc \- Font Descriptors table in a font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "version" 4 +.IX Item "version" +.PD 0 +.IP "descriptors" 4 +.IX Item "descriptors" +.PD +Hash keyed by descriptor tags +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Feat.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Feat.3pm" new file mode 100644 index 0000000000..291e111cdd --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Feat.3pm" @@ -0,0 +1,138 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Feat 3pm" +.TH Font::TTF::Feat 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Feat \- Font Features +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "version" 4 +.IX Item "version" +.PD 0 +.IP "features" 4 +.IX Item "features" +.PD +An array of hashes of the following form +.RS 4 +.IP "feature" 8 +.IX Item "feature" +feature id number +.IP "name" 8 +.IX Item "name" +name index in name table +.IP "exclusive" 8 +.IX Item "exclusive" +exclusive flag +.IP "settings" 8 +.IX Item "settings" +hash of setting number against name string index +.RE +.RS 4 +.RE +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the features from the \s-1TTF\s0 file into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the features to a \s-1TTF\s0 file +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Cvar.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Cvar.3pm" new file mode 100644 index 0000000000..c0d3afb1df --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Cvar.3pm" @@ -0,0 +1,137 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Features::Cvar 3pm" +.TH Font::TTF::Features::Cvar 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Features::Size \- Class for Character Variants Feature Parameters +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Handles the Feature Parameters valus forCharacter Variants features +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "\s-1INFILE\s0" 4 +.IX Item "INFILE" +The read file handle +.IP "\s-1OFFSET\s0" 4 +.IX Item "OFFSET" +Location of the file in the input file +.IP "Format" 4 +.IX Item "Format" +Table format \- set to 0 +.IP "UINameID" 4 +.IX Item "UINameID" +The 'name' table name \s-1ID\s0 that specifies a string (or strings, for multiple +languages) for a user-interface label for this feature +.IP "TooltipNameID" 4 +.IX Item "TooltipNameID" +The 'name' table name \s-1ID\s0 for tooltip text for the feature +.IP "SampleTextNameID" 4 +.IX Item "SampleTextNameID" +The 'name' table name \s-1ID\s0 for sample text to illustrate the feature +.IP "NumNamedParms" 4 +.IX Item "NumNamedParms" +The number of named parameters +.IP "FirstNamedParmID" 4 +.IX Item "FirstNamedParmID" +The 'name' table name \s-1ID\s0 for the first named parameter +.IP "Characters" 4 +.IX Item "Characters" +An array holding the unicode values of the characters for which the feature +provides glyph variants +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the Feature Params +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the FeatureParams table to the output +.SS "Font::TTF::Features::Sset\->\fBnew()\fP" +.IX Subsection "Font::TTF::Features::Sset->new()" +Creates a new FeatureParams object. +Values for \s-1INFILE\s0 and \s-1OFFSET\s0 canbe passed as parameters +.SH "AUTHOR" +.IX Header "AUTHOR" +David Raymond . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Size.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Size.3pm" new file mode 100644 index 0000000000..d73d891433 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Size.3pm" @@ -0,0 +1,129 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Features::Size 3pm" +.TH Font::TTF::Features::Size 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Features::Size \- Class for Size Feature Parameters +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Handles the Feature Parameters valus for Size features +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "\s-1INFILE\s0" 4 +.IX Item "INFILE" +The read file handle +.IP "\s-1OFFSET\s0" 4 +.IX Item "OFFSET" +Location of the file in the input file +.IP "DesignSize" 4 +.IX Item "DesignSize" +Design Size in decipoints +.IP "SubFID" 4 +.IX Item "SubFID" +Identifier for the fonts in a subfamily +.IP "SubFNameID" 4 +.IX Item "SubFNameID" +The 'name' table name \s-1ID\s0 for the subfamily name +.IP "MinSize" 4 +.IX Item "MinSize" +Bottom end of recomended usage size range +.IP "MaxSize" 4 +.IX Item "MaxSize" +Top end of recomended usage size range +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the Feature Params +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the FeatureParams table to the output +.SS "Font::TTF::Features::Sset\->\fBnew()\fP" +.IX Subsection "Font::TTF::Features::Sset->new()" +Creates a new FeatureParams object. Table instance variables are passed in +at this point as an associative array. +.SH "AUTHOR" +.IX Header "AUTHOR" +David Raymond . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Sset.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Sset.3pm" new file mode 100644 index 0000000000..e03f340b93 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Features\357\200\242\357\200\242Sset.3pm" @@ -0,0 +1,121 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Features::Sset 3pm" +.TH Font::TTF::Features::Sset 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Features::Sset \- Class for Stylistic Set Feature Parameters +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Handles the Feature Parameters valus for Stylistic Sets +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "\s-1INFILE\s0" 4 +.IX Item "INFILE" +The read file handle +.IP "\s-1OFFSET\s0" 4 +.IX Item "OFFSET" +Location of the file in the input file +.IP "Version" 4 +.IX Item "Version" +The minor version number, currently always 0 +.IP "UINameID" 4 +.IX Item "UINameID" +The 'name' table name \s-1ID\s0 that specifies a string (or strings, for multiple +languages) for a user-interface label for this feature +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the Feature Params +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the FeatureParams table to the output +.SS "Font::TTF::Features::Sset\->\fBnew()\fP" +.IX Subsection "Font::TTF::Features::Sset->new()" +Creates a new FeatureParams object. +Values for \s-1INFILE\s0 and \s-1OFFSET\s0 canbe passed as parameters +.SH "AUTHOR" +.IX Header "AUTHOR" +David Raymond . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fmtx.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fmtx.3pm" new file mode 100644 index 0000000000..c3455a7208 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fmtx.3pm" @@ -0,0 +1,119 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Fmtx 3pm" +.TH Font::TTF::Fmtx 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Fmtx \- Font Metrics table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a simple table with just standards specified instance variables +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.Vb 10 +\& version +\& glyphIndex +\& horizontalBefore +\& horizontalAfter +\& horizontalCaretHead +\& horizontalCaretBase +\& verticalBefore +\& verticalAfter +\& verticalCaretHead +\& verticalCaretBase +.Ve +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory as instance variables +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Font.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Font.3pm" new file mode 100644 index 0000000000..98e2b03bd8 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Font.3pm" @@ -0,0 +1,339 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Font 3pm" +.TH Font::TTF::Font 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Font \- Memory representation of a font +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +Here is the regression test (you provide your own font). Run it once and then +again on the output of the first run. There should be no differences between +the outputs of the two runs. +.PP +.Vb 1 +\& $f = Font::TTF::Font\->open($ARGV[0]); +\& +\& # force a read of all the tables +\& $f\->tables_do(sub { $_[0]\->read; }); +\& +\& # force read of all glyphs (use read_dat to use lots of memory!) +\& # $f\->{\*(Aqloca\*(Aq}\->glyphs_do(sub { $_[0]\->read; }); +\& $f\->{\*(Aqloca\*(Aq}\->glyphs_do(sub { $_[0]\->read_dat; }); +\& # NB. no need to $g\->update since $f\->{\*(Aqglyf\*(Aq}\->out will do it for us +\& +\& $f\->out($ARGV[1]); +\& $f\->release; # clear up memory forcefully! +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +A Truetype font consists of a header containing a directory of tables which +constitute the rest of the file. This class holds that header and directory and +also creates objects of the appropriate type for each table within the font. +Note that it does not read each table into memory, but creates a short reference +which can be read using the form: +.PP +.Vb 1 +\& $f\->{$tablename}\->read; +.Ve +.PP +Classes are included that support many of the different TrueType tables. For +those for which no special code exists, the table type \f(CW\*(C`table\*(C'\fR is used, which +defaults to Font::TTF::Table. The current tables which are supported are: +.PP +.Vb 10 +\& table Font::TTF::Table \- for unknown tables +\& EBDT Font::TTF::EBDT +\& EBLC Font::TTF::EBLC +\& Feat Font::TTF::GrFeat +\& GDEF Font::TTF::GDEF +\& GPOS Font::TTF::GPOS +\& GSUB Font::TTF::GSUB +\& Glat Font::TTF::Glat +\& Gloc Font::TTF::Gloc +\& LTSH Font::TTF::LTSH +\& OS/2 Font::TTF::OS_2 +\& PCLT Font::TTF::PCLT +\& Sill Font::TTF::Sill +\& Silf Font::TTF::Silf +\& bsln Font::TTF::Bsln +\& cmap Font::TTF::Cmap \- see also Font::TTF::OldCmap +\& cvt Font::TTF::Cvt_ +\& fdsc Font::TTF::Fdsc +\& feat Font::TTF::Feat +\& fmtx Font::TTF::Fmtx +\& fpgm Font::TTF::Fpgm +\& glyf Font::TTF::Glyf \- see also Font::TTF::Glyph +\& hdmx Font::TTF::Hdmx +\& head Font::TTF::Head +\& hhea Font::TTF::Hhea +\& hmtx Font::TTF::Hmtx +\& kern Font::TTF::Kern \- see alternative Font::TTF::AATKern +\& loca Font::TTF::Loca +\& maxp Font::TTF::Maxp +\& mort Font::TTF::Mort \- see also Font::TTF::OldMort +\& name Font::TTF::Name +\& post Font::TTF::Post +\& prep Font::TTF::Prep +\& prop Font::TTF::Prop +\& vhea Font::TTF::Vhea +\& vmtx Font::TTF::Vmtx +\& DSIG FONT::TTF::DSIG +.Ve +.PP +Links are: +.PP +Font::TTF::Table +Font::TTF::EBDT Font::TTF::EBLC Font::TTF::GrFeat +Font::TTF::GDEF Font::TTF::GPOS Font::TTF::GSUB Font::TTF::Glat Font::TTF::Gloc Font::TTF::LTSH +Font::TTF::OS_2 Font::TTF::PCLT Font::TTF::Sill Font::TTF::Silf Font::TTF::Bsln Font::TTF::Cmap Font::TTF::Cvt_ +Font::TTF::Fdsc Font::TTF::Feat Font::TTF::Fmtx Font::TTF::Fpgm Font::TTF::Glyf +Font::TTF::Hdmx Font::TTF::Head Font::TTF::Hhea Font::TTF::Hmtx Font::TTF::Kern +Font::TTF::Loca Font::TTF::Maxp Font::TTF::Mort Font::TTF::Name Font::TTF::Post +Font::TTF::Prep Font::TTF::Prop Font::TTF::Vhea Font::TTF::Vmtx Font::TTF::OldCmap +Font::TTF::Glyph Font::TTF::AATKern Font::TTF::OldMort +Font::TTF::DSIG +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +Instance variables begin with a space (and have lengths greater than the 4 +characters which make up table names). +.IP "nocsum" 4 +.IX Item "nocsum" +This is used during output to disable the creation of the file checksum in the +head table. For example, during \s-1DSIG\s0 table creation, this flag will be set to +ensure that the file checksum is left at zero. +.IP "noharmony" 4 +.IX Item "noharmony" +If set, do not harmonize the script and lang trees of \s-1GPOS\s0 and \s-1GSUB\s0 tables. See Font::TTF::Ttopen for more info. +.IP "nocompress" 4 +.IX Item "nocompress" +Is the default value controlling \s-1WOFF\s0 output table compression. If undef, all tables will be compressed if there is +a size benefit in doing so. +It may be set to an array of tagnames naming tables that should not be compressed, or to a scalar integer specifying a +table size threshold below which tables will not be compressed. +Note that individual Font::TTF::Table objects may override this default. See Font::TTF::Table for more info. +.IP "fname (R)" 4 +.IX Item "fname (R)" +Contains the filename of the font which this object was read from. +.IP "\s-1INFILE\s0 (P)" 4 +.IX Item "INFILE (P)" +The file handle which reflects the source file for this font. +.IP "\s-1OFFSET\s0 (P)" 4 +.IX Item "OFFSET (P)" +Contains the offset from the beginning of the read file of this particular +font directory, thus providing support for TrueType Collections. +.IP "\s-1WOFF\s0" 4 +.IX Item "WOFF" +Contains a reference to a \f(CW\*(C`Font::TTF::Woff\*(C'\fR object. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "Font::TTF::Font\->AddTable($tablename, $class)" +.el .SS "Font::TTF::Font\->AddTable($tablename, \f(CW$class\fP)" +.IX Subsection "Font::TTF::Font->AddTable($tablename, $class)" +Adds the given class to be used when representing the given table name. It also +\&'requires' the class for you. +.SS "Font::TTF::Font\->Init" +.IX Subsection "Font::TTF::Font->Init" +For those people who like making fonts without reading them. This subroutine +will require all the table code for the various table types for you. Not +needed if using Font::TTF::Font::read before using a table. +.SS "Font::TTF::Font\->new(%props)" +.IX Subsection "Font::TTF::Font->new(%props)" +Creates a new font object and initialises with the given properties. This is +primarily for use when a \s-1TTF\s0 is embedded somewhere. Notice that the properties +are automatically preceded by a space when inserted into the object. This is in +order that fields do not clash with tables. +.SS "Font::TTF::Font\->open($fname)" +.IX Subsection "Font::TTF::Font->open($fname)" +Reads the header and directory for the given font file and creates appropriate +objects for each table in the font. +.ie n .SS "$f\->read" +.el .SS "\f(CW$f\fP\->read" +.IX Subsection "$f->read" +Reads a Truetype font directory starting from location \f(CW\*(C`$self\-\*(C'\fR{' \s-1OFFSET\s0'}> in the file. +This has been separated from the \f(CW\*(C`open\*(C'\fR function to allow support for embedded +TTFs for example in TTCs. Also reads the \f(CW\*(C`head\*(C'\fR and \f(CW\*(C`maxp\*(C'\fR tables immediately. +.ie n .SS "$f\->out($fname [, @tablelist])" +.el .SS "\f(CW$f\fP\->out($fname [, \f(CW@tablelist\fP])" +.IX Subsection "$f->out($fname [, @tablelist])" +Writes a \s-1TTF\s0 file consisting of the tables in tablelist. The list is checked to +ensure that only tables that exist are output. (This means that you cannot have +non table information stored in the font object with key length of exactly 4) +.PP +In many cases the user simply wants to output all the tables in alphabetical order. +This can be done by not including a \f(CW@tablelist\fR, in which case the subroutine will +output all the defined tables in the font in alphabetical order. +.PP +Returns \f(CW$f\fR on success and undef on failure, including warnings. +.PP +All output files must include the \f(CW\*(C`head\*(C'\fR table. +.ie n .SS "$f\->out_xml($filename [, @tables])" +.el .SS "\f(CW$f\fP\->out_xml($filename [, \f(CW@tables\fP])" +.IX Subsection "$f->out_xml($filename [, @tables])" +Outputs the font in \s-1XML\s0 format +.ie n .SS "$f\->XML_start($context, $tag, %attrs)" +.el .SS "\f(CW$f\fP\->XML_start($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$f->XML_start($context, $tag, %attrs)" +Handles start messages from the \s-1XML\s0 parser. Of particular interest to us are and +
. +.ie n .SS "$f\->update" +.el .SS "\f(CW$f\fP\->update" +.IX Subsection "$f->update" +Sends update to all the tables in the font and then resets all the isDirty +flags on each table. The data structure in now consistent as a font (we hope). +.ie n .SS "$f\->dirty" +.el .SS "\f(CW$f\fP\->dirty" +.IX Subsection "$f->dirty" +Dirties all the tables in the font +.ie n .SS "$f\->tables_do(&func [, tables])" +.el .SS "\f(CW$f\fP\->tables_do(&func [, tables])" +.IX Subsection "$f->tables_do(&func [, tables])" +Calls &func for each table in the font. Calls the table in alphabetical sort +order as per the order in the directory: +.PP +.Vb 1 +\& &func($table, $name); +.Ve +.PP +May optionally take a list of table names in which case func is called +for each of them in the given order. +.ie n .SS "$f\->release" +.el .SS "\f(CW$f\fP\->release" +.IX Subsection "$f->release" +Releases \s-1ALL\s0 of the memory used by the \s-1TTF\s0 font and all of its component +objects. After calling this method, do \fB\s-1NOT\s0\fR expect to have anything left in +the \f(CW\*(C`Font::TTF::Font\*(C'\fR object. +.PP +\&\fB\s-1NOTE\s0\fR, that it is important that you call this method on any +\&\f(CW\*(C`Font::TTF::Font\*(C'\fR object when you wish to destruct it and free up its memory. +Internally, we track things in a structure that can result in circular +references, and without calling '\f(CW\*(C`release()\*(C'\fR' these will not properly get +cleaned up by Perl. Once you've called this method, though, don't expect to be +able to do anything else with the \f(CW\*(C`Font::TTF::Font\*(C'\fR object; it'll have \fBno\fR +internal state whatsoever. +.PP +\&\fBDeveloper note:\fR As part of the brute-force cleanup done here, this method +will throw a warning message whenever unexpected key values are found within +the \f(CW\*(C`Font::TTF::Font\*(C'\fR object. This is done to help ensure that any unexpected +and unfreed values are brought to your attention so that you can bug us to keep +the module updated properly; otherwise the potential for memory leaks due to +dangling circular references will exist. +.SH "BUGS" +.IX Header "BUGS" +Bugs abound aplenty I am sure. There is a lot of code here and plenty of scope. +The parts of the code which haven't been implemented yet are: +.IP "Post" 4 +.IX Item "Post" +Version 4 format types are not supported yet. +.IP "Cmap" 4 +.IX Item "Cmap" +Format type 2 (\s-1MBCS\s0) has not been implemented yet and therefore may cause +somewhat spurious results for this table type. +.IP "Kern" 4 +.IX Item "Kern" +Only type 0 & type 2 tables are supported (type 1 & type 3 yet to come). +.IP "\s-1TTC\s0 and \s-1WOFF\s0" 4 +.IX Item "TTC and WOFF" +The current Font::TTF::Font::out method does not support the writing of TrueType +Collections or \s-1WOFF\s0 files. +.IP "\s-1DSIG\s0" 4 +.IX Item "DSIG" +Haven't figured out how to correctly calculate and output digital signature (\s-1DSIG\s0) table +.PP +In addition there are weaknesses or features of this module library +.IP "\(bu" 4 +There is very little (or no) error reporting. This means that if you have +garbled data or garbled data structures, then you are liable to generate duff +fonts. +.IP "\(bu" 4 +The exposing of the internal data structures everywhere means that doing +radical re-structuring is almost impossible. But it stop the code from becoming +ridiculously large. +.PP +Apart from these, I try to keep the code in a state of \*(L"no known bugs\*(R", which +given the amount of testing this code has had, is not a guarantee of high +quality, yet. +.PP +For more details see the appropriate class files. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fpgm.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fpgm.3pm" new file mode 100644 index 0000000000..b03e3c4623 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Fpgm.3pm" @@ -0,0 +1,109 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Fpgm 3pm" +.TH Font::TTF::Fpgm 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Fpgm \- Font program in a TrueType font. Called when a font is loaded +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a minimal class adding nothing beyond a table, but is a repository +for fpgm type information for those processes brave enough to address hinting. +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reading this table is simply a process of reading all the data into the \s-1RAM\s0 +copy. Nothing more is done with it. +.ie n .SS "$t\->out_xml($context, $depth)" +.el .SS "\f(CW$t\fP\->out_xml($context, \f(CW$depth\fP)" +.IX Subsection "$t->out_xml($context, $depth)" +Outputs Fpgm program as \s-1XML\s0 +.ie n .SS "$t\->XML_end($context, $tag, %attrs)" +.el .SS "\f(CW$t\fP\->XML_end($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$t->XML_end($context, $tag, %attrs)" +Parse all that hinting code +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GDEF.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GDEF.3pm" new file mode 100644 index 0000000000..781a6b0b41 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GDEF.3pm" @@ -0,0 +1,173 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::GDEF 3pm" +.TH Font::TTF::GDEF 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::GDEF \- Opentype GDEF table support +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \s-1GDEF\s0 table contains various global lists of information which are apparantly +used in other places in an OpenType renderer. But precisely where is open to +speculation... +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +There are up to 5 tables in the \s-1GDEF\s0 table, each with their own structure: +.IP "\s-1GLYPH\s0" 4 +.IX Item "GLYPH" +This is an Font::TTF::Coverage Class Definition table containing information +as to what type each glyph is. +.IP "\s-1ATTACH\s0" 4 +.IX Item "ATTACH" +The attach table consists of a coverage table and then attachment points for +each glyph in the coverage table: +.RS 4 +.IP "\s-1COVERAGE\s0" 8 +.IX Item "COVERAGE" +This is a coverage table +.IP "\s-1POINTS\s0" 8 +.IX Item "POINTS" +This is an array of point elements. Each element is an array of curve points +corresponding to the attachment points on that glyph. The order of the curve points +in the array corresponds to the attachment point number specified in the \s-1MARKS\s0 +coverage table (see below). +.RE +.RS 4 +.RE +.IP "\s-1LIG\s0" 4 +.IX Item "LIG" +This contains the ligature caret positioning information for ligature glyphs +.RS 4 +.IP "\s-1COVERAGE\s0" 8 +.IX Item "COVERAGE" +A coverage table to say which glyphs are ligatures +.IP "\s-1LIGS\s0" 8 +.IX Item "LIGS" +An array of elements for each ligature. Each element is an array of information +for each caret position in the ligature (there being number of components \- 1 of +these, generally) +.RS 8 +.IP "\s-1FMT\s0" 12 +.IX Item "FMT" +This is the format of the information and is important to provide the semantics +for the value. This value must be set correctly before output +.IP "\s-1VAL\s0" 12 +.IX Item "VAL" +The value which has meaning according to \s-1FMT\s0 +.IP "\s-1DEVICE\s0" 12 +.IX Item "DEVICE" +For \s-1FMT\s0 = 3, a device table is also referenced which is stored here +.RE +.RS 8 +.RE +.RE +.RS 4 +.RE +.IP "\s-1MARKS\s0" 4 +.IX Item "MARKS" +This class definition table defines the classes of mark glyphs that can be selected +for processing using the MarkAttachmentType field of lookup \s-1FLAG\s0 words. +.IP "\s-1MARKSETS\s0" 4 +.IX Item "MARKSETS" +Contains an array of coverage tables indexed by the \s-1FILTER\s0 value of a lookup. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into the data structure +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes out this table. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Sort \s-1COVERAGE\s0 tables. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GPOS.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GPOS.3pm" new file mode 100644 index 0000000000..e3a9d18d10 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GPOS.3pm" @@ -0,0 +1,269 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::GPOS 3pm" +.TH Font::TTF::GPOS 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::GPOS \- Support for Opentype GPOS tables in conjunction with TTOpen +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \s-1GPOS\s0 table is one of the most complicated tables in the \s-1TTF\s0 spec and the +corresponding data structure abstraction is also not trivial. While much of the +structure of a \s-1GPOS\s0 is shared with a \s-1GSUB\s0 table via the Font::TTF::Ttopen +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +Here we describe the additions and lookup specific information for \s-1GPOS\s0 tables. +Unfortunately there is no one abstraction which seems to work comfortable for +all \s-1GPOS\s0 tables, so we will also examine how the variables are used for different +lookup types. +.PP +The following are the values allowed in the \s-1ACTION_TYPE\s0 and \s-1MATCH_TYPE\s0 variables: +.IP "\s-1ACTION_TYPE\s0" 4 +.IX Item "ACTION_TYPE" +This can take any of the following values +.RS 4 +.IP "a" 8 +.IX Item "a" +The \s-1ACTION\s0 is an array of anchor tables +.IP "o" 8 +.IX Item "o" +Offset. There is no \s-1RULE\s0 array. The \s-1ADJUST\s0 variable contains a value record (see +later in this description) +.IP "v" 8 +.IX Item "v" +The \s-1ACTION\s0 is a value record. +.IP "p" 8 +.IX Item "p" +Pair adjustment. The \s-1ACTION\s0 contains an array of two value records for the matched +two glyphs. +.IP "e" 8 +.IX Item "e" +Exit and Entry records. The \s-1ACTION\s0 contains an array of two anchors corresponding +to the exit and entry anchors for the glyph. +.IP "l" 8 +.IX Item "l" +Indicates a lookup based contextual rule as per the \s-1GSUB\s0 table. +.RE +.RS 4 +.RE +.IP "\s-1MATCH_TYPE\s0" 4 +.IX Item "MATCH_TYPE" +This can take any of the following values +.RS 4 +.IP "g" 8 +.IX Item "g" +A glyph array +.IP "c" 8 +.IX Item "c" +An array of class values +.IP "o" 8 +.IX Item "o" +An array of coverage tables +.RE +.RS 4 +.RE +.PP +The following variables are added for Attachment Positioning Subtables: +.IP "\s-1MATCH\s0" 4 +.IX Item "MATCH" +This contains an array of glyphs to match against for all \s-1RULES.\s0 It is much like +having the same \s-1MATCH\s0 string in all \s-1RULES.\s0 In the cases it is used so far, it only +ever contains one element. +.IP "\s-1MARKS\s0" 4 +.IX Item "MARKS" +This contains a Mark array consisting of each element being a subarray of two +elements: +.RS 4 +.IP "\s-1CLASS\s0" 8 +.IX Item "CLASS" +The class that this mark uses on its base +.IP "\s-1ANCHOR\s0" 8 +.IX Item "ANCHOR" +The anchor with which to attach this mark glyph +.RE +.RS 4 +.Sp +The base table for mark to base, ligature or mark attachment positioning is +structured with the \s-1ACTION\s0 containing an array of anchors corresponding to each +attachment class. For ligatures, there is more than one \s-1RULE\s0 in the \s-1RULE\s0 array +corresponding to each glyph in the coverage table. +.RE +.PP +Other variables which are provided for informational purposes are: +.IP "\s-1VFMT\s0" 4 +.IX Item "VFMT" +Value format for the adjustment of the glyph matched by the coverage table. +.IP "\s-1VFMT2\s0" 4 +.IX Item "VFMT2" +Value format used in pair adjustment for the second glyph in the pair +.SS "Value Records" +.IX Subsection "Value Records" +There is a subtype used in \s-1GPOS\s0 tables called a value record. It is used to adjust +the position of a glyph from its default position. The value record is variable +length with a bitfield at the beginning to indicate which of the following +entries are included. The bitfield is not stored since it is recalculated at +write time. +.IP "XPlacement" 4 +.IX Item "XPlacement" +Horizontal adjustment for placement (not affecting other unattached glyphs) +.IP "YPlacement" 4 +.IX Item "YPlacement" +Vertical adjustment for placement (not affecting other unattached glyphs) +.IP "XAdvance" 4 +.IX Item "XAdvance" +Adjust the advance width glyph (used only in horizontal writing systems) +.IP "YAdvance" 4 +.IX Item "YAdvance" +Adjust the vertical advance (used only in vertical writing systems) +.IP "XPlaDevice" 4 +.IX Item "XPlaDevice" +Device table for device specific adjustment of horizontal placement +.IP "YPlaDevice" 4 +.IX Item "YPlaDevice" +Device table for device specific adjustment of vertical placement +.IP "XAdvDevice" 4 +.IX Item "XAdvDevice" +Device table for device specific adjustment of horizontal advance +.IP "YAdDevice" 4 +.IX Item "YAdDevice" +Device table for device specific adjustment of vertical advance +.IP "XIdPlacement" 4 +.IX Item "XIdPlacement" +Horizontal placement metric id (for Multiple Master fonts \- but that is all I know!) +.IP "YIdPlacement" 4 +.IX Item "YIdPlacement" +Vertical placement metric id +.IP "XIdAdvance" 4 +.IX Item "XIdAdvance" +Horizontal advance metric id +.IP "YIdAdvance" 4 +.IX Item "YIdAdvance" +Vertical advance metric id +.SH "CORRESPONDANCE TO LAYOUT TYPES" +.IX Header "CORRESPONDANCE TO LAYOUT TYPES" +Here is what is stored in the \s-1ACTION_TYPE\s0 and \s-1MATCH_TYPE\s0 for each of the known +\&\s-1GPOS\s0 subtable types: +.PP +.Vb 3 +\& 1.1 1.2 2.1 2.2 3 4 5 6 7.1 7.2 7.3 8.1 8.2 8.3 +\& ACTION_TYPE o v p p e a a a l l l l l l +\& MATCH_TYPE g c g c o g c o +.Ve +.SH "METHODS" +.IX Header "METHODS" +.SS "read_sub" +.IX Subsection "read_sub" +Reads the subtable into the data structures +.ie n .SS "$t\->extension" +.el .SS "\f(CW$t\fP\->extension" +.IX Subsection "$t->extension" +Returns the table type number for the extension table +.ie n .SS "$t\->out_sub" +.el .SS "\f(CW$t\fP\->out_sub" +.IX Subsection "$t->out_sub" +Outputs the subtable to the given filehandle +.ie n .SS "$t\->read_value($format, $base, $lookup, $fh)" +.el .SS "\f(CW$t\fP\->read_value($format, \f(CW$base\fP, \f(CW$lookup\fP, \f(CW$fh\fP)" +.IX Subsection "$t->read_value($format, $base, $lookup, $fh)" +Reads a value record from the current location in the file, according to the +format given. +.ie n .SS "$t\->read_delta($offset, $base, $lookup, $fh)" +.el .SS "\f(CW$t\fP\->read_delta($offset, \f(CW$base\fP, \f(CW$lookup\fP, \f(CW$fh\fP)" +.IX Subsection "$t->read_delta($offset, $base, $lookup, $fh)" +Reads a delta (device table) at the given offset if it hasn not already been read. +Store the offset and item in the lookup cache ($lookup\->{' \s-1CACHE\s0'}) +.ie n .SS "$t\->read_anchor($offset, $base, $lookup, $fh)" +.el .SS "\f(CW$t\fP\->read_anchor($offset, \f(CW$base\fP, \f(CW$lookup\fP, \f(CW$fh\fP)" +.IX Subsection "$t->read_anchor($offset, $base, $lookup, $fh)" +Reads an Anchor table at the given offset if it has not already been read. +.ie n .SS "$t\->fmt_value" +.el .SS "\f(CW$t\fP\->fmt_value" +.IX Subsection "$t->fmt_value" +Returns the value format for a given value record +.ie n .SS "$t\->out_value" +.el .SS "\f(CW$t\fP\->out_value" +.IX Subsection "$t->out_value" +Returns the output string for the outputting of the value for a given format. Also +updates the offset cache for any device tables referenced. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GSUB.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GSUB.3pm" new file mode 100644 index 0000000000..4b851c020d --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GSUB.3pm" @@ -0,0 +1,174 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::GSUB 3pm" +.TH Font::TTF::GSUB 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::GSUB \- Module support for the GSUB table in conjunction with TTOpen +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Handles the \s-1GSUB\s0 subtables in relation to Ttopen tables. Due to the variety of +different lookup types, the data structures are not all that straightforward, +although I have tried to make life easy for myself when using this! +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The structure of a \s-1GSUB\s0 table is the same as that given in Font::TTF::Ttopen. +Here we give some of the semantics specific to \s-1GSUB\s0 lookups. +.IP "\s-1ACTION_TYPE\s0" 4 +.IX Item "ACTION_TYPE" +This is a string taking one of 4 values indicating the nature of the information +in the \s-1ACTION\s0 array of the rule: +.RS 4 +.IP "g" 8 +.IX Item "g" +The action contains a string of glyphs to replace the match string by +.IP "l" 8 +.IX Item "l" +The action array contains a list of offsets and lookups to run, in order, on +the matched string +.IP "a" 8 +.IX Item "a" +The action array is an unordered set of optional replacements for the matched +glyph. The application should make the selection somehow. +.IP "o" 8 +.IX Item "o" +The action array is empty (in fact there is no rule array for this type of +rule) and the \s-1ADJUST\s0 value should be added to the glyph id to find the replacement +glyph id value +.IP "r" 8 +.IX Item "r" +The action array is a list of replacement glyphs in coverage order. This \s-1ACTION_TYPE\s0 +is used only for Type 8 Reverse Chaining lookups which, by design, are single glyph +substitution. +.RE +.RS 4 +.RE +.IP "\s-1MATCH_TYPE\s0" 4 +.IX Item "MATCH_TYPE" +This indicates which type of information the various \s-1MATCH\s0 arrays (\s-1MATCH, PRE, +POST\s0) hold in the rule: +.RS 4 +.IP "g" 8 +.IX Item "g" +The array holds a string of glyph ids which should match exactly +.IP "c" 8 +.IX Item "c" +The array holds a sequence of class definitions which each glyph should +correspondingly match to +.IP "o" 8 +.IX Item "o" +The array holds offsets to coverage tables +.RE +.RS 4 +.RE +.SH "CORRESPONDANCE TO LAYOUT TYPES" +.IX Header "CORRESPONDANCE TO LAYOUT TYPES" +The following table gives the values for \s-1ACTION_TYPE\s0 and \s-1MATCH_TYPE\s0 for each +of the 12 different lookup types found in the \s-1GSUB\s0 table definition: +.PP +.Vb 3 +\& 1.1 1.2 2 3 4 5.1 5.2 5.3 6.1 6.2 6.3 8 +\& ACTION_TYPE o g g a g l l l l l l r +\& MATCH_TYPE g g c o g c o o +.Ve +.PP +Hopefully, the rest of the uses of the variables should make sense from this +table. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read_sub($fh, $lookup, $index)" +.el .SS "\f(CW$t\fP\->read_sub($fh, \f(CW$lookup\fP, \f(CW$index\fP)" +.IX Subsection "$t->read_sub($fh, $lookup, $index)" +Asked by the superclass to read in from the given file the indexth subtable from +lookup number lookup. The file is positioned ready for the read. +.ie n .SS "$t\->extension" +.el .SS "\f(CW$t\fP\->extension" +.IX Subsection "$t->extension" +Returns the table type number for the extension table +.ie n .SS "$t\->out_sub($fh, $lookup, $index)" +.el .SS "\f(CW$t\fP\->out_sub($fh, \f(CW$lookup\fP, \f(CW$index\fP)" +.IX Subsection "$t->out_sub($fh, $lookup, $index)" +Passed the filehandle to output to, suitably positioned, the lookup and subtable +index, this function outputs the subtable to \f(CW$fh\fR at that point. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glat.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glat.3pm" new file mode 100644 index 0000000000..e8c3b275dc --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glat.3pm" @@ -0,0 +1,104 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Glat 3pm" +.TH Font::TTF::Glat 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Glat \- Hold glyph attributes +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Holds glyph attributes associated with each glyph. +.IP "Version" 4 +.IX Item "Version" +Table format version +.IP "attribs" 4 +.IX Item "attribs" +An array of hashes. On array entry for each glyph id. Since the glyph attributes are usually in a sparse +array, they are stored in a hash keyed by the attribute id and with the value as attribute value. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Gloc.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Gloc.3pm" new file mode 100644 index 0000000000..fd5cbd5c0b --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Gloc.3pm" @@ -0,0 +1,110 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Gloc 3pm" +.TH Font::TTF::Gloc 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Gloc \- Offsets into Glat table for the start of the attributes for each glyph +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The Gloc table is a bit like the Loca table only for Graphite glyph attributes. The table +has the following elements: +.IP "Version" 4 +.IX Item "Version" +Table format version +.IP "numAttrib" 4 +.IX Item "numAttrib" +Maximum number of attributes associated with a glyph. +.IP "locations" 4 +.IX Item "locations" +An array of offsets into the Glat table for the start of each glyph +.IP "names" 4 +.IX Item "names" +If defined, an array of name table name ids indexed by attribute number. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glyf.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glyf.3pm" new file mode 100644 index 0000000000..862b1d3759 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glyf.3pm" @@ -0,0 +1,127 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Glyf 3pm" +.TH Font::TTF::Glyf 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Glyf \- The Glyf data table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a stub table. The real data is held in the loca table. If you want to get a glyf +look it up in the loca table as \f(CW\*(C`$f\-\*(C'\fR{'loca'}{'glyphs'}[$num]>. It will not be here! +.PP +The difference between reading this table as opposed to the loca table is that +reading this table will cause updated glyphs to be written out rather than just +copying the glyph information from the input file. This causes font writing to be +slower. So read the glyf as opposed to the loca table if you want to change glyf +data. Read the loca table only if you are just wanting to read the glyf information. +.PP +This class is used when writing the glyphs though. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the \f(CW\*(C`loca\*(C'\fR table instead! +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes out all the glyphs in the parent's location table, calculating a new +output location for each one. +.ie n .SS "$t\->out_xml($context, $depth)" +.el .SS "\f(CW$t\fP\->out_xml($context, \f(CW$depth\fP)" +.IX Subsection "$t->out_xml($context, $depth)" +Outputs all the glyphs in the glyph table just where they are supposed to be output! +.ie n .SS "$t\->XML_start($context, $tag, %attrs)" +.el .SS "\f(CW$t\fP\->XML_start($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$t->XML_start($context, $tag, %attrs)" +Pass control to glyphs as they occur +.ie n .SS "$t\->XML_end($context, $tag, %attrs)" +.el .SS "\f(CW$t\fP\->XML_end($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$t->XML_end($context, $tag, %attrs)" +Collect up glyphs and put them into the loca table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glyph.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glyph.3pm" new file mode 100644 index 0000000000..2e7c8a241e --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Glyph.3pm" @@ -0,0 +1,316 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Glyph 3pm" +.TH Font::TTF::Glyph 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Glyph \- Holds a information for a single glyph +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a single glyph description as held in a \s-1TT\s0 font. On creation only its +header is read. Thus you can get the bounding box of each glyph without having +to read all the other information. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +In addition to the named variables in a glyph header (\f(CW\*(C`xMin\*(C'\fR etc.), there are +also all capital instance variables for holding working information, mostly +from the location table. +.SS "Variables for all glyphs:" +.IX Subsection "Variables for all glyphs:" +The standard attributes each glyph has are: +.IP "numberOfContours" 4 +.IX Item "numberOfContours" +For simple glyphs this will be the count of contours. For compound glyphs this will be \-1. +.IP "xMin" 4 +.IX Item "xMin" +.PD 0 +.IP "yMin" 4 +.IX Item "yMin" +.IP "xMax" 4 +.IX Item "xMax" +.IP "yMax" 4 +.IX Item "yMax" +.PD +These identify the bounding box of the glyph. +.PP +There are also other, derived, instance variables for each glyph which are read +when the whole glyph is read (via \f(CW\*(C`read_dat\*(C'\fR): +.IP "instLen" 4 +.IX Item "instLen" +Number of bytes in the hinting instructions (Warning this variable is deprecated, +use \f(CW\*(C`length($g\-\*(C'\fR{'hints'})> instead). +.IP "hints" 4 +.IX Item "hints" +The string containing the hinting code for the glyph +.SS "Variables for simple glyphs (numberOfContours >= 0):" +.IX Subsection "Variables for simple glyphs (numberOfContours >= 0):" +.IP "endPoints" 4 +.IX Item "endPoints" +An array of endpoints for each contour in the glyph. There are +\&\f(CW\*(C`numberOfContours\*(C'\fR contours in a glyph. The number of points in a glyph is +equal to the highest endpoint of a contour. +.IP "numPoints" 4 +.IX Item "numPoints" +This is a generated value which contains the total number of points for this simple glyph. +.PP +There are also a number of arrays indexed by point number: +.IP "flags" 4 +.IX Item "flags" +The flags associated with reading this point. The flags for a point are +recalculated for a point when it is \f(CW\*(C`update\*(C'\fRd. Thus the flags are not very +useful. The only important bit is bit 0 which indicates whether the point is +an 'on' curve point, or an 'off' curve point. +.IP "x" 4 +.IX Item "x" +The absolute x co-ordinate of the point. +.IP "y" 4 +.IX Item "y" +The absolute y co-ordinate of the point +.SS "Variables for compound glyphs (numberOfContours == \-1):" +.IX Subsection "Variables for compound glyphs (numberOfContours == -1):" +.IP "metric" 4 +.IX Item "metric" +This holds the component number (not its glyph number) of the component from +which the metrics for this glyph should be taken. +.IP "comps" 4 +.IX Item "comps" +This is an array of hashes for each component. Each hash has a number of +elements: +.RS 4 +.IP "glyph" 4 +.IX Item "glyph" +The glyph number of the glyph which comprises this component of the composite. +\&\s-1NOTE:\s0 In some badly generated fonts, \f(CW\*(C`glyph\*(C'\fR may contain a numerical value +but that glyph might not actually exist in the font file. This could +occur in any glyph, but is particularly likely for glyphs that have +no strokes, such as \s-1SPACE, U+00A0\s0 NO-BREAK \s-1SPACE,\s0 or +U+200B \s-1ZERO WIDTH SPACE.\s0 +.IP "args" 4 +.IX Item "args" +An array of two arguments which may be an x, y co-ordinate or two attachment +points (one on the base glyph the other on the component). See flags for details. +.IP "flag" 4 +.IX Item "flag" +The flag for this component +.IP "scale" 4 +.IX Item "scale" +A 4 number array for component scaling. This allows stretching, rotating, etc. +Note that scaling applies to placement co-ordinates (rather than attachment points) +before locating rather than after. +.RE +.RS 4 +.RE +.IP "numPoints" 4 +.IX Item "numPoints" +This is a generated value which contains the number of components read in for this +compound glyph. +.SS "Private instance variables:" +.IX Subsection "Private instance variables:" +.IP "\s-1INFILE\s0 (P)" 4 +.IX Item "INFILE (P)" +The input file form which to read any information +.IP "\s-1LOC\s0 (P)" 4 +.IX Item "LOC (P)" +Location relative to the start of the glyf table in the read file +.IP "\s-1BASE\s0 (P)" 4 +.IX Item "BASE (P)" +The location of the glyf table in the read file +.IP "\s-1LEN\s0 (P)" 4 +.IX Item "LEN (P)" +This is the number of bytes required by the glyph. It should be kept up to date +by calling the \f(CW\*(C`update\*(C'\fR method whenever any of the glyph content changes. +.IP "\s-1OUTLOC\s0 (P)" 4 +.IX Item "OUTLOC (P)" +Location relative to the start of the glyf table. This variable is only active +whilst the output process is going on. It is used to inform the location table +where the glyph is located, since the glyf table is output before the loca +table due to alphabetical ordering. +.IP "\s-1OUTLEN\s0 (P)" 4 +.IX Item "OUTLEN (P)" +This indicates the length of the glyph data when it is output. This more +accurately reflects the internal memory form than the \f(CW\*(C`LEN\*(C'\fR variable which +only reflects the read file length. The \f(CW\*(C`OUTLEN\*(C'\fR variable is only set after +calling \f(CW\*(C`out\*(C'\fR or \f(CW\*(C`out_dat\*(C'\fR. +.SS "Editing" +.IX Subsection "Editing" +If you want to edit a glyph in some way, then you should read_dat the glyph, then +make your changes and then update the glyph or set the \f(CW$g\fR\->{' isDirty'} variable. +The application must ensure that the following instance variables are +correct, from which update will calculate the rest, including the bounding box +information. +.PP +.Vb 6 +\& numPoints +\& numberOfContours +\& endPoints +\& x, y, flags (only flags bit 0) +\& instLen +\& hints +.Ve +.PP +For components, the numPoints, x, y, endPoints & flags are not required but +the following information is required for each component. +.PP +.Vb 5 +\& flag (bits 2, 10, 11, 12) +\& glyph +\& args +\& scale +\& metric (glyph instance variable) +.Ve +.SH "METHODS" +.IX Header "METHODS" +.SH "Font::TTF::Glyph\->new(%parms)" +.IX Header "Font::TTF::Glyph->new(%parms)" +Creates a new glyph setting various instance variables +.ie n .SS "$g\->read" +.el .SS "\f(CW$g\fP\->read" +.IX Subsection "$g->read" +Reads the header component of the glyph (numberOfContours and bounding box) and also the +glyph content, but into a data field rather than breaking it down into +its constituent structures. Use read_dat for this. +.ie n .SS "$g\->read_dat" +.el .SS "\f(CW$g\fP\->read_dat" +.IX Subsection "$g->read_dat" +Reads the contents of the glyph (components and curves, etc.) from the memory +store \f(CW\*(C`DAT\*(C'\fR into structures within the object. +.ie n .SS "$g\->out($fh)" +.el .SS "\f(CW$g\fP\->out($fh)" +.IX Subsection "$g->out($fh)" +Writes the glyph data to outfile +.ie n .SS "$g\->out_xml($context, $depth)" +.el .SS "\f(CW$g\fP\->out_xml($context, \f(CW$depth\fP)" +.IX Subsection "$g->out_xml($context, $depth)" +Outputs an \s-1XML\s0 description of the glyph +.ie n .SS "$g\->dirty($val)" +.el .SS "\f(CW$g\fP\->dirty($val)" +.IX Subsection "$g->dirty($val)" +This sets the dirty flag to the given value or 1 if no given value. It returns the +value of the flag +.ie n .SS "$g\->update" +.el .SS "\f(CW$g\fP\->update" +.IX Subsection "$g->update" +Generates a \f(CW\*(C`$self\-\*(C'\fR{'\s-1DAT\s0'}> from the internal structures, if the data has +been read into structures in the first place. If you are building a glyph +from scratch you will need to set the instance variable \f(CW\*(Aq isDirty\*(Aq\fR. +.ie n .SS "$g\->update_bbox" +.el .SS "\f(CW$g\fP\->update_bbox" +.IX Subsection "$g->update_bbox" +Updates the bounding box for this glyph according to the points in the glyph +.ie n .SS "$g\->maxInfo" +.el .SS "\f(CW$g\fP\->maxInfo" +.IX Subsection "$g->maxInfo" +Returns lots of information about a glyph so that the \f(CW\*(C`maxp\*(C'\fR table can update +itself. Returns array containing contributions of this glyph to maxPoints, maxContours, +maxCompositePoints, maxCompositeContours, maxSizeOfInstructions, maxComponentElements, +and maxComponentDepth. +.ie n .SS "$g\->empty" +.el .SS "\f(CW$g\fP\->empty" +.IX Subsection "$g->empty" +Empties the glyph of all information to the level of not having been read. +Useful for saving memory in apps with many glyphs being read +.ie n .SS "$g\->get_points" +.el .SS "\f(CW$g\fP\->get_points" +.IX Subsection "$g->get_points" +This method creates point information for a compound glyph. The information is +stored in the same place as if the glyph was not a compound, but since +numberOfContours is negative, the glyph is still marked as being a compound +.ie n .SS "$g\->get_refs" +.el .SS "\f(CW$g\fP\->get_refs" +.IX Subsection "$g->get_refs" +Returns an array of all the glyph ids that are used to make up this glyph. That +is all the compounds and their references and so on. If this glyph is not a +compound, then returns an empty array. +.PP +Please note the warning about bad fonts that reference nonexistent glyphs +under \s-1INSTANCE VARIABLES\s0 above. This function will not attempt to +filter out nonexistent glyph numbers. +.SH "BUGS" +.IX Header "BUGS" +.IP "\(bu" 4 +The instance variables used here are somewhat clunky and inconsistent with +the other tables. +.IP "\(bu" 4 +\&\f(CW\*(C`update\*(C'\fR doesn't re-calculate the bounding box or \f(CW\*(C`numberOfContours\*(C'\fR. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GrFeat.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GrFeat.3pm" new file mode 100644 index 0000000000..384c5b6381 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242GrFeat.3pm" @@ -0,0 +1,157 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::GrFeat 3pm" +.TH Font::TTF::GrFeat 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::GrFeat \- Graphite Font Features +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "version" 4 +.IX Item "version" +.PD 0 +.IP "features" 4 +.IX Item "features" +.PD +An array of hashes of the following form +.RS 4 +.IP "feature" 8 +.IX Item "feature" +feature id number +.IP "name" 8 +.IX Item "name" +name index in name table +.IP "exclusive" 8 +.IX Item "exclusive" +exclusive flag +.IP "default" 8 +.IX Item "default" +the default setting number +.IP "settings" 8 +.IX Item "settings" +hash of setting number against name string index +.RE +.RS 4 +.RE +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the features from the \s-1TTF\s0 file into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the features to a \s-1TTF\s0 file +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.ie n .SS "$t\->tag_to_num ($feat_str)" +.el .SS "\f(CW$t\fP\->tag_to_num ($feat_str)" +.IX Subsection "$t->tag_to_num ($feat_str)" +Convert an alphanumeric feature id tag (string) to a number (32\-bit). +Tags are normally 4 chars. Graphite ignores space +padding if it is present, so we do the same here. +.ie n .SS "$t\->num_to_tag ($feat_num)" +.el .SS "\f(CW$t\fP\->num_to_tag ($feat_num)" +.IX Subsection "$t->num_to_tag ($feat_num)" +Convert a feature id number (32\-bit) back to a tag (string). +Trailing space or null padding is removed. +Feature id numbers that do not represent alphanumeric tags +are returned unchanged. +.SH "BUGS" +.IX Header "BUGS" +The version 1 Feat table ends with a feature (id 1) named NoName +with zero settings but with an offset to the last entry in the setting +array. This last setting has id 0 and an invalid name id. This last +feature is changed to have one setting. +.SH "AUTHOR" +.IX Header "AUTHOR" +Alan Ward (derived from Jonathan Kew's Feat.pm). +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hdmx.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hdmx.3pm" new file mode 100644 index 0000000000..f30cae13a2 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hdmx.3pm" @@ -0,0 +1,132 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Hdmx 3pm" +.TH Font::TTF::Hdmx 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Hdmx \- Horizontal device metrics +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The table consists of an hash of device metric tables indexed by the ppem for +that subtable. Each subtable consists of an array of advance widths in pixels +for each glyph at that ppem (horizontally). +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +Individual metrics are accessed using the following referencing: +.PP +.Vb 1 +\& $f\->{\*(Aqhdmx\*(Aq}{$ppem}[$glyph_num] +.Ve +.PP +In addition there is one instance variable: +.IP "Num" 4 +.IX Item "Num" +Number of device tables. +.SS "\s-1METHODS\s0" +.IX Subsection "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into data structures +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Outputs the device metrics for this font +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->tables_do(&func)" +.el .SS "\f(CW$t\fP\->tables_do(&func)" +.IX Subsection "$t->tables_do(&func)" +For each subtable it calls &sub($ref, \f(CW$ppem\fR) +.ie n .SS "$t\->XML_element($context, $depth, $key, $value)" +.el .SS "\f(CW$t\fP\->XML_element($context, \f(CW$depth\fP, \f(CW$key\fP, \f(CW$value\fP)" +.IX Subsection "$t->XML_element($context, $depth, $key, $value)" +Outputs device metrics a little more tidily +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Head.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Head.3pm" new file mode 100644 index 0000000000..bf68955e7a --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Head.3pm" @@ -0,0 +1,159 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Head 3pm" +.TH Font::TTF::Head 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Head \- The head table for a TTF Font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a very basic table with just instance variables as described in the +\&\s-1TTF\s0 documentation, using the same names. One of the most commonly used is +\&\f(CW\*(C`unitsPerEm\*(C'\fR. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The \f(CW\*(C`head\*(C'\fR table has no internal instance variables beyond those common to all +tables and those specified in the standard: +.PP +.Vb 10 +\& version +\& fontRevision +\& checkSumAdjustment +\& magicNumber +\& flags +\& unitsPerEm +\& created +\& modified +\& xMin +\& yMin +\& xMax +\& yMax +\& macStyle +\& lowestRecPPEM +\& fontDirectionHint +\& indexToLocFormat +\& glyphDataFormat +.Ve +.PP +The two dates are held as an array of two unsigned longs (32\-bits) +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory thanks to some utility functions +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying. If in memory +(which is usually) the checkSumAdjustment field is set to 0 as per the default +if the file checksum is not to be considered. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->XML_element($context, $depth, $key, $value)" +.el .SS "\f(CW$t\fP\->XML_element($context, \f(CW$depth\fP, \f(CW$key\fP, \f(CW$value\fP)" +.IX Subsection "$t->XML_element($context, $depth, $key, $value)" +Handles date process for the \s-1XML\s0 exporter +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Updates the head table based on the glyph data and the hmtx table +.ie n .SS "$t\->getdate($is_create)" +.el .SS "\f(CW$t\fP\->getdate($is_create)" +.IX Subsection "$t->getdate($is_create)" +Converts font modification time (or creation time if \f(CW$is_create\fR is set) to a 32\-bit integer as returned +from \fBtime()\fR. Returns undef if the value is out of range, either before the epoch or after the maximum +storable time. +.ie n .SS "$t\->setdate($time, $is_create)" +.el .SS "\f(CW$t\fP\->setdate($time, \f(CW$is_create\fP)" +.IX Subsection "$t->setdate($time, $is_create)" +Sets the time information for modification (or creation time if \f(CW$is_create\fR is set) according to the 32\-bit +time information. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hhea.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hhea.3pm" new file mode 100644 index 0000000000..e6efff2d9c --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hhea.3pm" @@ -0,0 +1,130 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Hhea 3pm" +.TH Font::TTF::Hhea 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Hhea \- Horizontal Header table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a simplte table with just standards specified instance variables +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.Vb 12 +\& version +\& Ascender +\& Descender +\& LineGap +\& advanceWidthMax +\& minLeftSideBearing +\& minRightSideBearing +\& xMaxExtent +\& caretSlopeRise +\& caretSlopeRun +\& metricDataFormat +\& numberOfHMetrics +.Ve +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory as instance variables +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Updates various parameters in the hhea table from the hmtx table. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hmtx.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hmtx.3pm" new file mode 100644 index 0000000000..cd79a7f61a --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Hmtx.3pm" @@ -0,0 +1,132 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Hmtx 3pm" +.TH Font::TTF::Hmtx 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Hmtx \- Horizontal Metrics +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Contains the advance width and left side bearing for each glyph. Given the +compressability of the data onto disk, this table uses information from +other tables, and thus must do part of its output during the output of +other tables +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The horizontal metrics are kept in two arrays by glyph id. The variable names +do not start with a space +.IP "advance" 4 +.IX Item "advance" +An array containing the advance width for each glyph +.IP "lsb" 4 +.IX Item "lsb" +An array containing the left side bearing for each glyph +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the horizontal metrics from the \s-1TTF\s0 file into memory +.ie n .SS "$t\->numMetrics" +.el .SS "\f(CW$t\fP\->numMetrics" +.IX Subsection "$t->numMetrics" +Calculates again the number of long metrics required to store the information +here. Returns undef if the table has not been read. +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the metrics to a \s-1TTF\s0 file. Assumes that the \f(CW\*(C`hhea\*(C'\fR has updated the +numHMetrics from here +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Updates the lsb values from the xMin from the each glyph +.ie n .SS "$t\->out_xml($context, $depth)" +.el .SS "\f(CW$t\fP\->out_xml($context, \f(CW$depth\fP)" +.IX Subsection "$t->out_xml($context, $depth)" +Outputs the table in \s-1XML\s0 +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern.3pm" new file mode 100644 index 0000000000..c0afaf54f6 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern.3pm" @@ -0,0 +1,185 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Kern 3pm" +.TH Font::TTF::Kern 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Kern \- Kerning tables +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Kerning tables are held as an ordered collection of subtables each giving +incremental information regarding the kerning of various pairs of glyphs. +.PP +The basic structure of the kerning data structure is: +.PP +.Vb 1 +\& $kern = $f\->{\*(Aqkern\*(Aq}{\*(Aqtables\*(Aq}[$tnum]{\*(Aqkerns\*(Aq}{$leftnum}{$rightnum}; +.Ve +.PP +Due to the possible complexity of some kerning tables the above information +is insufficient. Reference also needs to be made to the type of the table and +the coverage field. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The instance variables for a kerning table are relatively straightforward. +.IP "Version" 4 +.IX Item "Version" +Version number of the kerning table +.IP "Num" 4 +.IX Item "Num" +Number of subtables in the kerning table +.IP "tables" 4 +.IX Item "tables" +Array of subtables in the kerning table +.Sp +Each subtable has a number of instance variables. +.RS 4 +.IP "kern" 4 +.IX Item "kern" +A two level hash array containing kerning values. The indexing is left +is via left class and right class. It may seem using hashes is strange, +but most tables are not type 2 and this method saves empty array values. +.IP "type" 4 +.IX Item "type" +Stores the table type. Only type 0 and type 2 tables are specified for +TrueType so far. +.IP "coverage" 4 +.IX Item "coverage" +A bit field of coverage information regarding the kerning value. See the +TrueType specification for details. +.IP "Version" 4 +.IX Item "Version" +Contains the version number of the table. +.IP "Num" 4 +.IX Item "Num" +Number of kerning pairs in this type 0 table. +.IP "left" 4 +.IX Item "left" +An array indexed by glyph \- left_first which returns a class number for +the glyph in type 2 tables. +.IP "right" 4 +.IX Item "right" +An array indexed by glyph \- right_first which returns a class number for +the glyph in type 2 tables. +.IP "left_first" 4 +.IX Item "left_first" +the glyph number of the first element in the left array for type 2 tables. +.IP "right_first" 4 +.IX Item "right_first" +the glyph number of the first element in the right array for type 2 tables. +.IP "num_left" 4 +.IX Item "num_left" +Number of left classes +.IP "num_right" 4 +.IX Item "num_right" +Number of right classes +.RE +.RS 4 +.RE +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the whole kerning table into structures +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Outputs the kerning tables to the given file +.ie n .SS "$t\->XML_element($context, $depth, $key, $value)" +.el .SS "\f(CW$t\fP\->XML_element($context, \f(CW$depth\fP, \f(CW$key\fP, \f(CW$value\fP)" +.IX Subsection "$t->XML_element($context, $depth, $key, $value)" +Handles outputting the kern hash into \s-1XML\s0 a little more tidily +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "BUGS" +.IX Header "BUGS" +.IP "\(bu" 4 +Only supports kerning table types 0 & 2. +.IP "\(bu" 4 +No real support functions to \fIdo\fR anything with the kerning tables yet. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242ClassArray.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242ClassArray.3pm" new file mode 100644 index 0000000000..b2cb98e300 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242ClassArray.3pm" @@ -0,0 +1,106 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Kern::ClassArray 3pm" +.TH Font::TTF::Kern::ClassArray 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Kern::ClassArray \- ClassArray Kern Subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out_sub($fh)" +.el .SS "\f(CW$t\fP\->out_sub($fh)" +.IX Subsection "$t->out_sub($fh)" +Writes the table to a file +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242CompactClassArray.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242CompactClassArray.3pm" new file mode 100644 index 0000000000..5fea6fcd60 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242CompactClassArray.3pm" @@ -0,0 +1,106 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Kern::CompactClassArray 3pm" +.TH Font::TTF::Kern::CompactClassArray 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Kern::CompactClassArray \- Compact Class Array kern subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242OrderedList.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242OrderedList.3pm" new file mode 100644 index 0000000000..7f64040a30 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242OrderedList.3pm" @@ -0,0 +1,106 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Kern::OrderedList 3pm" +.TH Font::TTF::Kern::OrderedList 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Kern::OrderedList \- Ordered List Kern subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out_sub($fh)" +.el .SS "\f(CW$t\fP\->out_sub($fh)" +.IX Subsection "$t->out_sub($fh)" +Writes the table to a file +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242StateTable.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242StateTable.3pm" new file mode 100644 index 0000000000..d18b573fed --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242StateTable.3pm" @@ -0,0 +1,106 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Kern::StateTable 3pm" +.TH Font::TTF::Kern::StateTable 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Kern::StateTable \- State Table Kern subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out_sub($fh)" +.el .SS "\f(CW$t\fP\->out_sub($fh)" +.IX Subsection "$t->out_sub($fh)" +Writes the table to a file +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242Subtable.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242Subtable.3pm" new file mode 100644 index 0000000000..210a874b89 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Kern\357\200\242\357\200\242Subtable.3pm" @@ -0,0 +1,106 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Kern::Subtable 3pm" +.TH Font::TTF::Kern::Subtable 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Kern::Subtable \- Kern Subtable superclass for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.ie n .SS "$t\->print_classes($fh)" +.el .SS "\f(CW$t\fP\->print_classes($fh)" +.IX Subsection "$t->print_classes($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242LTSH.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242LTSH.3pm" new file mode 100644 index 0000000000..5550d67777 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242LTSH.3pm" @@ -0,0 +1,117 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::LTSH 3pm" +.TH Font::TTF::LTSH 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::LTSH \- Linear Threshold table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Holds the linear threshold for each glyph. This is the ppem value at which a +glyph's metrics become linear. The value is set to 1 if a glyph's metrics are +always linear. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "glyphs" 4 +.IX Item "glyphs" +An array of ppem values. One value per glyph +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Outputs the \s-1LTSH\s0 to the given fh. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Loca.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Loca.3pm" new file mode 100644 index 0000000000..36cbcb9792 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Loca.3pm" @@ -0,0 +1,148 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Loca 3pm" +.TH Font::TTF::Loca 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Loca \- the Locations table, which is intimately tied to the glyf table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The location table holds the directory of locations of each glyph within the +glyf table. Due to this relationship and the unimportance of the actual locations +when it comes to holding glyphs in memory, reading the location table results +in the creation of glyph objects for each glyph and stores them here. +So if you are looking for glyphs, do not look in the \f(CW\*(C`glyf\*(C'\fR table, look here +instead. +.PP +Things get complicated if you try to change the glyph list within the one table. +The recommendation is to create another clean location object to replace this +table in the font, ensuring that the old table is read first and to transfer +or copy glyphs across from the read table to the new table. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The instance variables do not start with a space +.IP "glyphs" 4 +.IX Item "glyphs" +An array of glyph objects for each glyph. +.IP "glyphtype" 4 +.IX Item "glyphtype" +A string containing the class name to create for each new glyph. If empty, +defaults to Font::TTF::Glyph. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->new" +.el .SS "\f(CW$t\fP\->new" +.IX Subsection "$t->new" +Creates a new location table making sure it has a glyphs array +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the location table creating glyph objects (Font::TTF::Glyph) for each glyph +allowing their later reading. +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the location table out to \f(CW$fh\fR. Notice that not having read the location +table implies that the glyf table has not been read either, so the numbers in +the location table are still valid. Let's hope that \f(CW\*(C`maxp/numGlyphs\*(C'\fR and +\&\f(CW\*(C`head/indexToLocFmt\*(C'\fR haven't changed otherwise we are in big trouble. +.PP +The function uses the \s-1OUTLOC\s0 location in the glyph calculated when the glyf +table was attempted to be output. +.ie n .SS "$t\->out_xml($context, $depth)" +.el .SS "\f(CW$t\fP\->out_xml($context, \f(CW$depth\fP)" +.IX Subsection "$t->out_xml($context, $depth)" +No need to output a loca table, this is dynamically generated +.ie n .SS "$t\->glyphs_do(&func)" +.el .SS "\f(CW$t\fP\->glyphs_do(&func)" +.IX Subsection "$t->glyphs_do(&func)" +Calls func for each glyph in this location table in numerical order: +.PP +.Vb 1 +\& &func($glyph, $glyph_num) +.Ve +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Manual.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Manual.3pm" new file mode 100644 index 0000000000..63e37c1ef6 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Manual.3pm" @@ -0,0 +1,299 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Manual 3pm" +.TH Font::TTF::Manual 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Manual \- Information regarding the whole module set +.SH "INTRODUCTION" +.IX Header "INTRODUCTION" +This document looks at the whole issue of how the various modules in the +TrueType Font work together. As such it is partly information on this font +system and partly information on TrueType fonts in general. +.PP +Due to the inter-relation between so many tables in a TrueType font, different +tables will make expectations as to which other tables exist. At the very least +a font should consist of a \f(CW\*(C`head\*(C'\fR table and a \f(CW\*(C`maxp\*(C'\fR table. The system has +been designed around the expectation that the necessary tables for font +rendering in the Windows environment exist. But inter table dependencies have +been kept to what are considered necessary. +.PP +This module set is not meant as a simple to use, mindless, font editing suite, +but as a low-level, get your hands dirty, know what you are doing, set of +classes for those who understand the intricacies (and there are many) of +TrueType fonts. To this end, if you get something wrong in the data structures, +etc. then this module set won't tell you and will happily create fonts which +don't work. +.PP +At the time of writing, not every TrueType table in existence has been +implemented! Only the core basic tables of TrueType 1.0 (i.e. no embedded bitmap +tables, no postscript type tables, no OpenType tables and no \s-1GX\s0 tables) have +been implemented. If you want to help by implementing another table or two, then +please go ahead and send me your code. For a full list of tables, see +Font::TTF::Font. +.SS "Design Principles" +.IX Subsection "Design Principles" +\&\s-1PERL\s0 is not \*(C+. \*(C+ encourages methods to be written for changing and reading +each instance variable in a class. If we did this in this \s-1PERL\s0 program the +results would be rather large and slow. Instead, since most access will be read +access, we expose as much of the inner storage of an object to user access +directly via hash lookup. The advantage this gives are great. For example, by +following an instance variable chain, looking up the \f(CW\*(C`yMax\*(C'\fR parameter for a +particular glyph becomes: +.PP +.Vb 1 +\& $f\->{\*(Aqloca\*(Aq}{\*(Aqglyphs\*(Aq}[$glyph]{\*(AqyMax\*(Aq} +.Ve +.PP +Or, if we are feeling very lazy and don't mind waiting: +.PP +.Vb 1 +\& $f\->{\*(Aqloca\*(Aq}{\*(Aqglyphs\*(Aq}[$f\->{\*(Aqcmap\*(Aq}\->ms_lookup(0x41)]{\*(AqyMax\*(Aq} +.Ve +.PP +The disadvantage of this method is that it behoves module users to behave +themselves. Thus it does not hold your hand and ensure that if you make a change +to a table, that the table is marked as \fIdirty\fR, or that other tables are +updated accordingly. +.PP +It is up to the application developer to understand the implications of the +changes they make to a font, and to take the necessary action to ensure that the +data they get out is what they want. Thus, you could go and change the \f(CW\*(C`yMax\*(C'\fR +value on a glyph and output a new font with this change, but it is up to you to +ensure that the font's bounding box details in the \f(CW\*(C`head\*(C'\fR table are correct, +and even that your changing \f(CW\*(C`yMax\*(C'\fR is well motivated. +.PP +To help with using the system, each module (or table) will not only describe the +methods it supports, which are relatively few, but also the instance variables +it supports, which are many. Most of the variables directly reflect table +attributes as specified in the OpenType specification, available from Microsoft +(), Adobe and Apple. A list of the names +used is also given in each module, but not necessarily with any further +description. After all, this code is not a TrueType manual as well! +.SS "Conventions" +.IX Subsection "Conventions" +There are various conventions used in this system. +.PP +Firstly we consider the documentation conventions regarding instance variables. +Each instance variable is marked indicating whether it is a \fB(P)\fRrivate +variable which users of the module are not expected to read and certainly not +write to or a \fB(R)\fRead only variable which users may well want to read but not +write to. +.SH "METHODS" +.IX Header "METHODS" +This section examines various methods and how the various modules work with +these methods. +.SS "read and read_dat" +.IX Subsection "read and read_dat" +Before the data structures for a table can be accessed, they need to be filled +in from somewhere. The usual way to do this is to read an existing TrueType +font. This may be achieved by: +.PP +.Vb 1 +\& $f = Font::TTF::Font\->open($filename) || die "Unable to read $filename"; +.Ve +.PP +This will open an existing font and read its directory header. Notice that at +this point, none of the tables in the font have been read. (Actually, the +\&\f(CW\*(C`head\*(C'\fR and \f(CW\*(C`maxp\*(C'\fR tables are read at this point too since they contain the +commonly required parameters of): +.PP +.Vb 2 +\& $f\->{\*(Aqhead\*(Aq}{\*(AqunitsPerEm\*(Aq} +\& $f\->{\*(Aqmaxp\*(Aq}{\*(AqnumGlyphs\*(Aq} +.Ve +.PP +In order to be able to access information from a table, it is first necessary to +\&\f(CW\*(C`read\*(C'\fR it. Consider trying to find the advance width of a space character +(U+0020). The following code should do it: +.PP +.Vb 4 +\& $f = Font::TTF::Font\->open($ARGV[0]); +\& $snum = $f\->{\*(Aqcmap\*(Aq}\->ms_lookup(0x0020); +\& $sadv = $f\->{\*(Aqhmtx\*(Aq}{\*(Aqadvance\*(Aq}[$snum]; +\& print $sadv; +.Ve +.PP +This would result in the value zero being printed, which is far from correct. +But why? The first line would correctly read the font directory. The second line +would, incidently, correctly locate the space character in the Windows cmap +(assuming a non symbol encoded font). The third line would not succeed in its +task since the \f(CW\*(C`hmtx\*(C'\fR table has not been filled in from the font file. To +achieve what we want we would first need to cause it to be read: +.PP +.Vb 2 +\& $f\->{\*(Aqhmtx\*(Aq}\->read; +\& $sadv = $f\->{\*(Aqhmtx\*(Aq}{\*(Aqadvance\*(Aq}[$snum]; +.Ve +.PP +Or for those who are too lazy to write multiple lines, \f(CW\*(C`read\*(C'\fR returns the +object it reads. Thus we could write: +.PP +.Vb 1 +\& $sadv = $f\->{\*(Aqhmtx\*(Aq}\->read\->{\*(Aqadvance\*(Aq}[$snum]; +.Ve +.PP +Why, if we always have to read tables before accessing information from them, +did we not have to do this for the \f(CW\*(C`cmap\*(C'\fR table? The answer lies in the method +call. It senses that the table hasn't been read and reads it for us. This will +generally happen with all method calls, it is only when we do direct data access +that we have to take the responsibility to read the table first. +.PP +Reading a table does not necessarily result in all the data being placed into +internal data structures. In the case of a simple table \f(CW\*(C`read\*(C'\fR is sufficient. +In fact, the normal case is that \f(CW\*(C`read_dat\*(C'\fR reads the data from the file into +an instance variable called \f(CW\*(Aq dat\*(Aq\fR (including the space) and not into the +data structures. +.PP +This is true except for the \f(CW\*(C`glyph\*(C'\fR class which represents a single glyph. Here +the process is reversed. Reading a \f(CW\*(C`glyph\*(C'\fR reads the data for the glyph into +the \f(CW\*(Aq dat\*(Aq\fR instance variable and sets various header attributes for the glyph +(\f(CW\*(C`xMin\*(C'\fR, \f(CW\*(C`numContours\*(C'\fR, etc.). The data is converted out of the variable into +data structures via the \f(CW\*(C`read_dat\*(C'\fR method. +.PP +The aim, therefore, is that \f(CW\*(C`read\*(C'\fR should do the natural thing (read into data +structures for those tables and elements for which it is helpful \*(-- all except +\&\f(CW\*(C`glyph\*(C'\fR at present) and \f(CW\*(C`read_dat\*(C'\fR should do the unnatural thing: read just +the binary data for normal tables and convert binary data to data structures for +\&\f(CW\*(C`glyph\*(C'\fRs. +.PP +In summary, therefore, use \f(CW\*(C`read\*(C'\fR unless you want to hack around with the +internals of glyphs in which case see Font::TTF::Glyph for more details. +.SS "update" +.IX Subsection "update" +The aim of this method is to allow the various data elements in a \f(CW\*(C`read\*(C'\fR font +to update themselves. All tables know how to update themselves. All tables also +contain information which cannot be \fIupdated\fR but is new knowledge in the font. +As a result, certain tables do nothing when they are updated. We can, therefore, +build an update hierarchy of tables, with the independent tables at the bottom +and \f(CW\*(C`Font\*(C'\fR at the top: +.PP +.Vb 7 +\& +\-\-loca +\& | +\& glyf\-\-+\-\-maxp +\& | +\& +\-\-\-+\-\-head +\& | +\& hmtx\-\-\-\-\-\-+\-\-hhea +\& +\& cmap\-\-\-\-\-OS/2 +\& +\& name\-\- +\& +\& post\-\- +\&There is an important universal dependency which it is up to the user to +\&keep up to date. This is C which is used to iterate over all +\&the glyphs. Note that the glyphs themselves are not held in the C table +\&but in the C table, so adding glyphs, etc. automatically involves keeping +\&the C table up to date. +.Ve +.SS "Creating fonts" +.IX Subsection "Creating fonts" +Suppose we were creating a font from scratch. How much information do we need +to supply and how much will \f(CW\*(C`update\*(C'\fR do for us? +.PP +The following information is required: +.PP +.Vb 8 +\& $f\->{\*(Aqloca\*(Aq}{\*(Aqglyphs\*(Aq} +\& $f\->{\*(Aqhead\*(Aq}{\*(Aqupem\*(Aq} +\& $f\->{\*(Aqmaxp\*(Aq}{\*(AqnumGlyphs\*(Aq} (doesn\*(Aqt come from $f\->{\*(Aqloca\*(Aq}{\*(Aqglyphs\*(Aq}) +\& $f\->{\*(Aqhmtx\*(Aq}{\*(Aqadvance\*(Aq} +\& $f\->{\*(Aqpost\*(Aq}[\*(Aqformat\*(Aq} +\& $f\->{\*(Aqpost\*(Aq}{\*(AqVAL\*(Aq} +\& $f\->{\*(Aqcmap\*(Aq} +\& $f\->{\*(Aqname\*(Aq} +.Ve +.PP +Pretty much everything else is calculated for you. Details of what is needed +for a glyph may be found in Font::TTF::Glyph. Once we have all the +information we need (and there is lots more that you could add) then we simply +.PP +.Vb 2 +\& $f\->dirty; # mark all tables dirty +\& $f\->update; # update the font +.Ve +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +(see \s-1CONTRIBUTORS\s0 for other authors). +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Maxp.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Maxp.3pm" new file mode 100644 index 0000000000..bdd9e1ddd7 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Maxp.3pm" @@ -0,0 +1,141 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Maxp 3pm" +.TH Font::TTF::Maxp 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Maxp \- Maximum Profile table in a font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +A collection of useful instance variables following the \s-1TTF\s0 standard. Probably +the most used being \f(CW\*(C`numGlyphs\*(C'\fR. Note that this particular value is +foundational and should be kept up to date by the application, it is not updated +by \f(CW\*(C`update\*(C'\fR. +.PP +Handles table versions 0.5, 1.0 +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +No others beyond those specified in the standard: +.PP +.Vb 10 +\& numGlyphs +\& maxPoints +\& maxContours +\& maxCompositePoints +\& maxCompositeContours +\& maxZones +\& maxTwilightPoints +\& maxStorage +\& maxFunctionDefs +\& maxInstructionDefs +\& maxStackElements +\& maxSizeOfInstructions +\& maxComponentElements +\& maxComponentDepth +.Ve +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Calculates all the maximum values for a font based on the glyphs in the font. +Only those fields which require hinting code interpretation are ignored and +left as they were read. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort.3pm" new file mode 100644 index 0000000000..544e3b9d26 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort.3pm" @@ -0,0 +1,111 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort 3pm" +.TH Font::TTF::Mort 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort \- Glyph Metamorphosis table in a font +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Chain.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Chain.3pm" new file mode 100644 index 0000000000..9104425b99 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Chain.3pm" @@ -0,0 +1,107 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort::Chain 3pm" +.TH Font::TTF::Mort::Chain 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort::Chain \- Chain Mort subtable for AAT +.ie n .SS "$t\->new" +.el .SS "\f(CW$t\fP\->new" +.IX Subsection "$t->new" +.ie n .SS "$t\->read($fh)" +.el .SS "\f(CW$t\fP\->read($fh)" +.IX Subsection "$t->read($fh)" +Reads the chain into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the chain +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Contextual.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Contextual.3pm" new file mode 100644 index 0000000000..254c6cfc5d --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Contextual.3pm" @@ -0,0 +1,105 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort::Contextual 3pm" +.TH Font::TTF::Mort::Contextual 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort::Contextual \- Contextual Mort subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->\fBpack_sub()\fP" +.el .SS "\f(CW$t\fP\->\fBpack_sub()\fP" +.IX Subsection "$t->pack_sub()" +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Insertion.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Insertion.3pm" new file mode 100644 index 0000000000..1d8a0bc557 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Insertion.3pm" @@ -0,0 +1,105 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort::Insertion 3pm" +.TH Font::TTF::Mort::Insertion 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort::Insertion \- Insertion Mort subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->\fBpack_sub()\fP" +.el .SS "\f(CW$t\fP\->\fBpack_sub()\fP" +.IX Subsection "$t->pack_sub()" +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Ligature.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Ligature.3pm" new file mode 100644 index 0000000000..793d1bd0cc --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Ligature.3pm" @@ -0,0 +1,105 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort::Ligature 3pm" +.TH Font::TTF::Mort::Ligature 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort::Ligature \- Ligature Mort subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->pack_sub($fh)" +.el .SS "\f(CW$t\fP\->pack_sub($fh)" +.IX Subsection "$t->pack_sub($fh)" +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Noncontextual.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Noncontextual.3pm" new file mode 100644 index 0000000000..180495b5bd --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Noncontextual.3pm" @@ -0,0 +1,105 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort::Noncontextual 3pm" +.TH Font::TTF::Mort::Noncontextual 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort::Noncontextual \- Noncontextual Mort subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->pack_sub($fh)" +.el .SS "\f(CW$t\fP\->pack_sub($fh)" +.IX Subsection "$t->pack_sub($fh)" +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Rearrangement.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Rearrangement.3pm" new file mode 100644 index 0000000000..be308d55ef --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Rearrangement.3pm" @@ -0,0 +1,105 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort::Rearrangement 3pm" +.TH Font::TTF::Mort::Rearrangement 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort::Rearrangement \- Rearrangement Mort subtable for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->\fBpack_sub()\fP" +.el .SS "\f(CW$t\fP\->\fBpack_sub()\fP" +.IX Subsection "$t->pack_sub()" +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Subtable.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Subtable.3pm" new file mode 100644 index 0000000000..d7607687b7 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Mort\357\200\242\357\200\242Subtable.3pm" @@ -0,0 +1,106 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Mort::Subtable 3pm" +.TH Font::TTF::Mort::Subtable 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Mort::Subtable \- Mort subtable superclass for AAT +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.ie n .SS "$t\->print_classes($fh)" +.el .SS "\f(CW$t\fP\->print_classes($fh)" +.IX Subsection "$t->print_classes($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Name.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Name.3pm" new file mode 100644 index 0000000000..70465ad5aa --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Name.3pm" @@ -0,0 +1,204 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Name 3pm" +.TH Font::TTF::Name 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Name \- String table for a TTF font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Strings are held by number, platform, encoding and language. Strings are +accessed as: +.PP +.Vb 1 +\& $f\->{\*(Aqname\*(Aq}{\*(Aqstrings\*(Aq}[$number][$platform_id][$encoding_id]{$language_id} +.Ve +.PP +Notice that the language is held in an associative array due to its sparse +nature on some platforms such as Microsoft ($pid = 3). Notice also that the +array order is different from the stored array order (platform, encoding, +language, number) to allow for easy manipulation of strings by number (which is +what I guess most people will want to do). +.PP +By default, \f(CW$Font::TTF::Name::utf8\fR is set to 1, and strings will be stored as \s-1UTF8\s0 wherever +possible. The method \f(CW\*(C`is_utf8\*(C'\fR can be used to find out if a string in a particular +platform and encoding will be returned as \s-1UTF8.\s0 Unicode strings are always +converted if utf8 is requested. Otherwise, strings are stored according to platform: +.PP +You now have to set <$Font::TTF::Name::utf8> to 0 to get the old behaviour. +.IP "Apple Unicode (platform id = 0)" 4 +.IX Item "Apple Unicode (platform id = 0)" +Data is stored as network ordered \s-1UCS2.\s0 There is no encoding id for this platform +but there are language ids as per Mac language ids. +.IP "Mac (platform id = 1)" 4 +.IX Item "Mac (platform id = 1)" +Data is stored as 8\-bit binary data, leaving the interpretation to the user +according to encoding id. +.IP "Unicode (platform id = 2)" 4 +.IX Item "Unicode (platform id = 2)" +Currently stored as 16\-bit network ordered \s-1UCS2.\s0 Upon release of Perl 5.005 this +will change to utf8 assuming current \s-1UCS2\s0 semantics for all encoding ids. +.IP "Windows (platform id = 3)" 4 +.IX Item "Windows (platform id = 3)" +As per Unicode, the data is currently stored as 16\-bit network ordered \s-1UCS2.\s0 Upon +release of Perl 5.005 this will change to utf8 assuming current \s-1UCS2\s0 semantics for +all encoding ids. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "strings" 4 +.IX Item "strings" +An array of arrays, etc. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads all the names into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes out all the strings +.ie n .SS "$t\->XML_element($context, $depth, $key, $value)" +.el .SS "\f(CW$t\fP\->XML_element($context, \f(CW$depth\fP, \f(CW$key\fP, \f(CW$value\fP)" +.IX Subsection "$t->XML_element($context, $depth, $key, $value)" +Outputs the string element in nice \s-1XML\s0 (which is all the table really!) +.ie n .SS "$t\->XML_end($context, $tag, %attrs)" +.el .SS "\f(CW$t\fP\->XML_end($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$t->XML_end($context, $tag, %attrs)" +Store strings in the right place +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "is_utf8($pid, $eid)" +.el .SS "is_utf8($pid, \f(CW$eid\fP)" +.IX Subsection "is_utf8($pid, $eid)" +Returns whether a string of a given platform and encoding is going to be in \s-1UTF8\s0 +.SS "find_name($nid)" +.IX Subsection "find_name($nid)" +Hunts down a name in all the standard places and returns the string and for an +array context the pid, eid & lid as well +.SS "remove_name($nid)" +.IX Subsection "remove_name($nid)" +Removes all strings with the given name id from the table. +.ie n .SS "set_name($nid, $str[, $lang[, @cover]])" +.el .SS "set_name($nid, \f(CW$str\fP[, \f(CW$lang\fP[, \f(CW@cover\fP]])" +.IX Subsection "set_name($nid, $str[, $lang[, @cover]])" +Sets the given name id string to \f(CW$str\fR for all platforms and encodings that +this module can handle. If \f(CW$lang\fR is set, it is interpretted as a language +tag and if the particular language of a string is found to match, then +that string is changed, otherwise no change occurs. +.PP +If supplied, \f(CW@cover\fR should be a list of references to two-element arrays +containing pid,eid pairs that should be added to the name table if not already present. +.PP +This function does not add any names to the table unless \f(CW@cover\fR is supplied. +.ie n .SS "Font::TTF::Name\->match_lang($pid, $lid, $lang)" +.el .SS "Font::TTF::Name\->match_lang($pid, \f(CW$lid\fP, \f(CW$lang\fP)" +.IX Subsection "Font::TTF::Name->match_lang($pid, $lid, $lang)" +Compares the language associated to the string of given platform and language +with the given language tag. If the language matches the tag (i.e. is equal +or more defined than the given language tag) returns true. This is calculated +by finding whether the associated language tag starts with the given language +tag. +.ie n .SS "Font::TTF::Name\->get_lang($pid, $lid)" +.el .SS "Font::TTF::Name\->get_lang($pid, \f(CW$lid\fP)" +.IX Subsection "Font::TTF::Name->get_lang($pid, $lid)" +Returns the language tag associated with a particular platform and language id +.ie n .SS "Font::TTF::Name\->find_lang($pid, $lang)" +.el .SS "Font::TTF::Name\->find_lang($pid, \f(CW$lang\fP)" +.IX Subsection "Font::TTF::Name->find_lang($pid, $lang)" +Looks up the language name and returns a lang id if one exists +.SS "Font::TTF::Name\->\fBpe_list()\fP" +.IX Subsection "Font::TTF::Name->pe_list()" +Returns an array of references to two-element arrays +containing pid,eid pairs that already exist in this name table. +Useful for creating \f(CW@cover\fR parameter to \fBset_name()\fR. +.SH "BUGS" +.IX Header "BUGS" +.IP "\(bu" 4 +Unicode type strings will be stored in utf8 for all known platforms, +once Perl 5.6 has been released and I can find all the mapping tables, etc. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OS_2.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OS_2.3pm" new file mode 100644 index 0000000000..b008d7103e --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OS_2.3pm" @@ -0,0 +1,213 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::OS_2 3pm" +.TH Font::TTF::OS_2 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::OS_2 \- the OS/2 table in a TTF font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \s-1OS/2\s0 table has two versions and forms, one an extension of the other. This +module supports both forms and the switching between them. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +No other variables than those in table and those in the standard: +.PP +.Vb 10 +\& Version +\& xAvgCharWidth +\& usWeightClass +\& usWidthClass +\& fsType +\& ySubscriptXSize +\& ySubScriptYSize +\& ySubscriptXOffset +\& ySubscriptYOffset +\& ySuperscriptXSize +\& ySuperscriptYSize +\& ySuperscriptXOffset +\& ySuperscriptYOffset +\& yStrikeoutSize +\& yStrikeoutPosition +\& sFamilyClass +\& bFamilyType +\& bSerifStyle +\& bWeight +\& bProportion +\& bContrast +\& bStrokeVariation +\& bArmStyle +\& bLetterform +\& bMidline +\& bXheight +\& ulUnicodeRange1 +\& ulUnicodeRange2 +\& ulUnicodeRange3 +\& ulUnicodeRange4 +\& achVendID +\& fsSelection +\& usFirstCharIndex +\& usLastCharIndex +\& sTypoAscender +\& sTypoDescender +\& sTypoLineGap +\& usWinAscent +\& usWinDescent +\& ulCodePageRange1 +\& ulCodePageRange2 +\& xHeight +\& CapHeight +\& defaultChar +\& breakChar +\& maxLookups +.Ve +.PP +Notice that versions 0, 1, 2 & 3 of the table are supported. Notice also that the +Panose variable has been broken down into its elements. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads in the various values from disk (see details of \s-1OS/2\s0 table) +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying. +.ie n .SS "$t\->XML_element($context, $depth, $key, $value)" +.el .SS "\f(CW$t\fP\->XML_element($context, \f(CW$depth\fP, \f(CW$key\fP, \f(CW$value\fP)" +.IX Subsection "$t->XML_element($context, $depth, $key, $value)" +Tidies up the hex values to output them in hex +.ie n .SS "$t\->XML_end($context, $tag, %attrs)" +.el .SS "\f(CW$t\fP\->XML_end($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$t->XML_end($context, $tag, %attrs)" +Now handle them on the way back in +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Updates the \s-1OS/2\s0 table by getting information from other sources: +.PP +Updates the \f(CW\*(C`firstChar\*(C'\fR and \f(CW\*(C`lastChar\*(C'\fR values based on the \s-1MS\s0 table in the +cmap. +.PP +Updates the sTypoAscender, sTypoDescender & sTypoLineGap to be the same values +as Ascender, Descender and Linegap from the hhea table (assuming it is dirty) +and also sets usWinAscent to be the sum of Ascender+Linegap and usWinDescent to +be the negative of Descender. +.ie n .SS "$t\->guessRangeBits (\e%map, [$cp_threshold, [%u_threshold]])" +.el .SS "\f(CW$t\fP\->guessRangeBits (\e%map, [$cp_threshold, [%u_threshold]])" +.IX Subsection "$t->guessRangeBits (%map, [$cp_threshold, [%u_threshold]])" +Set the ulCodePageRange and ulUnicodeRange fields based on characters actually present in the font. +.PP +\&\f(CW%map\fR is a hash keyed by \s-1USV\s0 returning non-zero for characters present (e.g. use {'val'} +a from Unicode cmap). +.PP +The two optional parameters are percentage of characters within the codepage or unicode range that need +to be present to constitute coverage. A threshold of 0 causes corresponding range bits to +be set if any characters are present at all, while a negative value causes the corresponding +range bits to be unchanged. Defaults are 50 and 0, respectively. +.PP +For codepage bits, the threshold is percentage of characters between 0xC0 and 0xFF that need +to be present to constitute coverage). For codepages other than 1252, +characters (e.g., punctuation) that are defined identically to cp1252 are ignored +for the purposes of this percentage calculation. Looks only for \s-1SBCS\s0 codepages, not \s-1DBCS.\s0 +.PP +For Unicode range bits that represent multiple ranges, e.g., bit 29 represents: +.PP +.Vb 3 +\& Latin Extended Additional 1E00\-1EFF +\& Latin Extended\-C 2C60\-2C7F +\& Latin Extended\-D A720\-A7FF +.Ve +.PP +the bit will be set if any of these ranges meet the threshold requirement. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OTTags.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OTTags.3pm" new file mode 100644 index 0000000000..ea2a053c56 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OTTags.3pm" @@ -0,0 +1,128 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::OTTags 3pm" +.TH Font::TTF::OTTags 3pm "2016-08-18" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::OTTags \- Utilities for TrueType/OpenType tags +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use Font::TTF::OTTags qw( %tttags %ttnames %iso639 readtagsfile ); +\& +\& # Look at built\-in stuff: +\& $script_tag = $tttags{\*(AqSCRIPT\*(Aq}{\*(AqCypriot Syllabary\*(Aq}; # returns \*(Aqcprt\*(Aq +\& $lang_name = $ttnames{\*(AqLANGUAGE\*(Aq}{\*(AqALT \*(Aq}; # returns \*(AqAltai\*(Aq +\& +\& # Map iso639\-2 tag to/from OT lang tag +\& @isotags = $iso639{\*(AqALT \*(Aq}; # returns [ \*(Aqatv\*(Aq, \*(Aqalt\*(Aq ] +\& $lang_tag = $iso639{\*(Aqatv\*(Aq}; # returns \*(AqALT \*(Aq +\& +\& # Read latest tags file to add to built\-in definitions +\& readtagsfile ("C:\e\eProgram Files\e\eMicrosoft VOLT\e\eTAGS.txt"); +.Ve +.PP +First-level keys to \f(CW%tttags\fR and \f(CW%ttnames\fR are: +.IP "\s-1SCRIPT\s0" 4 +.IX Item "SCRIPT" +retrieve script tag or name +.IP "\s-1LANGUAGE\s0" 4 +.IX Item "LANGUAGE" +retrieve language tag or name +.IP "\s-1FEATURE\s0" 4 +.IX Item "FEATURE" +retrieve feature tag or name +.PP +Built-in data has been derived from the 2014\-07\-11 draft of the +3rd edition of \s-1ISO/IEC 14496\-22\s0 +(Information technology \- Coding of audio-visual objects \- Part 22: Open Font Format) +which, when finalized and approved, will replace the second edition (\s-1ISO/IEC 14496\-22:2009\s0). +.SH "METHODS" +.IX Header "METHODS" +.SS "readtagsfile ( filename )" +.IX Subsection "readtagsfile ( filename )" +Read a file in the syntax of Tags.txt (included with Microsoft \s-1VOLT\s0) to obtain additional/replacement tag definitions. +.PP +Returns 0 if cannot open the file; else 1. +.SH "AUTHOR" +.IX Header "AUTHOR" +Bob Hallissy. . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OldCmap.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OldCmap.3pm" new file mode 100644 index 0000000000..b5eebbcedc --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OldCmap.3pm" @@ -0,0 +1,165 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::OldCmap 3pm" +.TH Font::TTF::OldCmap 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::OldCmap \- Character map table +.PP +This module is deprecated +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Looks after the character map. The primary structure used for handling a cmap +is the Font::TTF::Segarr which handles the segmented arrays of format 4 tables, +and in a simpler form for format 0 tables. +.PP +Due to the complexity of working with segmented arrays, most of the handling of +such arrays is via methods rather than via instance variables. +.PP +One important feature of a format 4 table is that it always contains a segment +with a final address of 0xFFFF. If you are creating a table from scratch this is +important (although Font::TTF::Segarr can work quite happily without it). +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The instance variables listed here are not preceded by a space due to their +emulating structural information in the font. +.IP "Num" 4 +.IX Item "Num" +Number of subtables in this table +.IP "Tables" 4 +.IX Item "Tables" +An array of subtables ([0..Num\-1]) +.PP +Each subtables also has its own instance variables which are, again, not +preceded by a space. +.IP "Platform" 4 +.IX Item "Platform" +The platform number for this subtable +.IP "Encoding" 4 +.IX Item "Encoding" +The encoding number for this subtable +.IP "Format" 4 +.IX Item "Format" +Gives the stored format of this subtable +.IP "Ver" 4 +.IX Item "Ver" +Gives the version (or language) information for this subtable +.IP "val" 4 +.IX Item "val" +This points to a Font::TTF::Segarr which contains the content of the particular +subtable. +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the cmap into memory. Format 4 subtables read the whole subtable and +fill in the segmented array accordingly. +.PP +Format 2 subtables are not read at all. +.ie n .SS "$t\->ms_lookup($uni)" +.el .SS "\f(CW$t\fP\->ms_lookup($uni)" +.IX Subsection "$t->ms_lookup($uni)" +Given a Unicode value in the \s-1MS\s0 table (Platform 3, Encoding 1) locates that +table and looks up the appropriate glyph number from it. +.ie n .SS "$t\->find_ms" +.el .SS "\f(CW$t\fP\->find_ms" +.IX Subsection "$t->find_ms" +Finds the Microsoft Unicode table and sets the \f(CW\*(C`mstable\*(C'\fR instance variable +to it if found. Returns the table it finds. +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes out a cmap table to a filehandle. If it has not been read, then +just copies from input file to output +.ie n .SS "@map = $t\->reverse([$num])" +.el .SS "\f(CW@map\fP = \f(CW$t\fP\->reverse([$num])" +.IX Subsection "@map = $t->reverse([$num])" +Returns a reverse map of the table of given number or the Microsoft +cmap. I.e. given a glyph gives the Unicode value for it. +.SH "BUGS" +.IX Header "BUGS" +.IP "\(bu" 4 +No support for format 2 tables (\s-1MBCS\s0) +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OldMort.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OldMort.3pm" new file mode 100644 index 0000000000..3236a19ee4 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242OldMort.3pm" @@ -0,0 +1,197 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::OldMort 3pm" +.TH Font::TTF::OldMort 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::OldMort \- Glyph Metamorphosis table in a font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "version" 4 +.IX Item "version" +table version number (Fixed: currently 1.0) +.IP "chains" 4 +.IX Item "chains" +list of metamorphosis chains, each of which has its own fields: +.RS 4 +.IP "defaultFlags" 4 +.IX Item "defaultFlags" +chain's default subfeature flags (UInt32) +.IP "featureEntries" 4 +.IX Item "featureEntries" +list of feature entries, each of which has fields: +.RS 4 +.IP "type" 4 +.IX Item "type" +.PD 0 +.IP "setting" 4 +.IX Item "setting" +.IP "enable" 4 +.IX Item "enable" +.IP "disable" 4 +.IX Item "disable" +.RE +.RS 4 +.RE +.IP "subtables" 4 +.IX Item "subtables" +.PD +list of metamorphosis subtables, each of which has fields: +.RS 4 +.IP "type" 4 +.IX Item "type" +subtable type (0: rearrangement; 1: contextual substitution; 2: ligature; +4: non-contextual substitution; 5: insertion) +.IP "direction" 4 +.IX Item "direction" +processing direction ('\s-1LR\s0' or '\s-1RL\s0') +.IP "orientation" 4 +.IX Item "orientation" +applies to text in which orientation ('\s-1VH\s0', 'V', or 'H') +.IP "subFeatureFlags" 4 +.IX Item "subFeatureFlags" +the subfeature flags controlling whether the table is used (UInt32) +.RE +.RS 4 +.Sp +Further fields depend on the type of subtable: +.Sp +.RS 4 +Rearrangement table: +.IP "classes" 4 +.IX Item "classes" +array of lists of glyphs +.IP "states" 4 +.IX Item "states" +array of arrays of hashes{'nextState', 'flags'} +.RE +.RS 4 +.Sp +Contextual substitution table: +.IP "classes" 4 +.IX Item "classes" +array of lists of glyphs +.IP "states" 4 +.IX Item "states" +array of array of hashes{'nextState', 'flags', 'actions'}, where \f(CW\*(C`actions\*(C'\fR +is an array of two elements which are offsets to be added to [marked, current] +glyph to get index into \f(CW\*(C`mappings\*(C'\fR (or \f(CW\*(C`undef\*(C'\fR if no mapping to be applied) +.IP "mappings" 4 +.IX Item "mappings" +list of glyph codes mapped to through the state table mappings +.RE +.RS 4 +.Sp +Ligature table: +.Sp +Non-contextual substitution table: +.Sp +Insertion table: +.RE +.RE +.RS 4 +.RE +.RE +.RS 4 +.RE +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242PCLT.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242PCLT.3pm" new file mode 100644 index 0000000000..69ca01e5fb --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242PCLT.3pm" @@ -0,0 +1,135 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::PCLT 3pm" +.TH Font::TTF::PCLT 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::PCLT \- PCLT TrueType font table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \s-1PCLT\s0 table holds various pieces HP-PCL specific information. Information +here is generally not used by other software, except for the xHeight and +CapHeight which are stored here (if the table exists in a font). +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +Only from table and the standard: +.PP +.Vb 10 +\& version +\& FontNumber +\& Pitch +\& xHeight +\& Style +\& TypeFamily +\& CapHeight +\& SymbolSet +\& Typeface +\& CharacterComplement +\& FileName +\& StrokeWeight +\& WidthType +\& SerifStyle +.Ve +.PP +Notice that \f(CW\*(C`Typeface\*(C'\fR, \f(CW\*(C`CharacterComplement\*(C'\fR and \f(CW\*(C`FileName\*(C'\fR return arrays +of unsigned characters of the appropriate length +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory thanks to some utility functions +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242PSNames.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242PSNames.3pm" new file mode 100644 index 0000000000..bc07107edb --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242PSNames.3pm" @@ -0,0 +1,117 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::PSNames 3pm" +.TH Font::TTF::PSNames 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::PSNames \- Utilities for Postscript glyph name processing +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 3 +\& use Font::TTF::PSNames qw(parse lookup); +\& $name = lookup($uni); +\& $uni = parse($name); +.Ve +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "lookup ( $usv [, $noAlt [, $noUni] ])" +.el .SS "lookup ( \f(CW$usv\fP [, \f(CW$noAlt\fP [, \f(CW$noUni\fP] ])" +.IX Subsection "lookup ( $usv [, $noAlt [, $noUni] ])" +return the Adobe-recommended glyph name for a specific Unicode codepoint (integer). By default +returns \f(CW\*(C`uniXXXX\*(C'\fR names rather than \f(CW\*(C`afiiNNNNN\*(C'\fR or \f(CW\*(C`SFnnnnnn\*(C'\fR names +.PP +If \f(CW$noAlt\fR is true, \f(CW\*(C`afii\*(C'\fR and \f(CW\*(C`SF\*(C'\fR names are returned rather than \f(CW\*(C`uniXXXX\*(C'\fR. +.PP +if \f(CW$noUni\fR is true, returns undef if it would have to resort to \f(CW\*(C`uniXXXX\*(C'\fR or \f(CW\*(C`uXXXXXX\*(C'\fR +style names. Essentially this represents a straight lookup in the Adobe-recommended list. +.ie n .SS "parse ( $glyphname )" +.el .SS "parse ( \f(CW$glyphname\fP )" +.IX Subsection "parse ( $glyphname )" +Parse an Adobe-conformant glyph name, generating a Unicode codepoint sequence equivalent to the glyph (or +glyph components, should the name represent a ligature). In scalar context, returns a reference to an +array of Unicodes (decimal). Array is empty if the glyph name is non-conformant. +In list context, the first item returned is the same array reference as above. The second item +is a reference to an array containing the extensions (if any) present on the glyph name. +The '.' that precedes each extension is not included. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Post.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Post.3pm" new file mode 100644 index 0000000000..9d062f5218 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Post.3pm" @@ -0,0 +1,163 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Post 3pm" +.TH Font::TTF::Post 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Post \- Holds the Postscript names for each glyph +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Holds the postscript names for glyphs. Note that they are not held as an +array, but as indexes into two lists. The first list is the standard Postscript +name list defined by the TrueType standard. The second comes from the font +directly. +.PP +Looking up a glyph from a Postscript name or a name from a glyph number is +achieved through methods rather than variable lookup. +.PP +This class handles PostScript table types of 1, 2, 2.5 & 3, but not version 4. +Support for version 2.5 is as per Apple spec rather than \s-1MS.\s0 +.PP +The way to look up Postscript names or glyphs is: +.PP +.Vb 2 +\& $pname = $f\->{\*(Aqpost\*(Aq}{\*(AqVAL\*(Aq}[$gnum]; +\& $gnum = $f\->{\*(Aqpost\*(Aq}{\*(AqSTRINGS\*(Aq}{$pname}; +.Ve +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +Due to different systems having different limitations, there are various class +variables available to control what post table types can be written. +.ie n .IP "$Font::TTF::Post::no25" 4 +.el .IP "\f(CW$Font::TTF::Post::no25\fR" 4 +.IX Item "$Font::TTF::Post::no25" +If set tells Font::TTF::Post::out to use table type 2 instead of 2.5 in case apps +cannot handle version 2.5. +.IP "\s-1VAL\s0" 4 +.IX Item "VAL" +Contains an array indexed by glyph number of Postscript names. This is used when +writing out a font. +.IP "\s-1STRINGS\s0" 4 +.IX Item "STRINGS" +An associative array of Postscript names mapping to the highest glyph with that +name. These may not be in sync with \s-1VAL.\s0 +.PP +In addition there are the standard introductory variables defined in the +standard: +.PP +.Vb 9 +\& FormatType +\& italicAngle +\& underlinePosition +\& underlineThickness +\& isFixedPitch +\& minMemType42 +\& maxMemType42 +\& minMemType1 +\& maxMemType1 +.Ve +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the Postscript table into memory from disk +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes out a new Postscript name table from memory or copies from disk +.ie n .SS "$t\->XML_element($context, $depth, $key, $val)" +.el .SS "\f(CW$t\fP\->XML_element($context, \f(CW$depth\fP, \f(CW$key\fP, \f(CW$val\fP)" +.IX Subsection "$t->XML_element($context, $depth, $key, $val)" +Outputs the names as one block of \s-1XML\s0 +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "BUGS" +.IX Header "BUGS" +.IP "\(bu" 4 +No support for type 4 tables +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Prep.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Prep.3pm" new file mode 100644 index 0000000000..f8db6b5d45 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Prep.3pm" @@ -0,0 +1,108 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Prep 3pm" +.TH Font::TTF::Prep 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Prep \- Preparation hinting program. Called when ppem changes +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a minimal class adding nothing beyond a table, but is a repository +for prep type information for those processes brave enough to address hinting. +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the data using \f(CW\*(C`read_dat\*(C'\fR. +.ie n .SS "$t\->out_xml($context, $depth)" +.el .SS "\f(CW$t\fP\->out_xml($context, \f(CW$depth\fP)" +.IX Subsection "$t->out_xml($context, $depth)" +Outputs Prep program as \s-1XML\s0 +.ie n .SS "$t\->XML_end($context, $tag, %attrs)" +.el .SS "\f(CW$t\fP\->XML_end($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$t->XML_end($context, $tag, %attrs)" +Parse all that hinting code +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Prop.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Prop.3pm" new file mode 100644 index 0000000000..dfe530ada3 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Prop.3pm" @@ -0,0 +1,126 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Prop 3pm" +.TH Font::TTF::Prop 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Prop \- Glyph Properties table in a font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "version" 4 +.IX Item "version" +.PD 0 +.IP "default" 4 +.IX Item "default" +.IP "lookup" 4 +.IX Item "lookup" +.PD +Hash of property values keyed by glyph number +.IP "lookupFormat" 4 +.IX Item "lookupFormat" +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->print($fh)" +.el .SS "\f(CW$t\fP\->print($fh)" +.IX Subsection "$t->print($fh)" +Prints a human-readable representation of the table +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Jonathan Kew . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Segarr.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Segarr.3pm" new file mode 100644 index 0000000000..27be753e0c --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Segarr.3pm" @@ -0,0 +1,161 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Segarr 3pm" +.TH Font::TTF::Segarr 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Segarr \- Segmented array +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Holds data either directly or indirectly as a series of arrays. This class +looks after the set of arrays and masks the individual sub-arrays, thus saving +a class, we hope. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +All instance variables do not start with a space. +.PP +The segmented array is simply an array of segments +.PP +Each segment is a more complex affair: +.IP "\s-1START\s0" 4 +.IX Item "START" +In terms of the array, the address for the 0th element in this segment. +.IP "\s-1LEN\s0" 4 +.IX Item "LEN" +Number of elements in this segment +.IP "\s-1VAL\s0" 4 +.IX Item "VAL" +The array which contains the elements +.SH "METHODS" +.IX Header "METHODS" +.SS "Font::TTF::Segarr\->new($size)" +.IX Subsection "Font::TTF::Segarr->new($size)" +Creates a new segmented array with a given data size +.ie n .SS "$s\->fastadd_segment($start, $is_sparse, @dat)" +.el .SS "\f(CW$s\fP\->fastadd_segment($start, \f(CW$is_sparse\fP, \f(CW@dat\fP)" +.IX Subsection "$s->fastadd_segment($start, $is_sparse, @dat)" +Creates a new segment and adds it to the array assuming no overlap between +the new segment and any others in the array. \f(CW$is_sparse\fR indicates whether the +passed in array contains \f(CW\*(C`undef\*(C'\fRs or not. If false no checking is done (which +is faster, but riskier). If equal to 2 then 0 is considered undef as well. +.PP +Returns the number of segments inserted. +.ie n .SS "$s\->add_segment($start, $overwrite, @dat)" +.el .SS "\f(CW$s\fP\->add_segment($start, \f(CW$overwrite\fP, \f(CW@dat\fP)" +.IX Subsection "$s->add_segment($start, $overwrite, @dat)" +Creates a new segment and adds it to the array allowing for possible overlaps +between the new segment and the existing ones. In the case of overlaps, elements +from the new segment are deleted unless \f(CW$overwrite\fR is set in which case the +elements already there are over-written. +.PP +This method also checks the data coming in to see if it is sparse (i.e. contains +undef values). Gaps cause new segments to be created or not to over-write existing +values. +.ie n .SS "$s\->tidy" +.el .SS "\f(CW$s\fP\->tidy" +.IX Subsection "$s->tidy" +Merges any immediately adjacent segments +.ie n .SS "$s\->at($addr, [$len])" +.el .SS "\f(CW$s\fP\->at($addr, [$len])" +.IX Subsection "$s->at($addr, [$len])" +Looks up the data held at the given address by locating the appropriate segment +etc. If \f(CW$len\fR > 1 then returns an array of values, spaces being filled with undef. +.ie n .SS "$s\->remove($addr, [$len])" +.el .SS "\f(CW$s\fP\->remove($addr, [$len])" +.IX Subsection "$s->remove($addr, [$len])" +Removes the item or items from addr returning them as an array or the first +value in a scalar context. This is very like \f(CW\*(C`at\*(C'\fR, including padding with +undef, but it deletes stuff as it goes. +.ie n .SS "$s\->copy" +.el .SS "\f(CW$s\fP\->copy" +.IX Subsection "$s->copy" +Deep copies this array +.ie n .SS "$s\->copy_seg($seg)" +.el .SS "\f(CW$s\fP\->copy_seg($seg)" +.IX Subsection "$s->copy_seg($seg)" +Creates a deep copy of a segment +.SH "BUGS" +.IX Header "BUGS" +No known bugs. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Silf.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Silf.3pm" new file mode 100644 index 0000000000..1649a96526 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Silf.3pm" @@ -0,0 +1,319 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Silf 3pm" +.TH Font::TTF::Silf 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Silf \- The main Graphite table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The Silf table holds the core of the Graphite rules for a font. A Silf table has +potentially multiple silf subtables, although there is usually only one. Within a silf subtable, +there are a number of passes which contain the actual finite state machines to match rules +and the constraint and action code to be executed when a rule matches. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "Version" 4 +.IX Item "Version" +Silf table format version +.IP "Compiler" 4 +.IX Item "Compiler" +Lowest compiler version necessary to fully support the semantics expressed in this +Graphite description +.IP "\s-1SILF\s0" 4 +.IX Item "SILF" +An array of Silf subtables +.RS 4 +.IP "maxGlyphID" 4 +.IX Item "maxGlyphID" +The maximum glyph id referenced including pseudo and non glyphs +.IP "Ascent" 4 +.IX Item "Ascent" +Extra ascent to be added to the font ascent. +.IP "Descent" 4 +.IX Item "Descent" +Extra descent to be added to the font descent. Both values are assumed to be +positive for a descender below the base line. +.IP "substPass" 4 +.IX Item "substPass" +Pass index into \s-1PASS\s0 of the first substitution pass. +.IP "posPass" 4 +.IX Item "posPass" +Pass index into \s-1PASS\s0 of the first positioning pass. +.IP "justPass" 4 +.IX Item "justPass" +Pass index into \s-1PASS\s0 of the first justification pass. +.IP "bidiPass" 4 +.IX Item "bidiPass" +Pass index of the pass before which the bidirectional processing pass will be executed. +0xFF indicates that there is no bidi pass to be executed. +.IP "Flags" 4 +.IX Item "Flags" +A bitfield of flags: +.Sp +.Vb 1 +\& 0 \- Indicates there are line end contextual rules in one of the passes +.Ve +.IP "maxPreContext" 4 +.IX Item "maxPreContext" +Maximum length of a context preceding a cross line boundary contextualisation. +.IP "maxPostContext" 4 +.IX Item "maxPostContext" +Maximum length of a context following a cross line boundary contextualsation. +.IP "attrPseudo" 4 +.IX Item "attrPseudo" +Glyph attribute for the actual glyph id associated with a pseudo glyph. +.IP "attrBreakWeight" 4 +.IX Item "attrBreakWeight" +Glyph attribute number of the attribute holding the default breakweight associated with a glyph. +.IP "attrDirectionality" 4 +.IX Item "attrDirectionality" +Glyph attribute number of the attribute holding the default directionality value associated with a glyph. +.IP "\s-1JUST\s0" 4 +.IX Item "JUST" +The may be a number of justification levels each with their own property values. +This points to an array of hashes, one for each justification level. +.RS 4 +.IP "attrStretch" 4 +.IX Item "attrStretch" +Glyph attribute number for the amount of stretch allowed before this glyph. +.IP "attrShrink" 4 +.IX Item "attrShrink" +Glyph attribute number for the amount of shrink allowed before this glyph. +.IP "attrStep" 4 +.IX Item "attrStep" +Glyph attribute number specifying the minimum granularity of actual spacing associated with this glyph at this level. +.IP "attrWeight" 4 +.IX Item "attrWeight" +Glyph attribute number giving the weight associated with spreading space across a run of glyphs. +.IP "runto" 4 +.IX Item "runto" +Which level starts the next stage. +.RE +.RS 4 +.RE +.IP "numLigComp" 4 +.IX Item "numLigComp" +Number of initial glyph attributes that represent ligature components +.IP "numUserAttr" 4 +.IX Item "numUserAttr" +Number of user defined slot attributes referenced. Tells the engine how much space to +allocate to a slot for user attributes. +.IP "maxCompPerLig" 4 +.IX Item "maxCompPerLig" +Maximum number of components per ligature. +.IP "direction" 4 +.IX Item "direction" +Supported directions for this writing system +.IP "\s-1CRIT_FEATURE\s0" 4 +.IX Item "CRIT_FEATURE" +Array of critical features. +.IP "scripts" 4 +.IX Item "scripts" +Array of script tags that indicate which set of \s-1GDL\s0 rules to execute if there is more than one in a font. +.IP "lbGID" 4 +.IX Item "lbGID" +Glyph \s-1ID\s0 of the linebreak pseudo glyph. +.IP "pseudos" 4 +.IX Item "pseudos" +Hash of Unicode values to pseduo glyph ids. +.IP "classes" 4 +.IX Item "classes" +This is an array of classes, each of which is an array of glyph ids in class order. +.IP "\s-1PASS\s0" 4 +.IX Item "PASS" +The details of rules and actions are stored in passes. This value is an array of pass subobjects one for each pass. +.RS 4 +.IP "flags" 4 +.IX Item "flags" +This is a bitfield: +.Sp +.Vb 2 +\& 0 \- If true, this pass makes no change to the slot stream considered as a sequence of glyph ids. +\& Only slot attributes are expected to change (for example during positioning). +.Ve +.IP "maxRuleLoop" 4 +.IX Item "maxRuleLoop" +How many times the engine will allow rules to be tested and run without the engine advancing through the +input slot stream. +.IP "maxRuleContext" 4 +.IX Item "maxRuleContext" +Number of slots of input needed to run this pass. +.IP "maxBackup" 4 +.IX Item "maxBackup" +Number of slots by which the following pass needs to trail this pass (i.e. the maximum this pass is allowed to back up). +.IP "numRules" 4 +.IX Item "numRules" +Number of action code blocks, and so uncompressed rules, in this pass. +.IP "numRows" 4 +.IX Item "numRows" +Number of rows in the finite state machine. +.IP "numTransitional" 4 +.IX Item "numTransitional" +Number of rows in the finite state machine that are not final states. This specifies the number of rows in the fsm +element. +.IP "numSuccess" 4 +.IX Item "numSuccess" +Number of success states. A success state may also be a transitional state. +.IP "numColumns" 4 +.IX Item "numColumns" +Number of columns in the finite state machine. +.IP "colmap" 4 +.IX Item "colmap" +A hash, indexed by glyphid, that gives the fsm column number associated with that glyphid. If not present, then +the glyphid is not part of the fsm and will finish fsm processing if it occurs. +.IP "rulemap" 4 +.IX Item "rulemap" +An array of arrays, one for each success state. Each array holds a list of rule numbers associated with that state. +.IP "minRulePreContext" 4 +.IX Item "minRulePreContext" +Minimum number of items in a rule's precontext. +.IP "maxRulePreContext" 4 +.IX Item "maxRulePreContext" +The maximum number of items in any rule's precontext. +.IP "startStates" 4 +.IX Item "startStates" +Array of starting state numbers dependeing on the length of actual precontext. +There are maxRulePreContext \- minRulePreContext + 1 of these. +.IP "ruleSortKeys" 4 +.IX Item "ruleSortKeys" +An array of sort keys one for each rule giving the length of the rule including its precontext. +.IP "rulePreContexts" 4 +.IX Item "rulePreContexts" +An array of precontext lengths for each rule. +.IP "fsm" 4 +.IX Item "fsm" +A two dimensional array such that \f(CW$p\fR\->{'fsm'}[$row][$col] gives the row of the next node to try in the fsm. +.IP "passConstraintLen" 4 +.IX Item "passConstraintLen" +Length in bytes of the passConstraint code. +.IP "passConstraintCode" 4 +.IX Item "passConstraintCode" +A byte string holding the pass constraint code. +.IP "constraintCode" 4 +.IX Item "constraintCode" +An array of byte strings holding the constraint code for each rule. +.IP "actionCode" 4 +.IX Item "actionCode" +An array of byte strings holding the action code for each rule. +.RE +.RS 4 +.RE +.RE +.RS 4 +.RE +.ie n .SS "@opcodes" +.el .SS "\f(CW@opcodes\fP" +.IX Subsection "@opcodes" +Each array holds the name of the opcode, the number of operand bytes and a string describing the operands. +The characters in the string have the following meaning: +.PP +.Vb 10 +\& c \- lsb of class id +\& C \- msb of class id +\& f \- feature index +\& g \- lsb of glyph attribute id +\& G \- msb of glyph attribute id +\& l \- lsb of a 32\-bit extension to a 16\-bit number +\& L \- msb of a 32\-bit number +\& m \- glyph metric id +\& n \- lsb of a number +\& N \- msb of a 16\-bit number +\& o \- offset (jump) +\& s \- slot reference +\& S \- slot attribute id +\& v \- variable number of following arguments +.Ve +.SS "read" +.IX Subsection "read" +Reads the Silf table into the internal data structure +.SS "out" +.IX Subsection "out" +Outputs a Silf data structure to a font file in binary format +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Sill.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Sill.3pm" new file mode 100644 index 0000000000..a0995ee430 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Sill.3pm" @@ -0,0 +1,109 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Sill 3pm" +.TH Font::TTF::Sill 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Sill \- Graphite language mapping table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.IP "version" 4 +.IX Item "version" +Table version number. +.IP "langs" 4 +.IX Item "langs" +Contains a hash where the key is the language id and the value is an array of +language records +.SS "Language Records" +.IX Subsection "Language Records" +Each language record is itself an array of two values [fid, val]. fid is the +feature id and is held as a long. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Table.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Table.3pm" new file mode 100644 index 0000000000..81df96a87d --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Table.3pm" @@ -0,0 +1,217 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Table 3pm" +.TH Font::TTF::Table 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Table \- Superclass for tables and used for tables we don't have a class for +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Looks after the purely table aspects of a \s-1TTF\s0 table, such as whether the table +has been read before, locating the file pointer, etc. Also copies tables from +input to output. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +Instance variables start with a space +.IP "read" 4 +.IX Item "read" +Flag which indicates that the table has already been read from file. +.IP "dat" 4 +.IX Item "dat" +Allows the creation of unspecific tables. Data is simply output to any font +file being created. +.IP "nocompress" 4 +.IX Item "nocompress" +If set, overrides the font default for \s-1WOFF\s0 table compression. Is a scalar integer specifying a +table size threshold below which this table will not be compressed. Set to \-1 to never +compress; 0 to always compress. +.IP "\s-1INFILE\s0" 4 +.IX Item "INFILE" +The read file handle +.IP "\s-1OFFSET\s0" 4 +.IX Item "OFFSET" +Location of the file in the input file +.IP "\s-1LENGTH\s0" 4 +.IX Item "LENGTH" +Length in the input directory +.IP "\s-1ZLENGTH\s0" 4 +.IX Item "ZLENGTH" +Compressed length of the table if a \s-1WOFF\s0 font. 0 < \s-1ZLENGTH\s0 < \s-1LENGTH\s0 implies table is compressed. +.IP "\s-1CSUM\s0" 4 +.IX Item "CSUM" +Checksum read from the input file's directory +.IP "\s-1PARENT\s0" 4 +.IX Item "PARENT" +The Font::TTF::Font that table is part of +.SH "METHODS" +.IX Header "METHODS" +.SS "Font::TTF::Table\->new(%parms)" +.IX Subsection "Font::TTF::Table->new(%parms)" +Creates a new table or subclass. Table instance variables are passed in +at this point as an associative array. +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table from the input file. Acts as a superclass to all true tables. +This method marks the table as read and then just sets the input file pointer +but does not read any data. If the table has already been read, then returns +\&\f(CW\*(C`undef\*(C'\fR else returns \f(CW$self\fR +.PP +For WOFF-compressed tables, the table is first decompressed and a +replacement file handle is created for reading the decompressed data. In this +case \s-1ORIGINALOFFSET\s0 will preserve the original value of \s-1OFFSET\s0 for +applications that care. +.ie n .SS "$t\->read_dat" +.el .SS "\f(CW$t\fP\->read_dat" +.IX Subsection "$t->read_dat" +Reads the table into the \f(CW\*(C`dat\*(C'\fR instance variable for those tables which don't +know any better +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes out the table to the font file. If there is anything in the +\&\f(CW\*(C`dat\*(C'\fR instance variable then this is output, otherwise the data is copied +from the input file to the output +.ie n .SS "$t\->out_xml($context)" +.el .SS "\f(CW$t\fP\->out_xml($context)" +.IX Subsection "$t->out_xml($context)" +Outputs this table in \s-1XML\s0 format. The table is first read (if not already read) and then if +there is no subclass, then the data is dumped as hex data +.ie n .SS "$t\->XML_element" +.el .SS "\f(CW$t\fP\->XML_element" +.IX Subsection "$t->XML_element" +Output a particular element based on its contents. +.ie n .SS "$t\->XML_end($context, $tag, %attrs)" +.el .SS "\f(CW$t\fP\->XML_end($context, \f(CW$tag\fP, \f(CW%attrs\fP)" +.IX Subsection "$t->XML_end($context, $tag, %attrs)" +Handles the default type of for those tables which aren't subclassed +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->dirty($val)" +.el .SS "\f(CW$t\fP\->dirty($val)" +.IX Subsection "$t->dirty($val)" +This sets the dirty flag to the given value or 1 if no given value. It returns the +value of the flag +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Each table knows how to update itself. This consists of doing whatever work +is required to ensure that the memory version of the table is consistent +and that other parameters in other tables have been updated accordingly. +I.e. by the end of sending \f(CW\*(C`update\*(C'\fR to all the tables, the memory version +of the font should be entirely consistent. +.PP +Some tables which do no work indicate to themselves the need to update +themselves by setting isDirty above 1. This method resets that accordingly. +.ie n .SS "$t\->empty" +.el .SS "\f(CW$t\fP\->empty" +.IX Subsection "$t->empty" +Clears a table of all data to the level of not having been read +.ie n .SS "$t\->release" +.el .SS "\f(CW$t\fP\->release" +.IX Subsection "$t->release" +Releases \s-1ALL\s0 of the memory used by this table, and all of its component/child +objects. This method is called automatically by +\&'Font::TTF::Font\->release' (so you don't have to call it yourself). +.PP +\&\fB\s-1NOTE\s0\fR, that it is important that this method get called at some point prior +to the actual destruction of the object. Internally, we track things in a +structure that can result in circular references, and without calling +\&'\f(CW\*(C`release()\*(C'\fR' these will not properly get cleaned up by Perl. Once this +method has been called, though, don't expect to be able to do anything with the +\&\f(CW\*(C`Font::TTF::Table\*(C'\fR object; it'll have \fBno\fR internal state whatsoever. +.PP +\&\fBDeveloper note:\fR As part of the brute-force cleanup done here, this method +will throw a warning message whenever unexpected key values are found within +the \f(CW\*(C`Font::TTF::Table\*(C'\fR object. This is done to help ensure that any +unexpected and unfreed values are brought to your attention so that you can bug +us to keep the module updated properly; otherwise the potential for memory +leaks due to dangling circular references will exist. +.SH "BUGS" +.IX Header "BUGS" +No known bugs +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Ttc.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Ttc.3pm" new file mode 100644 index 0000000000..ca778b3863 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Ttc.3pm" @@ -0,0 +1,141 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Ttc 3pm" +.TH Font::TTF::Ttc 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Ttc \- Truetype Collection class +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +A TrueType collection is a collection of TrueType fonts in one file in which +tables may be shared between different directories. In order to support this, +the \s-1TTC\s0 introduces the concept of a table being shared by different TrueType +fonts. This begs the question of what should happen to the ' \s-1PARENT\s0' property +of a particular table. It is made to point to the first directory object which +refers to it. It is therefore up to the application to sort out any confusion. +Confusion only occurs if shared tables require access to non-shared tables. +This should not happen since the shared tables are dealing with glyph +information only and the private tables are dealing with encoding and glyph +identification. Thus the general direction is from identification to glyph and +not the other way around (at least not without knowledge of the particular +context). +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The following instance variables are preceded by a space +.IP "fname (P)" 4 +.IX Item "fname (P)" +Filename for this TrueType Collection +.IP "\s-1INFILE\s0 (P)" 4 +.IX Item "INFILE (P)" +The filehandle of this collection +.PP +The following instance variable does not start with a space +.IP "directs" 4 +.IX Item "directs" +An array of directories (Font::TTF::Font objects) for each sub-font in the directory +.SH "METHODS" +.IX Header "METHODS" +.SS "Font::TTF::Ttc\->open($fname)" +.IX Subsection "Font::TTF::Ttc->open($fname)" +Opens and reads the given filename as a TrueType Collection. Reading a collection +involves reading each of the directories which go to make up the collection. +.ie n .SS "$c\->read" +.el .SS "\f(CW$c\fP\->read" +.IX Subsection "$c->read" +Reads a Collection by reading all the directories in the collection +.ie n .SS "$c\->find($direct, $name, $check, $off, $len)" +.el .SS "\f(CW$c\fP\->find($direct, \f(CW$name\fP, \f(CW$check\fP, \f(CW$off\fP, \f(CW$len\fP)" +.IX Subsection "$c->find($direct, $name, $check, $off, $len)" +Hunts around to see if a table with the given characteristics of name, checksum, +offset and length has been associated with a directory earlier in the list. +Actually on checks the offset since no two tables can share the same offset in +a TrueType font, collection or otherwise. +.ie n .SS "$c\->\s-1DESTROY\s0" +.el .SS "\f(CW$c\fP\->\s-1DESTROY\s0" +.IX Subsection "$c->DESTROY" +Closees any opened files by us +.SH "BUGS" +.IX Header "BUGS" +No known bugs, but then not ever executed! +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Ttopen.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Ttopen.3pm" new file mode 100644 index 0000000000..52c5d15a9d --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Ttopen.3pm" @@ -0,0 +1,422 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Ttopen 3pm" +.TH Font::TTF::Ttopen 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Ttopen \- Opentype superclass for standard Opentype lookup based tables +(GSUB and GPOS) +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Handles all the script, lang, feature, lookup stuff for a +Font::TTF::Gsub/Font::TTF::Gpos table leaving the class specifics to the +subclass +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The instance variables of an opentype table form a complex sub-module hierarchy. +.IP "Version" 4 +.IX Item "Version" +This contains the version of the table as a floating point number +.IP "\s-1SCRIPTS\s0" 4 +.IX Item "SCRIPTS" +The scripts list is a hash of script tags. Each script tag (of the form +\&\f(CW$t\fR\->{'\s-1SCRIPTS\s0'}{$tag}) has information below it. +.RS 4 +.IP "\s-1OFFSET\s0" 8 +.IX Item "OFFSET" +This variable is preceded by a space and gives the offset from the start of the +table (not the table section) to the script table for this script +.IP "\s-1REFTAG\s0" 8 +.IX Item "REFTAG" +This variable is preceded by a space and gives a corresponding script tag to this +one such that the offsets in the file are the same. When writing, it is up to the +caller to ensure that the REFTAGs are set correctly, since these will be used to +assume that the scripts are identical. Note that \s-1REFTAG\s0 must refer to a script which +has no \s-1REFTAG\s0 of its own. +.IP "\s-1DEFAULT\s0" 8 +.IX Item "DEFAULT" +This corresponds to the default language for this script, if there is one, and +contains the same information as an itemised language +.IP "\s-1LANG_TAGS\s0" 8 +.IX Item "LANG_TAGS" +This contains an array of language tag strings (each 4 bytes) corresponding to +the languages listed by this script +.ie n .IP "$lang" 8 +.el .IP "\f(CW$lang\fR" 8 +.IX Item "$lang" +Each language is a hash containing its information: +.RS 8 +.IP "\s-1OFFSET\s0" 12 +.IX Item "OFFSET" +This variable is preceded by a a space and gives the offset from the start of +the whole table to the language table for this language +.IP "\s-1REFTAG\s0" 12 +.IX Item "REFTAG" +This variable is preceded by a space and has the same function as for the script +\&\s-1REFTAG,\s0 only for the languages within a script. +.IP "RE-ORDER" 12 +.IX Item "RE-ORDER" +This indicates re-ordering information, and has not been set. The value should +always be 0. +.IP "\s-1DEFAULT\s0" 12 +.IX Item "DEFAULT" +This holds the index of the default feature, if there is one, or \-1 otherwise. +.IP "\s-1FEATURES\s0" 12 +.IX Item "FEATURES" +This is an array of feature tags for all the features enabled for this language +.RE +.RS 8 +.RE +.RE +.RS 4 +.RE +.IP "\s-1FEATURES\s0" 4 +.IX Item "FEATURES" +The features section of instance variables corresponds to the feature table in +the opentype table. +.RS 4 +.IP "\s-1FEAT_TAGS\s0" 8 +.IX Item "FEAT_TAGS" +This array gives the ordered list of feature tags for this table. It is used during +reading and writing for converting between feature index and feature tag. +.RE +.RS 4 +.Sp +The rest of the \s-1FEATURES\s0 variable is itself a hash based on the feature tag for +each feature. Each feature has the following structure: +.IP "\s-1OFFSET\s0" 8 +.IX Item "OFFSET" +This attribute is preceded by a space and gives the offset relative to the start of the whole +table of this particular feature. +.IP "\s-1PARMS\s0" 8 +.IX Item "PARMS" +If FeatureParams are defined for this feature, this contains a reference to the corresponding FeatureParams object. Otherwise set to null. +.IP "\s-1LOOKUPS\s0" 8 +.IX Item "LOOKUPS" +This is an array containing indices to lookups in the \s-1LOOKUP\s0 instance variable of the table +.IP "\s-1INDEX\s0" 8 +.IX Item "INDEX" +This gives the feature index for this feature and is used during reading and writing for +converting between feature tag and feature index. +.RE +.RS 4 +.RE +.IP "\s-1LOOKUP\s0" 4 +.IX Item "LOOKUP" +This variable is an array of lookups in order and is indexed via the features of a language of a +script. Each lookup contains subtables and other information: +.RS 4 +.IP "\s-1OFFSET\s0" 8 +.IX Item "OFFSET" +This name is preceded by a space and contains the offset from the start of the table to this +particular lookup +.IP "\s-1TYPE\s0" 8 +.IX Item "TYPE" +This is a subclass specific type for a lookup. It stipulates the type of lookup and hence subtables +within the lookup +.IP "\s-1FLAG\s0" 8 +.IX Item "FLAG" +Holds the lookup flag bits +.IP "\s-1FILTER\s0" 8 +.IX Item "FILTER" +Holds the MarkFilteringSet (that is, the index into \s-1GDEF\-\s0>\s-1MARKSETS\s0) for the lookup. +.IP "\s-1SUB\s0" 8 +.IX Item "SUB" +This holds an array of subtables which are subclass specific. Each subtable must have +an \s-1OFFSET.\s0 The other variables described here are an abstraction used in both the +\&\s-1GSUB\s0 and \s-1GPOS\s0 tables which are the target subclasses of this class. +.RS 8 +.IP "\s-1OFFSET\s0" 12 +.IX Item "OFFSET" +This is preceded by a space and gives the offset relative to the start of the table for this +subtable +.IP "\s-1FORMAT\s0" 12 +.IX Item "FORMAT" +Gives the sub-table sub format for this \s-1GSUB\s0 subtable. It is assumed that this +value is correct when it comes time to write the subtable. +.IP "\s-1COVERAGE\s0" 12 +.IX Item "COVERAGE" +Most lookups consist of a coverage table corresponding to the first +glyph to match. The offset of this coverage table is stored here and the coverage +table looked up against the \s-1GSUB\s0 table proper. There are two lookups +without this initial coverage table which is used to index into the \s-1RULES\s0 array. +These lookups have one element in the \s-1RULES\s0 array which is used for the whole +match. +.IP "\s-1RULES\s0" 12 +.IX Item "RULES" +The rules are a complex array. In most cases, each element of the array +corresponds to an element in the coverage table (governed by the coverage index). +In a few caess, such as when there is +no coverage table, then there is considered to be only one element in the rules +array. Each element of the array is itself an array corresponding to the +possibly multiple string matches which may follow the initial glyph. Each +element of this array is a hash with fixed keys corresponding to information +needed to match a glyph string or act upon it. Thus the \s-1RULES\s0 element is an +array of arrays of hashes which contain the following keys: +.RS 12 +.IP "\s-1MATCH\s0" 16 +.IX Item "MATCH" +This contains a sequence of elements held as an array. The elements may be +glyph ids (gid), class ids (cids), or offsets to coverage tables. Each element +corresponds to one glyph in the glyph string. See \s-1MATCH_TYPE\s0 for details of +how the different element types are marked. +.IP "\s-1PRE\s0" 16 +.IX Item "PRE" +This array holds the sequence of elements preceding the first match element +and has the same form as the \s-1MATCH\s0 array. +.IP "\s-1POST\s0" 16 +.IX Item "POST" +This array holds the sequence of elements to be tested for following the match +string and is of the same form as the \s-1MATCH\s0 array. +.IP "\s-1ACTION\s0" 16 +.IX Item "ACTION" +This array holds information regarding what should be done if a match is found. +The array may either hold glyph ids (which are used to replace or insert or +whatever glyphs in the glyph string) or 2 element arrays consisting of: +.RS 16 +.IP "\s-1OFFSET\s0" 20 +.IX Item "OFFSET" +Offset from the start of the matched string that the lookup should start at +when processing the substring. +.IP "\s-1LOOKUP_INDEX\s0" 20 +.IX Item "LOOKUP_INDEX" +The index to a lookup to be acted upon on the match string. +.RE +.RS 16 +.RE +.RE +.RS 12 +.RE +.IP "\s-1CLASS\s0" 12 +.IX Item "CLASS" +For those lookups which use class categories rather than glyph ids for matching +this is the offset to the class definition used to categories glyphs in the +match string. +.IP "\s-1PRE_CLASS\s0" 12 +.IX Item "PRE_CLASS" +This is the offset to the class definition for the before match glyphs +.IP "\s-1POST_CLASS\s0" 12 +.IX Item "POST_CLASS" +This is the offset to the class definition for the after match glyphs. +.IP "\s-1ACTION_TYPE\s0" 12 +.IX Item "ACTION_TYPE" +This string holds the type of information held in the \s-1ACTION\s0 variable of a \s-1RULE.\s0 +It is subclass specific. +.IP "\s-1MATCH_TYPE\s0" 12 +.IX Item "MATCH_TYPE" +This holds the type of information in the \s-1MATCH\s0 array of a \s-1RULE.\s0 This is subclass +specific. +.IP "\s-1ADJUST\s0" 12 +.IX Item "ADJUST" +This corresponds to a single action for all items in a coverage table. The meaning +is subclass specific. +.IP "\s-1CACHE\s0" 12 +.IX Item "CACHE" +This key starts with a space +.Sp +A hash of other tables (such as coverage tables, classes, anchors, device tables) +based on the offset given in the subtable to that other information. +Note that the documentation is particularly +unhelpful here in that such tables are given as offsets relative to the +beginning of the subtable not the whole \s-1GSUB\s0 table. This includes those items which +are stored relative to another base within the subtable. +.RE +.RS 8 +.RE +.RE +.RS 4 +.RE +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table passing control to the subclass to handle the subtable specifics +.ie n .SS "$t\->read_sub($fh, $lookup, $index)" +.el .SS "\f(CW$t\fP\->read_sub($fh, \f(CW$lookup\fP, \f(CW$index\fP)" +.IX Subsection "$t->read_sub($fh, $lookup, $index)" +This stub is to allow subclasses to read subtables of lookups in a table specific manner. A +reference to the lookup is passed in along with the subtable index. The file is located at the +start of the subtable to be read +.ie n .SS "$t\->\fBextension()\fP" +.el .SS "\f(CW$t\fP\->\fBextension()\fP" +.IX Subsection "$t->extension()" +Returns the lookup number for the extension table that allows access to 32\-bit offsets. +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes this Opentype table to the output calling \f(CW$t\fR\->out_sub for each sub table +at the appropriate point in the output. The assumption is that on entry the +number of scripts, languages, features, lookups, etc. are all resolved and +the relationships fixed. This includes a \s-1LANG_TAGS\s0 list for a script, and that all +scripts and languages in their respective dictionaries either have a \s-1REFTAG\s0 or contain +real data. +.ie n .SS "$t\->num_sub($lookup)" +.el .SS "\f(CW$t\fP\->num_sub($lookup)" +.IX Subsection "$t->num_sub($lookup)" +Asks the subclass to count the number of subtables for a particular lookup and to +return that value. Used in \fBout()\fR. +.ie n .SS "$t\->out_sub($fh, $lookup, $index)" +.el .SS "\f(CW$t\fP\->out_sub($fh, \f(CW$lookup\fP, \f(CW$index\fP)" +.IX Subsection "$t->out_sub($fh, $lookup, $index)" +This stub is to allow subclasses to output subtables of lookups in a table specific manner. A +reference to the lookup is passed in along with the subtable index. The file is located at the +start of the subtable to be output +.ie n .SS "$t\->dirty" +.el .SS "\f(CW$t\fP\->dirty" +.IX Subsection "$t->dirty" +Setting \s-1GPOS\s0 or \s-1GSUB\s0 dirty means that \s-1OS/2\s0 may need updating, so set it dirty. +.ie n .SS "$t\->maxContext" +.el .SS "\f(CW$t\fP\->maxContext" +.IX Subsection "$t->maxContext" +Returns the length of the longest opentype rule in this table. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Perform various housekeeping items: +.PP +For all lookups, set/clear 0x0010 bit of flag words based on '\s-1FILTER\s0' value. +.PP +Sort \s-1COVERAGE\s0 table and \s-1RULES\s0 for all lookups. +.PP +Unless \f(CW$t\fR\->{' \s-1PARENT\s0'}{' noharmony'} is true, update will make sure that \s-1GPOS\s0 and \s-1GSUB\s0 include +the same scripts and languages. Any added scripts and languages will have empty feature sets. +.SH "Internal Functions & Methods" +.IX Header "Internal Functions & Methods" +Most of these methods are used by subclasses for handling such things as coverage +tables. +.SS "copy($ref)" +.IX Subsection "copy($ref)" +Internal function to copy the top level of a dictionary to create a new dictionary. +Only the top level is copied. +.ie n .SS "$t\->read_cover($cover_offset, $lookup_loc, $lookup, $fh, $is_cover)" +.el .SS "\f(CW$t\fP\->read_cover($cover_offset, \f(CW$lookup_loc\fP, \f(CW$lookup\fP, \f(CW$fh\fP, \f(CW$is_cover\fP)" +.IX Subsection "$t->read_cover($cover_offset, $lookup_loc, $lookup, $fh, $is_cover)" +Reads a coverage table and stores the results in \f(CW$lookup\fR\->{' \s-1CACHE\s0'}, that is, if +it has not been read already. +.ie n .SS "ref_cache($obj, $cache, $offset [, $template])" +.el .SS "ref_cache($obj, \f(CW$cache\fP, \f(CW$offset\fP [, \f(CW$template\fP])" +.IX Subsection "ref_cache($obj, $cache, $offset [, $template])" +Internal function to keep track of the local positioning of subobjects such as +coverage and class definition tables, and their offsets. +What happens is that the cache is a hash of +sub objects indexed by the reference (using a string mashing of the +reference name which is valid for the duration of the reference) and holds a +list of locations in the output string which should be filled in with the +offset to the sub object when the final string is output in out_final. +.PP +Uses tricks for Tie::Refhash +.ie n .SS "out_final($fh, $out, $cache_list, $state)" +.el .SS "out_final($fh, \f(CW$out\fP, \f(CW$cache_list\fP, \f(CW$state\fP)" +.IX Subsection "out_final($fh, $out, $cache_list, $state)" +Internal function to actually output everything to the file handle given that +now we know the offset to the first sub object to be output and which sub objects +are to be output and what locations need to be updated, we can now +generate everything. \f(CW$cache_list\fR is an array of two element arrays. The first element +is a cache object, the second is an offset to be subtracted from each reference +to that object made in the cache. +.PP +If \f(CW$state\fR is 1, then the output is not sent to the filehandle and the return value +is the string to be output. If \f(CW$state\fR is absent or 0 then output is not limited +by storing in a string first and the return value is ""; +.ie n .SS "$self\->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc)" +.el .SS "\f(CW$self\fP\->read_context($lookup, \f(CW$fh\fP, \f(CW$type\fP, \f(CW$fmt\fP, \f(CW$cover\fP, \f(CW$count\fP, \f(CW$loc\fP)" +.IX Subsection "$self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc)" +Internal method to read context (simple and chaining context) lookup subtables for +the \s-1GSUB\s0 and \s-1GPOS\s0 table types. The assumed values for \f(CW$type\fR correspond to those +for \s-1GSUB,\s0 so \s-1GPOS\s0 should adjust the values upon calling. +.ie n .SS "$self\->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num)" +.el .SS "\f(CW$self\fP\->out_context($lookup, \f(CW$fh\fP, \f(CW$type\fP, \f(CW$fmt\fP, \f(CW$ctables\fP, \f(CW$out\fP, \f(CW$num\fP)" +.IX Subsection "$self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num)" +Provides shared behaviour between \s-1GSUB\s0 and \s-1GPOS\s0 tables during output for context +(chained and simple) rules. In addition, support is provided here for type 4 \s-1GSUB\s0 +tables, which are not used in \s-1GPOS.\s0 The value for \f(CW$type\fR corresponds to the type +in a \s-1GSUB\s0 table so calling from \s-1GPOS\s0 should adjust the value accordingly. +.SH "BUGS" +.IX Header "BUGS" +.IP "\(bu" 4 +No way to share cachable items (coverage tables, classes, anchors, device tables) +across different lookups. The items are always output after the lookup and +repeated if necessary. Within lookup sharing is possible. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Useall.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Useall.3pm" new file mode 100644 index 0000000000..63497aba05 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Useall.3pm" @@ -0,0 +1,98 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Useall 3pm" +.TH Font::TTF::Useall 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Useall \- shortcut to 'use' all the Font::TTF modules +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use Font::TTF::Useall; +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Useful for debugging, this module simply does a 'use' on all the other +modules that are part of Font::TTF. +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Utils.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Utils.3pm" new file mode 100644 index 0000000000..6a8118d54e --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Utils.3pm" @@ -0,0 +1,200 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Utils 3pm" +.TH Font::TTF::Utils 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Utils \- Utility functions to save fingers +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Lots of useful functions to save my fingers, especially for trivial tables +.SH "FUNCTIONS" +.IX Header "FUNCTIONS" +The following functions are exported +.ie n .SS "($val, $pos) = TTF_Init_Fields ($str, $pos)" +.el .SS "($val, \f(CW$pos\fP) = TTF_Init_Fields ($str, \f(CW$pos\fP)" +.IX Subsection "($val, $pos) = TTF_Init_Fields ($str, $pos)" +Given a field description from the \f(CW\*(C`DATA\*(C'\fR section, creates an absolute entry +in the fields associative array for the class +.ie n .SS "TTF_Read_Fields($obj, $dat, $fields)" +.el .SS "TTF_Read_Fields($obj, \f(CW$dat\fP, \f(CW$fields\fP)" +.IX Subsection "TTF_Read_Fields($obj, $dat, $fields)" +Given a block of data large enough to account for all the fields in a table, +processes the data block to convert to the values in the objects instance +variables by name based on the list in the \f(CW\*(C`DATA\*(C'\fR block which has been run +through \f(CW\*(C`TTF_Init_Fields\*(C'\fR +.ie n .SS "TTF_Unpack($fmt, $dat)" +.el .SS "TTF_Unpack($fmt, \f(CW$dat\fP)" +.IX Subsection "TTF_Unpack($fmt, $dat)" +A TrueType types equivalent of Perls \f(CW\*(C`unpack\*(C'\fR function. Thus \f(CW$fmt\fR consists of +type followed by an optional number of elements to read including *. The type +may be one of: +.PP +.Vb 9 +\& c BYTE +\& C CHAR +\& f FIXED +\& F F2DOT14 +\& l LONG +\& L ULONG +\& s SHORT +\& S USHORT +\& v Version number (FIXED) +.Ve +.PP +Note that \f(CW\*(C`FUNIT\*(C'\fR, \f(CW\*(C`FWORD\*(C'\fR and \f(CW\*(C`UFWORD\*(C'\fR are not data types but units. +.PP +Returns array of scalar (first element) depending on context +.ie n .SS "$dat = TTF_Out_Fields($obj, $fields, $len)" +.el .SS "\f(CW$dat\fP = TTF_Out_Fields($obj, \f(CW$fields\fP, \f(CW$len\fP)" +.IX Subsection "$dat = TTF_Out_Fields($obj, $fields, $len)" +Given the fields table from \f(CW\*(C`TTF_Init_Fields\*(C'\fR writes out the instance variables from +the object to the filehandle in \s-1TTF\s0 binary form. +.ie n .SS "$dat = TTF_Pack($fmt, @data)" +.el .SS "\f(CW$dat\fP = TTF_Pack($fmt, \f(CW@data\fP)" +.IX Subsection "$dat = TTF_Pack($fmt, @data)" +The TrueType equivalent to Perl's \f(CW\*(C`pack\*(C'\fR function. See details of \f(CW\*(C`TTF_Unpack\*(C'\fR +for how to work the \f(CW$fmt\fR string. +.ie n .SS "($num, $range, $select, $shift) = TTF_bininfo($num)" +.el .SS "($num, \f(CW$range\fP, \f(CW$select\fP, \f(CW$shift\fP) = TTF_bininfo($num)" +.IX Subsection "($num, $range, $select, $shift) = TTF_bininfo($num)" +Calculates binary search information from a number of elements +.SS "TTF_word_utf8($str)" +.IX Subsection "TTF_word_utf8($str)" +Returns the \s-1UTF8\s0 form of the 16 bit string, assumed to be in big endian order, +including surrogate handling +.SS "TTF_utf8_word($str)" +.IX Subsection "TTF_utf8_word($str)" +Returns the 16\-bit form in big endian order of the \s-1UTF 8\s0 string, including +surrogate handling to Unicode. +.ie n .SS "XML_hexdump($context, $dat)" +.el .SS "XML_hexdump($context, \f(CW$dat\fP)" +.IX Subsection "XML_hexdump($context, $dat)" +Dumps out the given data as a sequence of blocks each 16 bytes wide +.SS "XML_outhints" +.IX Subsection "XML_outhints" +Converts a binary string of hinting code into a textual representation +.ie n .SS "make_circle($f, $cmap, [$dia, $sb, $opts])" +.el .SS "make_circle($f, \f(CW$cmap\fP, [$dia, \f(CW$sb\fP, \f(CW$opts\fP])" +.IX Subsection "make_circle($f, $cmap, [$dia, $sb, $opts])" +Adds a dotted circle to a font. This function is very configurable. The +parameters passed in are: +.ie n .IP "$f" 4 +.el .IP "\f(CW$f\fR" 4 +.IX Item "$f" +Font to work with. This is required. +.ie n .IP "$cmap" 4 +.el .IP "\f(CW$cmap\fR" 4 +.IX Item "$cmap" +A cmap table (not the 'val' sub-element of a cmap) to add the glyph too. Optional. +.ie n .IP "$dia" 4 +.el .IP "\f(CW$dia\fR" 4 +.IX Item "$dia" +Optional diameter for the main circle. Defaults to 80% em +.ie n .IP "$sb" 4 +.el .IP "\f(CW$sb\fR" 4 +.IX Item "$sb" +Side bearing. The left and right side-bearings are always the same. This value +defaults to 10% em. +.PP +There are various options to control all sorts of interesting aspects of the circle +.IP "numDots" 4 +.IX Item "numDots" +Number of dots in the circle +.IP "numPoints" 4 +.IX Item "numPoints" +Number of curve points to use to create each dot +.IP "uid" 4 +.IX Item "uid" +Unicode reference to store this glyph under in the cmap. Defaults to 0x25CC +.IP "pname" 4 +.IX Item "pname" +Postscript name to give the glyph. Defaults to uni25CC. +.IP "\-dRadius" 4 +.IX Item "-dRadius" +Radius of each dot. +.SH "BUGS" +.IX Header "BUGS" +No known bugs +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Vhea.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Vhea.3pm" new file mode 100644 index 0000000000..f9e3a36737 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Vhea.3pm" @@ -0,0 +1,131 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Vhea 3pm" +.TH Font::TTF::Vhea 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Vhea \- Vertical Header table +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This is a simple table with just standards specified instance variables +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +.Vb 12 +\& version +\& Ascender +\& Descender +\& LineGap +\& advanceHeightMax +\& minTopSideBearing +\& minBottomSideBearing +\& yMaxExtent +\& caretSlopeRise +\& caretSlopeRun +\& metricDataFormat +\& numberOfVMetrics +.Ve +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the table into memory as instance variables +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the table to a file either from memory or by copying. +.ie n .SS "$t\->\fBminsize()\fP" +.el .SS "\f(CW$t\fP\->\fBminsize()\fP" +.IX Subsection "$t->minsize()" +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. +.ie n .SS "$t\->update" +.el .SS "\f(CW$t\fP\->update" +.IX Subsection "$t->update" +Updates various parameters in the hhea table from the hmtx table, assuming +the \f(CW\*(C`hmtx\*(C'\fR table is dirty. +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Vmtx.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Vmtx.3pm" new file mode 100644 index 0000000000..00a8343c63 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Vmtx.3pm" @@ -0,0 +1,119 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Vmtx 3pm" +.TH Font::TTF::Vmtx 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Vmtx \- Vertical Metrics +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Contains the advance height and top side bearing for each glyph. Given the +compressability of the data onto disk, this table uses information from +other tables, and thus must do part of its output during the output of +other tables +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +The vertical metrics are kept in two arrays by glyph id. The variable names +do not start with a space +.IP "advance" 4 +.IX Item "advance" +An array containing the advance height for each glyph +.IP "top" 4 +.IX Item "top" +An array containing the top side bearing for each glyph +.SH "METHODS" +.IX Header "METHODS" +.ie n .SS "$t\->read" +.el .SS "\f(CW$t\fP\->read" +.IX Subsection "$t->read" +Reads the vertical metrics from the \s-1TTF\s0 file into memory +.ie n .SS "$t\->out($fh)" +.el .SS "\f(CW$t\fP\->out($fh)" +.IX Subsection "$t->out($fh)" +Writes the metrics to a \s-1TTF\s0 file. Assumes that the \f(CW\*(C`vhea\*(C'\fR has updated the +numVMetrics from here +.SH "BUGS" +.IX Header "BUGS" +None known +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Win32.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Win32.3pm" new file mode 100644 index 0000000000..f0446154e9 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Win32.3pm" @@ -0,0 +1,87 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Win32 3pm" +.TH Font::TTF::Win32 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff.3pm" new file mode 100644 index 0000000000..963dc7e486 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff.3pm" @@ -0,0 +1,111 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Woff 3pm" +.TH Font::TTF::Woff 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::WOFF \- holds Web Open Font File (WOFF) data for the font +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This contains the \s-1WOFF\s0 packaging data. +.SH "INSTANCE VARIABLES" +.IX Header "INSTANCE VARIABLES" +This object supports the following instance variables (which, because they +reflect the structure of the table, do not begin with a space): +.IP "majorVersion" 4 +.IX Item "majorVersion" +.PD 0 +.IP "minorVersion" 4 +.IX Item "minorVersion" +.PD +The two version integers come directly from the \s-1WOFF\s0 font header. +.IP "metaData" 4 +.IX Item "metaData" +Contains a reference to Font::TTF::Woff::Meta structure, if the font has \s-1WOFF\s0 metadata. +.IP "privateData" 4 +.IX Item "privateData" +Contains a reference to a Font::TTF::Woff::Private structure, if the font has a \s-1WOFF\s0 private data block +.SH "METHODS" +.IX Header "METHODS" +.SH "AUTHOR" +.IX Header "AUTHOR" +Bob Hallissy. . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff\357\200\242\357\200\242MetaData.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff\357\200\242\357\200\242MetaData.3pm" new file mode 100644 index 0000000000..eff2bb5dfc --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff\357\200\242\357\200\242MetaData.3pm" @@ -0,0 +1,92 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Woff::MetaData 3pm" +.TH Font::TTF::Woff::MetaData 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Woff::MetaData \- WOFF metadata +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Currently a stub, thus \fBread()\fR results in \fBread_dat()\fR +.SH "AUTHOR" +.IX Header "AUTHOR" +Bob Hallissy. . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff\357\200\242\357\200\242PrivateData.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff\357\200\242\357\200\242PrivateData.3pm" new file mode 100644 index 0000000000..adf74f3cbe --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242Woff\357\200\242\357\200\242PrivateData.3pm" @@ -0,0 +1,92 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::Woff::PrivateData 3pm" +.TH Font::TTF::Woff::PrivateData 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::Woff::PrivateData \- WOFF Private data +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Currently a stub, thus \fBread()\fR results in \fBread_dat()\fR +.SH "AUTHOR" +.IX Header "AUTHOR" +Bob Hallissy. . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git "a/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242XMLparse.3pm" "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242XMLparse.3pm" new file mode 100644 index 0000000000..84917b1d42 --- /dev/null +++ "b/.cpan/build/Font-TTF-1.06-0/blib/man3/Font\357\200\242\357\200\242TTF\357\200\242\357\200\242XMLparse.3pm" @@ -0,0 +1,171 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "Font::TTF::XMLparse 3pm" +.TH Font::TTF::XMLparse 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Font::TTF::XMLparse \- provides support for XML parsing. Requires Expat module XML::Parser::Expat +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use Font::TTF::Font; +\& use Font::TTF::XMLparse; +\& +\& $f = Font::TTF::Font\->new; +\& read_xml($f, $ARGV[0]); +\& $f\->out($ARGV[1]); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This module contains the support routines for parsing \s-1XML\s0 and generating the +Truetype font structures as a result. The module has been separated from the rest +of the package in order to reduce the dependency that this would bring, of the +whole package on XML::Parser. This way, people without the XML::Parser can still +use the rest of the package. +.PP +The package interacts with another package through the use of a context containing +and element 'receiver' which is an object which can possibly receive one of the +following messages: +.IP "XML_start" 4 +.IX Item "XML_start" +This message is called when an open tag occurs. It is called with the context, +tag name and the attributes. The return value has no meaning. +.IP "XML_end" 4 +.IX Item "XML_end" +This messages is called when a close tag occurs. It is called with the context, +tag name and attributes (held over from when the tag was opened). There are 3 +possible return values from such a message: +.RS 4 +.IP "undef" 8 +.IX Item "undef" +This is the default return value indicating that default processing should +occur in which either the current element on the tree, or the text of this element +should be stored in the parent object. +.ie n .IP "$context" 8 +.el .IP "\f(CW$context\fR" 8 +.IX Item "$context" +This magic value marks that the element should be deleted from the parent. +Nothing is stored in the parent. (This rather than '' is used to allow 0 returns.) +.IP "anything" 8 +.IX Item "anything" +Anything else is taken as the element content to be stored in the parent. +.RE +.RS 4 +.Sp +In addition, the context hash passed to these messages contains the following +keys: +.IP "xml" 4 +.IX Item "xml" +This is the expat xml object. The context is also available as +\&\f(CW$context\fR\->{'xml'}{' mycontext'}. But that is a long winded way of not saying much! +.IP "font" 4 +.IX Item "font" +This is the base object that was passed in for \s-1XML\s0 parsing. +.IP "receiver" 4 +.IX Item "receiver" +This holds the current receiver of parsing events. It may be set in associated +application to adjust which objects should receive messages when. It is also stored +in the parsing stack to ensure that where an object changes it during XML_start, that +that same object that received XML_start will receive the corresponding XML_end +.IP "stack" 4 +.IX Item "stack" +This is the parsing stack, used internally to hold the current receiver and attributes +for each element open, as a complete hierarchy back to the root element. +.IP "tree" 4 +.IX Item "tree" +This element contains the storage tree corresponding to the parent of each element +in the stack. The default action is to push undef onto this stack during XML_start +and then to resolve this, either in the associated application (by changing +\&\f(CW$context\fR\->{'tree'}[\-1]) or during XML_end of a child element, by which time we know +whether we are dealing with an array or a hash or what. +.IP "text" 4 +.IX Item "text" +Character processing is to insert all the characters into the text element of the +context for available use later. +.RE +.RS 4 +.RE +.SH "METHODS" +.IX Header "METHODS" +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/man3/ttfmod.3pm b/.cpan/build/Font-TTF-1.06-0/blib/man3/ttfmod.3pm new file mode 100644 index 0000000000..3d24d674cb --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/blib/man3/ttfmod.3pm @@ -0,0 +1,87 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "ttfmod 3pm" +.TH ttfmod 3pm "2016-08-03" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "AUTHOR" +.IX Header "AUTHOR" +Martin Hosken . +.SH "LICENSING" +.IX Header "LICENSING" +Copyright (c) 1998\-2016, \s-1SIL\s0 International (http://www.sil.org) +.PP +This script is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file \s-1LICENSE.\s0 diff --git a/.cpan/build/Font-TTF-1.06-0/blib/script/.exists b/.cpan/build/Font-TTF-1.06-0/blib/script/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/buildutils/convert_tags.pl b/.cpan/build/Font-TTF-1.06-0/buildutils/convert_tags.pl new file mode 100644 index 0000000000..6aaa953ecf --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/buildutils/convert_tags.pl @@ -0,0 +1,96 @@ +# This utility script interprets a plain-text file that typically is generated by +# cut&paste from the tables contained in the three reference pages of the OpenType Spec: +# Script tags: http://www.microsoft.com/typography/otspec/scripttags.htm +# Langauge tags: http://www.microsoft.com/typography/otspec/languagetags.htm +# Feature tags: http://www.microsoft.com/typography/otspec/featurelist.htm +# Alternatively, input can be VOLT's tags.txt +# Output (to stdout) is in perl syntax for the hash initialization, e.g.: +# "Arabic" => "arab", +# "Armenian" => "armn", +# This output can the be transferred to Tags.pm +# +# Bob Hallissy 2008-01-31 + +use strict; + +my $which; +my %iso639list; + +while (<>) +{ + s/\s+$//o; # trim trailing whitespace (including line ending). + if (/^\s*$/o) + { + print "\n"; # Just print empty lines + next; + } + + s/^\s+//o; # trim leading whitespace + + if (/^"(SCRIPT|LANGUAGE|FEATURE)"\s*,\s*"([^"]+)"\s*,\s*"([^"]+)"/) + { + # VOLT's tags.txt + my ($type, $name, $tag) = ($1, $2, $3); + print "\n\n//$type\n\n" if $type != $which; + $which = $type; + print " \"$name\" => '$tag',\n"; + } + + elsif (/^'(.{1,4})'\s+(.*)$/o) + { + # Special reverse formatting for feature names + my ($name, $tag) = ($2, $1); + $tag .= " " x (4 - length($tag)); # pad tag + print " \"$name\" => '$tag',\n"; + } + + elsif (/^'(.{1,4})-(.{1,4})'\s+(.*)$/o) + { + # Special reverse formatting for feature names like 'cv01-cv99' + my ($name, $tag1, $tag2) = ($3, $1, $2); + for my $tag ($tag1 .. $tag2) + { + $tag =~ /(\d+)$/; + my $index = $1; + $tag .= " " x (4 - length($tag)); # pad tag + print " \"$name $index\" => '$tag',\n"; + } + } + elsif (/^([^\t]*)\t([\w]{2,4})(?: +(\([^\t]*\)))?(?:\t(.*))?$/o) + { + # Script and language names + my ($name, $tag, $extra, $iso639list) = ($1, $2, $3, $4); + $name =~ s/\s*\(Standard\)\s*//oi; # Remove "(Standard)" from French and German entries + $name .= " $extra" if defined $extra; # Dhivehi has "(deprecated)" after the "DHV " tag -- move it to name. + $tag .= " " x (4 - length($tag)); # pad tag + print " \"$name\" => '$tag',\n"; + if (defined $iso639list) + { + $iso639list =~ s/,//g; + $iso639list{$tag} = $iso639list # Save for later + } + } + else + { + print "UNEXPECTED DATA: '$_'\n"; + } +} + +print "\n"; +foreach my $tag (sort keys(%iso639list)) +{ + printf " '$tag' => '$iso639list{$tag}',\n"; +} + +=head1 AUTHOR + +Bob Hallissy L. + +=head1 LICENSING + +Copyright (c) 1998-2014, SIL International (http://www.sil.org) + +This script is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/buildutils/convert_tags_from_html.pl b/.cpan/build/Font-TTF-1.06-0/buildutils/convert_tags_from_html.pl new file mode 100644 index 0000000000..57b275f12c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/buildutils/convert_tags_from_html.pl @@ -0,0 +1,189 @@ +# This utility script interprets HTML files from MS's version of the OT spec +# to generate tags script for OTTags.pm +# The three files processed are scripttags.htm, featurelist.htm, and languagetags.htm +# These files are assumed to be in "C:\Reference\Microsoft\OpenType 1.6" unless +# a folder name is supplied as the sole argument on the command name. +# +# Output (to stdout) is in perl syntax for the hash initialization, e.g.: +# "Arabic" => "arab", +# "Armenian" => "armn", +# This output can the be transferred to Tags.pm +# +# Bob Hallissy 2010-09-16 + +use strict; + +use File::Spec::Functions; +use HTML::Parser; + +my $dir = ($ARGV[0] ? $ARGV[0] : "/Reference/Microsoft/OpenType 1.6"); + +die "Cannot locate .HTM files in '$dir'.\n" unless ( + -f catfile($dir, "languagetags.htm") and + -f catfile($dir, "featurelist.htm") and + -f catfile($dir, "scripttags.htm") + ); + +my $filename; +my $which; # either LANGUAGE, FEATURE, or SCRIPT + +my $curText; # Text accumulator. +my $curCol; # Which column of the table we're processing -- reset to 0 by +my $td; # ref to array of text from a containing
+ +my (%tttags, %iso639list); # Accumulated data + +sub text +{ + my ($self, $text) = @_; + $curText .= $text; +} + +sub start +{ + my ($self, $tagname) = @_; + $curText = ''; + if ($tagname eq 'tr') + { + $curCol = 0; + undef $td; + } +} + +sub end +{ + my ($self, $tagname) = @_; + if ($tagname eq 'th') + { + if ($curCol++ == 0) + { + # confirm which table we have: + $curText =~ /^(\S+)/; + $which = uc($1); + die "Unexpected table header '$curText' in '$filename'./n" unless $filename =~ /^${which}/i; + } + } + elsif ($tagname eq 'td') + { + # trip leading and trailing whitespace and quotes: + $curText =~ s/[\s']+$//; + $curText =~ s/^[\s']+//; + # fold dashes to hyphen-minus: + $curText =~ s/[\x{2010}-\x{201F}]/-/g; + $td->[$curCol++] = $curText; + } + elsif ($tagname eq 'tr' && defined $td) + { + # Ok -- got a complete row of data to work with + + # Feature table is reversed with tag being first: + $td = [ reverse @{$td} ] if $which eq "FEATURE"; + + # So now + # $td->[0] is the name (of script, language, or feature(s)) + # $td->[1] is the tag name plus possibly extra stuff + # $td->[3], if exists, is comma-separated iso639 language codes + + my ($name, $tag, $iso639list) = @{$td}; + + if ($tag =~ /^(\S+)\s+(.+)$/) + { + # Extra text after the tag name, such as Dhivehi has "(deprecated)" after the "DHV " tag -- move it to name. + $tag = $1; + $name .= " $2"; + } + + if ($tag =~ /^(.{1,4})-(.{1,4})$/) + { + # Special handling for feature names like 'cv01-cv99' + my ($tag1, $tag2) = ($1, $2); + for my $tag ($tag1 .. $tag2) + { + $tag =~ /(\d+)$/; + my $index = $1; + $tag .= ' ' x (4 - length($tag)); # pad tag + $tttags{$which}{"$name $index"} = "$tag"; + } + } + else + { + # Normal tags + # Pad the tag: + $tag .= ' ' x (4 - length($tag)); + $tttags{$which}{$name} = $tag; + } + + if (defined $iso639list) + { + $iso639list =~ s/[, ]+/ /g; # Strip commas, leaving space. + $iso639list{$tag} = $iso639list # Save for later + } + } +} + +sub VerifyAnsi +{ + my $str = shift; + my $strA = $str; + $strA =~ s/[^\x00-\x7F]/?/g; + print STDERR "Wide data:\n$strA\n$str\n" if $str ne $strA; +} + +my $p = HTML::Parser->new( + api_version => 3, + start_h => [\&start, 'self,tagname'], + end_h => [\&end, 'self,tagname'], + text_h => [\&text, 'self,text'], + report_tags => [qw(table th tr td)], + ); + +foreach (qw (scripttags.htm languagetags.htm featurelist.htm)) +{ + $filename = $_; + my $fh; + open($fh, "<:utf8", catfile($dir, $filename)) || die "cannot open '$filename': $!/n"; + $p->parse_file($fh); + close $fh; +} + +print < {\n"; + # Alpha order by name (not tag) + foreach my $name (sort keys (%{$tttags{$which}})) + { + VerifyAnsi "$name => $tttags{$which}{$name}"; + print " \"$name\" => '$tttags{$which}{$name}',\n"; + } + print " },\n\n"; +} +print ");\n\n"; + +print "\%iso639 = (\n"; +foreach my $tag (sort keys(%iso639list)) +{ + VerifyAnsi "$tag => $iso639list{$tag}"; + printf " '$tag' => '$iso639list{$tag}',\n"; +} +print ");\n"; + +=head1 AUTHOR + +Bob Hallissy L. + +=head1 LICENSING + +Copyright (c) 1998-2014, SIL International (http://www.sil.org) + +This script is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF.pm new file mode 100644 index 0000000000..5613ed77f4 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF.pm @@ -0,0 +1,59 @@ +package Font::TTF; + +$VERSION = '1.06'; # RMH 02-Aug-2016 Bug fixes; updated OT tags; +# $VERSION = '1.05'; # MJPH 19-Jan-2015 Bug fixes; updated OT tags; GSUB Lookup Type 8 support +# $VERSION = '1.04'; # MJPH 8-Jan-2014 License, POD, and perl -w tidying; bug fixes +# $VERSION = '1.03'; # MJPH 5-Sep-2013 Add $t->minsize() +# $VERSION = '1.02'; # MJPH 30-Aug-2012 Fix case typo in Useall +# $VERSION = '1.01'; # MJPH 30-Aug-2012 add IO::String prerequisite +# $VERSION = '1.00'; # MJPH 21-Aug-2012 OS/2, OT & Graphite improvements; bug fixes +# $VERSION = '0.48'; # MJPH 15-DEC-2010 Bug fixes +# $VERSION = '0.47'; # MJPH 7-AUG-2009 Minor bug fix in Name.pm +# $VERSION = '0.46'; # MJPH 26-JAN-2009 Various bug fixes, add Sill table +# $VERSION = '0.45'; # MJPH 11-JUN-2008 Packaging tidying +# $VERSION = '0.44'; # MJPH 9-JUN-2008 Various bug fixes +# $VERSION = '0.43'; # MJPH 20-NOV-2007 Add a test! +# $VERSION = '0.42'; # MJPH 11-OCT-2007 Add Volt2ttf support +# $VERSION = '0.41'; # MJPH 27-MAR-2007 Remove warnings from font copy +# Bug fixes in Ttopen, GDEF +# Remove redundant head and maxp ->reads +# $VERSION = '0.40'; # MJPH 31-JUL-2006 Add EBDT, EBLC tables +# $VERSION = 0.39; + +1; + +=head1 NAME + +Font::TTF - Perl module for TrueType Font hacking + +=head1 DESCRIPTION + +This module allows you to do almost anything to a TrueType/OpenType Font +including modify and inspect nearly all tables. + +=head1 AUTHOR + +Martin Hosken L. +(see CONTRIBUTORS for other authors). + +Repository available at L + +=head1 HISTORY + +See F file for a change log. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +The fonts in the test suite are released under the Open Font License 1.1, see F. + + +=head1 SEE ALSO + +L + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/AATKern.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/AATKern.pm new file mode 100644 index 0000000000..f75e81c63d --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/AATKern.pm @@ -0,0 +1,150 @@ +package Font::TTF::AATKern; + +=head1 NAME + +Font::TTF::AATKern - AAT Kern table + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Kern::Subtable; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + + $self->SUPER::read or return $self; + + my ($dat, $fh, $numSubtables); + $fh = $self->{' INFILE'}; + + $fh->read($dat, 8); + ($self->{'version'}, $numSubtables) = TTF_Unpack("vL", $dat); + + my $subtables = []; + foreach (1 .. $numSubtables) { + my $subtableStart = $fh->tell(); + + $fh->read($dat, 8); + my ($length, $coverage, $tupleIndex) = TTF_Unpack("LSS", $dat); + my $type = $coverage & 0x00ff; + + my $subtable = Font::TTF::Kern::Subtable->create($type, $coverage, $length); + $subtable->read($fh); + + $subtable->{'tupleIndex'} = $tupleIndex if $subtable->{'variation'}; + $subtable->{' PARENT'} = $self; + push @$subtables, $subtable; + } + + $self->{'subtables'} = $subtables; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $subtables = $self->{'subtables'}; + $fh->print(TTF_Pack("vL", $self->{'version'}, scalar @$subtables)); + + foreach (@$subtables) { + $_->out($fh); + } +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read unless $self->{' read'}; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\n", $self->{'version'}); + + my $subtables = $self->{'subtables'}; + foreach (@$subtables) { + $_->print($fh); + } +} + +sub dumpXML +{ + my ($self, $fh) = @_; + $self->read unless $self->{' read'}; + + my $post = $self->{' PARENT'}->{'post'}; + $post->read; + + $fh = 'STDOUT' unless defined $fh; + $fh->printf("\n", $self->{'version'}); + + my $subtables = $self->{'subtables'}; + foreach (@$subtables) { + $fh->printf("<%s", $_->type); + $fh->printf(" vertical=\"1\"") if $_->{'vertical'}; + $fh->printf(" crossStream=\"1\"") if $_->{'crossStream'}; + $fh->printf(" variation=\"1\"") if $_->{'variation'}; + $fh->printf(" tupleIndex=\"%s\"", $_->{'tupleIndex'}) if exists $_->{'tupleIndex'}; + $fh->printf(">\n"); + + $_->dumpXML($fh); + + $fh->printf("\n", $_->type); + } + + $fh->printf("\n"); +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/AATutils.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/AATutils.pm new file mode 100644 index 0000000000..544dc93af6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/AATutils.pm @@ -0,0 +1,712 @@ +package Font::TTF::AATutils; + +=head1 NAME + +Font::TTF::AATutils - Utility functions for AAT tables + +=cut + +use strict; +use vars qw(@ISA @EXPORT); +require Exporter; + +use Font::TTF::Utils; +use Font::TTF::Segarr; +use IO::File; + +@ISA = qw(Exporter); +@EXPORT = qw( + AAT_read_lookup + AAT_pack_lookup + AAT_write_lookup + AAT_pack_classes + AAT_write_classes + AAT_pack_states + AAT_write_states + AAT_read_state_table + AAT_read_subtable + xmldump +); + +sub xmldump +{ + my ($var, $links, $depth, $processedVars, $type) = @_; + + $processedVars = {} unless (defined $processedVars); + print("\n") if $depth == 0; # not necessarily true encoding for all text! + + my $indent = "\t" x $depth; + + my ($objType, $addr) = ($var =~ m/^.+=(.+)\((.+)\)$/); + unless (defined $type) { + if (defined $addr) { + if (defined $processedVars->{$addr}) { + if ($links) { + printf("%s%s\n", $indent, "$objType"); + } + else { + printf("%s%s\n", $indent, "$objType"); + } + return; + } + $processedVars->{$addr} = 1; + } + } + + $type = ref $var unless defined $type; + + if ($type eq 'REF') { + printf("%s\n", $indent, $$var); + } + elsif ($type eq 'SCALAR') { + printf("%s%s\n", $indent, $var); + } + elsif ($type eq 'ARRAY') { + # printf("%s\n", $indent); + foreach (0 .. $#$var) { + if (ref($var->[$_])) { + printf("%s\n", $indent, $_); + xmldump($var->[$_], $links, $depth + 1, $processedVars); + printf("%s\n", $indent); + } + else { + printf("%s%s\n", $indent, $_, $var->[$_]); + } + } + # printf("%s\n", $indent); + } + elsif ($type eq 'HASH') { + # printf("%s\n", $indent); + foreach (sort keys %$var) { + if (ref($var->{$_})) { + printf("%s\n", $indent, $_); + xmldump($var->{$_}, $links, $depth + 1, $processedVars); + printf("%s\n", $indent); + } + else { + printf("%s%s\n", $indent, $_, $var->{$_}); + } + } + # printf("%s\n", $indent); + } + elsif ($type eq 'CODE') { + printf("%s\n", $indent, $var); + } + elsif ($type eq 'GLOB') { + printf("%s\n", $indent, $var); + } + elsif ($type eq '') { + printf("%s%s\n", $indent, $var); + } + else { + if ($links) { + printf("%s\n", $indent, $type, $addr); + } + else { + printf("%s\n", $indent, $type); + } + xmldump($var, $links, $depth + 1, $processedVars, $objType); + printf("%s\n", $indent); + } +} + +=head2 ($classes, $states) = AAT_read_subtable($fh, $baseOffset, $subtableStart, $limits) + +=cut + +sub AAT_read_subtable +{ + my ($fh, $baseOffset, $subtableStart, $limits) = @_; + + my $limit = 0xffffffff; + foreach (@$limits) { + $limit = $_ if ($_ > $subtableStart and $_ < $limit); + } + die if $limit == 0xffffffff; + + my $dat; + $fh->seek($baseOffset + $subtableStart, IO::File::SEEK_SET); + $fh->read($dat, $limit - $subtableStart); + + $dat; +} + +=head2 $length = AAT_write_state_table($fh, $classes, $states, $numExtraTables, $packEntry) + +$packEntry is a subroutine for packing an entry into binary form, called as + +$dat = $packEntry($entry, $entryTable, $numEntries) + +where the entry is a comma-separated list of nextStateOffset, flags, actions + +=cut + +sub AAT_pack_state_table +{ + my ($classes, $states, $numExtraTables, $packEntry) = @_; + + my ($dat) = pack("n*", (0) x (4 + $numExtraTables)); # placeholders for stateSize, classTable, stateArray, entryTable + + my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0); + my (@classTable, $i); + foreach $i (0 .. $#$classes) { + my $class = $classes->[$i]; + foreach (@$class) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + $classTable[$_] = $i; + } + } + + my $classTable = length($dat); + $dat .= pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1, + map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph)); + $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0; # pad if odd number of glyphs + + my $stateArray = length($dat); + my (@entries, %entries); + my $state = $states->[0]; + my $stateSize = @$state; + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $actions = $_->{'actions'}; + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions); + if (not defined $entries{$entry}) { + push @entries, $entry; + $entries{$entry} = $#entries; + die "too many different state array entries" if $#entries == 256; + } + $dat .= pack("C", $entries{$entry}); + } + } + $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + my $entryTable = length($dat); + $dat .= map { &$packEntry($_, $entryTable, $#entries + 1) } @entries; + + my ($dat1) = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +sub AAT_write_state_table +{ + my ($fh, $classes, $states, $numExtraTables, $packEntry) = @_; + + my $stateTableStart = $fh->tell(); + + $fh->print(pack("n*", (0) x (4 + $numExtraTables))); # placeholders for stateSize, classTable, stateArray, entryTable + + my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0); + my (@classTable, $i); + foreach $i (0 .. $#$classes) { + my $class = $classes->[$i]; + foreach (@$class) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + $classTable[$_] = $i; + } + } + + my $classTable = $fh->tell() - $stateTableStart; + $fh->print(pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1, + map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph))); + $fh->print(pack("C", 0)) if (($lastGlyph - $firstGlyph) & 1) == 0; # pad if odd number of glyphs + + my $stateArray = $fh->tell() - $stateTableStart; + my (@entries, %entries); + my $state = $states->[0]; + my $stateSize = @$state; + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $actions = $_->{'actions'}; + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, $_->{'flags'}, ref($actions) eq 'ARRAY' ? @$actions : $actions); + if (not defined $entries{$entry}) { + push @entries, $entry; + $entries{$entry} = $#entries; + die "too many different state array entries" if $#entries == 256; + } + $fh->print(pack("C", $entries{$entry})); + } + } + $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + my $entryTable = $fh->tell() - $stateTableStart; + $fh->print(map { &$packEntry($_, $entryTable, $#entries + 1) } @entries); + + my $length = $fh->tell() - $stateTableStart; + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->print(pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable)); + + $fh->seek($stateTableStart + $length, IO::File::SEEK_SET); + $length; +} + +sub AAT_pack_classes +{ + my ($classes) = @_; + + my ($firstGlyph, $lastGlyph) = (0xffff, 0, 0); + my (@classTable, $i); + foreach $i (0 .. $#$classes) { + my $class = $classes->[$i]; + foreach (@$class) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + $classTable[$_] = $i; + } + } + + my ($dat) = pack("nnC*", $firstGlyph, $lastGlyph - $firstGlyph + 1, + map { defined $classTable[$_] ? $classTable[$_] : 1 } ($firstGlyph .. $lastGlyph)); + $dat .= pack("C", 0) if (($lastGlyph - $firstGlyph) & 1) == 0; # pad if odd number of glyphs + + return $dat; +} + +sub AAT_write_classes +{ + my ($fh, $classes) = @_; + + $fh->print(AAT_pack_classes($fh, $classes)); +} + +sub AAT_pack_states +{ + my ($classes, $stateArray, $states, $buildEntryProc) = @_; + + my ($entries, %entryHash); + my $state = $states->[0]; + my $stateSize = @$state; + + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + my ($dat); + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_)); + if (not defined $entryHash{$entry}) { + push @$entries, $entry; + $entryHash{$entry} = $#$entries; + die "too many different state array entries" if $#$entries == 256; + } + $dat .= pack("C", $entryHash{$entry}); + } + } + $dat .= pack("C", 0) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + ($dat, $stateSize, $entries); +} + +sub AAT_write_states +{ + my ($fh, $classes, $stateArray, $states, $buildEntryProc) = @_; + + my ($entries, %entryHash); + my $state = $states->[0]; + my $stateSize = @$state; + + die "stateSize below minimum allowed (4)" if $stateSize < 4; + die "stateSize (" . $stateSize . ") too small for max class number (" . $#$classes . ")" if $stateSize < $#$classes + 1; + warn "state array has unreachable columns" if $stateSize > $#$classes + 1; + + foreach (@$states) { + die "inconsistent state size" if @$_ != $stateSize; + foreach (@$_) { + my $entry = join(",", $stateArray + $_->{'nextState'} * $stateSize, &$buildEntryProc($_)); + if (not defined $entryHash{$entry}) { + push @$entries, $entry; + $entryHash{$entry} = $#$entries; + die "too many different state array entries" if $#$entries == 256; + } + $fh->print(pack("C", $entryHash{$entry})); + } + } + $fh->print(pack("C", 0)) if (@$states & 1) != 0 and ($stateSize & 1) != 0; # pad if state array size is odd + + ($stateSize, $entries); +} + +=head2 ($classes, $states, $entries) = AAT_read_state_table($fh, $numActionWords) + +=cut + +sub AAT_read_state_table +{ + my ($fh, $numActionWords) = @_; + + my $stateTableStart = $fh->tell(); + my $dat; + $fh->read($dat, 8); + my ($stateSize, $classTable, $stateArray, $entryTable) = unpack("nnnn", $dat); + + my $classes; # array of lists of glyphs + + $fh->seek($stateTableStart + $classTable, IO::File::SEEK_SET); + $fh->read($dat, 4); + my ($firstGlyph, $nGlyphs) = unpack("nn", $dat); + $fh->read($dat, $nGlyphs); + foreach (unpack("C*", $dat)) { + if ($_ != 1) { + my $class = $classes->[$_]; + push(@$class, $firstGlyph); + $classes->[$_] = $class unless defined $classes->[$_]; + } + $firstGlyph++; + } + + $fh->seek($stateTableStart + $stateArray, IO::File::SEEK_SET); + my $states; # array of arrays of hashes{nextState, flags, actions} + + my $entrySize = 4 + ($numActionWords * 2); + my $lastState = 1; + my $entries; + while ($#$states < $lastState) { + $fh->read($dat, $stateSize); + my @stateEntries = unpack("C*", $dat); + my $state; + foreach (@stateEntries) { + if (not defined $entries->[$_]) { + my $loc = $fh->tell(); + $fh->seek($stateTableStart + $entryTable + ($_ * $entrySize), IO::File::SEEK_SET); + $fh->read($dat, $entrySize); + my ($nextState, $flags, $actions); + ($nextState, $flags, @$actions) = unpack("n*", $dat); + $nextState -= $stateArray; + $nextState /= $stateSize; + $entries->[$_] = { 'nextState' => $nextState, 'flags' => $flags }; + $entries->[$_]->{'actions'} = $actions if $numActionWords > 0; + $lastState = $nextState if ($nextState > $lastState); + $fh->seek($loc, IO::File::SEEK_SET); + } + push(@$state, $entries->[$_]); + } + push(@$states, $state); + } + + ($classes, $states, $entries); +} + +=head2 ($format, $lookup) = AAT_read_lookup($fh, $valueSize, $length, $default) + +=cut + +sub AAT_read_lookup +{ + my ($fh, $valueSize, $length, $default) = @_; + + my $lookupStart = $fh->tell(); + my ($dat, $unpackChar); + if ($valueSize == 1) { + $unpackChar = "C"; + } + elsif ($valueSize == 2) { + $unpackChar = "n"; + } + elsif ($valueSize == 4) { + $unpackChar = "N"; + } + else { + die "unsupported value size"; + } + + $fh->read($dat, 2); + my $format = unpack("n", $dat); + my $lookup; + + if ($format == 0) { + $fh->read($dat, $length - 2); + my $i = -1; + $lookup = { map { $i++; ($_ != $default) ? ($i, $_) : () } unpack($unpackChar . "*", $dat) }; + } + + elsif ($format == 2) { + $fh->read($dat, 10); + my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat); + die if $unitSize != 4 + $valueSize; + foreach (1 .. $nUnits) { + $fh->read($dat, $unitSize); + my ($lastGlyph, $firstGlyph, $value) = unpack("nn" . $unpackChar, $dat); + if ($firstGlyph != 0xffff and $value != $default) { + foreach ($firstGlyph .. $lastGlyph) { + $lookup->{$_} = $value; + } + } + } + } + + elsif ($format == 4) { + $fh->read($dat, 10); + my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat); + die if $unitSize != 6; + foreach (1 .. $nUnits) { + $fh->read($dat, $unitSize); + my ($lastGlyph, $firstGlyph, $offset) = unpack("nnn", $dat); + if ($firstGlyph != 0xffff) { + my $loc = $fh->tell(); + $fh->seek($lookupStart + $offset, IO::File::SEEK_SET); + $fh->read($dat, ($lastGlyph - $firstGlyph + 1) * $valueSize); + my @values = unpack($unpackChar . "*", $dat); + foreach (0 .. $lastGlyph - $firstGlyph) { + $lookup->{$firstGlyph + $_} = $values[$_] if $values[$_] != $default; + } + $fh->seek($loc, IO::File::SEEK_SET); + } + } + } + + elsif ($format == 6) { + $fh->read($dat, 10); + my ($unitSize, $nUnits, $searchRange, $entrySelector, $rangeShift) = unpack("nnnnn", $dat); + die if $unitSize != 2 + $valueSize; + foreach (1 .. $nUnits) { + $fh->read($dat, $unitSize); + my ($glyph, $value) = unpack("n" . $unpackChar, $dat); + $lookup->{$glyph} = $value if $glyph != 0xffff and $value != $default; + } + } + + elsif ($format == 8) { + $fh->read($dat, 4); + my ($firstGlyph, $glyphCount) = unpack("nn", $dat); + $fh->read($dat, $glyphCount * $valueSize); + $firstGlyph--; + $lookup = { map { $firstGlyph++; $_ != $default ? ($firstGlyph, $_) : () } unpack($unpackChar . "*", $dat) }; + } + + else { + die "unknown lookup format"; + } + + $fh->seek($lookupStart + $length, IO::File::SEEK_SET); + + ($format, $lookup); +} + +=head2 AAT_write_lookup($fh, $format, $lookup, $valueSize, $default) + +=cut + +sub AAT_pack_lookup +{ + my ($format, $lookup, $valueSize, $default) = @_; + + my $packChar; + if ($valueSize == 1) { + $packChar = "C"; + } + elsif ($valueSize == 2) { + $packChar = "n"; + } + elsif ($valueSize == 4) { + $packChar = "N"; + } + else { + die "unsupported value size"; + } + + my ($dat) = pack("n", $format); + + my ($firstGlyph, $lastGlyph) = (0xffff, 0); + foreach (keys %$lookup) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + } + my $glyphCount = $lastGlyph - $firstGlyph + 1; + + if ($format == 0) { + $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph)); + } + + elsif ($format == 2) { + my $prev = $default; + my $segStart = $firstGlyph; + my $dat1; + foreach ($firstGlyph .. $lastGlyph + 1) { + my $val = $lookup->{$_}; + $val = $default unless defined $val; + if ($val != $prev) { + $dat1 .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default; + $prev = $val; + $segStart = $_; + } + } + $dat1 .= pack("nn" . $packChar, 0xffff, 0xffff, 0); + my $unitSize = 4 + $valueSize; + $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize)); + $dat .= $dat1; + } + + elsif ($format == 4) { + my $segArray = new Font::TTF::Segarr($valueSize); + $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph)); + my ($start, $end, $offset); + $offset = 12 + @$segArray * 6 + 6; # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment + my $dat1; + foreach (@$segArray) { + $start = $_->{'START'}; + $end = $start + $_->{'LEN'} - 1; + $dat1 .= pack("nnn", $end, $start, $offset); + $offset += $_->{'LEN'} * 2; + } + $dat1 .= pack("nnn", 0xffff, 0xffff, 0); + $dat .= pack("nnnnn", 6, TTF_bininfo(length($dat1) / 6, 6)); + $dat .= $dat1; + foreach (@$segArray) { + $dat1 = $_->{'VAL'}; + $dat .= pack($packChar . "*", @$dat1); + } + } + + elsif ($format == 6) { + die "unsupported" if $valueSize != 2; + my $dat1 = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup); + my $unitSize = 2 + $valueSize; + $dat .= pack("nnnnn", $unitSize, TTF_bininfo(length($dat1) / $unitSize, $unitSize)); + $dat .= $dat1; + } + + elsif ($format == 8) { + $dat .= pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1); + $dat .= pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph)); + } + + else { + die "unknown lookup format"; + } + + my $padBytes = (4 - (length($dat) & 3)) & 3; + $dat .= pack("C*", (0) x $padBytes); + + return $dat; +} + +sub AAT_write_lookup +{ + my ($fh, $format, $lookup, $valueSize, $default) = @_; + + my $lookupStart = $fh->tell(); + my $packChar; + if ($valueSize == 1) { + $packChar = "C"; + } + elsif ($valueSize == 2) { + $packChar = "n"; + } + elsif ($valueSize == 4) { + $packChar = "N"; + } + else { + die "unsupported value size"; + } + + $fh->print(pack("n", $format)); + + my ($firstGlyph, $lastGlyph) = (0xffff, 0); + foreach (keys %$lookup) { + $firstGlyph = $_ if $_ < $firstGlyph; + $lastGlyph = $_ if $_ > $lastGlyph; + } + my $glyphCount = $lastGlyph - $firstGlyph + 1; + + if ($format == 0) { + $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } (0 .. $lastGlyph))); + } + + elsif ($format == 2) { + my $prev = $default; + my $segStart = $firstGlyph; + my $dat; + foreach ($firstGlyph .. $lastGlyph + 1) { + my $val = $lookup->{$_}; + $val = $default unless defined $val; + if ($val != $prev) { + $dat .= pack("nn" . $packChar, $_ - 1, $segStart, $prev) if $prev != $default; + $prev = $val; + $segStart = $_; + } + } + $dat .= pack("nn" . $packChar, 0xffff, 0xffff, 0); + my $unitSize = 4 + $valueSize; + $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize))); + $fh->print($dat); + } + + elsif ($format == 4) { + my $segArray = new Font::TTF::Segarr($valueSize); + $segArray->add_segment($firstGlyph, 1, map { $lookup->{$_} } ($firstGlyph .. $lastGlyph)); + my ($start, $end, $offset); + $offset = 12 + @$segArray * 6 + 6; # 12 is size of format word + binSearchHeader; 6 bytes per segment; 6 for terminating segment + my $dat; + foreach (@$segArray) { + $start = $_->{'START'}; + $end = $start + $_->{'LEN'} - 1; + $dat .= pack("nnn", $end, $start, $offset); + $offset += $_->{'LEN'} * 2; + } + $dat .= pack("nnn", 0xffff, 0xffff, 0); + $fh->print(pack("nnnnn", 6, TTF_bininfo(length($dat) / 6, 6))); + $fh->print($dat); + foreach (@$segArray) { + $dat = $_->{'VAL'}; + $fh->print(pack($packChar . "*", @$dat)); + } + } + + elsif ($format == 6) { + die "unsupported" if $valueSize != 2; + my $dat = pack("n*", map { $_, $lookup->{$_} } sort { $a <=> $b } grep { $lookup->{$_} ne $default } keys %$lookup); + my $unitSize = 2 + $valueSize; + $fh->print(pack("nnnnn", $unitSize, TTF_bininfo(length($dat) / $unitSize, $unitSize))); + $fh->print($dat); + } + + elsif ($format == 8) { + $fh->print(pack("nn", $firstGlyph, $lastGlyph - $firstGlyph + 1)); + $fh->print(pack($packChar . "*", map { defined $lookup->{$_} ? $lookup->{$_} : defined $default ? $default : $_ } ($firstGlyph .. $lastGlyph))); + } + + else { + die "unknown lookup format"; + } + + my $length = $fh->tell() - $lookupStart; + my $padBytes = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + + $length; +} + +1; + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Anchor.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Anchor.pm new file mode 100644 index 0000000000..fdacb9c881 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Anchor.pm @@ -0,0 +1,224 @@ +package Font::TTF::Anchor; + +=head1 NAME + +Font::TTF::Anchor - Anchor points for GPOS tables + +=head1 DESCRIPTION + +The Anchor defines an anchor point on a glyph providing various information +depending on how much is available, including such information as the co-ordinates, +a curve point and even device specific modifiers. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item x + +XCoordinate of the anchor point + +=item y + +YCoordinate of the anchor point + +=item p + +Curve point on the glyph to use as the anchor point + +=item xdev + +Device table (delta) for the xcoordinate + +=item ydev + +Device table (delta) for the ycoordinate + +=item xid + +XIdAnchor for multiple master horizontal metric id + +=item yid + +YIdAnchor for multiple master vertical metric id + +=back + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; + + +=head2 new + +Creates a new Anchor + +=cut + +sub new +{ + my ($class) = shift; + my ($self) = {@_}; + + bless $self, $class; +} + + +=head2 read($fh) + +Reads the anchor from the given file handle at that point. The file handle is left +at an arbitrary read point, usually the end of something! + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat, $loc, $fmt, $p, $xoff, $yoff); + + $fh->read($dat, 6); + $fmt = unpack('n', $dat); + if ($fmt == 4) + { ($self->{'xid'}, $self->{'yid'}) = TTF_Unpack('S2', substr($dat,2)); } + else + { ($self->{'x'}, $self->{'y'}) = TTF_Unpack('s2', substr($dat,2)); } + + if ($fmt == 2) + { + $fh->read($dat, 2); + $self->{'p'} = unpack('n', $dat); + } elsif ($fmt == 3) + { + $fh->read($dat, 4); + ($xoff, $yoff) = unpack('n2', $dat); + $loc = $fh->tell() - 10; + if ($xoff) + { + $fh->seek($loc + $xoff, 0); + $self->{'xdev'} = Font::TTF::Delta->new->read($fh); + } + if ($yoff) + { + $fh->seek($loc + $yoff, 0); + $self->{'ydev'} = Font::TTF::Delta->new->read($fh); + } + } + $self; +} + + +=head2 out($fh, $style) + +Outputs the Anchor to the given file handle at this point also addressing issues +of deltas. If $style is set, then no output is sent to the file handle. The return +value is the output string. + +=cut + +sub out +{ + my ($self, $fh, $style) = @_; + my ($xoff, $yoff, $fmt, $out); + + if (defined $self->{'xid'} || defined $self->{'yid'}) + { $out = TTF_Pack('SSS', 4, $self->{'xid'}, $self->{'yid'}); } + elsif (defined $self->{'p'}) + { $out = TTF_Pack('Ssss', 2, @{$self}{'x', 'y', 'p'}); } + elsif (defined $self->{'xdev'} || defined $self->{'ydev'}) + { + $out = TTF_Pack('Sss', 3, @{$self}{'x', 'y'}); + if (defined $self->{'xdev'}) + { + $out .= pack('n2', 10, 0); + $out .= $self->{'xdev'}->out($fh, 1); + $yoff = length($out) - 10; + } + else + { $out .= pack('n2', 0, 0); } + if (defined $self->{'ydev'}) + { + $yoff = 10 unless $yoff; + substr($out, 8, 2) = pack('n', $yoff); + $out .= $self->{'ydev'}->out($fh, 1); + } + } else + { $out = TTF_Pack('Sss', 1, @{$self}{'x', 'y'}); } + $fh->print($out) unless $style; + $out; +} + + +sub signature +{ + my ($self) = @_; + return join (",", map {"${_}=$self->{$_}"} qw(x y p xdev ydev xid yid)); +} + + +=head2 $a->out_xml($context) + +Outputs the anchor in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($end); + + $fh->print("$depthprint(" p='$self->{'p'}'") if defined ($self->{'p'}); + $end = (defined $self->{'xdev'} || defined $self->{'ydev'} || defined $self->{'xid'} || defined $self->{'yid'}); + unless ($end) + { + $fh->print("/>\n"); + return $self; + } + + if (defined $self->{'xdev'}) + { + $fh->print("$depth$context->{'indent'}\n"); + $self->{'xdev'}->out_xml($context, $depth . ($context->{'indent'} x 2)); + $fh->print("$depth$context->{'indent'}\n"); + } + + if (defined $self->{'ydev'}) + { + $fh->print("$depth$context->{'indent'}\n"); + $self->{'ydev'}->out_xml($context, $depth . ($context->{'indent'} x 2)); + $fh->print("$depth$context->{'indent'}\n"); + } + + if (defined $self->{'xid'} || defined $self->{'yid'}) + { + $fh->print("$depth$context->{'indent'}print(" xid='$self->{'xid'}'") if defined ($self->{'xid'}); + $fh->print(" yid='$self->{'yid'}'") if defined ($self->{'yid'}); + $fh->print("/>\n"); + } + $fh->print("$depth\n"); + $self; +} + +1; + + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Bsln.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Bsln.pm new file mode 100644 index 0000000000..30c42b74a0 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Bsln.pm @@ -0,0 +1,176 @@ +package Font::TTF::Bsln; + +=head1 NAME + +Font::TTF::Bsln - Baseline table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +=item xformat + +=item defaultBaseline + +=item deltas + +=item stdGlyph + +=item ctlPoints + +=item lookupFormat + +=item lookup + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +use Font::TTF::AATutils; +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + $fh->read($dat, 8); + my ($version, $format, $defaultBaseline) = TTF_Unpack("vSS", $dat); + + if ($format == 0 or $format == 1) { + $fh->read($dat, 64); + $self->{'deltas'} = [TTF_Unpack("s*", $dat)]; + } + elsif ($format == 2 or $format == 3) { + $fh->read($dat, 2); + $self->{'stdGlyph'} = unpack("n", $dat); + $fh->read($dat, 64); + $self->{'ctlPoints'} = unpack("n*", $dat); + } + else { + die "unknown table format"; + } + + if ($format == 1 or $format == 3) { + my $len = $self->{' LENGTH'} - ($fh->tell() - $self->{' OFFSET'}); + my ($lookupFormat, $lookup) = AAT_read_lookup($fh, 2, $len, $defaultBaseline); + $self->{'lookupFormat'} = $lookupFormat; + $self->{'lookup'} = $lookup; + } + + $self->{'version'} = $version; + $self->{'format'} = $format; + $self->{'defaultBaseline'} = $defaultBaseline; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $format = $self->{'format'}; + my $defaultBaseline = $self->{'defaultBaseline'}; + $fh->print(TTF_Pack("vSS", $self->{'version'}, $format, $defaultBaseline)); + + AAT_write_lookup($fh, $self->{'lookupFormat'}, $self->{'lookup'}, 2, $defaultBaseline) if ($format == 1 or $format == 3); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read; + + $fh = 'STDOUT' unless defined $fh; + + my $format = $self->{'format'}; + $fh->printf("version %f\nformat %d\ndefaultBaseline %d\n", $self->{'version'}, $format, $self->{'defaultBaseline'}); + if ($format == 0 or $format == 1) { + $fh->printf("\tdeltas:\n"); + my $deltas = $self->{'deltas'}; + foreach (0 .. 31) { + $fh->printf("\t\t%d: %d%s\n", $_, $deltas->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : ""); + } + } + if ($format == 2 or $format == 3) { + $fh->printf("\tstdGlyph = %d\n", $self->{'stdGlyph'}); + my $ctlPoints = $self->{'ctlPoints'}; + foreach (0 .. 31) { + $fh->printf("\t\t%d: %d%s\n", $_, $ctlPoints->[$_], defined baselineName_($_) ? "\t# " . baselineName_($_) : ""); + } + } + if ($format == 1 or $format == 3) { + $fh->printf("lookupFormat %d\n", $self->{'lookupFormat'}); + my $lookup = $self->{'lookup'}; + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\tglyph %d: %d%s\n", $_, $lookup->{$_}, defined baselineName_($_) ? "\t# " . baselineName_($_) : ""); + } + } +} + +sub baselineName_ +{ + my ($b) = @_; + my @baselines = ( 'Roman', 'Ideographic centered', 'Ideographic low', 'Hanging', 'Math' ); + $baselines[$b]; +} + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Changes_old.txt b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Changes_old.txt new file mode 100644 index 0000000000..7c939f498f --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Changes_old.txt @@ -0,0 +1,108 @@ +Note. The version number implies a release point. Thus changes that go into a +version occur above the version number, not after it. + +* 0.05 +** cmap + debug reverse() + provide scripts as .pl instead of .bat to placate Unix world + rename makefile.pl to Makefile.PL to keep Unix happy + Add ttfremap script + +* 0.06 .. 0.08 + Fixes to get this stuff working in Unix + +* 0.09 + Never released + +* 0.10 +** cmap + Make reverse return the lowest codepoint that matches rather than + the highest +** font + Use IO::File everywhere to allow passing in of psuedo-file objects + rather than file names +** Utils + Debug FDot2.14 conversion + +* 0.11 +** cmap + Don't store empty entries in the cmap + +* 0.12 +Various changes to reduce warnings + +** glyph + Add update_bbox + Do full glyph writes if loca read rather than glyf read + Get glyph update working usefully. Clarify glyf->read + +* 0.13 + +** glyph + Debug update_bbox for compound glyphs + Add empty() to clear to unread state (allows apps to save memory) + +** OS/2 + update update() to account for new cmap structure + +** Post + Correct mu to pi in Postscript name list. The list now follows the + MS convention for good or ill. + +** Table + Add empty() to clear a table to its unread state + +** Scripts +*** psfix + Added. Creates Post table based on cmap information + +*** eurofix + Added bullet hacking and generally backwards, forwards, all + ways mapping. + +*** ttfenc + Now supports the difference between MS post name list and TeXs + +* 0.14 + + Sort out mix up over CVS mess + +* 0.15 + +** Table + read_dat no longer marks table as read + +** Cvt_ + Mark table as read when read + +** Fpgm + Mark table as read when read + +** Prep + Mark table as read when read + +** Font + Add support for Mac sfnt version code ('true') + Be stricter on out @fontlist, only output tables that exist + +* 0.16 + +** Install + add pmake support + +** glyph + tidy up pod + +** kern + tidy up pod + +** name + add utf8 support + +* 0.17 + +** Utils + Debug TTF_bininfo >>= seems to have stopped working! + +* 0.18 + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Cmap.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Cmap.pm new file mode 100644 index 0000000000..3d8c3cf553 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Cmap.pm @@ -0,0 +1,746 @@ +package Font::TTF::Cmap; + +=head1 NAME + +Font::TTF::Cmap - Character map table + +=head1 DESCRIPTION + +Looks after the character map. For ease of use, the actual cmap is held in +a hash against codepoint. Thus for a given table: + + $gid = $font->{'cmap'}{'Tables'}[0]{'val'}{$code}; + +Note that C<$code> should be a true value (0x1234) rather than a string representation. + +=head1 INSTANCE VARIABLES + +The instance variables listed here are not preceded by a space due to their +emulating structural information in the font. + +=over 4 + +=item Num + +Number of subtables in this table + +=item Tables + +An array of subtables ([0..Num-1]) + +Each subtable also has its own instance variables which are, again, not +preceded by a space. + +=over 4 + +=item Platform + +The platform number for this subtable + +=item Encoding + +The encoding number for this subtable + +=item Format + +Gives the stored format of this subtable + +=item Ver + +Gives the version (or language) information for this subtable + +=item val + +A hash keyed by the codepoint value (not a string) storing the glyph id + +=back + +=back + +The following cmap options are controlled by instance variables that start with a space: + +=over 4 + +=item allowholes + +By default, when generating format 4 cmap subtables character codes that point to glyph zero +(normally called .notdef) are not included in the subtable. In some cases including some of these +character codes can result in a smaller format 4 subtable. To enable this behavior, set allowholes +to non-zero. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the cmap into memory. Format 4 subtables read the whole subtable and +fill in the segmented array accordingly. + +=cut + +sub read +{ + my ($self, $keepzeros) = @_; + $self->SUPER::read or return $self; + + my ($dat, $i, $j, $k, $id, @ids, $s); + my ($start, $end, $range, $delta, $form, $len, $num, $ver, $sg); + my ($fh) = $self->{' INFILE'}; + + $fh->read($dat, 4); + $self->{'Num'} = unpack("x2n", $dat); + $self->{'Tables'} = []; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = {}; + $fh->read($dat, 8); + ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat)); + $s->{'LOC'} += $self->{' OFFSET'}; + push(@{$self->{'Tables'}}, $s); + } + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + $fh->seek($s->{'LOC'}, 0); + $fh->read($dat, 2); + $form = unpack("n", $dat); + + $s->{'Format'} = $form; + if ($form == 0) + { + my $j = 0; + + $fh->read($dat, 4); + ($len, $s->{'Ver'}) = unpack('n2', $dat); + $fh->read($dat, 256); + $s->{'val'} = {map {$j++; ($_ ? ($j - 1, $_) : ())} unpack("C*", $dat)}; + } elsif ($form == 6) + { + my ($start, $ecount); + + $fh->read($dat, 8); + ($len, $s->{'Ver'}, $start, $ecount) = unpack('n4', $dat); + $fh->read($dat, $ecount << 1); + $s->{'val'} = {map {$start++; ($_ ? ($start - 1, $_) : ())} unpack("n*", $dat)}; + } elsif ($form == 2) # Contributed by Huw Rogers + { + $fh->read($dat, 4); + ($len, $s->{'Ver'}) = unpack('n2', $dat); + $fh->read($dat, 512); + my ($j, $k, $l, $m, $n, @subHeaderKeys, @subHeaders, $subHeader); + $n = 1; + for ($j = 0; $j < 256; $j++) { + my $k = unpack('@'.($j<<1).'n', $dat)>>3; + $n = $k + 1 if $k >= $n; + $subHeaders[$subHeaderKeys[$j] = $k] ||= [ ]; + } + $fh->read($dat, $n<<3); # read subHeaders[] + for ($k = 0; $k < $n; $k++) { + $subHeader = $subHeaders[$k]; + $l = $k<<3; + @$subHeader = unpack('@'.$l.'n4', $dat); + $subHeader->[2] = unpack('s', pack('S', $subHeader->[2])) + if $subHeader->[2] & 0x8000; # idDelta + $subHeader->[3] = + ($subHeader->[3] - (($n - $k)<<3) + 6)>>1; # idRangeOffset + } + $fh->read($dat, $len - ($n<<3) - 518); # glyphIndexArray[] + for ($j = 0; $j < 256; $j++) { + $k = $subHeaderKeys[$j]; + $subHeader = $subHeaders[$k]; + unless ($k) { + $l = $j - $subHeader->[0]; + if ($l >= 0 && $l < $subHeader->[1]) { + $m = unpack('@'.(($l + $subHeader->[3])<<1).'n', $dat); + $m += $subHeader->[2] if $m; + $s->{'val'}{$j} = $m; + } + } else { + for ($l = 0; $l < $subHeader->[1]; $l++) { + $m = unpack('@'.(($l + $subHeader->[3])<<1).'n', $dat); + $m += $subHeader->[2] if $m; + $s->{'val'}{($j<<8) + $l + $subHeader->[0]} = $m; + } + } + } + } elsif ($form == 4) + { + $fh->read($dat, 12); + ($len, $s->{'Ver'}, $num) = unpack('n3', $dat); + $num >>= 1; + $fh->read($dat, $len - 14); + for ($j = 0; $j < $num; $j++) + { + $end = unpack("n", substr($dat, $j << 1, 2)); + $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2)); + $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2)); + $delta -= 65536 if $delta > 32767; + $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2)); + for ($k = $start; $k <= $end; $k++) + { + if ($range == 0 || $range == 65535) # support the buggy FOG with its range=65535 for final segment + { $id = $k + $delta; } + else + { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 + + 2 + ($k - $start) * 2 + $range, 2)) + $delta; } + $id -= 65536 if $id >= 65536; + $s->{'val'}{$k} = $id if ($id || $keepzeros); + } + } + } elsif ($form == 8 || $form == 12 || $form == 13) + { + $fh->read($dat, 10); + ($len, $s->{'Ver'}) = unpack('x2N2', $dat); + if ($form == 8) + { + $fh->read($dat, 8196); + $num = unpack("N", substr($dat, 8192, 4)); # don't need the map + } else + { + $fh->read($dat, 4); + $num = unpack("N", $dat); + } + $fh->read($dat, 12 * $num); + for ($j = 0; $j < $num; $j++) + { + ($start, $end, $sg) = unpack("N3", substr($dat, $j * 12, 12)); + for ($k = $start; $k <= $end; $k++) + { $s->{'val'}{$k} = $form == 13 ? $sg : $sg++; } + } + } elsif ($form == 10) + { + $fh->read($dat, 18); + ($len, $s->{'Ver'}, $start, $num) = unpack('x2N4', $dat); + $fh->read($dat, $num << 1); + for ($j = 0; $j < $num; $j++) + { $s->{'val'}{$start + $j} = unpack("n", substr($dat, $j << 1, 2)); } + } + } + $self; +} + + +=head2 $t->ms_lookup($uni) + +Finds a Unicode table, giving preference to the MS one, and looks up the given +Unicode codepoint in it to find the glyph id. + +=cut + +sub ms_lookup +{ + my ($self, $uni) = @_; + + $self->find_ms || return undef unless (defined $self->{' mstable'}); + return $self->{' mstable'}{'val'}{$uni}; +} + + +=head2 $t->find_ms + +Finds the a Unicode table, giving preference to the Microsoft one, and sets the C instance variable +to it if found. Returns the table it finds. + +=cut + +sub find_ms +{ + my ($self) = @_; + my ($i, $s, $alt, $found); + + return $self->{' mstable'} if defined $self->{' mstable'}; + $self->read; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + if ($s->{'Platform'} == 3) + { + $self->{' mstable'} = $s; + return $s if ($s->{'Encoding'} == 10); + $found = 1 if ($s->{'Encoding'} == 1); + } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1)) + { $alt = $s; } + } + $self->{' mstable'} = $alt if ($alt && !$found); + $self->{' mstable'}; +} + + +=head2 $t->ms_enc + +Returns the encoding of the microsoft table (0 => symbol, etc.). Returns undef if there is +no Microsoft cmap. + +=cut + +sub ms_enc +{ + my ($self) = @_; + my ($s); + + return $self->{' mstable'}{'Encoding'} + if (defined $self->{' mstable'} && $self->{' mstable'}{'Platform'} == 3); + + foreach $s (@{$self->{'Tables'}}) + { + return $s->{'Encoding'} if ($s->{'Platform'} == 3); + } + return undef; +} + + +=head2 $t->out($fh) + +Writes out a cmap table to a filehandle. If it has not been read, then +just copies from input file to output + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($loc, $s, $i, $base_loc, $j, @keys); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + + $self->{'Tables'} = [sort {$a->{'Platform'} <=> $b->{'Platform'} + || $a->{'Encoding'} <=> $b->{'Encoding'} + || $a->{'Ver'} <=> $b->{'Ver'}} @{$self->{'Tables'}}]; + $self->{'Num'} = scalar @{$self->{'Tables'}}; + + $base_loc = $fh->tell(); + $fh->print(pack("n2", 0, $self->{'Num'})); + + for ($i = 0; $i < $self->{'Num'}; $i++) + { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); } + + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + if ($s->{'Format'} < 8) + { @keys = sort {$a <=> $b} grep { $_ <= 0xFFFF} keys %{$s->{'val'}}; } + else + { @keys = sort {$a <=> $b} keys %{$s->{'val'}}; } + $s->{' outloc'} = $fh->tell(); + if ($s->{'Format'} < 8) + { $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'})); } # come back for length + else + { $fh->print(pack("n2N2", $s->{'Format'}, 0, 0, $s->{'Ver'})); } + + if ($s->{'Format'} == 0) + { + $fh->print(pack("C256", map {defined $_ ? $_ : 0} @{$s->{'val'}}{0 .. 255})); + } elsif ($s->{'Format'} == 6) + { + $fh->print(pack("n2", $keys[0], $keys[-1] - $keys[0] + 1)); + $fh->print(pack("n*", map {defined $_ ? $_ : 0} @{$s->{'val'}}{$keys[0] .. $keys[-1]})); + } elsif ($s->{'Format'} == 2) # Contributed by Huw Rogers + { + my ($g, $k, $h, $l, $m, $n); + my (@subHeaderKeys, @subHeaders, $subHeader, @glyphIndexArray); + $n = 0; + @subHeaderKeys = (-1) x 256; + for $j (@keys) { + next unless defined($g = $s->{'val'}{$j}); + $h = int($j>>8); + $l = ($j & 0xff); + if (($k = $subHeaderKeys[$h]) < 0) { + $subHeader = [ $l, 1, 0, 0, [ $g ] ]; + $subHeaders[$k = $n++] = $subHeader; + $subHeaderKeys[$h] = $k; + } else { + $subHeader = $subHeaders[$k]; + $m = ($l - $subHeader->[0] + 1) - $subHeader->[1]; + $subHeader->[1] += $m; + push @{$subHeader->[4]}, (0) x ($m - 1), $g - $subHeader->[2]; + } + } + @subHeaderKeys = map { $_ < 0 ? 0 : $_ } @subHeaderKeys; + $subHeader = $subHeaders[0]; + $subHeader->[3] = 0; + push @glyphIndexArray, @{$subHeader->[4]}; + splice(@$subHeader, 4); + { + my @subHeaders_ = sort {@{$a->[4]} <=> @{$b->[4]}} @subHeaders[1..$#subHeaders]; + my ($f, $d, $r, $subHeader_); + for ($k = 0; $k < @subHeaders_; $k++) { + $subHeader = $subHeaders_[$k]; + $f = $r = shift @{$subHeader->[4]}; + $subHeader->[5] = join(':', + map { + $d = $_ - $r; + $r = $_; + $d < 0 ? + sprintf('-%04x', -$d) : + sprintf('+%04x', $d) + } @{$subHeader->[4]}); + unshift @{$subHeader->[4]}, $f; + } + for ($k = 0; $k < @subHeaders_; $k++) { + $subHeader = $subHeaders_[$k]; + next unless $subHeader->[4]; + $subHeader->[3] = @glyphIndexArray; + push @glyphIndexArray, @{$subHeader->[4]}; + for ($l = $k + 1; $l < @subHeaders_; $l++) { + $subHeader_ = $subHeaders_[$l]; + next unless $subHeader_->[4]; + $d = $subHeader_->[5]; + if ($subHeader->[5] =~ /\Q$d\E/) { + my $o = length($`)/6; #` + $subHeader_->[2] += + $subHeader_->[4]->[$o] - $subHeader->[4]->[0]; + $subHeader_->[3] = $subHeader->[3] + $o; + splice(@$subHeader_, 4); + } + } + splice(@$subHeader, 4); + } + } + $fh->print(pack('n*', map { $_<<3 } @subHeaderKeys)); + for ($j = 0; $j < 256; $j++) { + $k = $subHeaderKeys[$j]; + $subHeader = $subHeaders[$k]; + } + for ($k = 0; $k < $n; $k++) { + $subHeader = $subHeaders[$k]; + $fh->print(pack('n4', + $subHeader->[0], + $subHeader->[1], + $subHeader->[2] < 0 ? + unpack('S', pack('s', $subHeader->[2])) : + $subHeader->[2], + ($subHeader->[3]<<1) + (($n - $k)<<3) - 6 + )); + } + $fh->print(pack('n*', @glyphIndexArray)); + } elsif ($s->{'Format'} == 4) + { + my (@starts, @ends, @deltas, @range); + + # There appears to be a bug in Windows that requires the final 0xFFFF (sentry) + # to be in a segment by itself -- otherwise Windows 7 and 8 (at least) won't install + # or preview the font, complaining that it doesn't appear to be a valid font. + # Therefore we can't just add 0XFFFF to the USV list as we used to do: + # push(@keys, 0xFFFF) unless ($keys[-1] == 0xFFFF); + # Instead, for now *remove* 0xFFFF from the USV list, and add a segement + # for it after all the other segments are computed. + pop @keys if $keys[-1] == 0xFFFF; + + # Step 1: divide into maximal length idDelta runs + + my ($prevUSV, $prevgid); + for ($j = 0; $j <= $#keys; $j++) + { + my $u = $keys[$j]; + my $g = $s->{'val'}{$u}; + if ($j == 0 || $u != $prevUSV+1 || $g != $prevgid+1) + { + push @ends, $prevUSV unless $j == 0; + push @starts, $u; + push @range, 0; + } + $prevUSV = $u; + $prevgid = $g; + } + push @ends, $prevUSV; + + # Step 2: find each macro-range + + my ($start, $end); # Start and end of macro-range + for ($start = 0; $start < $#starts; $start++) + { + next if $ends[$start] - $starts[$start] > 7; # if count > 8, we always treat this as a run unto itself + for ($end = $start+1; $end <= $#starts; $end++) + { + last if $starts[$end] - $ends[$end-1] > ($self->{' allowholes'} ? 5 : 1) + || $ends[$end] - $starts[$end] > 7; # gap > 4 or count > 8 so $end is beyond end of macro-range + } + $end--; #Ending index of this macro-range + + # Step 3: optimize this macro-range (from $start through $end) + L1: for ($j = $start; $j < $end; ) + { + my $size1 = ($range[$j] ? 8 + 2 * ($ends[$j] - $starts[$j] + 1) : 8); # size of first range (which may now be idRange type) + for (my $k = $j+1; $k <= $end; $k++) + { + if (8 + 2 * ($ends[$k] - $starts[$j] + 1) <= $size1 + 8 * ($k - $j)) + { + # Need to coalesce $j..$k into $j: + $ends[$j] = $ends[$k]; + $range[$j] = 1; # for now use boolean to indicate this is an idRange segment + splice @starts, $j+1, $k-$j; + splice @ends, $j+1, $k-$j; + splice @range, $j+1, $k-$j; + $end -= ($k-$j); + next L1; # Note that $j isn't incremented so this is a redo + } + } + # Nothing coalesced + $j++; + } + + # Finished with this macro-range + $start = $end; + } + + # Ok, add the final segment containing the sentry value + push(@keys, 0xFFFF); + push @starts, 0xFFFF; + push @ends, 0xFFFF; + push @range, 0; + + # What is left is a collection of segments that will represent the cmap in mimimum-sized format 4 subtable + + my ($num, $count, $sRange, $eSel, $eShift); + + $num = scalar(@starts); + $count = 0; + for ($j = 0; $j < $num; $j++) + { + if ($range[$j]) + { + $range[$j] = ($count + $num - $j) << 1; + $count += $ends[$j] - $starts[$j] + 1; + push @deltas, 0; + } + else + { + push @deltas, ($s->{'val'}{$starts[$j]} || 0) - $starts[$j]; + } + } + + ($num, $sRange, $eSel, $eShift) = Font::TTF::Utils::TTF_bininfo($num, 2); + $fh->print(pack("n4", $num * 2, $sRange, $eSel, $eShift)); + $fh->print(pack("n*", @ends)); + $fh->print(pack("n", 0)); + $fh->print(pack("n*", @starts)); + $fh->print(pack("n*", @deltas)); + $fh->print(pack("n*", @range)); + + for ($j = 0; $j < $num; $j++) + { + next if ($range[$j] == 0); + $fh->print(pack("n*", map {$_ || 0} @{$s->{'val'}}{$starts[$j] .. $ends[$j]})); + } + } elsif ($s->{'Format'} == 8 || $s->{'Format'} == 12 || $s->{'Format'} == 13) + { + my (@jobs, $start, $current, $curr_glyf, $map); + + $current = 0; $curr_glyf = 0; + $map = "\000" x 8192; + foreach $j (@keys) + { + if ($j > 0xFFFF && $s->{'Format'} == 8) + { + if (defined $s->{'val'}{$j >> 16}) + { $s->{'Format'} = 12; } + vec($map, $j >> 16, 1) = 1; + } + if ($j != $current + 1 || $s->{'val'}{$j} != ($s->{'Format'} == 13 ? $curr_glyf : $curr_glyf + 1)) + { + push (@jobs, [$start, $current, $s->{'Format'} == 13 ? $curr_glyf : $curr_glyf - ($current - $start)]) if (defined $start); + $start = $j; $current = $j; $curr_glyf = $s->{'val'}{$j}; + } + $current = $j; + $curr_glyf = $s->{'val'}{$j}; + } + push (@jobs, [$start, $current, $s->{'Format'} == 13 ? $curr_glyf : $curr_glyf - ($current - $start)]) if (defined $start); + $fh->print($map) if ($s->{'Format'} == 8); + $fh->print(pack('N', $#jobs + 1)); + foreach $j (@jobs) + { $fh->print(pack('N3', @{$j})); } + } elsif ($s->{'Format'} == 10) + { + $fh->print(pack('N2', $keys[0], $keys[-1] - $keys[0] + 1)); + $fh->print(pack('n*', $s->{'val'}{$keys[0] .. $keys[-1]})); + } + + $loc = $fh->tell(); + if ($s->{'Format'} < 8) + { + $fh->seek($s->{' outloc'} + 2, 0); + $fh->print(pack("n", $loc - $s->{' outloc'})); + } else + { + $fh->seek($s->{' outloc'} + 4, 0); + $fh->print(pack("N", $loc - $s->{' outloc'})); + } + $fh->seek($base_loc + 8 + ($i << 3), 0); + $fh->print(pack("N", $s->{' outloc'} - $base_loc)); + $fh->seek($loc, 0); + } + $self; +} + + +=head2 $t->XML_element($context, $depth, $name, $val) + +Outputs the elements of the cmap in XML. We only need to process val here + +=cut + +sub XML_element +{ + my ($self, $context, $depth, $k, $val) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self if ($k eq 'LOC'); + return $self->SUPER::XML_element($context, $depth, $k, $val) unless ($k eq 'val'); + + $fh->print("$depth\n"); + foreach $i (sort {$a <=> $b} keys %{$val}) + { $fh->printf("%s\n", $depth . $context->{'indent'}, $i, $val->{$i}); } + $fh->print("$depth\n"); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be in bytes. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + + +=head2 $t->update + +Tidies the cmap table. + +Removes MS Fmt12 cmap if it is no longer needed. + +Removes from all cmaps any codepoint that map to GID=0. Note that such entries will +be re-introduced as necessary depending on the cmap format. + +=cut + +sub update +{ + my ($self) = @_; + my ($max, $code, $gid, @keep); + + return undef unless ($self->SUPER::update); + + foreach my $s (@{$self->{'Tables'}}) + { + $max = 0; + while (($code, $gid) = each %{$s->{'val'}}) + { + if ($gid) + { + # remember max USV + $max = $code if $max < $code; + } + else + { + # Remove unneeded key + delete $s->{'val'}{$code}; # nb: this is a safe delete according to perldoc perlfunc. + } + } + push @keep, $s unless $s->{'Platform'} == 3 && $s->{'Encoding'} == 10 && $s->{'Format'} == 12 && $max <= 0xFFFF; + } + + $self->{'Tables'} = [ @keep ]; + + delete $self->{' mstable'}; # Force rediscovery of this. + + $self; +} + +=head2 @map = $t->reverse(%opt) + +Returns a reverse map of the Unicode cmap. I.e. given a glyph gives the Unicode value for it. Options are: + +=over 4 + +=item tnum + +Table number to use rather than the default Unicode table + +=item array + +Returns each element of reverse as an array since a glyph may be mapped by more +than one Unicode value. The arrays are unsorted. Otherwise store any one unicode value for a glyph. + +=back + +=cut + +sub reverse +{ + my ($self, %opt) = @_; + my ($table) = defined $opt{'tnum'} ? $self->{'Tables'}[$opt{'tnum'}] : $self->find_ms; + my (@res, $code, $gid); + + while (($code, $gid) = each(%{$table->{'val'}})) + { + if ($opt{'array'}) + { push (@{$res[$gid]}, $code); } + else + { $res[$gid] = $code unless (defined $res[$gid] && $res[$gid] > 0 && $res[$gid] < $code); } + } + @res; +} + + +=head2 is_unicode($index) + +Returns whether the table of a given index is known to be a unicode table +(as specified in the specifications) + +=cut + +sub is_unicode +{ + my ($self, $index) = @_; + my ($pid, $eid) = ($self->{'Tables'}[$index]{'Platform'}, $self->{'Tables'}[$index]{'Encoding'}); + + return ($pid == 3 || $pid == 0 || ($pid == 2 && $eid == 1)); +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +Format 14 (Unicode Variation Sequences) cmaps are not supported. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Coverage.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Coverage.pm new file mode 100644 index 0000000000..db5ab26bcb --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Coverage.pm @@ -0,0 +1,351 @@ +package Font::TTF::Coverage; + +=head1 NAME + +Font::TTF::Coverage - Opentype coverage and class definition objects + +=head1 DESCRIPTION + +Coverage tables and class definition objects are virtually identical concepts +in OpenType. Their difference comes purely in their storage. Therefore we can +say that a coverage table is a class definition in which the class definition +for each glyph is the corresponding index in the coverage table. The resulting +data structure is that a Coverage table has the following fields: + +=over + +=item cover + +A boolean to indicate whether this table is a coverage table (TRUE) or a +class definition (FALSE) + +=item val + +A hash of glyph ids against values (either coverage index or class value) + +=item fmt + +The storage format used is given here, but is recalculated when the table +is written out. + +=item count + +A count of the elements in a coverage table for use with add. Each subsequent +addition is added with the current count and increments the count. + +=item max + +Maximum class value in a class table. + +=back + +=head1 METHODS + +=cut + +=head2 new($isCover [, vals]) + +Creates a new coverage table or class definition table, depending upon the +value of $isCover. if $isCover then vals may be a list of glyphs to include in order. +If no $isCover, then vals is a hash of glyphs against class values. + +=cut + +our $dontsort; + +sub new +{ + my ($class) = shift; + my ($isCover) = shift; + my ($self) = {}; + + $self->{'cover'} = $isCover; + if ($isCover) + { + $self->{'count'} = 0; + my ($v); + foreach $v (@_) + { $self->{'val'}{$v} = $self->{'count'}++; } + } + else + { + $self->{'max'} = 0; + $self->{'val'} = {@_}; + foreach (values %{$self->{'val'}}) {$self->{'max'} = $_ if $_ > $self->{'max'}} + } + bless $self, $class; +} + + +=head2 read($fh) + +Reads the coverage/class table from the given file handle + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat, $fmt, $num, $i, $c); + + $fh->read($dat, 4); + ($fmt, $num) = unpack("n2", $dat); + $self->{'fmt'} = $fmt; + + if ($self->{'cover'}) + { + if ($fmt == 1) + { + $fh->read($dat, $num << 1); + map {$self->{'val'}{$_} = $i++} unpack("n*", $dat); + $self->{'count'} = $num; + } elsif ($fmt == 2) + { + $fh->read($dat, $num * 6); + for ($i = 0; $i < $num; $i++) + { + ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6)); + map {$self->{'val'}{$_} = $c++} ($first .. $last); + } + $self->{'count'} = $c; + } + } elsif ($fmt == 1) + { + $fh->read($dat, 2); + $first = $num; + ($num) = unpack("n", $dat); + $fh->read($dat, $num << 1); + map {$self->{'val'}{$first++} = $_; $self->{'max'} = $_ if ($_ > $self->{'max'})} unpack("n*", $dat); + } elsif ($fmt == 2) + { + $fh->read($dat, $num * 6); + for ($i = 0; $i < $num; $i++) + { + ($first, $last, $c) = unpack("n3", substr($dat, $i * 6, 6)); + map {$self->{'val'}{$_} = $c} ($first .. $last); + $self->{'max'} = $c if ($c > $self->{'max'}); + } + } + $self; +} + + +=head2 out($fh, $state) + +Writes the coverage/class table to the given file handle. If $state is 1 then +the output string is returned rather than being output to a filehandle. + +=cut + +sub out +{ + my ($self, $fh, $state) = @_; + my ($g, $eff, $grp, $out); + my ($shipout) = ($state ? sub {$out .= $_[0];} : sub {$fh->print($_[0]);}); + my (@gids) = sort {$a <=> $b} keys %{$self->{'val'}}; + + if ($self->{'cover'}) + { $self->sort() unless ($self->{'dontsort'} or $dontsort); } + else + { @gids = grep {$self->{'val'}{$_} > 0} @gids;} # class value=0 is not explicitly coded in class table + + $fmt = 1; $grp = 1; $eff = 0; + for ($i = 1; $i <= $#gids; $i++) + { + if ($self->{'val'}{$gids[$i]} < $self->{'val'}{$gids[$i-1]} && $self->{'cover'}) + { + $fmt = 2; + last; + } elsif ($gids[$i] == $gids[$i-1] + 1 && ($self->{'cover'} || $self->{'val'}{$gids[$i]} == $self->{'val'}{$gids[$i-1]})) + { $eff++; } + else + { + $grp++; + $eff += $gids[$i] - $gids[$i-1] if (!$self->{'cover'}); + } + } +# if ($self->{'cover'}) + { $fmt = 2 if ($eff / $grp > 3 || scalar (@gids) == 0); } +# else +# { $fmt = 2 if ($grp > 1); } + + if ($fmt == 1 && $self->{'cover'}) + { + my ($last) = 0; + &$shipout(pack('n2', 1, scalar @gids)); + &$shipout(pack('n*', @gids)); + } elsif ($fmt == 1) + { + my ($last) = $gids[0]; + &$shipout(pack("n3", 1, $last, $gids[-1] - $last + 1)); + foreach $g (@gids) + { + if ($g > $last + 1) + { &$shipout(pack('n*', (0) x ($g - $last - 1))); } + &$shipout(pack('n', $self->{'val'}{$g})); + $last = $g; + } + } else + { + my ($start, $end, $ind, $numloc, $endloc, $num); + &$shipout(pack("n2", 2, 0)); + $numloc = $fh->tell() - 2 unless $state; + + $start = 0; $end = 0; $num = 0; + while ($end < $#gids) + { + if ($gids[$end + 1] == $gids[$end] + 1 + && $self->{'val'}{$gids[$end + 1]} + == $self->{'val'}{$gids[$end]} + + ($self->{'cover'} ? 1 : 0)) + { + $end++; + next; + } + + &$shipout(pack("n3", $gids[$start], $gids[$end], + $self->{'val'}{$gids[$start]})); + $start = $end + 1; + $end++; + $num++; + } + if (scalar(@gids)) + { + &$shipout(pack("n3", $gids[$start], $gids[$end], + $self->{'val'}{$gids[$start]})); + $num++; + } + if ($state) + { substr($out, 2, 2) = pack('n', $num); } + else + { + $endloc = $fh->tell(); + $fh->seek($numloc, 0); + $fh->print(pack("n", $num)); + $fh->seek($endloc, 0); + } + } + return ($state ? $out : $self); +} + + +=head2 $c->add($glyphid[, $class]) + +Adds a glyph id to the coverage or class table. +Returns the index or class number of the glyphid added. + +=cut + +sub add +{ + my ($self, $gid, $class) = @_; + + return $self->{'val'}{$gid} if (defined $self->{'val'}{$gid}); + if ($self->{'cover'}) + { + $self->{'val'}{$gid} = $self->{'count'}; + return $self->{'count'}++; + } + else + { + $self->{'val'}{$gid} = $class || '0'; + $self->{'max'} = $class if ($class > $self->{'max'}); + return $class; + } +} + + +=head2 $c->signature + +Returns a vector of all the glyph ids covered by this coverage table or class + +=cut + +sub signature +{ + my ($self) = @_; + my ($vec, $range, $size); + +if (0) +{ + if ($self->{'cover'}) + { $range = 1; $size = 1; } + else + { + $range = $self->{'max'}; + $size = 1; + while ($range > 1) + { + $size = $size << 1; + $range = $range >> 1; + } + $range = $self->{'max'} + 1; + } + foreach (keys %{$self->{'val'}}) + { vec($vec, $_, $size) = $self->{'val'}{$_} > $range ? $range : $self->{'val'}{$_}; } + length($vec) . ":" . $vec; +} + $vec = join(";", map{"$_,$self->{'val'}{$_}"} sort { $a <=> $b} keys %{$self->{'val'}}); +} + +=head2 @map=$c->sort + +Sorts the coverage table so that indexes are in ascending order of glyphid. +Returns a map such that $map[$new_index]=$old_index. + +=cut + +sub sort +{ + my ($self) = @_; + my (@res, $i); + + foreach (sort {$a <=> $b} keys %{$self->{'val'}}) + { + push(@res, $self->{'val'}{$_}); + $self->{'val'}{$_} = $i++; + } + @res; +} + +=head2 $c->out_xml($context) + +Outputs this coverage/class in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + + $fh->print("$depth<" . ($self->{'cover'} ? 'coverage' : 'class') . ">\n"); + foreach $gid (sort {$a <=> $b} keys %{$self->{'val'}}) + { + $fh->printf("$depth$context->{'indent'}\n", $gid, $self->{'val'}{$gid}); + } + $fh->print("$depth{'cover'} ? 'coverage' : 'class') . ">\n"); + $self; +} + +sub release +{ } + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Cvt_.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Cvt_.pm new file mode 100644 index 0000000000..d7695ac216 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Cvt_.pm @@ -0,0 +1,90 @@ +package Font::TTF::Cvt_; + +=head1 NAME + +Font::TTF::Cvt_ - Control Value Table in a TrueType font + +=head1 DESCRIPTION + +This is a minimal class adding nothing beyond a table, but is a repository +for cvt type information for those processes brave enough to address hinting. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item val + +This is an array of CVT values. Thus access to the CVT is via: + + $f->{'cvt_'}{'val'}[$num]; + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA $VERSION); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +$VERSION = 0.0001; + +=head2 $t->read + +Reads the CVT table into both the tables C<' dat'> variable and the C +array. + +=cut + +sub read +{ + my ($self) = @_; + + $self->read_dat || return undef; + $self->{' read'} = 1; + $self->{'val'} = [TTF_Unpack("s*", $self->{' dat'})]; + $self; +} + + +=head2 $t->update + +Updates the RAM file copy C<' dat'> to be the same as the array. + +=cut + +sub update +{ + my ($self) = @_; + + return undef unless ($self->{' read'} && $#{$self->{'val'}} >= 0); + $self->{' dat'} = TTF_Pack("s*", @{$self->{'val'}}); + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/DSIG.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/DSIG.pm new file mode 100644 index 0000000000..af9a24dc97 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/DSIG.pm @@ -0,0 +1,88 @@ +package Font::TTF::DSIG; + +use strict; +use vars qw(@ISA); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +sub create +{ + my ($class) = @_; + my ($self) = { 'version' => 1, 'numtables' => 0, 'perms' => 0 }; + bless $self, ref $class || $class; + return $self; +} + +sub read +{ + my ($self) = @_; + my ($dat, $i, @records, $r); + + $self->SUPER::read || return $self; + $self->{' INFILE'}->read($dat, 8); + ($self->{'version'}, $self->{'numtables'}, $self->{'perms'}) = unpack("Nnn", $dat); + for ($i = 0; $i < $self->{'numtables'}; $i++) + { + $self->{' INFILE'}->read($dat, 12); + push (@records, [unpack("N3", $dat)]); + } + foreach $r (@records) + { + if ($r->[0] == 1) + { + $self->{' INFILE'}->seek($self->{' OFFSET'} + $r->[2],0); + $self->{' INFILE'}->read($dat, $r->[1]); + push @{$self->{'records'}}, substr($dat, 8); + } + } + $self; +} + +sub isempty +{ + my ($self) = @_; + return $self->read->{'numtables'} == 0; +} + +sub out +{ + my ($self, $fh) = @_; + my ($i, $curlen); + + return $self->SUPER::out($fh) unless $self->{' read'}; # this is never true + $fh->print(pack("Nnn", $self->{'version'}, $self->{'numtables'}, $self->{'perms'})); + $curlen = 0; + for ($i = 0; $i < $self->{'numtables'}; $i++) + { + $fh->print(pack("N3", 1, length($self->{'records'}[$i]) + 8, $curlen + $self->{'numtables'} * 12 + 8)); + $curlen += length($self->{'records'}[$i]) + 8; + } + for ($i = 0; $i < $self->{'numtables'}; $i++) + { + $fh->print(pack("nnN", 0, 0, length($self->{'records'}[$i]))); + $fh->print($self->{'records'}[$i]); + } + $self; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Delta.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Delta.pm new file mode 100644 index 0000000000..718d49383e --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Delta.pm @@ -0,0 +1,186 @@ +package Font::TTF::Delta; + +=head1 NAME + +Font::TTF::Delta - Opentype Device tables + +=head1 DESCRIPTION + +Each device table corresponds to a set of deltas for a particular point over +a range of ppem values. + +=over + +=item first + +The first ppem value in the range + +=item last + +The last ppem value in the range + +=item val + +This is an array of deltas corresponding to each ppem in the range between +first and last inclusive. + +=item fmt + +This is the fmt used (log2 of number bits per value) when the device table was +read. It is recalculated on output. + +=back + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; + +=head2 new + +Creates a new device table + +=cut + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + bless $self, $class; +} + + +=head2 read + +Reads a device table from the given IO object at the current location + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat, $fmt, $num, $i, $j, $mask); + + $fh->read($dat, 6); + ($self->{'first'}, $self->{'last'}, $fmt) = TTF_Unpack("S3", $dat); + $self->{'fmt'} = $fmt; + + $fmt = 1 << $fmt; + $num = ((($self->{'last'} - $self->{'first'} + 1) * $fmt) + 15) >> 8; + $fh->read($dat, $num); + + $mask = (0xffff << (16 - $fmt)) & 0xffff; + $j = 0; + for ($i = $self->{'first'}; $i <= $self->{'last'}; $i++) + { + if ($j == 0) + { + $num = TTF_Unpack("S", substr($dat, 0, 2)); + substr($dat, 0, 2) = ''; + } + push (@{$self->{'val'}}, ($num & $mask) >> (16 - $fmt)); + $num <<= $fmt; + $j += $fmt; + $j = 0 if ($j >= 16); + } + $self; +} + + +=head2 out($fh, $style) + +Outputs a device table to the given IO object at the current location, or just +returns the data to be output if $style != 0 + +=cut + +sub out +{ + my ($self, $fh, $style) = @_; + my ($dat, $fmt, $num, $mask, $j, $f, $out); + + foreach $f (@{$self->{'val'}}) + { + my ($tfmt) = $f > 0 ? $f + 1 : -$f; + $fmt = $tfmt if $tfmt > $fmt; + } + + if ($fmt > 8) + { $fmt = 3; } + elsif ($fmt > 2) + { $fmt = 2; } + else + { $fmt = 1; } + + $out = TTF_Pack("S3", $self->{'first'}, $self->{'last'}, $fmt); + + $fmt = 1 << $fmt; + $mask = 0xffff >> (16 - $fmt); + $j = 0; $dat = 0; + foreach $f (@{$self->{'val'}}) + { + $dat |= ($f & $mask) << (16 - $fmt - $j); + $j += $fmt; + if ($j >= 16) + { + $j = 0; + $out .= TTF_Pack("S", $dat); + $dat = 0; + } + } + $out .= pack('n', $dat) if ($j > 0); + $fh->print($out) unless $style; + $out; +} + +=head2 $d->signature() + +Returns a content based identifying string for this delta for +compression purposes + +=cut + +sub signature +{ + my ($self) = @_; + return join (",", $self->{'first'}, $self->{'last'}, @{$self->{'val'}}); +} + + +=head2 $d->out_xml($context) + +Outputs a delta in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + + $fh->printf("%s\n", $depth, $self->{'first'}, $self->{'last'}); + $fh->print("$depth$context->{'indent'}" . join (' ', @{$self->{'val'}}) . "\n") if defined ($self->{'val'}); + $fh->print("$depth\n"); +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Dumper.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Dumper.pm new file mode 100644 index 0000000000..ffb8e17203 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Dumper.pm @@ -0,0 +1,97 @@ +package Font::TTF::Dumper; + +=head1 NAME + +Font::TTF::Dumper - Debug dump of a font datastructure, avoiding recursion on ' PARENT' + +=head1 SYNOPSIS + + use Font::TTF::Dumper; + + # Print a table from the font structure: + print ttfdump($font->{$tag}); + + # Print font table with name + print ttfdump($font->{'head'}, 'head'); + + # Print font table with name and other options + print ttfdump($font->{'head'}, 'head', %opts); + + # Print one glyph's data: + print ttfdump($font->{'loca'}->read->{'glyphs'}[$gid], "glyph_$gid"); + +=head1 DESCRIPTION + +Font::TTF data structures are trees created from hashes and arrays. When trying to figure +out how the structures work, sometimes it is helpful to use Data::Dumper on them. However, +many of the object structures have ' PARENT' links that refer back to the object's parent, +which means that Data::Dumper ends up dumping the whole font no matter what. + +The main purpose of this module is to invoke Data::Dumper with a +filter that skips over the ' PARENT' element of any hash. + +To reduce output further, this module also skips over ' CACHE' elements and any +hash element whose value is a Font::TTF::Glyph or Font::TTF::Font object. +(Really should make this configurable.) + +If $opts{'d'}, then set Deepcopy mode to minimize use of crossreferencing. + +=cut + +use strict; +use Data::Dumper; + +use vars qw(@EXPORT @ISA); +require Exporter; +@ISA = qw( Exporter ); +@EXPORT = qw( ttfdump ); + +my %skip = ( Font => 1, Glyph => 1 ); + +sub ttfdump +{ + my ($var, $name, %opts) = @_; + my $res; + + my $d = Data::Dumper->new([$var]); + $d->Names([$name]) if defined $name; + $d->Sortkeys(\&myfilter); # This is the trick to keep from dumping the whole font + $d->Deepcopy($opts{'d'}); # Caller controls whether to use crossreferencing + $d->Indent(3); # I want array indicies + $d->Useqq(1); # Perlquote -- slower but there might be binary data. + $res = $d->Dump; + $d->DESTROY; + $res; +} + +sub myfilter +{ + my ($hash) = @_; + my @a = grep { + ($_ eq ' PARENT' || $_ eq ' CACHE') ? 0 : + ref($hash->{$_}) =~ m/^Font::TTF::(.*)$/ ? !$skip{$1} : + 1 + } (keys %{$hash}) ; + # Sort numerically if that is reasonable: + return [ sort {$a =~ /\D/ || $b =~ /\D/ ? $a cmp $b : $a <=> $b} @a ]; +} + +1; + + +=head1 AUTHOR + +Bob Hallissy L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/EBDT.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/EBDT.pm new file mode 100644 index 0000000000..6ba07a550d --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/EBDT.pm @@ -0,0 +1,311 @@ +package Font::TTF::EBDT; + +=head1 NAME + +Font::TTF::EBDT - Embeeded Bitmap Data Table + +=head1 DESCRIPTION + +Contains the metrics and bitmap image data. + +=head1 INSTANCE VARIABLES + +Only has 'bitmap' instance variable. It is an array of assosiative +array keyed by glyph-id. The element is an object which consists +of metric information and image data. + +=over 4 + +=item bitmap object + +=over 8 + +=item format + +Only 7 is supported. + +=item height + +=item width + +=item horiBearingX + +=item horiBearingY + +=item horiAdvance + +=item vertBearingX + +=item vertBearingY + +=item vertAdvance + +=item imageData + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the embedded bitmap data from the TTF file into memory. +This routine should be called _after_ {'EBLC'}->read. + +=cut + +sub read +{ + my ($self) = shift; + my ($fh); + my ($i, $dat); + my ($eblc) = $self->{' PARENT'}->{'EBLC'}; + my ($bst_array); + + $eblc->read; + $self->SUPER::read || return $self; + $fh = $self->{' INFILE'}; + + # ebdtHeader + $fh->read($dat, 4); # version + + $bst_array = $eblc->{'bitmapSizeTable'}; + + for ($i = 0; $i < $eblc->{'Num'}; $i++) + { + my ($bst) = $bst_array->[$i]; + my ($format) = $bst->{'imageFormat'}; + my ($offset) = $bst->{'imageDataOffset'}; + my ($j); + my ($ist_array) = $eblc->{'indexSubTableArray'}[$i]; + my ($bitmap) = {}; + + die "Only EBDT format 7 is implemented." unless ($format == 7); + + $self->{'bitmap'}[$i] = $bitmap; + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + my ($ista) = $ist_array->[$j]; + my ($offsetArray) = $eblc->{'indexSubTable'}[$i][$j]; + my ($p, $o0, $c); + +# if ($fh->tell != $self->{' OFFSET'} + $offset) { +# $fh->seek($self->{' OFFSET'} + $offset, 0); +# } + + $p = 0; + $o0 = $offsetArray->[$p++]; + for ($c = $ista->{'firstGlyphIndex'}; $c <= $ista->{'lastGlyphIndex'}; $c++) + { + my ($b) = {}; + my ($o1) = $offsetArray->[$p++]; + my ($len) = $o1 - $o0 - 8; + +# if ($fh->tell != $self->{' OFFSET'} + $offset + $o0) { +# $fh->seek($self->{' OFFSET'} + $offset + $o0, 0); +# } + + $fh->read($dat, 8); + ($b->{'height'}, + $b->{'width'}, + $b->{'horiBearingX'}, + $b->{'horiBearingY'}, + $b->{'horiAdvance'}, + $b->{'vertBearingX'}, + $b->{'vertBearingY'}, + $b->{'vertAdvance'}) + = unpack("cccccccc", $dat); + + $fh->read($dat, $len); + $b->{'imageData'} = $dat; + $b->{'format'} = 7; # bitmap and bigMetrics + + $bitmap->{$c} = $b; + $o0 = $o1; + } + + $offset += $o0; + } + } + + $self; +} + + +=head2 $t->update + +Update EBLC information using EBDT data. + +=cut + +sub get_regions +{ + my (@l) = @_; + my (@r) = (); + my ($e); + my ($first); + my ($last); + + $first = $l[0]; + $last = $first - 1; + foreach $e (@l) { + if ($last + 1 != $e) { # not contiguous + $r[++$#r] = [$first, $last]; + $first = $e; + } + + $last = $e; + } + + $r[++$#r] = [$first, $last]; + @r; +} + +sub update +{ + my ($self) = @_; + my ($eblc) = $self->{' PARENT'}->{'EBLC'}; + my ($bst_array) = []; + my ($offset) = 4; + my ($i); + my ($bitmap_array) = $self->{'bitmap'}; + my ($istao) = 8 + 48 * $eblc->{'Num'}; + + $eblc->{'bitmapSizeTable'} = $bst_array; + + for ($i = 0; $i < $eblc->{'Num'}; $i++) { + my ($bst) = {}; + my ($ist_array) = []; + my ($j); + my ($bitmap) = $bitmap_array->[$i]; + my (@regions) = get_regions(sort {$a <=> $b} keys (%$bitmap)); + my ($aotis) = 8 * (1+$#regions); + + $bst->{'indexFormat'} = 1; + $bst->{'imageFormat'} = 7; + $bst->{'imageDataOffset'} = $offset; + $bst->{'numberOfIndexSubTables'} = 1+$#regions; + $bst->{'indexSubTableArrayOffset'} = $istao; + $bst->{'colorRef'} = 0; + + $bst->{'startGlyphIndex'} = $regions[0][0]; + $bst->{'endGlyphIndex'} = $regions[-1][1]; + $bst->{'bitDepth'} = 1; + $bst->{'flags'} = 1; # Horizontal + $bst_array->[$i] = $bst; + + $eblc->{'indexSubTableArray'}[$i] = $ist_array; + for ($j = 0; $j <= $#regions; $j++) { + my ($ista) = {}; + my ($offsetArray) = []; + my ($p, $o0, $c); + $ist_array->[$j] = $ista; + + $ista->{'firstGlyphIndex'} = $regions[$j][0]; + $ista->{'lastGlyphIndex'} = $regions[$j][1]; + $ista->{'additionalOffsetToIndexSubtable'} = $aotis; + $eblc->{'indexSubTable'}[$i][$j] = $offsetArray; + $p = 0; + $o0 = 0; + for ($c = $regions[$j][0]; $c <= $regions[$j][1]; $c++) { + my ($b) = $bitmap->{$c}; + + $offsetArray->[$p++] = $o0; + $o0 += 8 + length($b->{'imageData'}); + } + + $offsetArray->[$p++] = $o0; + + $aotis += ($regions[$j][1] - $regions[$j][0] + 1 + 1)*4; + $offset += $o0; + + # Do we need the element of 0x10007 and absolute offset here, + # at the end of offsetArray? +# if ($j + 1 <= $#regions) { +# $offsetArray->[$p++] = 0x10007; +# $offsetArray->[$p++] = $offset; +# $aotis += 8; +# } + } + + $istao += $aotis + 8; + $bst->{'indexTablesSize'} = $aotis + 8; + } +} + +=head2 $t->out($fh) + +Outputs the bitmap data of embedded bitmap for this font. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my ($eblc) = $self->{' PARENT'}->{'EBLC'}; + my ($i); + my ($bitmap_array) = $self->{'bitmap'}; + + $fh->print(pack("N", 0x00020000)); + + for ($i = 0; $i < $eblc->{'Num'}; $i++) { + my ($j); + my ($bitmap) = $bitmap_array->[$i]; + my (@regions) = get_regions(sort {$a <=> $b} keys (%$bitmap)); + + for ($j = 0; $j <= $#regions; $j++) { + my ($c); + + for ($c = $regions[$j][0]; $c <= $regions[$j][1]; $c++) { + my ($b) = $bitmap->{$c}; + + $fh->print(pack("cccccccc", + $b->{'height'}, $b->{'width'}, + $b->{'horiBearingX'}, $b->{'horiBearingY'}, + $b->{'horiAdvance'}, $b->{'vertBearingX'}, + $b->{'vertBearingY'}, $b->{'vertAdvance'})); + $fh->print($b->{'imageData'}); + } + } + } +} + +1; + +=head1 BUGS + +Only Format 7 is implemented. XML output is not supported (yet). + +=head1 AUTHOR + +NIIBE Yutaka L. +This was written at the CodeFest Akihabara 2006 hosted by FSIJ. + +?? patch sent with licensing requirements or not? + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/EBLC.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/EBLC.pm new file mode 100644 index 0000000000..2eca08cbcc --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/EBLC.pm @@ -0,0 +1,259 @@ +package Font::TTF::EBLC; + +=head1 NAME + +Font::TTF::EBLC - Embeeded Bitmap Location Table + +=head1 DESCRIPTION + +Contains the sizes and glyph ranges of bitmaps, and the offsets to +glyph bitmap data in indexSubTables for EBDT. + +Possibly contains glyph metrics information. + +=head1 INSTANCE VARIABLES + +The information specified 'B<(R)>ead only' is read only, those +are calculated from EBDT, when it is 'update'-ed. + +=over 4 + +=item bitmapSizeTable + +An array of tables of following information + +=over 8 + +=item indexSubTableArrayOffset (R) + +=item indexTablesSize (R) + +=item numberOfIndexSubTables (R) + +=item colorRef + +=item hori + +=item vert + +=item startGlyphIndex (R) + +=item endGlyphIndex (R) + +=item ppemX + +=item ppemY + +=item bitDepth + +=item flags + +=back + +=item indexSubTableArray (R) + +An array which contains range information. + +=item indexSubTable (R) + +An array which contains offsets of EBDT table. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the location information of embedded bitmap from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($i, $dat); + my ($indexSubTableArrayOffset, + $indexTablesSize, + $numberOfIndexSubTables, + $colorRef); + my ($startGlyphIndex, + $endGlyphIndex, + $ppemX, $ppemY, + $bitDepth, $flags); + my (@hori, @vert); + my ($bst, $ista, $ist); + my ($j); + + + # eblcHeader + $fh->read($dat, 4); + $self->{'version'} = unpack("N",$dat); + + $fh->read($dat, 4); + $self->{'Num'} = unpack("N",$dat); + + # bitmapSizeTable + for ($i = 0; $i < $self->{'Num'}; $i++) { + $fh->read($dat, 16); + ($indexSubTableArrayOffset, $indexTablesSize, + $numberOfIndexSubTables, $colorRef) = unpack("NNNN", $dat); + $fh->read($dat, 12); @hori = unpack("cccccccccccc", $dat); + $fh->read($dat, 12); @vert = unpack("cccccccccccc", $dat); + + $fh->read($dat, 8); + ($startGlyphIndex, $endGlyphIndex, + $ppemX, $ppemY, $bitDepth, $flags) = unpack("nnCCCC", $dat); + + $self->{'bitmapSizeTable'}[$i] = { + 'indexSubTableArrayOffset' => $indexSubTableArrayOffset, + 'indexTablesSize' => $indexTablesSize, + 'numberOfIndexSubTables' => $numberOfIndexSubTables, + 'colorRef' => $colorRef, + 'hori' => [@hori], + 'vert' => [@vert], + 'startGlyphIndex' => $startGlyphIndex, + 'endGlyphIndex' => $endGlyphIndex, + 'ppemX' => $ppemX, + 'ppemY' => $ppemY, + 'bitDepth' => $bitDepth, + 'flags' => $flags + }; + } + + for ($i = 0; $i < $self->{'Num'}; $i++) { + my ($count, $x); + + $bst = $self->{'bitmapSizeTable'}[$i]; + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + $ista = {}; + + # indexSubTableArray + $self->{'indexSubTableArray'}[$i][$j] = $ista; + $fh->read($dat, 8); + ($ista->{'firstGlyphIndex'}, + $ista->{'lastGlyphIndex'}, + $ista->{'additionalOffsetToIndexSubtable'}) + = unpack("nnN", $dat); + } + + # indexSubTable + # indexSubHeader + $fh->read($dat, 8); + ($bst->{'indexFormat'}, + $bst->{'imageFormat'}, + $bst->{'imageDataOffset'}) = unpack("nnN", $dat); + + die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1); + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + $ista = $self->{'indexSubTableArray'}[$i][$j]; + $count = $ista->{'lastGlyphIndex'} - $ista->{'firstGlyphIndex'} + 1 + 1; + $fh->seek($self->{' OFFSET'} + $bst->{'indexSubTableArrayOffset'} + + $ista->{'additionalOffsetToIndexSubtable'} + 8, 0); + +# $count += 2 if $j < $bst->{'numberOfIndexSubTables'} - 1; + + $fh->read($dat, 4*$count); + + $self->{'indexSubTable'}[$i][$j] = [unpack("N*", $dat)]; + } + } + + $self; +} + +=head2 $t->out($fh) + +Outputs the location information of embedded bitmap for this font. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my ($bst_array) = $self->{'bitmapSizeTable'}; + + $fh->print(pack("N", 0x00020000)); + $fh->print(pack("N", $self->{'Num'})); + + for ($i = 0; $i < $self->{'Num'}; $i++) { + my ($bst) = $bst_array->[$i]; + + $fh->print(pack("NNNN", + $bst->{'indexSubTableArrayOffset'}, + $bst->{'indexTablesSize'}, + $bst->{'numberOfIndexSubTables'}, + $bst->{'colorRef'})); + $fh->print(pack("cccccccccccc", @{$bst->{'hori'}})); + $fh->print(pack("cccccccccccc", @{$bst->{'vert'}})); + $fh->print(pack("nnCCCC", $bst->{'startGlyphIndex'}, + $bst->{'endGlyphIndex'}, $bst->{'ppemX'}, + $bst->{'ppemY'}, $bst->{'bitDepth'}, $bst->{'flags'})); + } + + for ($i = 0; $i < $self->{'Num'}; $i++) { + my ($bst) = $bst_array->[$i]; + my ($j); + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + my ($ista) = $self->{'indexSubTableArray'}[$i][$j]; + + $fh->print("nnN", + $ista->{'firstGlyphIndex'}, + $ista->{'lastGlyphIndex'}, + $ista->{'additionalOffsetToIndexSubtable'}); + } + + $fh->print(pack("nnN", $bst->{'indexFormat'}, $bst->{'imageFormat'}, + $bst->{'imageDataOffset'})); + + die "Only indexFormat == 1 is supported" unless ($bst->{'indexFormat'} == 1); + + for ($j = 0; $j < $bst->{'numberOfIndexSubTables'}; $j++) { + $fh->print(pack("N*", $self->{'indexSubTable'}[$i][$j])); + } + } +} + +1; + +=head1 BUGS + +Only indexFormat ==1 is implemented. XML output is not supported (yet). + +=head1 AUTHOR + +NIIBE Yutaka L. +This was written at the CodeFest Akihabara 2006 hosted by FSIJ. + +Patch sent with licensing requirements?? + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fdsc.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fdsc.pm new file mode 100644 index 0000000000..d919caeb9b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fdsc.pm @@ -0,0 +1,138 @@ +package Font::TTF::Fdsc; + +=head1 NAME + +Font::TTF::Fdsc - Font Descriptors table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +=item descriptors + +Hash keyed by descriptor tags + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh, $numDescs, $tag, $descs); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + $fh->read($dat, 4); + $self->{'version'} = TTF_Unpack("v", $dat); + + $fh->read($dat, 4); + + foreach (1 .. unpack("N", $dat)) { + $fh->read($tag, 4); + $fh->read($dat, 4); + $descs->{$tag} = ($tag eq 'nalf') ? unpack("N", $dat) : TTF_Unpack("f", $dat); + } + + $self->{'descriptors'} = $descs; + + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($descs); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $fh->print(TTF_Pack("v", $self->{'version'})); + + $descs = $self->{'descriptors'} || {}; + + $fh->print(pack("N", scalar keys %$descs)); + foreach (sort keys %$descs) { + $fh->print($_); + $fh->print(($_ eq 'nalf') ? pack("N", $descs->{$_}) : TTF_Pack("f", $descs->{$_})); + } + + $self; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($descs, $k); + + $self->read; + + $fh = 'STDOUT' unless defined $fh; + + $descs = $self->{'descriptors'}; + foreach $k (sort keys %$descs) { + if ($k eq 'nalf') { + $fh->printf("Descriptor '%s' = %d\n", $k, $descs->{$k}); + } + else { + $fh->printf("Descriptor '%s' = %f\n", $k, $descs->{$k}); + } + } + + $self; +} + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Feat.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Feat.pm new file mode 100644 index 0000000000..90f8d58f13 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Feat.pm @@ -0,0 +1,215 @@ +package Font::TTF::Feat; + +=head1 NAME + +Font::TTF::Feat - Font Features + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over 4 + +=item version + +=item features + +An array of hashes of the following form + +=over 8 + +=item feature + +feature id number + +=item name + +name index in name table + +=item exclusive + +exclusive flag + +=item settings + +hash of setting number against name string index + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +use Font::TTF::Utils; + +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the features from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($featureCount, $features); + + $self->SUPER::read_dat or return $self; + + ($self->{'version'}, $featureCount) = TTF_Unpack("vS", $self->{' dat'}); + + $features = []; + foreach (1 .. $featureCount) { + my ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex) + = TTF_Unpack("SSLSS", substr($self->{' dat'}, $_ * 12, 12)); + push @$features, + { + 'feature' => $feature, + 'name' => $nameIndex, + 'exclusive' => (($featureFlags & 0x8000) != 0), + 'settings' => { TTF_Unpack("S*", substr($self->{' dat'}, $settingTable, $nSettings * 4)) } + }; + } + $self->{'features'} = $features; + + delete $self->{' dat'}; # no longer needed, and may become obsolete + + $self; +} + +=head2 $t->out($fh) + +Writes the features to a TTF file + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($features, $numFeatures, $settings, $featuresData, $settingsData); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $features = $self->{'features'}; + $numFeatures = @$features; + + foreach (@$features) { + $settings = $_->{'settings'}; + $featuresData .= TTF_Pack("SSLSS", + $_->{'feature'}, + scalar keys %$settings, + 12 + 12 * $numFeatures + length $settingsData, + ($_->{'exclusive'} ? 0x8000 : 0x0000), + $_->{'name'}); + foreach (sort {$a <=> $b} keys %$settings) { + $settingsData .= TTF_Pack("SS", $_, $settings->{$_}); + } + } + + $fh->print(TTF_Pack("vSSL", $self->{'version'}, $numFeatures, 0, 0)); + $fh->print($featuresData); + $fh->print($settingsData); + + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($names, $features, $settings); + + $self->read; + + $names = $self->{' PARENT'}->{'name'}; + $names->read; + + $fh = 'STDOUT' unless defined $fh; + + $features = $self->{'features'}; + foreach (@$features) { + $fh->printf("Feature %d, %s, name %d # '%s'\n", + $_->{'feature'}, + ($_->{'exclusive'} ? "exclusive" : "additive"), + $_->{'name'}, + $names->{'strings'}[$_->{'name'}][1][0]{0}); + $settings = $_->{'settings'}; + foreach (sort { $a <=> $b } keys %$settings) { + $fh->printf("\tSetting %d, name %d # '%s'\n", + $_, $settings->{$_}, $names->{'strings'}[$settings->{$_}][1][0]{0}); + } + } + + $self; +} + +sub settingName +{ + my ($self, $feature, $setting) = @_; + + $self->read; + + my $names = $self->{' PARENT'}->{'name'}; + $names->read; + + my $features = $self->{'features'}; + my ($featureEntry) = grep { $_->{'feature'} == $feature } @$features; + my $featureName = $names->{'strings'}[$featureEntry->{'name'}][1][0]{0}; + my $settingName = $featureEntry->{'exclusive'} + ? $names->{'strings'}[$featureEntry->{'settings'}->{$setting}][1][0]{0} + : $names->{'strings'}[$featureEntry->{'settings'}->{$setting & ~1}][1][0]{0} + . (($setting & 1) == 0 ? " On" : " Off"); + + ($featureName, $settingName); +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Cvar.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Cvar.pm new file mode 100644 index 0000000000..3b8f9c183c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Cvar.pm @@ -0,0 +1,165 @@ +package Font::TTF::Features::Cvar; + +=head1 NAME + +Font::TTF::Features::Size - Class for Character Variants Feature Parameters + +=head1 DESCRIPTION + +Handles the Feature Parameters valus forCharacter Variants features + +=head1 INSTANCE VARIABLES + +=over 4 + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item Format + +Table format - set to 0 + +=item UINameID + +The 'name' table name ID that specifies a string (or strings, for multiple +languages) for a user-interface label for this feature + +=item TooltipNameID + +The 'name' table name ID for tooltip text for the feature + +=item SampleTextNameID + +The 'name' table name ID for sample text to illustrate the feature + +=item NumNamedParms + +The number of named parameters + +=item FirstNamedParmID + +The 'name' table name ID for the first named parameter + +=item Characters + +An array holding the unicode values of the characters for which the feature +provides glyph variants + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Utils; +use strict; + +=head2 $t->read + +Reads the Feature Params + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($off) = $self->{' OFFSET'}; + my ($dat, $i, $charcount); + $fh->seek($off, 0); + $fh->read($dat, 14); + ( $self->{'Format'} + ,$self->{'UINameID'} + ,$self->{'TooltipNameID'} + ,$self->{'SampleTextNameID'} + ,$self->{'NumNamedParm'} + ,$self->{'FirstNamedParmID'} + ,$charcount ) = TTF_Unpack("S*", $dat); + +# Now read the list of characters. Since these are 24bit insigned integers, need to +# read add a zero value byte to the front then treat as a 32bit integer + + foreach $i (0 .. $charcount-1) + { + $fh->read($dat,3); + $dat = pack("C","0") . $dat; + $self->{'Characters'}->[$i] = TTF_Unpack("L",$dat); + } + + return $self; +} + +=head2 $t->out($fh) + +Writes the FeatureParams table to the output + +=cut + + + +sub out +{ + my ($self, $fh) = @_; + my $chars = $self->{'Characters'}; + my $charcount = 0; + if ($chars) { $charcount = scalar @{$chars} } + my ($dat, $i); + + $fh->print(TTF_Pack("S*" + ,$self->{'Format'} + ,$self->{'UINameID'} + ,$self->{'TooltipNameID'} + ,$self->{'SampleTextNameID'} + ,$self->{'NumNamedParms'} + ,$self->{'FirstNamedParmID'} + ,$charcount )); + + foreach $i ( 0 .. $charcount-1) + { + $dat = substr ( TTF_Pack("L",$chars->[$i]) ,1,3); # Pack as long then remove first byte to get UINT22 + $fh->print($dat); + } + + $self; +} + +=head2 Font::TTF::Features::Sset->new() + +Creates a new FeatureParams object. +Values for INFILE and OFFSET canbe passed as parameters + +=cut + +sub new +{ + my ($class,%parms) = @_; + my ($self) = {}; + my ($p); + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +sub out_xml +{ +} + +1; + +=head1 AUTHOR + +David Raymond L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Size.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Size.pm new file mode 100644 index 0000000000..74c1ce5fb4 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Size.pm @@ -0,0 +1,131 @@ +package Font::TTF::Features::Size; + +=head1 NAME + +Font::TTF::Features::Size - Class for Size Feature Parameters + +=head1 DESCRIPTION + +Handles the Feature Parameters valus for Size features + +=head1 INSTANCE VARIABLES + +=over 4 + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item DesignSize + +Design Size in decipoints + +=item SubFID + +Identifier for the fonts in a subfamily + +=item SubFNameID + +The 'name' table name ID for the subfamily name + +=item MinSize + +Bottom end of recomended usage size range + +=item MaxSize + +Top end of recomended usage size range + + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Utils; +use strict; + +=head2 $t->read + +Reads the Feature Params + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($off) = $self->{' OFFSET'}; + my $dat; + $fh->seek($off, 0); + $fh->read($dat, 10); + + ( $self->{'DesignSize'} + ,$self->{'SubFID'} + ,$self->{'SubFNameID'} + ,$self->{'MinSize'} + ,$self->{'MaxSize'} ) = TTF_Unpack("S*", $dat); + + return $self; +} + +=head2 $t->out($fh) + +Writes the FeatureParams table to the output + +=cut + +sub out +{ + my ($self, $fh) = @_; + + $fh->print(TTF_Pack("S*" + ,$self->{'DesignSize'} + ,$self->{'SubFID'} + ,$self->{'SubFNameID'} + ,$self->{'MinSize'} + ,$self->{'MaxSize'} )); + $self; +} + +=head2 Font::TTF::Features::Sset->new() + +Creates a new FeatureParams object. Table instance variables are passed in +at this point as an associative array. + +=cut + +sub new +{ + my ($class,%parms) = @_; + my ($self) = {}; + my ($p); + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +sub out_xml +{ +} + +1; + +=head1 AUTHOR + +David Raymond L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Sset.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Sset.pm new file mode 100644 index 0000000000..78d4fe69c5 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Features/Sset.pm @@ -0,0 +1,108 @@ +package Font::TTF::Features::Sset; + +=head1 NAME + +Font::TTF::Features::Sset - Class for Stylistic Set Feature Parameters + +=head1 DESCRIPTION + +Handles the Feature Parameters valus for Stylistic Sets + +=head1 INSTANCE VARIABLES + +=over 4 + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item Version + +The minor version number, currently always 0 + +=item UINameID + +The 'name' table name ID that specifies a string (or strings, for multiple +languages) for a user-interface label for this feature + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Utils; +use strict; + +=head2 $t->read + +Reads the Feature Params + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($off) = $self->{' OFFSET'}; + my $dat; + $fh->seek($off, 0); + $fh->read($dat, 4); + ($self->{'Version'}, $self->{'UINameID'}) = TTF_Unpack("SS", $dat); + + return $self; +} + +=head2 $t->out($fh) + +Writes the FeatureParams table to the output + +=cut + +sub out +{ + my ($self, $fh) = @_; + $fh->print(TTF_Pack("S", $self->{'Version'})); + $fh->print(TTF_Pack("S", $self->{'UINameID'})); + $self; +} + +=head2 Font::TTF::Features::Sset->new() + +Creates a new FeatureParams object. +Values for INFILE and OFFSET canbe passed as parameters + +=cut + +sub new +{ + my ($class,%parms) = @_; + my ($self) = {}; + my ($p); + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +sub out_xml +{ +} + +1; + +=head1 AUTHOR + +David Raymond L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fmtx.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fmtx.pm new file mode 100644 index 0000000000..f7640a7456 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fmtx.pm @@ -0,0 +1,118 @@ +package Font::TTF::Fmtx; + +=head1 NAME + +Font::TTF::Fmtx - Font Metrics table + +=head1 DESCRIPTION + +This is a simple table with just standards specified instance variables + +=head1 INSTANCE VARIABLES + + version + glyphIndex + horizontalBefore + horizontalAfter + horizontalCaretHead + horizontalCaretBase + verticalBefore + verticalAfter + verticalCaretHead + verticalCaretBase + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'glyphIndex' => 'L', + 'horizontalBefore' => 'c', + 'horizontalAfter' => 'c', + 'horizontalCaretHead' => 'c', + 'horizontalCaretBase' => 'c', + 'verticalBefore' => 'c', + 'verticalAfter' => 'c', + 'verticalCaretHead' => 'c', + 'verticalCaretBase' => 'c'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory as instance variables + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + init unless defined $fields{'glyphIndex'}; + $self->{' INFILE'}->read($dat, 16); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $fh->print(TTF_Out_Fields($self, \%fields, 16)); + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Font.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Font.pm new file mode 100644 index 0000000000..2dd5f22355 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Font.pm @@ -0,0 +1,927 @@ +package Font::TTF::Font; + +=head1 NAME + +Font::TTF::Font - Memory representation of a font + +=head1 SYNOPSIS + +Here is the regression test (you provide your own font). Run it once and then +again on the output of the first run. There should be no differences between +the outputs of the two runs. + + $f = Font::TTF::Font->open($ARGV[0]); + + # force a read of all the tables + $f->tables_do(sub { $_[0]->read; }); + + # force read of all glyphs (use read_dat to use lots of memory!) + # $f->{'loca'}->glyphs_do(sub { $_[0]->read; }); + $f->{'loca'}->glyphs_do(sub { $_[0]->read_dat; }); + # NB. no need to $g->update since $f->{'glyf'}->out will do it for us + + $f->out($ARGV[1]); + $f->release; # clear up memory forcefully! + +=head1 DESCRIPTION + +A Truetype font consists of a header containing a directory of tables which +constitute the rest of the file. This class holds that header and directory and +also creates objects of the appropriate type for each table within the font. +Note that it does not read each table into memory, but creates a short reference +which can be read using the form: + + $f->{$tablename}->read; + +Classes are included that support many of the different TrueType tables. For +those for which no special code exists, the table type C is used, which +defaults to L. The current tables which are supported are: + + table Font::TTF::Table - for unknown tables + EBDT Font::TTF::EBDT + EBLC Font::TTF::EBLC + Feat Font::TTF::GrFeat + GDEF Font::TTF::GDEF + GPOS Font::TTF::GPOS + GSUB Font::TTF::GSUB + Glat Font::TTF::Glat + Gloc Font::TTF::Gloc + LTSH Font::TTF::LTSH + OS/2 Font::TTF::OS_2 + PCLT Font::TTF::PCLT + Sill Font::TTF::Sill + Silf Font::TTF::Silf + bsln Font::TTF::Bsln + cmap Font::TTF::Cmap - see also Font::TTF::OldCmap + cvt Font::TTF::Cvt_ + fdsc Font::TTF::Fdsc + feat Font::TTF::Feat + fmtx Font::TTF::Fmtx + fpgm Font::TTF::Fpgm + glyf Font::TTF::Glyf - see also Font::TTF::Glyph + hdmx Font::TTF::Hdmx + head Font::TTF::Head + hhea Font::TTF::Hhea + hmtx Font::TTF::Hmtx + kern Font::TTF::Kern - see alternative Font::TTF::AATKern + loca Font::TTF::Loca + maxp Font::TTF::Maxp + mort Font::TTF::Mort - see also Font::TTF::OldMort + name Font::TTF::Name + post Font::TTF::Post + prep Font::TTF::Prep + prop Font::TTF::Prop + vhea Font::TTF::Vhea + vmtx Font::TTF::Vmtx + DSIG FONT::TTF::DSIG + +Links are: + +L +L L L +L L L L L L +L L L L L L L +L L L L L +L L L L L +L L L L L +L L L L L +L L L +L + + +=head1 INSTANCE VARIABLES + +Instance variables begin with a space (and have lengths greater than the 4 +characters which make up table names). + +=over + +=item nocsum + +This is used during output to disable the creation of the file checksum in the +head table. For example, during DSIG table creation, this flag will be set to +ensure that the file checksum is left at zero. + +=item noharmony + +If set, do not harmonize the script and lang trees of GPOS and GSUB tables. See L for more info. + +=item nocompress + +Is the default value controlling WOFF output table compression. If undef, all tables will be compressed if there is +a size benefit in doing so. +It may be set to an array of tagnames naming tables that should not be compressed, or to a scalar integer specifying a +table size threshold below which tables will not be compressed. +Note that individual L objects may override this default. See L for more info. + +=item fname (R) + +Contains the filename of the font which this object was read from. + +=item INFILE (P) + +The file handle which reflects the source file for this font. + +=item OFFSET (P) + +Contains the offset from the beginning of the read file of this particular +font directory, thus providing support for TrueType Collections. + +=item WOFF + +Contains a reference to a C object. + +=back + +=head1 METHODS + +=cut + +use IO::File; + +use strict; +use vars qw(%tables $VERSION $dumper); +use Symbol(); + +require 5.004; + +my $havezlib = eval {require Compress::Zlib}; + +$VERSION = 0.39; # MJPH 2-FEB-2008 Add DSIG table +# $VERSION = 0.38; # MJPH 2-FEB-2008 Add Sill table +# $VERSION = 0.37; # MJPH 7-OCT-2005 Force hhea update if dirty, give more OS/2 stuff in update +# $VERSION = 0.36; # MJPH 19-AUG-2005 Change cmap::reverse api to be opts based +# $VERSION = 0.35; # MJPH 4-MAY-2004 Various fixes to OpenType stuff, separate off scripts +# $VERSION = 0.34; # MJPH 22-MAY-2003 Update PSNames to latest AGL +# $VERSION = 0.33; # MJPH 9-OCT-2002 Support CFF OpenType (just by version=='OTTO'?!) +# $VERSION = 0.32; # MJPH 2-OCT-2002 Bug fixes to TTFBuilder, new methods and some +# extension table support in Ttopen and Coverage +# $VERSION = 0.31; # MJPH 1-JUL-2002 fix read format 12 cmap (bart@cs.pdx.edu) +# improve surrogate support in ttfremap +# fix return warn to return warn,undef +# ensure correct indexToLocFormat +# $VERSION = 0.30; # MJPH 28-MAY-2002 add updated release +# $VERSION = 0.29; # MJPH 9-APR-2002 update ttfbuilder, sort out surrogates +# $VERSION = 0.28; # MJPH 13-MAR-2002 update ttfbuilder, add Font::TTF::Cmap::ms_enc() +# $VERSION = 0.27; # MJPH 6-FEB-2002 update ttfbuilder, support no fpgm, no more __DATA__ +# $VERSION = 0.26; # MJPH 19-SEP-2001 Update ttfbuilder +# $VERSION = 0.25; # MJPH 18-SEP-2001 problems in update of head +# $VERSION = 0.24; # MJPH 1-AUG-2001 Sort out update +# $VERSION = 0.23; # GST 30-MAY-2001 Memory leak fixed +# $VERSION = 0.22; # MJPH 09-APR-2001 Ensure all of AAT stuff included +# $VERSION = 0.21; # MJPH 23-MAR-2001 Improve Opentype support +# $VERSION = 0.20; # MJPH 13-JAN-2001 Add XML output and some of XML input, AAT & OT tables +# $VERSION = 0.19; # MJPH 29-SEP-2000 Add cmap::is_unicode, debug makefile.pl +# $VERSION = 0.18; # MJPH 21-JUL-2000 Debug Utils::TTF_bininfo +# $VERSION = 0.17; # MJPH 16-JUN-2000 Add utf8 support to names +# $VERSION = 0.16; # MJPH 26-APR-2000 Mark read tables as read, tidy up POD +# $VERSION = 0.15; # MJPH 5-FEB-2000 Ensure right versions released +# $VERSION = 0.14; # MJPH 11-SEP-1999 Sort out Unixisms, agian! +# $VERSION = 0.13; # MJPH 9-SEP-1999 Add empty, debug update_bbox +# $VERSION = 0.12; # MJPH 22-JUL-1999 Add update_bbox +# $VERSION = 0.11; # MJPH 7-JUL-1999 Don't store empties in cmaps +# $VERSION = 0.10; # MJPH 21-JUN-1999 Use IO::File +# $VERSION = 0.09; # MJPH 9-JUN-1999 Add 5.004 require, minor tweeks in cmap +# $VERSION = 0.08; # MJPH 19-MAY-1999 Sort out line endings for Unix +# $VERSION = 0.07; # MJPH 28-APR-1999 Get the regression tests to work +# $VERSION = 0.06; # MJPH 26-APR-1999 Start to add to CVS, correct MANIFEST.SKIP +# $VERSION = 0.05; # MJPH 13-APR-1999 See changes for 0.05 +# $VERSION = 0.04; # MJPH 13-MAR-1999 Tidy up Tarball +# $VERSION = 0.03; # MJPH 9-MAR-1999 Move to Font::TTF for CPAN +# $VERSION = 0.02; # MJPH 12-FEB-1999 Add support for ' nocsum' for DSIGS +# $VERSION = 0.0001; + +%tables = ( + 'table' => 'Font::TTF::Table', + 'DSIG' => 'Font::TTF::DSIG', + 'EBDT' => 'Font::TTF::EBDT', + 'EBLC' => 'Font::TTF::EBLC', + 'Feat' => 'Font::TTF::GrFeat', + 'GDEF' => 'Font::TTF::GDEF', + 'Glat' => 'Font::TTF::Glat', + 'Gloc' => 'Font::TTF::Gloc', + 'GPOS' => 'Font::TTF::GPOS', + 'GSUB' => 'Font::TTF::GSUB', + 'Glat' => 'Font::TTF::Glat', + 'Gloc' => 'Font::TTF::Gloc', + 'LTSH' => 'Font::TTF::LTSH', + 'OS/2' => 'Font::TTF::OS_2', + 'PCLT' => 'Font::TTF::PCLT', + 'Sill' => 'Font::TTF::Sill', + 'Silf' => 'Font::TTF::Silf', + 'bsln' => 'Font::TTF::Bsln', + 'cmap' => 'Font::TTF::Cmap', + 'cvt ' => 'Font::TTF::Cvt_', + 'fdsc' => 'Font::TTF::Fdsc', + 'feat' => 'Font::TTF::Feat', + 'fmtx' => 'Font::TTF::Fmtx', + 'fpgm' => 'Font::TTF::Fpgm', + 'glyf' => 'Font::TTF::Glyf', + 'hdmx' => 'Font::TTF::Hdmx', + 'head' => 'Font::TTF::Head', + 'hhea' => 'Font::TTF::Hhea', + 'hmtx' => 'Font::TTF::Hmtx', + 'kern' => 'Font::TTF::Kern', + 'loca' => 'Font::TTF::Loca', + 'maxp' => 'Font::TTF::Maxp', + 'mort' => 'Font::TTF::Mort', + 'name' => 'Font::TTF::Name', + 'post' => 'Font::TTF::Post', + 'prep' => 'Font::TTF::Prep', + 'prop' => 'Font::TTF::Prop', + 'vhea' => 'Font::TTF::Vhea', + 'vmtx' => 'Font::TTF::Vmtx', + ); + +# This is special code because I am fed up of every time I x a table in the debugger +# I get the whole font printed. Thus substitutes my 3 line change to dumpvar into +# the debugger. Clunky, but nice. You are welcome to a copy if you want one. + +BEGIN { + my ($p); + + foreach $p (@INC) + { + if (-f "$p/mydumpvar.pl") + { + $dumper = 'mydumpvar.pl'; + last; + } + } + $dumper ||= 'dumpvar.pl'; +} + +sub main::dumpValue +{ do $dumper; &main::dumpValue; } + + +=head2 Font::TTF::Font->AddTable($tablename, $class) + +Adds the given class to be used when representing the given table name. It also +'requires' the class for you. + +=cut + +sub AddTable +{ + my ($class, $table, $useclass) = @_; + + $tables{$table} = $useclass; +# $useclass =~ s|::|/|oig; +# require "$useclass.pm"; +} + + +=head2 Font::TTF::Font->Init + +For those people who like making fonts without reading them. This subroutine +will require all the table code for the various table types for you. Not +needed if using Font::TTF::Font::read before using a table. + +=cut + +sub Init +{ + my ($class) = @_; + my ($t); + + foreach $t (values %tables) + { + $t =~ s|::|/|oig; + require "$t.pm"; + } +} + +=head2 Font::TTF::Font->new(%props) + +Creates a new font object and initialises with the given properties. This is +primarily for use when a TTF is embedded somewhere. Notice that the properties +are automatically preceded by a space when inserted into the object. This is in +order that fields do not clash with tables. + +=cut + +sub new +{ + my ($class, %props) = @_; + my ($self) = {}; + + bless $self, $class; + + foreach (keys %props) + { $self->{" $_"} = $props{$_}; } + $self; +} + + +=head2 Font::TTF::Font->open($fname) + +Reads the header and directory for the given font file and creates appropriate +objects for each table in the font. + +=cut + +sub open +{ + my ($class, $fname) = @_; + my ($fh); + my ($self) = {}; + + unless (ref($fname)) + { + $fh = IO::File->new($fname) or return undef; + binmode $fh; + } else + { $fh = $fname; } + + $self->{' INFILE'} = $fh; + $self->{' fname'} = $fname; + $self->{' OFFSET'} = 0; + bless $self, $class; + + $self->read; +} + +=head2 $f->read + +Reads a Truetype font directory starting from location C<$self->{' OFFSET'}> in the file. +This has been separated from the C function to allow support for embedded +TTFs for example in TTCs. Also reads the C and C tables immediately. + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($dat, $i, $ver, $dir_num, $type, $name, $check, $off, $len, $t); + my ($iswoff, $woffLength, $sfntSize, $zlen); # needed for WOFF files + + $fh->seek($self->{' OFFSET'}, 0); + $fh->read($dat, 4); + $ver = unpack("N", $dat); + $iswoff = ($ver == unpack('N', 'wOFF')); + if ($iswoff) + { + require Font::TTF::Woff; + my $woff = Font::TTF::Woff->new(PARENT => $self); + $fh->read($dat, 32); + ($ver, $woffLength, $dir_num, undef, $sfntSize, $woff->{'majorVersion'}, $woff->{'minorVersion'}, + $off, $zlen, $len) = unpack('NNnnNnnNNN', $dat); + # TODO: According to WOFF spec we should verify $woffLength and $sfntSize, and fail if the values are wrong. + if ($off) + { + # Font has metadata + if ($off + $zlen > $woffLength) + { + warn "invalid WOFF header in $self->{' fname'}: meta data beyond end."; + return undef; + } + require Font::TTF::Woff::MetaData; + $woff->{'metaData'} = Font::TTF::Woff::MetaData->new( + PARENT => $woff, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len, + ZLENGTH => $zlen); + } + + $fh->read($dat, 8); + ($off, $len) = unpack('NN', $dat); + if ($off) + { + # Font has private data + if ($off + $len > $woffLength) + { + warn "invalid WOFF header in $self->{' fname'}: private data beyond end."; + return undef; + } + require Font::TTF::Woff::PrivateData; + $woff->{'privateData'} = Font::TTF::Woff::PrivateData->new( + PARENT => $woff, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len); + } + + $self->{' WOFF'} = $woff; + } + else + { + $fh->read($dat, 8); + $dir_num = unpack("n", $dat); + } + + $ver == 1 << 16 # TrueType outlines + || $ver == unpack('N', 'OTTO') # 0x4F54544F CFF outlines + || $ver == unpack('N', 'true') # 0x74727565 Mac sfnts + or return undef; # else unrecognized type + + + for ($i = 0; $i < $dir_num; $i++) + { + $fh->read($dat, $iswoff ? 20 : 16) || die "Reading table entry"; + if ($iswoff) + { + ($name, $off, $zlen, $len, $check) = unpack("a4NNNN", $dat); + if ($off + $zlen > $woffLength || $zlen > $len) + { + my $err; + $err = "Offset + compressed length > total length. " if $off + $zlen > $woffLength; + $err = "Compressed length > uncompressed length. " if $zlen > $len; + warn "invalid WOFF '$name' table in $self->{' fname'}: $err\n"; + return undef; + } + } + else + { + ($name, $check, $off, $len) = unpack("a4NNN", $dat); + $zlen = $len; + } + $self->{$name} = $self->{' PARENT'}->find($self, $name, $check, $off, $len) and next + if (defined $self->{' PARENT'}); + $type = $tables{$name} || 'Font::TTF::Table'; + $t = $type; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $self->{$name} = $type->new(PARENT => $self, + NAME => $name, + INFILE => $fh, + OFFSET => $off, + LENGTH => $len, + ZLENGTH => $zlen, + CSUM => $check); + } + + foreach $t ('head', 'maxp') + { $self->{$t}->read if defined $self->{$t}; } + + $self; +} + + +=head2 $f->out($fname [, @tablelist]) + +Writes a TTF file consisting of the tables in tablelist. The list is checked to +ensure that only tables that exist are output. (This means that you cannot have +non table information stored in the font object with key length of exactly 4) + +In many cases the user simply wants to output all the tables in alphabetical order. +This can be done by not including a @tablelist, in which case the subroutine will +output all the defined tables in the font in alphabetical order. + +Returns $f on success and undef on failure, including warnings. + +All output files must include the C table. + +=cut + +sub out +{ + my ($self, $fname, @tlist) = @_; + my ($fh); + my ($dat, $numTables, $sRange, $eSel); + my (%dir, $k, $mloc, $count); + my ($csum, $lsum, $msum, $loc, $oldloc, $len, $shift); + + my ($iswoff); # , $woffLength, $sfntSize, $zlen); # needed for WOFF files + + unless (ref($fname)) + { + $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname for writing"), undef; + binmode $fh; + } else + { $fh = $fname; } + + $self->{' oname'} = $fname; + $self->{' outfile'} = $fh; + + if ($self->{' wantsig'}) + { + $self->{' nocsum'} = 1; +# $self->{'head'}{'checkSumAdjustment'} = 0; + $self->{' tempDSIG'} = $self->{'DSIG'}; + $self->{' tempcsum'} = $self->{'head'}{' CSUM'}; + delete $self->{'DSIG'}; + @tlist = sort {$self->{$a}{' OFFSET'} <=> $self->{$b}{' OFFSET'}} + grep (length($_) == 4 && defined $self->{$_}, keys %$self) if ($#tlist < 0); + } + elsif ($#tlist < 0) + { @tlist = sort keys %$self; } + + @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist); + $numTables = $#tlist + 1; + $numTables++ if ($self->{' wantsig'}); + + if ($iswoff) + { + } + else + { + ($numTables, $sRange, $eSel, $shift) = Font::TTF::Utils::TTF_bininfo($numTables, 16); + $dat = pack("Nnnnn", 1 << 16, $numTables, $sRange, $eSel, $shift); + $fh->print($dat); + $msum = unpack("%32N*", $dat); + } + +# reserve place holders for each directory entry + foreach $k (@tlist) + { + $dir{$k} = pack("A4NNN", $k, 0, 0, 0); + $fh->print($dir{$k}); + } + + $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'}); + + $loc = $fh->tell(); + if ($loc & 3) + { + $fh->print(substr("\000" x 4, $loc & 3)); + $loc += 4 - ($loc & 3); + } + + foreach $k (@tlist) + { + $oldloc = $loc; + if ($iswoff && $havezlib && + # output font is WOFF -- should we try to compress this table? + exists ($self->{$k}->{' nocompress'}) ? $self->{$k}->{' nocompress'} != -1 : + ref($self->{' nocompress'}) eq 'ARRAY' ? !exists($self->{' nocompress'}{$k}) : + ref($self->{' nocompress'}) eq 'SCALAR' && $self->{' nocompress'} != -1) + { + # Yes -- we may want to compress this table. + # Create string file handle to hold uncompressed table + my $dat; + my $fh2 = IO::String->new($dat); + binmode $fh2; + $self->{$k}->out($fh2); + $len = $fh2->tell(); + close $fh2; + + # Is table long enough to try compression? + unless ( + exists ($self->{$k}->{' nocompress'}) && $len <= $self->{$k}->{' nocompress'} || + ref($self->{' nocompress'}) eq 'SCALAR' && $len <= $self->{' nocompress'}) + { + # Yes -- so compress and check lengths: + my $zdat = Compress::Zlib::compress($dat); + my $zlen = bytes::length($zdat); + if ($zlen < $len) + { + # write the compressed $zdat + + } + else + { + # write the uncompressed $dat + } + } + else + { + # write uncompressed $dat + } + + + } + else + { + # Output table normally + $self->{$k}->out($fh); + $loc = $fh->tell(); + $len = $loc - $oldloc; + } + if ($loc & 3) + { + $fh->print(substr("\000" x 4, $loc & 3)); + $loc += 4 - ($loc & 3); + } + $fh->seek($oldloc, 0); + $csum = 0; $mloc = $loc; + while ($mloc > $oldloc) + { + $count = ($mloc - $oldloc > 4096) ? 4096 : $mloc - $oldloc; + $fh->read($dat, $count); + $csum += unpack("%32N*", $dat); +# this line ensures $csum stays within 32 bit bounds, clipping as necessary + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + $mloc -= $count; + } + $dir{$k} = pack("A4NNN", $k, $csum, $oldloc, $len); + $msum += $csum + unpack("%32N*", $dir{$k}); + while ($msum > 0xffffffff) { $msum -= 0xffffffff; $msum--; } + $fh->seek($loc, 0); + } + + unless ($self->{' nocsum'}) # assuming we want a file checksum + { +# Now we need to sort out the head table's checksum + if (!defined $dir{'head'}) + { # you have to have a head table + $fh->close(); + return warn("No 'head' table to output in $fname"), undef; + } + ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'}); + $fh->seek($loc + 8, 0); + $fh->read($dat, 4); + $lsum = unpack("N", $dat); + if ($lsum != 0) + { + $csum -= $lsum; + if ($csum < 0) { $csum += 0xffffffff; $csum++; } + $msum -= $lsum * 2; # twice (in head and in csum) + while ($msum < 0) { $msum += 0xffffffff; $msum++; } + } + $lsum = 0xB1B0AFBA - $msum; + $fh->seek($loc + 8, 0); + $fh->print(pack("N", $lsum)); + $dir{'head'} = pack("A4NNN", 'head', $csum, $loc, $len); + } elsif ($self->{' wantsig'}) + { + if (!defined $dir{'head'}) + { # you have to have a head table + $fh->close(); + return warn("No 'head' table to output in $fname"), undef; + } + ($csum, $loc, $len) = unpack("x4NNN", $dir{'head'}); + $fh->seek($loc + 8, 0); + $fh->print(pack("N", 0)); +# $dir{'head'} = pack("A4NNN", 'head', $self->{' tempcsum'}, $loc, $len); + } + +# Now we can output the directory again + if ($self->{' wantsig'}) + { @tlist = sort @tlist; } + $fh->seek(12, 0); + foreach $k (@tlist) + { $fh->print($dir{$k}); } + $fh->print(pack('A4NNN', '', 0, 0, 0)) if ($self->{' wantsig'}); + $fh->close(); + $self; +} + + +=head2 $f->out_xml($filename [, @tables]) + +Outputs the font in XML format + +=cut + +sub out_xml +{ + my ($self, $fname, @tlist) = @_; + my ($fh, $context, $numTables, $k); + + $context->{'indent'} = ' ' x 4; + + unless (ref($fname)) + { + $fh = IO::File->new("+>$fname") || return warn("Unable to open $fname"), undef; + binmode $fh; + } else + { $fh = $fname; } + + unless (scalar @tlist > 0) + { + @tlist = sort keys %$self; + @tlist = grep(length($_) == 4 && defined $self->{$_}, @tlist); + } + $numTables = $#tlist + 1; + + $context->{'fh'} = $fh; + $fh->print("\n"); + $fh->print("\n\n"); + + foreach $k (@tlist) + { + $fh->print("
\n"); + $self->{$k}->out_xml($context, $context->{'indent'}); + $fh->print("
\n"); + } + + $fh->print("\n"); + $fh->close; + $self; +} + + +=head2 $f->XML_start($context, $tag, %attrs) + +Handles start messages from the XML parser. Of particular interest to us are and +. + +=cut + +sub XML_start +{ + my ($self, $context, $tag, %attrs) = @_; + my ($name, $type, $t); + + if ($tag eq 'font') + { $context->{'tree'}[-1] = $self; } + elsif ($tag eq 'table') + { + $name = $attrs{'name'}; + unless (defined $self->{$name}) + { + $type = $tables{$name} || 'Font::TTF::Table'; + $t = $type; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $self->{$name} = $type->new('PARENT' => $self, 'NAME' => $name, 'read' => 1); + } + $context->{'receiver'} = ($context->{'tree'}[-1] = $self->{$name}); + } + $context; +} + + +sub XML_end +{ + my ($self) = @_; + my ($context, $tag, %attrs) = @_; + my ($i); + + return undef unless ($tag eq 'table' && $attrs{'name'} eq 'loca'); + if (defined $context->{'glyphs'} && $context->{'glyphs'} ne $self->{'loca'}{'glyphs'}) + { + for ($i = 0; $i <= $#{$context->{'glyphs'}}; $i++) + { $self->{'loca'}{'glyphs'}[$i] = $context->{'glyphs'}[$i] if defined $context->{'glyphs'}[$i]; } + $context->{'glyphs'} = $self->{'loca'}{'glyphs'}; + } + return undef; +} + +=head2 $f->update + +Sends update to all the tables in the font and then resets all the isDirty +flags on each table. The data structure in now consistent as a font (we hope). + +=cut + +sub update +{ + my ($self) = @_; + + $self->tables_do(sub { $_[0]->update; }); + + $self; +} + +=head2 $f->dirty + +Dirties all the tables in the font + +=cut + +sub dirty +{ $_[0]->tables_do(sub { $_[0]->dirty; }); $_[0]; } + +=head2 $f->tables_do(&func [, tables]) + +Calls &func for each table in the font. Calls the table in alphabetical sort +order as per the order in the directory: + + &func($table, $name); + +May optionally take a list of table names in which case func is called +for each of them in the given order. + +=cut + +sub tables_do +{ + my ($self, $func, @tables) = @_; + my ($t); + + foreach $t (@tables ? @tables : sort grep {length($_) == 4} keys %$self) + { &$func($self->{$t}, $t); } + $self; +} + + +=head2 $f->release + +Releases ALL of the memory used by the TTF font and all of its component +objects. After calling this method, do B expect to have anything left in +the C object. + +B, that it is important that you call this method on any +C object when you wish to destruct it and free up its memory. +Internally, we track things in a structure that can result in circular +references, and without calling 'C' these will not properly get +cleaned up by Perl. Once you've called this method, though, don't expect to be +able to do anything else with the C object; it'll have B +internal state whatsoever. + +B As part of the brute-force cleanup done here, this method +will throw a warning message whenever unexpected key values are found within +the C object. This is done to help ensure that any unexpected +and unfreed values are brought to your attention so that you can bug us to keep +the module updated properly; otherwise the potential for memory leaks due to +dangling circular references will exist. + +=cut + +sub release +{ + my ($self) = @_; + +# delete stuff that we know we can, here + + my @tofree = map { delete $self->{$_} } keys %{$self}; + + while (my $item = shift @tofree) + { + my $ref = ref($item); + if (UNIVERSAL::can($item, 'release')) + { $item->release(); } + elsif ($ref eq 'ARRAY') + { push( @tofree, @{$item} ); } + elsif (UNIVERSAL::isa($ref, 'HASH')) + { release($item); } + } + +# check that everything has gone - it better had! + foreach my $key (keys %{$self}) + { warn ref($self) . " still has '$key' key left after release.\n"; } +} + +1; + +=head1 BUGS + +Bugs abound aplenty I am sure. There is a lot of code here and plenty of scope. +The parts of the code which haven't been implemented yet are: + +=over 4 + +=item Post + +Version 4 format types are not supported yet. + +=item Cmap + +Format type 2 (MBCS) has not been implemented yet and therefore may cause +somewhat spurious results for this table type. + +=item Kern + +Only type 0 & type 2 tables are supported (type 1 & type 3 yet to come). + +=item TTC and WOFF + +The current Font::TTF::Font::out method does not support the writing of TrueType +Collections or WOFF files. + +=item DSIG + +Haven't figured out how to correctly calculate and output digital signature (DSIG) table + +=back + +In addition there are weaknesses or features of this module library + +=over 4 + +=item * + +There is very little (or no) error reporting. This means that if you have +garbled data or garbled data structures, then you are liable to generate duff +fonts. + +=item * + +The exposing of the internal data structures everywhere means that doing +radical re-structuring is almost impossible. But it stop the code from becoming +ridiculously large. + +=back + +Apart from these, I try to keep the code in a state of "no known bugs", which +given the amount of testing this code has had, is not a guarantee of high +quality, yet. + +For more details see the appropriate class files. + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fpgm.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fpgm.pm new file mode 100644 index 0000000000..b51adb1bf2 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Fpgm.pm @@ -0,0 +1,97 @@ +package Font::TTF::Fpgm; + +=head1 NAME + +Font::TTF::Fpgm - Font program in a TrueType font. Called when a font is loaded + +=head1 DESCRIPTION + +This is a minimal class adding nothing beyond a table, but is a repository +for fpgm type information for those processes brave enough to address hinting. + +=cut + +use strict; +use vars qw(@ISA $VERSION); + +@ISA = qw(Font::TTF::Table); + +$VERSION = 0.0001; + +=head2 $t->read + +Reading this table is simply a process of reading all the data into the RAM +copy. Nothing more is done with it. + +=cut + +sub read +{ + $_[0]->read_dat; + $_[0]->{' read'} = 1; +} + +=head2 $t->out_xml($context, $depth) + +Outputs Fpgm program as XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($dat); + + $self->read; + $dat = Font::TTF::Utils::XML_binhint($self->{' dat'}); + $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg; + $fh->print("$depth\n"); + $fh->print("$depth$context->{'indent'}$dat"); + $fh->print("$depth\n"); + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Parse all that hinting code + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'code') + { + $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'}); + return $context; + } else + { return $self->SUPER::XML_end(@_); } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GDEF.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GDEF.pm new file mode 100644 index 0000000000..12005d43f5 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GDEF.pm @@ -0,0 +1,476 @@ +package Font::TTF::GDEF; + +=head1 NAME + +Font::TTF::GDEF - Opentype GDEF table support + +=head1 DESCRIPTION + +The GDEF table contains various global lists of information which are apparantly +used in other places in an OpenType renderer. But precisely where is open to +speculation... + +=head1 INSTANCE VARIABLES + +There are up to 5 tables in the GDEF table, each with their own structure: + +=over 4 + +=item GLYPH + +This is an L Class Definition table containing information +as to what type each glyph is. + +=item ATTACH + +The attach table consists of a coverage table and then attachment points for +each glyph in the coverage table: + +=over 8 + +=item COVERAGE + +This is a coverage table + +=item POINTS + +This is an array of point elements. Each element is an array of curve points +corresponding to the attachment points on that glyph. The order of the curve points +in the array corresponds to the attachment point number specified in the MARKS +coverage table (see below). + +=back + +=item LIG + +This contains the ligature caret positioning information for ligature glyphs + +=over 8 + +=item COVERAGE + +A coverage table to say which glyphs are ligatures + +=item LIGS + +An array of elements for each ligature. Each element is an array of information +for each caret position in the ligature (there being number of components - 1 of +these, generally) + +=over 12 + +=item FMT + +This is the format of the information and is important to provide the semantics +for the value. This value must be set correctly before output + +=item VAL + +The value which has meaning according to FMT + +=item DEVICE + +For FMT = 3, a device table is also referenced which is stored here + +=back + +=back + +=item MARKS + +This class definition table defines the classes of mark glyphs that can be selected +for processing using the MarkAttachmentType field of lookup FLAG words. + +=item MARKSETS + +Contains an array of coverage tables indexed by the FILTER value of a lookup. + +=back + + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Table; +use Font::TTF::Utils; +use Font::TTF::Ttopen; +use vars qw(@ISA $new_gdef); + +@ISA = qw(Font::TTF::Table); +$new_gdef = 1; # Prior to 2012-07, this config variable did more than it does today. + # Currently all it does is force the GDEF to include a field in the + # header for the MARKS class definition. That is, it makes sure the + # font is compatible with at least the OT 1.2 specification. + +=head2 $t->read + +Reads the table into the data structure + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($boff) = $self->{' OFFSET'}; + my ($dat, $goff, $aoff, $loff, $macoff, $mgsoff, $r, $s, $bloc); + + $bloc = $fh->tell(); + $fh->read($dat, 10); + ($self->{'Version'}, $goff, $aoff, $loff) = TTF_Unpack('LS3', $dat); + + # GDEF is the ONLY table that uses a ULONG for version rather than a Fixed or USHORT, + # and this seems to clearly be a hack. + # OpenType 1.2 introduced MarkAttachClassDef but left the table version at 0x00010000 + # Up through OpenType 1.5, the Version field was typed as Fixed. + # OpenType 1.6 introduced MarkGlyphSetsDef and bumped table version to 0x00010002 (sic) + # and changed it to ULONG. + + + # Thus some trickery here to read the table correctly! + + if ($self->{'Version'} > 0x00010000) + { + # Ok, header guaranteed to have both MarAttachClassDef MarkGlyphSetsDef + $fh->read($dat, 4); + ($macoff, $mgsoff) = TTF_Unpack('S2', $dat); + } + else + { + # What I've seen in other code (examples: + # http://skia.googlecode.com/svn/trunk/third_party/harfbuzz/src/harfbuzz-gdef.c and + # http://doxygen.reactos.org/d0/d55/otvalid_8h_a0487daffceceb98ba425bbf2806fbaff.html + # ) is to read GPOS and GDEF and see if any lookups have a + # MarkAttachType in the upper byte of their flag word and if so then assume that the + # MarkAttachClassDef field is in the header. While this is probably the most + # reliable way to do it, it would require us to read GSUB and GPOS. + # Prior to 2012-07 what we did is depend on our $new_gdef class variable to tell us + # whether to assume a MarkAttachClassDef. + # What we do now is see if the header actually has room for the MarkAttachClassDef field. + + my $minOffset = $self->{' LENGTH'}; + foreach ($goff, $aoff, $loff) + { + $minOffset = $_ if $_ > 0 && $_ < $minOffset; + } + if ($minOffset >= 12) + { + # There is room for the field, so read it: + $fh->read($dat, 2); + ($macoff) = TTF_Unpack('S', $dat); + # Sanity check: + $macoff = 0 if $macoff >= $self->{' LENGTH'}; + } + } + + if ($goff > 0) + { + $fh->seek($goff + $boff, 0); + $self->{'GLYPH'} = Font::TTF::Coverage->new(0)->read($fh); + } + + if ($aoff > 0) + { + my ($off, $gcount, $pcount); + + $fh->seek($aoff + $boff, 0); + $fh->read($dat, 4); + ($off, $gcount) = TTF_Unpack('SS', $dat); + $fh->read($dat, $gcount << 1); + + $fh->seek($aoff + $boff + $off, 0); + $self->{'ATTACH'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh); + + foreach $r (TTF_Unpack('S*', $dat)) + { + unless ($r) + { + push (@{$self->{'ATTACH'}{'POINTS'}}, []); + next; + } + $fh->seek($aoff + $boff + $r, 0); + $fh->read($dat, 2); + $pcount = TTF_Unpack('S', $dat); + $fh->read($dat, $pcount << 1); + push (@{$self->{'ATTACH'}{'POINTS'}}, [TTF_Unpack('S*', $dat)]); + } + } + + if ($loff > 0) + { + my ($lcount, $off, $ccount, $srec, $comp); + + $fh->seek($loff + $boff, 0); + $fh->read($dat, 4); + ($off, $lcount) = TTF_Unpack('SS', $dat); + $fh->read($dat, $lcount << 1); + + $fh->seek($off + $loff + $boff, 0); + $self->{'LIG'}{'COVERAGE'} = Font::TTF::Coverage->new(1)->read($fh); + + foreach $r (TTF_Unpack('S*', $dat)) + { + $fh->seek($r + $loff + $boff, 0); + $fh->read($dat, 2); + $ccount = TTF_Unpack('S', $dat); + $fh->read($dat, $ccount << 1); + + $srec = []; + foreach $s (TTF_Unpack('S*', $dat)) + { + $comp = {}; + $fh->seek($s + $r + $loff + $boff, 0); + $fh->read($dat, 4); + ($comp->{'FMT'}, $comp->{'VAL'}) = TTF_Unpack('S*', $dat); + if ($comp->{'FMT'} == 3) + { + $fh->read($dat, 2); + $off = TTF_Unpack('S', $dat); + if (defined $self->{' CACHE'}{$off + $s + $r + $loff}) + { $comp->{'DEVICE'} = $self->{' CACHE'}{$off + $s + $r + $loff}; } + else + { + $fh->seek($off + $s + $r + $loff + $boff, 0); + $comp->{'DEVICE'} = Font::TTF::Delta->new->read($fh); + $self->{' CACHE'}{$off + $s + $r + $loff} = $comp->{'DEVICE'}; + } + } + push (@$srec, $comp); + } + push (@{$self->{'LIG'}{'LIGS'}}, $srec); + } + } + + if ($macoff > 0) + { + $fh->seek($macoff + $boff, 0); + $self->{'MARKS'} = Font::TTF::Coverage->new(0)->read($fh); + } + + if ($mgsoff > 0) + { + my ($fmt, $count, $off); + $fh->seek($mgsoff + $boff, 0); + $fh->read($dat, 4); + ($fmt, $count) = TTF_Unpack('SS', $dat); + # Sanity check opportunity: Could verify $fmt == 1, but I don't. + $self->{'MARKSETS'} = []; + $fh->read($dat, $count << 2); # NB: These offets are ULONGs! + foreach $off (TTF_Unpack('L*', $dat)) + { + unless (defined $self->{' CACHE'}{$off + $mgsoff}) + { + $fh->seek($off + $mgsoff + $boff, 0); + $self->{' CACHE'}{$off + $mgsoff} = Font::TTF::Coverage->new(1)->read($fh); + } + push @{$self->{'MARKSETS'}}, $self->{' CACHE'}{$off + $mgsoff}; + } + } + + $self; +} + + +=head2 $t->out($fh) + +Writes out this table. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($goff, $aoff, $loff, $macoff, $mgsoff, @offs, $loc1, $coff, $loc); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $loc = $fh->tell(); + if (defined $self->{'MARKSETS'} && @{$self->{'MARKSETS'}} > 0) + { + $self->{'Version'} = 0x00010002 if ($self->{'Version'} < 0x00010002); + $fh->print(TTF_Pack('LSSSSS', $self->{'Version'}, 0, 0, 0, 0, 0)); + } + else + { + $self->{'Version'} = 0x00010000; + if ($new_gdef || defined $self->{'MARKS'}) + { $fh->print(TTF_Pack('LSSSS', $self->{'Version'}, 0, 0, 0, 0)); } + else + { $fh->print(TTF_Pack('LSSS', $self->{'Version'}, 0, 0, 0)); } + } + + if (defined $self->{'GLYPH'}) + { + $goff = $fh->tell() - $loc; + $self->{'GLYPH'}->out($fh); + } + + if (defined $self->{'ATTACH'}) + { + my ($r); + + $aoff = $fh->tell() - $loc; + $fh->print(pack('n*', (0) x ($#{$self->{'ATTACH'}{'POINTS'}} + 3))); + foreach $r (@{$self->{'ATTACH'}{'POINTS'}}) + { + push (@offs, $fh->tell() - $loc - $aoff); + $fh->print(pack('n*', $#{$r} + 1, @$r)); + } + $coff = $fh->tell() - $loc - $aoff; + $self->{'ATTACH'}{'COVERAGE'}->out($fh); + $loc1 = $fh->tell(); + $fh->seek($aoff + $loc, 0); + $fh->print(pack('n*', $coff, $#offs + 1, @offs)); + $fh->seek($loc1, 0); + } + + if (defined $self->{'LIG'}) + { + my (@reftables, $ltables, $i, $j, $out, $r, $s); + + $ltables = {}; + $loff = $fh->tell() - $loc; + $out = pack('n*', + Font::TTF::Ttopen::ref_cache($self->{'LIG'}{'COVERAGE'}, $ltables, 0), + $#{$self->{'LIG'}{'LIGS'}} + 1, + (0) x ($#{$self->{'LIG'}{'LIGS'}} + 1)); + push (@reftables, [$ltables, 0]); + $i = 0; + foreach $r (@{$self->{'LIG'}{'LIGS'}}) + { + $ltables = {}; + $loc1 = length($out); + substr($out, ($i << 1) + 4, 2) = TTF_Pack('S', $loc1); + $out .= pack('n*', $#{$r} + 1, (0) x ($#{$r} + 1)); + @offs = (); $j = 0; + foreach $s (@$r) + { + substr($out, ($j << 1) + 2 + $loc1, 2) = + TTF_Pack('S', length($out) - $loc1); + $out .= TTF_Pack('SS', $s->{'FMT'}, $s->{'VAL'}); + $out .= pack('n', Font::TTF::Ttopen::ref_cache($s->{'DEVICE'}, + $ltables, length($out))) if ($s->{'FMT'} == 3); + $j++; + } + push (@reftables, [$ltables, $loc1]); + $i++; + } + Font::TTF::Ttopen::out_final($fh, $out, \@reftables); + } + + if (defined $self->{'MARKS'}) + { + $macoff = $fh->tell() - $loc; + $self->{'MARKS'}->out($fh); + } + + if (defined $self->{'MARKSETS'}) + { + + my (@reftables, $ctables, $c, $out); + $ctables = {}; + $mgsoff = $fh->tell() - $loc; + $out = TTF_Pack('SS', 1, $#{$self->{'MARKSETS'}}+1); + foreach $c (@{$self->{'MARKSETS'}}) + { + $out .= pack('N', Font::TTF::Ttopen::ref_cache($c, $ctables, length($out), 'N')); + } + push (@reftables, [$ctables, 0]); + Font::TTF::Ttopen::out_final($fh, $out, \@reftables); + } + + $loc1 = $fh->tell(); + $fh->seek($loc + 4, 0); + if ($mgsoff) + { $fh->print(TTF_Pack('S5', $goff, $aoff, $loff, $macoff, $mgsoff)); } + elsif ($macoff) + { $fh->print(TTF_Pack('S4', $goff, $aoff, $loff, $macoff)); } + else + { $fh->print(TTF_Pack('S3', $goff, $aoff, $loff)); } + $fh->seek($loc1, 0); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 10; +} + + +=head2 $t->update + +Sort COVERAGE tables. + +=cut + +sub update +{ + my ($self) = @_; + + return undef unless ($self->SUPER::update); + + unless ($Font::TTF::Coverage::dontsort) + { + if (defined $self->{'ATTACH'} and defined $self->{'ATTACH'}{'COVERAGE'} and !$self->{'ATTACH'}{'COVERAGE'}{'dontsort'} ) + { + my @map = $self->{'ATTACH'}{'COVERAGE'}->sort(); + if (defined $self->{'ATTACH'}{'POINTS'}) + { + # And also a POINTS array which now needs to be re-sorted + my $newpoints = []; + foreach (0 .. $#map) + { push @{$newpoints}, $self->{'ATTACH'}{'POINTS'}[$map[$_]]; } + $self->{'ATTACH'}{'POINTS'} = $newpoints; + } + } + if (defined $self->{'LIG'} and defined $self->{'LIG'}{'COVERAGE'} and !$self->{'LIG'}{'COVERAGE'}{'dontsort'} ) + { + my @map = $self->{'LIG'}{'COVERAGE'}->sort(); + if (defined $self->{'LIG'}{'LIGS'}) + { + # And also a LIGS array which now needs to be re-sorted + my $newligs = []; + foreach (0 .. $#map) + { push @{$newligs}, $self->{'LIG'}{'LIGS'}[$map[$_]]; } + $self->{'LIG'}{'LIGS'} = $newligs; + } + } + if (defined $self->{'MARKSETS'}) + { + foreach (@{$self->{'MARKSETS'}}) + {$_->sort();} # Don't care about map + } + } + + $self; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GPOS.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GPOS.pm new file mode 100644 index 0000000000..4df6582bda --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GPOS.pm @@ -0,0 +1,711 @@ +package Font::TTF::GPOS; + +=head1 NAME + +Font::TTF::GPOS - Support for Opentype GPOS tables in conjunction with TTOpen + +=head1 DESCRIPTION + +The GPOS table is one of the most complicated tables in the TTF spec and the +corresponding data structure abstraction is also not trivial. While much of the +structure of a GPOS is shared with a GSUB table via the L + +=head1 INSTANCE VARIABLES + +Here we describe the additions and lookup specific information for GPOS tables. +Unfortunately there is no one abstraction which seems to work comfortable for +all GPOS tables, so we will also examine how the variables are used for different +lookup types. + +The following are the values allowed in the ACTION_TYPE and MATCH_TYPE variables: + +=over 4 + +=item ACTION_TYPE + +This can take any of the following values + +=over 8 + +=item a + +The ACTION is an array of anchor tables + +=item o + +Offset. There is no RULE array. The ADJUST variable contains a value record (see +later in this description) + +=item v + +The ACTION is a value record. + +=item p + +Pair adjustment. The ACTION contains an array of two value records for the matched +two glyphs. + +=item e + +Exit and Entry records. The ACTION contains an array of two anchors corresponding +to the exit and entry anchors for the glyph. + +=item l + +Indicates a lookup based contextual rule as per the GSUB table. + +=back + +=item MATCH_TYPE + +This can take any of the following values + +=over 8 + +=item g + +A glyph array + +=item c + +An array of class values + +=item o + +An array of coverage tables + +=back + +=back + +The following variables are added for Attachment Positioning Subtables: + +=over 4 + +=item MATCH + +This contains an array of glyphs to match against for all RULES. It is much like +having the same MATCH string in all RULES. In the cases it is used so far, it only +ever contains one element. + +=item MARKS + +This contains a Mark array consisting of each element being a subarray of two +elements: + +=over 8 + +=item CLASS + +The class that this mark uses on its base + +=item ANCHOR + +The anchor with which to attach this mark glyph + +=back + +The base table for mark to base, ligature or mark attachment positioning is +structured with the ACTION containing an array of anchors corresponding to each +attachment class. For ligatures, there is more than one RULE in the RULE array +corresponding to each glyph in the coverage table. + +=back + +Other variables which are provided for informational purposes are: + +=over 4 + +=item VFMT + +Value format for the adjustment of the glyph matched by the coverage table. + +=item VFMT2 + +Value format used in pair adjustment for the second glyph in the pair + +=back + +=head2 Value Records + +There is a subtype used in GPOS tables called a value record. It is used to adjust +the position of a glyph from its default position. The value record is variable +length with a bitfield at the beginning to indicate which of the following +entries are included. The bitfield is not stored since it is recalculated at +write time. + +=over 4 + +=item XPlacement + +Horizontal adjustment for placement (not affecting other unattached glyphs) + +=item YPlacement + +Vertical adjustment for placement (not affecting other unattached glyphs) + +=item XAdvance + +Adjust the advance width glyph (used only in horizontal writing systems) + +=item YAdvance + +Adjust the vertical advance (used only in vertical writing systems) + +=item XPlaDevice + +Device table for device specific adjustment of horizontal placement + +=item YPlaDevice + +Device table for device specific adjustment of vertical placement + +=item XAdvDevice + +Device table for device specific adjustment of horizontal advance + +=item YAdDevice + +Device table for device specific adjustment of vertical advance + +=item XIdPlacement + +Horizontal placement metric id (for Multiple Master fonts - but that is all I know!) + +=item YIdPlacement + +Vertical placement metric id + +=item XIdAdvance + +Horizontal advance metric id + +=item YIdAdvance + +Vertical advance metric id + +=back + +=head1 CORRESPONDANCE TO LAYOUT TYPES + +Here is what is stored in the ACTION_TYPE and MATCH_TYPE for each of the known +GPOS subtable types: + + 1.1 1.2 2.1 2.2 3 4 5 6 7.1 7.2 7.3 8.1 8.2 8.3 + ACTION_TYPE o v p p e a a a l l l l l l + MATCH_TYPE g c g c o g c o + + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Ttopen; +use Font::TTF::Delta; +use Font::TTF::Anchor; +use Font::TTF::Utils; +use vars qw(@ISA); + +@ISA = qw(Font::TTF::Ttopen); + + +=head2 read_sub + +Reads the subtable into the data structures + +=cut + +sub read_sub +{ + my ($self, $fh, $main_lookup, $sindex) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($loc) = $fh->tell(); + my ($lookup) = $main_lookup->{'SUB'}[$sindex]; + my ($dat, $mcount, $scount, $i, $j, $count, $fmt, $fmt2, $cover, $srec, $subst); + my ($c1, $c2, $s, $moff, $boff); + + + if ($type == 8) + { + $fh->read($dat, 4); + ($fmt, $cover) = TTF_Unpack('S2', $dat); + if ($fmt < 3) + { + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + } + } else + { + $fh->read($dat, 6); + ($fmt, $cover, $count) = TTF_Unpack("S3", $dat); + } + unless ($fmt == 3 && ($type == 7 || $type == 8)) + { $lookup->{'COVERAGE'} = $self->read_cover($cover, $loc, $lookup, $fh, 1); } + + $lookup->{'FORMAT'} = $fmt; + if ($type == 1 && $fmt == 1) + { + $lookup->{'VFMT'} = $count; + $lookup->{'ADJUST'} = $self->read_value($count, $loc, $lookup, $fh); + $lookup->{'ACTION_TYPE'} = 'o'; + } elsif ($type == 1 && $fmt == 2) + { + $lookup->{'VFMT'} = $count; + $fh->read($dat, 2); + $mcount = unpack('n', $dat); + for ($i = 0; $i < $mcount; $i++) + { push (@{$lookup->{'RULES'}}, [{'ACTION' => + [$self->read_value($count, $loc, $lookup, $fh)]}]); } + $lookup->{'ACTION_TYPE'} = 'v'; + } elsif ($type == 2 && $fmt == 1) + { + $lookup->{'VFMT'} = $count; + $fh->read($dat, 4); + ($fmt2, $mcount) = unpack('n2', $dat); + $lookup->{'VFMT2'} = $fmt2; + $fh->read($dat, $mcount << 1); + foreach $s (unpack('n*', $dat)) + { + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $scount = TTF_Unpack('S', $dat); + $subst = []; + for ($i = 0; $i < $scount; $i++) + { + $srec = {}; + $fh->read($dat, 2); + $srec->{'MATCH'} = [TTF_Unpack('S', $dat)]; + $srec->{'ACTION'} = [$self->read_value($count, $loc, $lookup, $fh), + $self->read_value($fmt2, $loc, $lookup, $fh)]; + push (@$subst, $srec); + } + push (@{$lookup->{'RULES'}}, $subst); + } + $lookup->{'ACTION_TYPE'} = 'p'; + $lookup->{'MATCH_TYPE'} = 'g'; + } elsif ($type == 2 && $fmt == 2) + { + $fh->read($dat, 10); + ($lookup->{'VFMT2'}, $c1, $c2, $mcount, $scount) = TTF_Unpack('S*', $dat); + $lookup->{'CLASS'} = $self->read_cover($c1, $loc, $lookup, $fh, 0); + $lookup->{'MATCH'} = [$self->read_cover($c2, $loc, $lookup, $fh, 0)]; + $lookup->{'VFMT'} = $count; + for ($i = 0; $i < $mcount; $i++) + { + $subst = []; + for ($j = 0; $j < $scount; $j++) + { + $srec = {}; + $srec->{'ACTION'} = [$self->read_value($lookup->{'VFMT'}, $loc, $lookup, $fh), + $self->read_value($lookup->{'VFMT2'}, $loc, $lookup, $fh)]; + push (@$subst, $srec); + } + push (@{$lookup->{'RULES'}}, $subst); + } + $lookup->{'ACTION_TYPE'} = 'p'; + $lookup->{'MATCH_TYPE'} = 'c'; + } elsif ($type == 3 && $fmt == 1) + { + $fh->read($dat, $count << 2); + for ($i = 0; $i < $count; $i++) + { push (@{$lookup->{'RULES'}}, [{'ACTION' => + [$self->read_anchor(TTF_Unpack('S', substr($dat, $i << 2, 2)), + $loc, $lookup, $fh), + $self->read_anchor(TTF_Unpack('S', substr($dat, ($i << 2) + 2, 2)), + $loc, $lookup, $fh)]}]); } + $lookup->{'ACTION_TYPE'} = 'e'; + } elsif ($type == 4 || $type == 5 || $type == 6) + { + my (@offs, $mloc, $thisloc, $ncomp, $k); + + $lookup->{'MATCH'} = [$lookup->{'COVERAGE'}]; # Attaching mark + $lookup->{'COVERAGE'} = $self->read_cover($count, $loc, $lookup, $fh, 1); # base/lig/mark being attached to + $fh->read($dat, 6); + ($mcount, $moff, $boff) = TTF_Unpack('S*', $dat); + # Read MarkArray + $fh->seek($loc + $moff, 0); + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + for ($i = 0; $i < $count; $i++) + { + $fh->read($dat, 4); + push (@{$lookup->{'MARKS'}}, [TTF_Unpack('S', $dat), + $self->read_anchor(TTF_Unpack('S', substr($dat, 2, 2)) + $moff, + $loc, $lookup, $fh)]); + } + # Read BaseArray/LigatureArray/Mark2Array + $fh->seek($loc + $boff, 0); + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + $mloc = $fh->tell() - 2; + $thisloc = $mloc; + if ($type == 5) + { + $fh->read($dat, $count << 1); + @offs = TTF_Unpack('S*', $dat); + } + for ($i = 0; $i < $count; $i++) + { + if ($type == 5) + { + $thisloc = $mloc + $offs[$i]; + $fh->seek($thisloc, 0); + $fh->read($dat, 2); + $ncomp = TTF_Unpack('S', $dat); + } else + { $ncomp = 1; } + for ($j = 0; $j < $ncomp; $j++) + { + $subst = []; + $fh->read($dat, $mcount << 1); + for ($k = 0; $k < $mcount; $k++) + { push (@$subst, $self->read_anchor(TTF_Unpack('S', substr($dat, $k << 1, 2)), + $thisloc, $lookup, $fh)); } + + push (@{$lookup->{'RULES'}[$i]}, {'ACTION' => $subst}); + } + } + $lookup->{'ACTION_TYPE'} = 'a'; + } elsif ($type == 7 || $type == 8) + { $self->read_context($lookup, $fh, $type - 2, $fmt, $cover, $count, $loc); } + $lookup; +} + + +=head2 $t->extension + +Returns the table type number for the extension table + +=cut + +sub extension +{ return 9; } + + +=head2 $t->out_sub + +Outputs the subtable to the given filehandle + +=cut + +sub out_sub +{ + my ($self, $fh, $main_lookup, $index, $ctables, $base) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($lookup) = $main_lookup->{'SUB'}[$index]; + my ($fmt) = $lookup->{'FORMAT'}; + my ($out, $r, $s, $t, $i, $j, $vfmt, $vfmt2, $loc1); + my ($num) = $#{$lookup->{'RULES'}} + 1; + my ($mtables) = {}; + my (@reftables); + + if ($type == 1 && $fmt == 1) + { + $out = pack('n2', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base)); + $vfmt = $self->fmt_value($lookup->{'ADJUST'}); + $out .= pack('n', $vfmt) . $self->out_value($lookup->{'ADJUST'}, $vfmt, $ctables, 6 + $base); + } elsif ($type == 1 && $fmt == 2) + { + $vfmt = 0; + foreach $r (@{$lookup->{'RULES'}}) + { $vfmt |= $self->fmt_value($r->[0]{'ACTION'}[0]); } + $out = pack('n4', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $vfmt, $#{$lookup->{'RULES'}} + 1); + foreach $r (@{$lookup->{'RULES'}}) + { $out .= $self->out_value($r->[0]{'ACTION'}[0], $vfmt, $ctables, length($out) + $base); } + } elsif ($type == 2 && $fmt < 3) + { + $vfmt = 0; + $vfmt2 = 0; + foreach $r (@{$lookup->{'RULES'}}) + { + foreach $t (@$r) + { + $vfmt |= $self->fmt_value($t->{'ACTION'}[0]); + $vfmt2 |= $self->fmt_value($t->{'ACTION'}[1]); + } + } + if ($fmt == 1) + { + # start PairPosFormat1 subtable + $out = pack('n5', + $fmt, + Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $vfmt, + $vfmt2, + $#{$lookup->{'RULES'}} + 1); # PairSetCount + my $off = 0; + $off += length($out); + $off += 2 * ($#{$lookup->{'RULES'}} + 1); # there will be PairSetCount offsets here + my $pairsets = ''; + my (%cache); + foreach $r (@{$lookup->{'RULES'}}) # foreach PairSet table + { + # write offset to this PairSet at end of PairPosFormat1 table + if (defined $cache{"$r"}) + { $out .= pack('n', $cache{"$r"}); } + else + { + $out .= pack('n', $off); + $cache{"$r"} = $off; + + # generate PairSet itself (using $off as eventual offset within PairPos subtable) + my $pairset = pack('n', $#{$r} + 1); # PairValueCount + foreach $t (@$r) # foreach PairValueRecord + { + $pairset .= pack('n', $t->{'MATCH'}[0]); # SecondGlyph - MATCH has only one entry + $pairset .= + $self->out_value($t->{'ACTION'}[0], $vfmt, $ctables, $off + length($pairset) + $base); + $pairset .= + $self->out_value($t->{'ACTION'}[1], $vfmt2, $ctables, $off + length($pairset) + $base); + } + $off += length($pairset); + $pairsets .= $pairset; + } + } + $out .= $pairsets; + die "internal error: PairPos size not as calculated" if (length($out) != $off); + } else + { + $out = pack('n8', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $vfmt, $vfmt2, + Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 8 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 10 + $base), + $lookup->{'CLASS'}{'max'} + 1, $lookup->{'MATCH'}[0]{'max'} + 1); + + for ($i = 0; $i <= $lookup->{'CLASS'}{'max'}; $i++) + { + for ($j = 0; $j <= $lookup->{'MATCH'}[0]{'max'}; $j++) + { + $out .= $self->out_value($lookup->{'RULES'}[$i][$j]{'ACTION'}[0], $vfmt, $ctables, length($out) + $base); + $out .= $self->out_value($lookup->{'RULES'}[$i][$j]{'ACTION'}[1], $vfmt2, $ctables, length($out) + $base); + } + } + } + } elsif ($type == 3 && $fmt == 1) + { + $out = pack('n3', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $#{$lookup->{'RULES'}} + 1); + foreach $r (@{$lookup->{'RULES'}}) + { + $out .= pack('n2', Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[0], $ctables, length($out) + $base), + Font::TTF::Ttopen::ref_cache($r->[0]{'ACTION'}[1], $ctables, length($out) + 2 + $base)); + } + } elsif ($type == 4 || $type == 5 || $type == 6) + { + my ($loc_off, $loc_t, $ltables); + + $out = pack('n7', $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'MATCH'}[0], $ctables, 2 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 4 + $base), + $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1, 12, ($#{$lookup->{'MARKS'}} + 4) << 2, + $#{$lookup->{'MARKS'}} + 1); + foreach $r (@{$lookup->{'MARKS'}}) + { $out .= pack('n2', $r->[0], Font::TTF::Ttopen::ref_cache($r->[1], $mtables, length($out) + 2)); } + push (@reftables, [$mtables, 12]); + + $loc_t = length($out); + substr($out, 10, 2) = pack('n', $loc_t); + $out .= pack('n', $#{$lookup->{'RULES'}} + 1); + if ($type == 5) + { + $loc1 = length($out); + $out .= pack('n*', (0) x ($#{$lookup->{'RULES'}} + 1)); + } + $ltables = {}; + for ($i = 0; $i <= $#{$lookup->{'RULES'}}; $i++) + { + if ($type == 5) + { + $ltables = {}; + $loc_t = length($out); + substr($out, $loc1 + ($i << 1), 2) = TTF_Pack('S', $loc_t - $loc1 + 2); + } + + $r = $lookup->{'RULES'}[$i]; + $out .= pack('n', $#{$r} + 1) if ($type == 5); + foreach $t (@$r) + { + foreach $s (@{$t->{'ACTION'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($s, $ltables, length($out))); } + } + push (@reftables, [$ltables, $loc_t]) if ($type == 5); + } + push (@reftables, [$ltables, $loc_t]) unless ($type == 5); + $out = Font::TTF::Ttopen::out_final($fh, $out, \@reftables, 1); + } elsif ($type == 7 || $type == 8) + { $out = $self->out_context($lookup, $fh, $type - 2, $fmt, $ctables, $out, $num, $base); } +# push (@reftables, [$ctables, 0]); + $out; +} + + +=head2 $t->read_value($format, $base, $lookup, $fh) + +Reads a value record from the current location in the file, according to the +format given. + +=cut + +sub read_value +{ + my ($self, $fmt, $base, $lookup, $fh) = @_; + my ($flag) = 1; + my ($res) = {}; + my ($s, $i, $dat); + + $s = 0; + for ($i = 0; $i < 12; $i++) + { + $s++ if ($flag & $fmt); + $flag <<= 1; + } + + $fh->read($dat, $s << 1); + $flag = 1; $i = 0; + foreach $s (qw(XPlacement YPlacement XAdvance YAdvance)) + { + $res->{$s} = TTF_Unpack('s', substr($dat, $i++ << 1, 2)) if ($fmt & $flag); + $flag <<= 1; + } + + foreach $s (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice)) + { + if ($fmt & $flag) + { $res->{$s} = $self->read_delta(TTF_Unpack('S', substr($dat, $i++ << 1, 2)), + $base, $lookup, $fh); } + $flag <<= 1; + } + + foreach $s (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance)) + { + $res->{$s} = TTF_Unpack('S', substr($dat, $i++ << 1, 2)) if ($fmt & $flag); + $flag <<= 1; + } + $res; +} + + +=head2 $t->read_delta($offset, $base, $lookup, $fh) + +Reads a delta (device table) at the given offset if it hasn not already been read. +Store the offset and item in the lookup cache ($lookup->{' CACHE'}) + +=cut + +sub read_delta +{ + my ($self, $offset, $base, $lookup, $fh) = @_; + my ($loc) = $fh->tell(); + my ($res, $str); + + return undef unless $offset; + $str = sprintf("%X", $base + $offset); + return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str}; + $fh->seek($base + $offset, 0); + $res = Font::TTF::Delta->new->read($fh); + $fh->seek($loc, 0); + $lookup->{' CACHE'}{$str} = $res; + return $res; +} + + +=head2 $t->read_anchor($offset, $base, $lookup, $fh) + +Reads an Anchor table at the given offset if it has not already been read. + +=cut + +sub read_anchor +{ + my ($self, $offset, $base, $lookup, $fh) = @_; + my ($loc) = $fh->tell(); + my ($res, $str); + + return undef unless $offset; + $str = sprintf("%X", $base + $offset); + return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str}; + $fh->seek($base + $offset, 0); + $res = Font::TTF::Anchor->new->read($fh); + $fh->seek($loc, 0); + $lookup->{' CACHE'}{$str} = $res; + return $res; +} + + +=head2 $t->fmt_value + +Returns the value format for a given value record + +=cut + +sub fmt_value +{ + my ($self, $value) = @_; + my ($fmt) = 0; + my ($n); + + foreach $n (reverse qw(XPlacement YPlacement XAdvance YAdvance XPlaDevice YPlaDevice + XAdvDevice YAdvDevice XIdPlacement YIdPlacement XIdAdvance + YIdAdvance)) + { + $fmt <<= 1; + $fmt |= 1 if (defined $value->{$n} && (ref $value->{$n} || $value->{$n})); + } + $fmt; +} + + +=head2 $t->out_value + +Returns the output string for the outputting of the value for a given format. Also +updates the offset cache for any device tables referenced. + +=cut + +sub out_value +{ + my ($self, $value, $fmt, $tables, $offset) = @_; + my ($n, $flag, $out); + + $flag = 1; + foreach $n (qw(XPlacement YPlacement XAdvance YAdvance)) + { + $out .= pack('n', $value->{$n}) if ($flag & $fmt); + $flag <<= 1; + } + foreach $n (qw(XPlaDevice YPlaDevice XAdvDevice YAdvDevice)) + { + if ($flag & $fmt) + { + $out .= pack('n', Font::TTF::Ttopen::ref_cache( + $value->{$n}, $tables, $offset + length($out))); + } + $flag <<= 1; + } + foreach $n (qw(XIdPlacement YIdPlacement XIdAdvance YIdAdvance)) + { + $out .= pack('n', $value->{$n}) if ($flag & $fmt); + $flag <<= 1; + } + $out; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GSUB.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GSUB.pm new file mode 100644 index 0000000000..1550a3d02a --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GSUB.pm @@ -0,0 +1,299 @@ +package Font::TTF::GSUB; + +=head1 NAME + +Font::TTF::GSUB - Module support for the GSUB table in conjunction with TTOpen + +=head1 DESCRIPTION + +Handles the GSUB subtables in relation to Ttopen tables. Due to the variety of +different lookup types, the data structures are not all that straightforward, +although I have tried to make life easy for myself when using this! + +=head1 INSTANCE VARIABLES + +The structure of a GSUB table is the same as that given in L. +Here we give some of the semantics specific to GSUB lookups. + +=over 4 + +=item ACTION_TYPE + +This is a string taking one of 4 values indicating the nature of the information +in the ACTION array of the rule: + +=over 8 + +=item g + +The action contains a string of glyphs to replace the match string by + +=item l + +The action array contains a list of offsets and lookups to run, in order, on +the matched string + +=item a + +The action array is an unordered set of optional replacements for the matched +glyph. The application should make the selection somehow. + +=item o + +The action array is empty (in fact there is no rule array for this type of +rule) and the ADJUST value should be added to the glyph id to find the replacement +glyph id value + +=item r + +The action array is a list of replacement glyphs in coverage order. This ACTION_TYPE +is used only for Type 8 Reverse Chaining lookups which, by design, are single glyph +substitution. + +=back + +=item MATCH_TYPE + +This indicates which type of information the various MATCH arrays (MATCH, PRE, +POST) hold in the rule: + +=over 8 + +=item g + +The array holds a string of glyph ids which should match exactly + +=item c + +The array holds a sequence of class definitions which each glyph should +correspondingly match to + +=item o + +The array holds offsets to coverage tables + +=back + +=back + +=head1 CORRESPONDANCE TO LAYOUT TYPES + +The following table gives the values for ACTION_TYPE and MATCH_TYPE for each +of the 12 different lookup types found in the GSUB table definition: + + 1.1 1.2 2 3 4 5.1 5.2 5.3 6.1 6.2 6.3 8 + ACTION_TYPE o g g a g l l l l l l r + MATCH_TYPE g g c o g c o o + +Hopefully, the rest of the uses of the variables should make sense from this +table. + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::Ttopen; + +@ISA = qw(Font::TTF::Ttopen); + +=head2 $t->read_sub($fh, $lookup, $index) + +Asked by the superclass to read in from the given file the indexth subtable from +lookup number lookup. The file is positioned ready for the read. + +=cut + +sub read_sub +{ + my ($self, $fh, $main_lookup, $sindex) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($loc) = $fh->tell(); + my ($lookup) = $main_lookup->{'SUB'}[$sindex]; + my ($dat, $s, @subst, $t, $fmt, $cover, $count, $mcount, $scount, $i, $gid); + my (@srec); + + if ($type == 6) + { + $fh->read($dat, 4); + ($fmt, $cover) = TTF_Unpack('S2', $dat); + if ($fmt < 3) + { + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + } + } else + { + $fh->read($dat, 6); + ($fmt, $cover, $count) = TTF_Unpack("S3", $dat); + } + unless ($fmt == 3 && ($type == 5 || $type == 6)) + { $lookup->{'COVERAGE'} = $self->read_cover($cover, $loc, $lookup, $fh, 1); } + + $lookup->{'FORMAT'} = $fmt; + if ($type == 1 && $fmt == 1) + { + $count -= 65536 if ($count > 32767); + $lookup->{'ADJUST'} = $count; + $lookup->{'ACTION_TYPE'} = 'o'; + } elsif ($type == 1 && $fmt == 2) + { + $fh->read($dat, $count << 1); + @subst = TTF_Unpack('S*', $dat); + foreach $s (@subst) + { push(@{$lookup->{'RULES'}}, [{'ACTION' => [$s]}]); } + $lookup->{'ACTION_TYPE'} = 'g'; + } elsif ($type == 2 || $type == 3) + { + $fh->read($dat, $count << 1); # number of offsets + foreach $s (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + push(@{$lookup->{'RULES'}}, [{'ACTION' => [TTF_Unpack('S*', $dat)]}]); + } + $lookup->{'ACTION_TYPE'} = ($type == 2 ? 'g' : 'a'); + } elsif ($type == 4) + { + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { + @subst = (); + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + foreach $t (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s + $t, 0); + $fh->read($dat, 4); + ($gid, $mcount) = TTF_Unpack('S2', $dat); + $fh->read($dat, ($mcount - 1) << 1); + push(@subst, {'ACTION' => [$gid], 'MATCH' => [TTF_Unpack('S*', $dat)]}); + } + push(@{$lookup->{'RULES'}}, [@subst]); + } + $lookup->{'ACTION_TYPE'} = 'g'; + $lookup->{'MATCH_TYPE'} = 'g'; + } elsif ($type == 8) + { + $t = {}; + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'PRE'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'POST'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + $fh->read($dat, $count << 1); + $t->{'ACTION'} = [TTF_Unpack('S*', $dat)]; + $lookup->{'RULES'} = [[$t]]; + $lookup->{'ACTION_TYPE'} = 'r'; + $lookup->{'MATCH_TYPE'} = 'o'; + } elsif ($type == 5 || $type == 6) + { $self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc); } + $lookup; +} + + +=head2 $t->extension + +Returns the table type number for the extension table + +=cut + +sub extension +{ return 7; } + + +=head2 $t->out_sub($fh, $lookup, $index) + +Passed the filehandle to output to, suitably positioned, the lookup and subtable +index, this function outputs the subtable to $fh at that point. + +=cut + +sub out_sub +{ + my ($self, $fh, $main_lookup, $index, $ctables, $base) = @_; + my ($type) = $main_lookup->{'TYPE'}; + my ($lookup) = $main_lookup->{'SUB'}[$index]; + my ($fmt) = $lookup->{'FORMAT'}; + my ($out, $r, $t, $i, $j, $offc, $offd, $numd); + my ($num) = $#{$lookup->{'RULES'}} + 1; + + if ($type == 1) + { + $out = pack("nn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base)); + if ($fmt == 1) + { $out .= pack("n", $lookup->{'ADJUST'}); } + else + { + $out .= pack("n", $num); + foreach $r (@{$lookup->{'RULES'}}) + { $out .= pack("n", $r->[0]{'ACTION'}[0]); } + } + } elsif ($type == 2 || $type == 3) + { + $out = pack("nnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $num); + $out .= pack('n*', (0) x $num); + $offc = length($out); + for ($i = 0; $i < $num; $i++) + { + $out .= pack("n*", $#{$lookup->{'RULES'}[$i][0]{'ACTION'}} + 1, + @{$lookup->{'RULES'}[$i][0]{'ACTION'}}); + substr($out, ($i << 1) + 6, 2) = pack('n', $offc); + $offc = length($out); + } + } elsif ($type == 8) + { + $out = pack("nn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base)); + $r = $lookup->{'RULES'}[0][0]; + $out .= pack('n', defined $r->{'PRE'} ? scalar @{$r->{'PRE'}} : 0); + foreach $t (@{$r->{'PRE'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'POST'} ? scalar @{$r->{'POST'}} : 0); + foreach $t (@{$r->{'POST'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack("n*", $#{$r->{'ACTION'}} + 1, @{$r->{'ACTION'}}); + } elsif ($type == 4 || $type == 5 || $type == 6) + { $out = $self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num, $base); } +# Font::TTF::Ttopen::out_final($fh, $out, [[$ctables, 0]]); + $out; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glat.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glat.pm new file mode 100644 index 0000000000..b341815686 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glat.pm @@ -0,0 +1,146 @@ +package Font::TTF::Glat; + +=head1 NAME + +Font::TTF::Glat - Hold glyph attributes + +=head1 DESCRIPTION + +Holds glyph attributes associated with each glyph. + +=over 4 + +=item Version + +Table format version + +=item attribs + +An array of hashes. On array entry for each glyph id. Since the glyph attributes are usually in a sparse +array, they are stored in a hash keyed by the attribute id and with the value as attribute value. + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($gloc) = $self->{' PARENT'}{'Gloc'}; + my ($fh) = $self->{' INFILE'}; + my ($numGlyphs); + my ($base) = $self->{' OFFSET'}; + my ($dat, $i); + + $gloc->read; + $numGlyphs = $gloc->{'numGlyphs'}; + $fh->seek($base, 0); + $fh->read($dat, 4); + ($self->{'Version'}) = TTF_Unpack('v', $dat); + + for ($i = 0; $i < $numGlyphs; $i++) + { + my ($j) = 0; + my ($num) = $gloc->{'locations'}[$i + 1] - $gloc->{'locations'}[$i]; + my ($first, $number, @vals); + $fh->seek($base + $gloc->{'locations'}[$i], 0); + $fh->read($dat, $num); + while ($j < $num) + { + if ($self->{'Version'} > 1) + { + ($first, $number) = unpack("n2", substr($dat, $j, 4)); + @vals = unpack("n$number", substr($dat, $j + 4, $number * 2)); + $j += ($number + 2) * 2; + } + else + { + ($first, $number) = unpack("C2", substr($dat, $j, 2)); + @vals = unpack("n$number", substr($dat, $j + 2, $number * 2)); + $j += $number * 2 + 2; + } + for (my $k = 0; $k < $number; $k++) + { $self->{'attribs'}[$i]{$first + $k} = $vals[$k]; } + } + } +} + +sub out +{ + my ($self, $fh) = @_; + my ($gloc) = $self->{' PARENT'}{'Gloc'}; + my ($numGlyphs) = 0; + my ($base) = $fh->tell(); + my ($i, $type); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $numGlyphs = scalar @{$self->{'attribs'}}; + if ($gloc->{'numAttrib'} > 256) + { + $self->{'Version'} = 2; + $type = "n"; + } + else + { + $self->{'Version'} = 1; + $type = "C"; + } + + $gloc->{'locations'} = []; + $fh->print(TTF_Pack('v', $self->{'Version'})); + for ($i = 0; $i < $numGlyphs; $i++) + { + my (@a) = sort {$a <=> $b} keys %{$self->{'attribs'}[$i]}; + push(@{$gloc->{'locations'}}, $fh->tell() - $base); + while (@a) + { + my ($first) = shift(@a); + my ($next) = $first; + my (@v, $j); + while (@a and $a[0] <= $next + 2) + { $next = shift(@a); } + for ($j = $first; $j <= $next; $j++) + { push (@v, $self->{'attribs'}[$i]{$j}); } + { $fh->print(pack("${type}2n*", $first, $next - $first + 1, @v)); } + } + } + push(@{$gloc->{'locations'}}, $fh->tell() - $base); +} + +=back + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Gloc.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Gloc.pm new file mode 100644 index 0000000000..6a0ee8367c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Gloc.pm @@ -0,0 +1,118 @@ +package Font::TTF::Gloc; + +=head1 NAME + +Font::TTF::Gloc - Offsets into Glat table for the start of the attributes for each glyph + +=head1 DESCRIPTION + +The Gloc table is a bit like the Loca table only for Graphite glyph attributes. The table +has the following elements: + +=over 4 + +=item Version + +Table format version + +=item numAttrib + +Maximum number of attributes associated with a glyph. + +=item locations + +An array of offsets into the Glat table for the start of each glyph + +=item names + +If defined, an array of name table name ids indexed by attribute number. + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($numGlyphs); + my ($dat, $flags); + + $fh->read($dat, 4); + ($self->{'Version'}) = TTF_Unpack("v", $dat); + $fh->read($dat, 4); + ($flags, $self->{'numAttrib'}) = TTF_Unpack("SS", $dat); + $numGlyphs = ($self->{' LENGTH'} - 8 - ($flags & 2 ? $self->{'numAttrib'} * 2 : 0)) / (($flags & 1) ? 4 : 2) - 1; + $self->{'numGlyphs'} = $numGlyphs; + if ($flags & 1) + { + $fh->read($dat, 4 * ($numGlyphs + 1)); + $self->{'locations'} = [unpack("N*", $dat)]; + } + else + { + $fh->read($dat, 2 * ($numGlyphs + 1)); + $self->{'locations'} = [unpack("n*", $dat)]; + } + if ($flags & 2) + { + $fh->read($dat, 2 * $self->{'numAttrib'}); + $self->{'names'} = [unpack("n*", $dat)]; + } + return $self; +} + +sub out +{ + my ($self, $fh) = @_; + my ($numGlyphs) = 0; + my ($flags, $num); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $numGlyphs = scalar @{$self->{' PARENT'}{'Glat'}{'attribs'}}; + $num = $self->{'numAttrib'}; + $flags = 1 if ($self->{'locations'}[-1] > 0xFFFF); + $flags |= 2 if ($self->{'names'}); + $fh->print(TTF_Pack("vSS", $self->{'Version'}, $flags, $num)); + $fh->write(pack(($flags & 1 ? "N" : "n") . ($numGlyphs + 1), @{$self->{'locations'}})); + if ($flags & 2) + { $fh->write(pack("n$num", @{$self->{'names'}})); } +} + +=back + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glyf.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glyf.pm new file mode 100644 index 0000000000..7a12e3f8ea --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glyf.pm @@ -0,0 +1,180 @@ +package Font::TTF::Glyf; + +=head1 NAME + +Font::TTF::Glyf - The Glyf data table + +=head1 DESCRIPTION + +This is a stub table. The real data is held in the loca table. If you want to get a glyf +look it up in the loca table as C<$f->{'loca'}{'glyphs'}[$num]>. It will not be here! + +The difference between reading this table as opposed to the loca table is that +reading this table will cause updated glyphs to be written out rather than just +copying the glyph information from the input file. This causes font writing to be +slower. So read the glyf as opposed to the loca table if you want to change glyf +data. Read the loca table only if you are just wanting to read the glyf information. + +This class is used when writing the glyphs though. + +=head1 METHODS + +=cut + + +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the C table instead! + +=cut + +sub read +{ + my ($self) = @_; + + $self->{' PARENT'}{'loca'}->read; + $self->{' read'} = 1; + $self; +} + +# Internal function called by loca -- decompresses WOFF data if needed. + +sub _read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + # Nothing else to do + $self; +} + +=head2 $t->out($fh) + +Writes out all the glyphs in the parent's location table, calculating a new +output location for each one. + +=cut + +# ' match for syntax coloring + +sub out +{ + my ($self, $fh) = @_; + my ($i, $loca, $offset, $numGlyphs); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $loca = $self->{' PARENT'}{'loca'}{'glyphs'}; + $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + $offset = 0; + for ($i = 0; $i < $numGlyphs; $i++) + { + next unless defined $loca->[$i]; + $loca->[$i]->update; + $loca->[$i]{' OUTLOC'} = $offset; + $loca->[$i]->out($fh); + $offset += $loca->[$i]{' OUTLEN'}; + } + $self->{' PARENT'}{'head'}{'indexToLocFormat'} = ($offset >= 0x20000); + $self; +} + + +=head2 $t->out_xml($context, $depth) + +Outputs all the glyphs in the glyph table just where they are supposed to be output! + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($loca, $i, $numGlyphs); + + $loca = $self->{' PARENT'}{'loca'}{'glyphs'}; + $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + for ($i = 0; $i < $numGlyphs; $i++) + { + $context->{'gid'} = $i; + $loca->[$i]->out_xml($context, $depth) if (defined $loca->[$i]); + } + + $self; +} + + +=head2 $t->XML_start($context, $tag, %attrs) + +Pass control to glyphs as they occur + +=cut + +sub XML_start +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'glyph') + { + $context->{'tree'}[-1] = Font::TTF::Glyph->new(read => 2, PARENT => $self->{' PARENT'}); + $context->{'receiver'} = $context->{'tree'}[-1]; + } +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Collect up glyphs and put them into the loca table + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'glyph') + { + unless (defined $context->{'glyphs'}) + { + if (defined $self->{' PARENT'}{'loca'}) + { $context->{'glyphs'} = $self->{' PARENT'}{'loca'}{'glyphs'}; } + else + { $context->{'glyphs'} = []; } + } + $context->{'glyphs'}[$attrs{'gid'}] = $context->{'tree'}[-1]; + return $context; + } else + { return $self->SUPER::XML_end(@_); } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glyph.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glyph.pm new file mode 100644 index 0000000000..4f0961e328 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Glyph.pm @@ -0,0 +1,902 @@ +package Font::TTF::Glyph; + +=head1 NAME + +Font::TTF::Glyph - Holds a information for a single glyph + +=head1 DESCRIPTION + +This is a single glyph description as held in a TT font. On creation only its +header is read. Thus you can get the bounding box of each glyph without having +to read all the other information. + +=head1 INSTANCE VARIABLES + +In addition to the named variables in a glyph header (C etc.), there are +also all capital instance variables for holding working information, mostly +from the location table. + +=head2 Variables for all glyphs: + +The standard attributes each glyph has are: + +=over 4 + +=item numberOfContours + +For simple glyphs this will be the count of contours. For compound glyphs this will be -1. + +=item xMin + +=item yMin + +=item xMax + +=item yMax + +These identify the bounding box of the glyph. + +=back + +There are also other, derived, instance variables for each glyph which are read +when the whole glyph is read (via C): + +=over 4 + +=item instLen + +Number of bytes in the hinting instructions (Warning this variable is deprecated, +use C{'hints'})> instead). + +=item hints + +The string containing the hinting code for the glyph + +=back + +=head2 Variables for simple glyphs (numberOfContours E= 0): + +=over 4 + +=item endPoints + +An array of endpoints for each contour in the glyph. There are +C contours in a glyph. The number of points in a glyph is +equal to the highest endpoint of a contour. + +=item numPoints + +This is a generated value which contains the total number of points for this simple glyph. + +=back + +There are also a number of arrays indexed by point number: + +=over 4 + +=item flags + +The flags associated with reading this point. The flags for a point are +recalculated for a point when it is Cd. Thus the flags are not very +useful. The only important bit is bit 0 which indicates whether the point is +an 'on' curve point, or an 'off' curve point. + +=item x + +The absolute x co-ordinate of the point. + +=item y + +The absolute y co-ordinate of the point + +=back + +=head2 Variables for compound glyphs (numberOfContours == -1): + +=over 4 + +=item metric + +This holds the component number (not its glyph number) of the component from +which the metrics for this glyph should be taken. + +=item comps + +This is an array of hashes for each component. Each hash has a number of +elements: + +=over 4 + +=item glyph + +The glyph number of the glyph which comprises this component of the composite. +NOTE: In some badly generated fonts, C may contain a numerical value +but that glyph might not actually exist in the font file. This could +occur in any glyph, but is particularly likely for glyphs that have +no strokes, such as SPACE, U+00A0 NO-BREAK SPACE, or +U+200B ZERO WIDTH SPACE. + +=item args + +An array of two arguments which may be an x, y co-ordinate or two attachment +points (one on the base glyph the other on the component). See flags for details. + +=item flag + +The flag for this component + +=item scale + +A 4 number array for component scaling. This allows stretching, rotating, etc. +Note that scaling applies to placement co-ordinates (rather than attachment points) +before locating rather than after. + +=back + +=item numPoints + +This is a generated value which contains the number of components read in for this +compound glyph. + +=back + +=head2 Private instance variables: + +=over 4 + +=item INFILE (P) + +The input file form which to read any information + +=item LOC (P) + +Location relative to the start of the glyf table in the read file + +=item BASE (P) + +The location of the glyf table in the read file + +=item LEN (P) + +This is the number of bytes required by the glyph. It should be kept up to date +by calling the C method whenever any of the glyph content changes. + +=item OUTLOC (P) + +Location relative to the start of the glyf table. This variable is only active +whilst the output process is going on. It is used to inform the location table +where the glyph is located, since the glyf table is output before the loca +table due to alphabetical ordering. + +=item OUTLEN (P) + +This indicates the length of the glyph data when it is output. This more +accurately reflects the internal memory form than the C variable which +only reflects the read file length. The C variable is only set after +calling C or C. + +=back + +=head2 Editing + +If you want to edit a glyph in some way, then you should read_dat the glyph, then +make your changes and then update the glyph or set the $g->{' isDirty'} variable. +The application must ensure that the following instance variables are +correct, from which update will calculate the rest, including the bounding box +information. + + numPoints + numberOfContours + endPoints + x, y, flags (only flags bit 0) + instLen + hints + +For components, the numPoints, x, y, endPoints & flags are not required but +the following information is required for each component. + + flag (bits 2, 10, 11, 12) + glyph + args + scale + metric (glyph instance variable) + + +=head1 METHODS + +=cut + +use strict; +use vars qw(%fields @field_info); +use Font::TTF::Utils; +use Font::TTF::Table; + +@field_info = ( + 'numberOfContours' => 's', + 'xMin' => 's', + 'yMin' => 's', + 'xMax' => 's', + 'yMax' => 's'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head1 Font::TTF::Glyph->new(%parms) + +Creates a new glyph setting various instance variables + +=cut + +sub new +{ + my ($class, %parms) = @_; + my ($self) = {}; + my ($p); + + bless $self, $class; + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + init unless defined $fields{'xMin'}; + $self; +} + + +=head2 $g->read + +Reads the header component of the glyph (numberOfContours and bounding box) and also the +glyph content, but into a data field rather than breaking it down into +its constituent structures. Use read_dat for this. + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($dat); + + return $self if (defined $self->{' read'} && $self->{' read'} > 0); + $self->{' read'} = 1; + $fh->seek($self->{' LOC'} + $self->{' BASE'}, 0); + $fh->read($dat, $self->{' LEN'}); + TTF_Read_Fields($self, $self->{' DAT'} = $dat, \%fields); + $self; +} + + +=head2 $g->read_dat + +Reads the contents of the glyph (components and curves, etc.) from the memory +store C into structures within the object. + +=cut + +sub read_dat +{ + my ($self) = @_; + my ($dat, $num, $max, $i, $flag, $len, $val, $val1, $fp); + + return $self if (defined $self->{' read'} && $self->{' read'} > 1); + $self->read unless $self->{' read'}; + $dat = $self->{' DAT'}; + $fp = 10; + $num = $self->{'numberOfContours'}; + if ($num > 0) + { + $self->{'endPoints'} = [unpack("n*", substr($dat, $fp, $num << 1))]; + $fp += $num << 1; + $max = 0; + foreach (@{$self->{'endPoints'}}) + { $max = $_ if $_ > $max; } +# print STDERR join(",", unpack('C*', $self->{" DAT"})); +# printf STDERR ("(%d,%d in %d=%d @ %d)", scalar @{$self->{'endPoints'}}, $max, length($dat), $self->{' LEN'}, $fp); + $max++ if (@{$self->{'endPoints'}}); + $self->{'numPoints'} = $max; + $self->{'instLen'} = unpack("n", substr($dat, $fp)); + $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'}); + $fp += 2 + $self->{'instLen'}; +# read the flags array + for ($i = 0; $i < $max; $i++) + { + $flag = unpack("C", substr($dat, $fp++)); + $self->{'flags'}[$i] = $flag; + if ($flag & 8) + { + $len = unpack("C", substr($dat, $fp++)); + while ($len-- > 0) + { + $i++; + $self->{'flags'}[$i] = $flag; + } + } + } +#read the x array + for ($i = 0; $i < $max; $i++) + { + $flag = $self->{'flags'}[$i]; + if ($flag & 2) + { + $val = unpack("C", substr($dat, $fp++)); + $val = -$val unless ($flag & 16); + } elsif ($flag & 16) + { $val = 0; } + else + { + $val = TTF_Unpack("s", substr($dat, $fp)); + $fp += 2; + } + $self->{'x'}[$i] = $i == 0 ? $val : $self->{'x'}[$i - 1] + $val; + } +#read the y array + for ($i = 0; $i < $max; $i++) + { + $flag = $self->{'flags'}[$i]; + if ($flag & 4) + { + $val = unpack("C", substr($dat, $fp++)); + $val = -$val unless ($flag & 32); + } elsif ($flag & 32) + { $val = 0; } + else + { + $val = TTF_Unpack("s", substr($dat, $fp)); + $fp += 2; + } + $self->{'y'}[$i] = $i == 0 ? $val : $self->{'y'}[$i - 1] + $val; + } + } + +# compound glyph + elsif ($num < 0) + { + $flag = 1 << 5; # cheat to get the loop going + for ($i = 0; $flag & 32; $i++) + { + ($flag, $self->{'comps'}[$i]{'glyph'}) = unpack("n2", substr($dat, $fp)); + $fp += 4; + $self->{'comps'}[$i]{'flag'} = $flag; + if ($flag & 1) # ARGS1_AND_2_ARE_WORDS + { + $self->{'comps'}[$i]{'args'} = [TTF_Unpack("s2", substr($dat, $fp))]; + $fp += 4; + } else + { + $self->{'comps'}[$i]{'args'} = [unpack("c2", substr($dat, $fp))]; + $fp += 2; + } + + if ($flag & 8) + { + $val = TTF_Unpack("F", substr($dat, $fp)); + $fp += 2; + $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val]; + } elsif ($flag & 64) + { + ($val, $val1) = TTF_Unpack("F2", substr($dat, $fp)); + $fp += 4; + $self->{'comps'}[$i]{'scale'} = [$val, 0, 0, $val1]; + } elsif ($flag & 128) + { + $self->{'comps'}[$i]{'scale'} = [TTF_Unpack("F4", substr($dat, $fp))]; + $fp += 8; + } + $self->{'metric'} = $i if ($flag & 512); + } + $self->{'numPoints'} = $i; + if ($flag & 256) # HAVE_INSTRUCTIONS + { + $self->{'instLen'} = unpack("n", substr($dat, $fp)); + $self->{'hints'} = substr($dat, $fp + 2, $self->{'instLen'}); + $fp += 2 + $self->{'instLen'}; + } + } + return undef if ($fp > length($dat)); + $self->{' read'} = 2; + $self; +} + + +=head2 $g->out($fh) + +Writes the glyph data to outfile + +=cut + +sub out +{ + my ($self, $fh) = @_; + + $self->read unless $self->{' read'}; + $self->update if $self->{' isDirty'}; + $fh->print($self->{' DAT'}); + $self->{' OUTLEN'} = length($self->{' DAT'}); + $self; +} + + +=head2 $g->out_xml($context, $depth) + +Outputs an XML description of the glyph + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($addr) = ($self =~ m/\((.+)\)$/o); + my ($k, $ndepth); + + if ($context->{'addresses'}{$addr}) + { + $context->{'fh'}->printf("%s\n", $depth, $context->{'gid'}, $context->{'addresses'}{$addr}); + return $self; + } + else + { + $context->{'fh'}->printf("%s\n", $depth, $context->{'gid'}); + } + + $ndepth = $depth . $context->{'indent'}; + $self->read_dat; + foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self}) + { + $self->XML_element($context, $ndepth, $k, $self->{$k}); + } + $context->{'fh'}->print("$depth\n"); + delete $context->{'done_points'}; + $self; +} + + +sub XML_element +{ + my ($self, $context, $depth, $key, $val) = @_; + my ($fh) = $context->{'fh'}; + my ($dind) = $depth . $context->{'indent'}; + my ($i); + + if ($self->{'numberOfContours'} >= 0 && ($key eq 'x' || $key eq 'y' || $key eq 'flags')) + { + return $self if ($context->{'done_points'}); + $context->{'done_points'} = 1; + + $fh->print("$depth\n"); + for ($i = 0; $i <= $#{$self->{'flags'}}; $i++) + { $fh->printf("%s\n", $dind, + $self->{'x'}[$i], $self->{'y'}[$i], $self->{'flags'}[$i]); } + $fh->print("$depth\n"); + } + elsif ($key eq 'hints') + { + my ($dat); + $fh->print("$depth\n"); +# Font::TTF::Utils::XML_hexdump($context, $depth . $context->{'indent'}, $self->{'hints'}); + $dat = Font::TTF::Utils::XML_binhint($self->{'hints'}) || ""; + $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/mg; + $fh->print("$depth$context->{'indent'}$dat"); + $fh->print("$depth\n"); + } + else + { return Font::TTF::Table::XML_element(@_); } + + $self; +} + +=head2 $g->dirty($val) + +This sets the dirty flag to the given value or 1 if no given value. It returns the +value of the flag + +=cut + +sub dirty +{ + my ($self, $val) = @_; + my ($res) = $self->{' isDirty'}; + + $self->{' isDirty'} = defined $val ? $val : 1; + $res; +} + +=head2 $g->update + +Generates a C<$self->{'DAT'}> from the internal structures, if the data has +been read into structures in the first place. If you are building a glyph +from scratch you will need to set the instance variable C<' isDirty'>. + +=cut + +sub update +{ + my ($self) = @_; + my ($dat, $loc, $len, $flag, $x, $y, $i, $comp, $num, @rflags, $repeat); + + return $self unless ($self->{' isDirty'}); + $self->read_dat->update_bbox; + $self->{' DAT'} = TTF_Out_Fields($self, \%fields, 10); + $num = $self->{'numberOfContours'}; + if ($num > 0) + { + $self->{' DAT'} .= pack("n*", @{$self->{'endPoints'}}); + $len = $self->{'instLen'}; + $self->{' DAT'} .= pack("n", $len); + $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)) if ($len > 0); + $repeat = 0; + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + $flag = $self->{'flags'}[$i] & 1; + if ($i == 0) + { + $x = $self->{'x'}[$i]; + $y = $self->{'y'}[$i]; + } else + { + $x = $self->{'x'}[$i] - $self->{'x'}[$i - 1]; + $y = $self->{'y'}[$i] - $self->{'y'}[$i - 1]; + } + $flag |= 16 if ($x == 0); + $flag |= 32 if ($y == 0); + if (($flag & 16) == 0 && $x < 256 && $x > -256) + { + $flag |= 2; + $flag |= 16 if ($x >= 0); + } + if (($flag & 32) == 0 && $y < 256 && $y > -256) + { + $flag |= 4; + $flag |= 32 if ($y >= 0); + } + if ($i > 0 && $rflags[-1] == $flag && $repeat < 255) + { + $repeat++; + } else + { + if ($repeat) + { + $rflags[-1] |= 8; + push @rflags, $repeat; + } + push @rflags, $flag; + $repeat = 0; + } + $self->{'flags'}[$i] = $flag; + } + # Add final repeat if needed, then pack up the flag bytes: + if ($repeat) + { + $rflags[-1] |= 8; + push @rflags, $repeat; + } + $self->{' DAT'} .= pack("C*", @rflags); + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + $flag = $self->{'flags'}[$i]; + $x = $self->{'x'}[$i] - (($i == 0) ? 0 : $self->{'x'}[$i - 1]); + if (($flag & 18) == 0) + { $self->{' DAT'} .= TTF_Pack("s", $x); } + elsif (($flag & 18) == 18) + { $self->{' DAT'} .= pack("C", $x); } + elsif (($flag & 18) == 2) + { $self->{' DAT'} .= pack("C", -$x); } + } + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + $flag = $self->{'flags'}[$i]; + $y = $self->{'y'}[$i] - (($i == 0) ? 0 : $self->{'y'}[$i - 1]); + if (($flag & 36) == 0) + { $self->{' DAT'} .= TTF_Pack("s", $y); } + elsif (($flag & 36) == 36) + { $self->{' DAT'} .= pack("C", $y); } + elsif (($flag & 36) == 4) + { $self->{' DAT'} .= pack("C", -$y); } + } + } + + elsif ($num < 0) + { + for ($i = 0; $i <= $#{$self->{'comps'}}; $i++) + { + $comp = $self->{'comps'}[$i]; + $flag = $comp->{'flag'} & 7158; # bits 2,10,11,12 + $flag |= 1 unless ($comp->{'args'}[0] > -129 && $comp->{'args'}[0] < 128 + && $comp->{'args'}[1] > -129 && $comp->{'args'}[1] < 128); + if (defined $comp->{'scale'}) + { + if ($comp->{'scale'}[1] == 0 && $comp->{'scale'}[2] == 0) + { + if ($comp->{'scale'}[0] == $comp->{'scale'}[3]) + { $flag |= 8 unless ($comp->{'scale'}[0] == 0 + || $comp->{'scale'}[0] == 1); } + else + { $flag |= 64; } + } else + { $flag |= 128; } + } + + $flag |= 512 if (defined $self->{'metric'} && $self->{'metric'} == $i); + if ($i == $#{$self->{'comps'}}) + { $flag |= 256 if (defined $self->{'instLen'} && $self->{'instLen'} > 0); } + else + { $flag |= 32; } + + $self->{' DAT'} .= pack("n", $flag); + $self->{' DAT'} .= pack("n", $comp->{'glyph'}); + $comp->{'flag'} = $flag; + + if ($flag & 1) + { $self->{' DAT'} .= TTF_Pack("s2", @{$comp->{'args'}}); } + else + { $self->{' DAT'} .= pack("CC", @{$comp->{'args'}}); } + + if ($flag & 8) + { $self->{' DAT'} .= TTF_Pack("F", $comp->{'scale'}[0]); } + elsif ($flag & 64) + { $self->{' DAT'} .= TTF_Pack("F2", $comp->{'scale'}[0], $comp->{'scale'}[3]); } + elsif ($flag & 128) + { $self->{' DAT'} .= TTF_Pack("F4", @{$comp->{'scale'}}); } + } + if (defined $self->{'instLen'} && $self->{'instLen'} > 0) + { + $len = $self->{'instLen'}; + $self->{' DAT'} .= pack("n", $len); + $self->{' DAT'} .= pack("a" . $len, substr($self->{'hints'}, 0, $len)); + } + } + my ($olen) = length($self->{' DAT'}); + $self->{' DAT'} .= ("\000") x (4 - ($olen & 3)) if ($olen & 3); + $self->{' OUTLEN'} = length($self->{' DAT'}); + $self->{' read'} = 2; # changed from 1 to 2 so we don't read_dat() again +# we leave numPoints and instLen since maxp stats use this + $self; +} + + +=head2 $g->update_bbox + +Updates the bounding box for this glyph according to the points in the glyph + +=cut + +sub update_bbox +{ + my ($self) = @_; + my ($num, $maxx, $minx, $maxy, $miny, $i, $comp, $x, $y, $compg); + + return $self unless (defined $self->{' read'} && $self->{' read'} > 1); # only if read_dat done + $miny = $minx = 65537; $maxx = $maxy = -65537; + $num = $self->{'numberOfContours'}; + if ($num > 0) + { + for ($i = 0; $i < $self->{'numPoints'}; $i++) + { + ($x, $y) = ($self->{'x'}[$i], $self->{'y'}[$i]); + + $maxx = $x if ($x > $maxx); + $minx = $x if ($x < $minx); + $maxy = $y if ($y > $maxy); + $miny = $y if ($y < $miny); + } + } + + elsif ($num < 0) + { + foreach $comp (@{$self->{'comps'}}) + { + my ($gnx, $gny, $gxx, $gxy); + my ($sxx, $sxy, $syx, $syy); + + my $otherg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]; + # work around bad fonts: see documentation for 'comps' above + next unless (defined $otherg); + $compg = $otherg->read->update_bbox; + ($gnx, $gny, $gxx, $gxy) = @{$compg}{'xMin', 'yMin', 'xMax', 'yMax'}; + if (defined $comp->{'scale'}) + { + ($sxx, $sxy, $syx, $syy) = @{$comp->{'scale'}}; + ($gnx, $gny, $gxx, $gxy) = ($gnx*$sxx+$gny*$syx + $comp->{'args'}[0], + $gnx*$sxy+$gny*$syy + $comp->{'args'}[1], + $gxx*$sxx+$gxy*$syx + $comp->{'args'}[0], + $gxx*$sxy+$gxy*$syy + $comp->{'args'}[1]); + } elsif ($comp->{'args'}[0] || $comp->{'args'}[1]) + { + $gnx += $comp->{'args'}[0]; + $gny += $comp->{'args'}[1]; + $gxx += $comp->{'args'}[0]; + $gxy += $comp->{'args'}[1]; + } + ($gnx, $gxx) = ($gxx, $gnx) if $gnx > $gxx; + ($gny, $gxy) = ($gxy, $gny) if $gny > $gxy; + $maxx = $gxx if $gxx > $maxx; + $minx = $gnx if $gnx < $minx; + $maxy = $gxy if $gxy > $maxy; + $miny = $gny if $gny < $miny; + } + } + $self->{'xMax'} = $maxx; + $self->{'xMin'} = $minx; + $self->{'yMax'} = $maxy; + $self->{'yMin'} = $miny; + $self; +} + + +=head2 $g->maxInfo + +Returns lots of information about a glyph so that the C table can update +itself. Returns array containing contributions of this glyph to maxPoints, maxContours, +maxCompositePoints, maxCompositeContours, maxSizeOfInstructions, maxComponentElements, +and maxComponentDepth. + +=cut + +sub maxInfo +{ + my ($self) = @_; + my (@res, $i, @n); + + $self->read_dat; # make sure we've read some data + $res[4] = length($self->{'hints'}) if defined $self->{'hints'}; + $res[6] = 1; + if ($self->{'numberOfContours'} > 0) + { + $res[0] = $self->{'numPoints'}; + $res[1] = $self->{'numberOfContours'}; + } elsif ($self->{'numberOfContours'} < 0) + { + for ($i = 0; $i <= $#{$self->{'comps'}}; $i++) + { + my $otherg = + $self->{' PARENT'}{'loca'}{'glyphs'} + [$self->{'comps'}[$i]{'glyph'}]; + + # work around bad fonts: see documentation for 'comps' above + next unless (defined $otherg ); + + @n = $otherg->maxInfo; + + $res[2] += $n[2] == 0 ? $n[0] : $n[2]; + $res[3] += $n[3] == 0 ? $n[1] : $n[3]; + $res[5]++; + $res[6] = $n[6] + 1 if ($n[6] >= $res[6]); + } + } + @res; +} + +=head2 $g->empty + +Empties the glyph of all information to the level of not having been read. +Useful for saving memory in apps with many glyphs being read + +=cut + +sub empty +{ + my ($self) = @_; + my (%keep) = map {(" $_" => 1)} ('LOC', 'OUTLOC', 'PARENT', 'INFILE', 'BASE', + 'OUTLEN', 'LEN'); + map {delete $self->{$_} unless $keep{$_}} keys %$self; + + $self; +} + + +=head2 $g->get_points + +This method creates point information for a compound glyph. The information is +stored in the same place as if the glyph was not a compound, but since +numberOfContours is negative, the glyph is still marked as being a compound + +=cut + +sub get_points +{ + my ($self) = @_; + my ($comp, $compg, $nump, $e, $i); + + $self->read_dat; + return undef unless ($self->{'numberOfContours'} < 0); + + foreach $comp (@{$self->{'comps'}}) + { + $compg = $self->{' PARENT'}{'loca'}{'glyphs'}[$comp->{'glyph'}]; + # work around bad fonts: see documentation for 'comps' above + next unless (defined $compg ); + $compg->get_points; + + for ($i = 0; $i < $compg->{'numPoints'}; $i++) + { + my ($x, $y) = ($compg->{'x'}[$i], $compg->{'y'}[$i]); + if (defined $comp->{'scale'}) + { + ($x, $y) = ($x * $comp->{'scale'}[0] + $y * $comp->{'scale'}[2], + $x * $comp->{'scale'}[1] + $y * $comp->{'scale'}[3]); + } + if (defined $comp->{'args'}) + { ($x, $y) = ($x + $comp->{'args'}[0], $y + $comp->{'args'}[1]); } + push (@{$self->{'x'}}, $x); + push (@{$self->{'y'}}, $y); + push (@{$self->{'flags'}}, $compg->{'flags'}[$i]); + } + foreach $e (@{$compg->{'endPoints'}}) + { push (@{$self->{'endPoints'}}, $e + $nump); } + $nump += $compg->{'numPoints'}; + } + $self->{'numPoints'} = $nump; + $self; +} + + +=head2 $g->get_refs + +Returns an array of all the glyph ids that are used to make up this glyph. That +is all the compounds and their references and so on. If this glyph is not a +compound, then returns an empty array. + +Please note the warning about bad fonts that reference nonexistent glyphs +under INSTANCE VARIABLES above. This function will not attempt to +filter out nonexistent glyph numbers. + +=cut + +sub get_refs +{ + my ($self) = @_; + my (@res, $g); + + $self->read_dat; + return unless ($self->{'numberOfContours'} < 0); + foreach $g (@{$self->{'comps'}}) + { + push (@res, $g->{'glyph'}); + my $otherg = $self->{' PARENT'}{'loca'}{'glyphs'}[$g->{'glyph'}]; + # work around bad fonts: see documentation for 'comps' above + next unless (defined $otherg); + my @list = $otherg->get_refs; + push(@res, @list); + } + return @res; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +The instance variables used here are somewhat clunky and inconsistent with +the other tables. + +=item * + +C doesn't re-calculate the bounding box or C. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GrFeat.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GrFeat.pm new file mode 100644 index 0000000000..525ce99af5 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/GrFeat.pm @@ -0,0 +1,320 @@ +package Font::TTF::GrFeat; + +=head1 NAME + +Font::TTF::GrFeat - Graphite Font Features + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over 4 + +=item version + +=item features + +An array of hashes of the following form + +=over 8 + +=item feature + +feature id number + +=item name + +name index in name table + +=item exclusive + +exclusive flag + +=item default + +the default setting number + +=item settings + +hash of setting number against name string index + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +use Font::TTF::Utils; + +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the features from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($featureCount, $features); + + return $self if $self->{' read'}; + $self->SUPER::read_dat or return $self; + + ($self->{'version'}, $featureCount) = TTF_Unpack("vS", $self->{' dat'}); + + $features = []; + foreach (1 .. $featureCount) { + my ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex, $reserved); + if ($self->{'version'} == 1) + { + ($feature, $nSettings, $settingTable, $featureFlags, $nameIndex) + = TTF_Unpack("SSLSS", substr($self->{' dat'}, $_ * 12, 12)); + #The version 1 Feat table ends with a feature (id 1) named NoName + #with zero settings but with an offset to the last entry in the setting + #array. This last setting has id 0 and an invalid name id. This last + #feature is changed to have one setting. + if ($_ == $featureCount && $nSettings == 0) {$nSettings = 1;} + } + else #version == 2 + {($feature, $nSettings, $reserved, $settingTable, $featureFlags, $nameIndex) + = TTF_Unpack("LSSLSS", substr($self->{' dat'}, 12 + ($_ - 1) * 16, 16))}; + $feature = + { + 'feature' => $feature, + 'name' => $nameIndex, + }; + + #interpret the featureFlags & store settings + $feature->{'exclusive'} = (($featureFlags & 0x8000) != 0); + + my @settings = TTF_Unpack("S*", substr($self->{' dat'}, $settingTable, $nSettings * 4)); + if ($featureFlags & 0x4000) + {$feature->{'default'} = $featureFlags & 0x00FF;} + else + {$feature->{'default'} = $settings[0];} + $feature->{'settings'} = {@settings}; + + push(@$features, $feature); + } + + $self->{'features'} = $features; + + delete $self->{' dat'}; # no longer needed, and may become obsolete + $self->{' read'} = 1; + $self; +} + +=head2 $t->out($fh) + +Writes the features to a TTF file + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($features, $numFeatures, $settings, $featureFlags, $featuresData, $settingsData); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $features = $self->{'features'}; + $numFeatures = @$features; + $featuresData = $settingsData = ''; + + foreach (@$features) { + $settings = $_->{'settings'}; + $featureFlags = ($_->{'exclusive'} ? 0x8000 : 0x0000); + +# output default setting first instead of using the featureFlags (as done below) +# $featureFlags = ($_->{'exclusive'} ? 0x8000 : 0x0000) | +# ($_->{'default'} != 0 ? 0x4000 | ($_->{'default'} & 0x00FF) +# : 0x0000); + if ($self->{'version'} == 1) + { + $featuresData .= TTF_Pack("SSLSS", + $_->{'feature'}, + scalar keys %$settings, + 12 + 12 * $numFeatures + length $settingsData, + $featureFlags, + $_->{'name'}); + } + else #version == 2 + { + $featuresData .= TTF_Pack("LSSLSS", + $_->{'feature'}, + scalar keys %$settings, + 0, + 12 + 16 * $numFeatures + length $settingsData, + $featureFlags, + $_->{'name'}); + } + + #output default setting first + #the settings may not be in their original order + my $defaultSetting = $_->{'default'}; + $settingsData .= TTF_Pack("SS", $defaultSetting, $settings->{$defaultSetting}); + foreach (sort {$a <=> $b} keys %$settings) { + if ($_ == $defaultSetting) {next;} #skip default setting + $settingsData .= TTF_Pack("SS", $_, $settings->{$_}); + } + } + + $fh->print(TTF_Pack("vSSL", $self->{'version'}, $numFeatures, 0, 0)); + $fh->print($featuresData); + $fh->print($settingsData); + + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($names, $features, $settings); + + $self->read; + + $names = $self->{' PARENT'}->{'name'}; + $names->read; + + $fh = 'STDOUT' unless defined $fh; + + $features = $self->{'features'}; + foreach (@$features) { + $fh->printf("Feature %s, %s, default: %d name %d # '%s'\n", + $_->{'feature'} > 0x01000000 ? '"' . $self->num_to_tag($_->{'feature'}) . '"' : $_->{'feature'}, + ($_->{'exclusive'} ? "exclusive" : "additive"), + $_->{'default'}, + $_->{'name'}, + $names->{'strings'}[$_->{'name'}][3][1]{1033}); + $settings = $_->{'settings'}; + foreach (sort { $a <=> $b } keys %$settings) { + $fh->printf("\tSetting %d, name %d # '%s'\n", + $_, $settings->{$_}, $names->{'strings'}[$settings->{$_}][3][1]{1033}); + } + } + + $self; +} + +sub settingName +{ + my ($self, $feature, $setting) = @_; + + $self->read; + + my $names = $self->{' PARENT'}->{'name'}; + $names->read; + + my $features = $self->{'features'}; + my ($featureEntry) = grep { $_->{'feature'} == $feature } @$features; + my $featureName = $names->{'strings'}[$featureEntry->{'name'}][3][1]{1033}; + my $settingName = $featureEntry->{'exclusive'} + ? $names->{'strings'}[$featureEntry->{'settings'}->{$setting}][3][1]{1033} + : $names->{'strings'}[$featureEntry->{'settings'}->{$setting & ~1}][3][1]{1033} + . (($setting & 1) == 0 ? " On" : " Off"); + + ($featureName, $settingName); +} + +=head2 $t->tag_to_num ($feat_str) + +Convert an alphanumeric feature id tag (string) to a number (32-bit). +Tags are normally 4 chars. Graphite ignores space +padding if it is present, so we do the same here. + +=cut + +sub tag_to_num +{ + my ($self, $feat_tag) = @_; + my $new_feat_num; + + if ($feat_tag > 0) + {$new_feat_num = $feat_tag;} # already a number, so just return it. + else + { + $feat_tag =~ s/[ \000]+$//o; # strip trailing nulls or space + $new_feat_num = unpack('N', pack('a4', $feat_tag)); #adds null padding on right if less than 4 chars + } + + return $new_feat_num; +} + +=head2 $t->num_to_tag ($feat_num) + +Convert a feature id number (32-bit) back to a tag (string). +Trailing space or null padding is removed. +Feature id numbers that do not represent alphanumeric tags +are returned unchanged. + +=cut + +sub num_to_tag +{ + my ($self, $feat_num) = @_; + my $new_feat_tag; + + if ($feat_num > 0x01000000) + { + $new_feat_tag = unpack('a4', pack('N', $feat_num)); + $new_feat_tag =~ s/[ \000]+$//o; # strip trailing nulls or space + } + else + {$new_feat_tag = $feat_num;} + + return $new_feat_tag; +} + +1; + +=head1 BUGS + +The version 1 Feat table ends with a feature (id 1) named NoName +with zero settings but with an offset to the last entry in the setting +array. This last setting has id 0 and an invalid name id. This last +feature is changed to have one setting. + +=head1 AUTHOR + +Alan Ward (derived from Jonathan Kew's Feat.pm). + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hdmx.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hdmx.pm new file mode 100644 index 0000000000..2b2f7c56b2 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hdmx.pm @@ -0,0 +1,172 @@ +package Font::TTF::Hdmx; + +=head1 NAME + +Font::TTF::Hdmx - Horizontal device metrics + +=head1 DESCRIPTION + +The table consists of an hash of device metric tables indexed by the ppem for +that subtable. Each subtable consists of an array of advance widths in pixels +for each glyph at that ppem (horizontally). + +=head1 INSTANCE VARIABLES + +Individual metrics are accessed using the following referencing: + + $f->{'hdmx'}{$ppem}[$glyph_num] + +In addition there is one instance variable: + +=over 4 + +=item Num + +Number of device tables. + +=back + +=head2 METHODS + +=cut + +use strict; +use vars qw(@ISA); + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the table into data structures + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($numg, $ppem, $i, $numt, $dat, $len); + + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + $fh->read($dat, 8); + ($self->{'Version'}, $numt, $len) = unpack("nnN", $dat); + $self->{'Num'} = $numt; + + for ($i = 0; $i < $numt; $i++) + { + $fh->read($dat, $len); + $ppem = unpack("C", $dat); + $self->{$ppem} = [unpack("C$numg", substr($dat, 2))]; + } + $self; +} + + +=head2 $t->out($fh) + +Outputs the device metrics for this font + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg, $i, $pad, $len, $numt, @ppem, $max); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + @ppem = grep(/^\d+$/, sort {$a <=> $b} keys %$self); + $pad = "\000" x (3 - ($numg + 1) % 4); + $len = $numg + 2 + length($pad); + $fh->print(pack("nnN", 0, $#ppem + 1, $len)); + for $i (@ppem) + { + $max = 0; + foreach (@{$self->{$i}}[0..($numg - 1)]) + { $max = $_ if $_ > $max; } + $fh->print(pack("C*", $i, $max, @{$self->{$i}}[0..($numg - 1)]) . $pad); + } + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + + +=head2 $t->tables_do(&func) + +For each subtable it calls &sub($ref, $ppem) + +=cut + +sub tables_do +{ + my ($self, $func) = @_; + my ($i); + + foreach $i (grep(/^\d+$/, %$self)) + { &$func($self->{$i}, $i); } + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Outputs device metrics a little more tidily + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self->SUPER::XML_element(@_) if (ref($value) ne 'ARRAY'); + $fh->print("$depth\n"); + for ($i = 0; $i <= $#{$value}; $i += 25) + { + $fh->print("$depth$context->{'indent'}". join(' ', @{$value}[$i .. $i + 24]) . "\n"); + } + $fh->print("$depth\n"); + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Head.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Head.pm new file mode 100644 index 0000000000..e2211babd3 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Head.pm @@ -0,0 +1,273 @@ +package Font::TTF::Head; + +=head1 NAME + +Font::TTF::Head - The head table for a TTF Font + +=head1 DESCRIPTION + +This is a very basic table with just instance variables as described in the +TTF documentation, using the same names. One of the most commonly used is +C. + +=head1 INSTANCE VARIABLES + +The C table has no internal instance variables beyond those common to all +tables and those specified in the standard: + + version + fontRevision + checkSumAdjustment + magicNumber + flags + unitsPerEm + created + modified + xMin + yMin + xMax + yMax + macStyle + lowestRecPPEM + fontDirectionHint + indexToLocFormat + glyphDataFormat + +The two dates are held as an array of two unsigned longs (32-bits) + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'fontRevision' => 'f', + 'checkSumAdjustment' => 'L', + 'magicNumber' => 'L', + 'flags' => 'S', + 'unitsPerEm' => 'S', + 'created' => 'L2', + 'modified' => 'L2', + 'xMin' => 's', + 'yMin' => 's', + 'xMax' => 's', + 'yMax' => 's', + 'macStyle' => 'S', + 'lowestRecPPEM' => 'S', + 'fontDirectionHint' => 's', + 'indexToLocFormat' => 's', + 'glyphDataFormat' => 's'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory thanks to some utility functions + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read || return $self; + + init unless defined $fields{'Ascender'}; + $self->{' INFILE'}->read($dat, 54); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. If in memory +(which is usually) the checkSumAdjustment field is set to 0 as per the default +if the file checksum is not to be considered. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; # this is never true +# $self->{'checkSumAdjustment'} = 0 unless $self->{' PARENT'}{' wantsig'}; + $fh->print(TTF_Out_Fields($self, \%fields, 54)); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 54; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Handles date process for the XML exporter + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($output, @time); + my (@month) = qw(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC); + + return $self->SUPER::XML_element(@_) unless ($key eq 'created' || $key eq 'modified'); + + @time = gmtime($self->getdate($key eq 'created')); + $output = sprintf("%d/%s/%d %d:%d:%d", $time[3], $month[$time[4]], $time[5] + 1900, + $time[2], $time[1], $time[0]); + $fh->print("$depth<$key>$output\n"); + $self; +} + + +=head2 $t->update + +Updates the head table based on the glyph data and the hmtx table + +=cut + +sub update +{ + my ($self) = @_; + my ($num, $i, $loc, $hmtx); + my ($xMin, $yMin, $xMax, $yMax, $lsbx); + + return undef unless ($self->SUPER::update); + + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + return undef unless (defined $self->{' PARENT'}{'hmtx'} && defined $self->{' PARENT'}{'loca'}); + $hmtx = $self->{' PARENT'}{'hmtx'}->read; + + $self->{' PARENT'}{'loca'}->update; + $hmtx->update; # if we updated, then the flags will be set anyway. + $lsbx = 1; + for ($i = 0; $i < $num; $i++) + { + $loc = $self->{' PARENT'}{'loca'}{'glyphs'}[$i]; + next unless defined $loc; + $loc->read->update_bbox; + $xMin = $loc->{'xMin'} if ($loc->{'xMin'} < $xMin || $i == 0); + $yMin = $loc->{'yMin'} if ($loc->{'yMin'} < $yMin || $i == 0); + $xMax = $loc->{'xMax'} if ($loc->{'xMax'} > $xMax); + $yMax = $loc->{'yMax'} if ($loc->{'yMax'} > $yMax); + $lsbx &= ($loc->{'xMin'} == $hmtx->{'lsb'}[$i]); + } + $self->{'xMin'} = $xMin; + $self->{'yMin'} = $yMin; + $self->{'xMax'} = $xMax; + $self->{'yMax'} = $yMax; + if ($lsbx) + { $self->{'flags'} |= 2; } + else + { $self->{'flags'} &= ~2; } + $self; +} + + +=head2 $t->getdate($is_create) + +Converts font modification time (or creation time if $is_create is set) to a 32-bit integer as returned +from time(). Returns undef if the value is out of range, either before the epoch or after the maximum +storable time. + +=cut + +sub getdate +{ + my ($self, $is_create) = @_; + my (@arr) = (@{$self->{$is_create ? 'created' : 'modified'}}); + + $arr[1] -= 2082844800; # seconds between 1/Jan/1904 and 1/Jan/1970 (midnight) + if ($arr[1] < 0) + { + $arr[1] += 0xFFFFFFF; $arr[1]++; + $arr[0]--; + } + return undef if $arr[0] != 0; + return $arr[1]; +} + + +=head2 $t->setdate($time, $is_create) + +Sets the time information for modification (or creation time if $is_create is set) according to the 32-bit +time information. + +=cut + +sub setdate +{ + my ($self, $time, $is_create) = @_; + my (@arr); + + $arr[1] = $time; + if ($arr[1] >= 0x83DA4F80) + { + $arr[1] -= 0xFFFFFFFF; + $arr[1]--; + $arr[0]++; + } + $arr[1] += 2082844800; + $self->{$is_create ? 'created' : 'modified'} = \@arr; + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hhea.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hhea.pm new file mode 100644 index 0000000000..a7d5fdcc19 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hhea.pm @@ -0,0 +1,182 @@ +package Font::TTF::Hhea; + +=head1 NAME + +Font::TTF::Hhea - Horizontal Header table + +=head1 DESCRIPTION + +This is a simplte table with just standards specified instance variables + +=head1 INSTANCE VARIABLES + + version + Ascender + Descender + LineGap + advanceWidthMax + minLeftSideBearing + minRightSideBearing + xMaxExtent + caretSlopeRise + caretSlopeRun + metricDataFormat + numberOfHMetrics + + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'Ascender' => 's', + 'Descender' => 's', + 'LineGap' => 's', + 'advanceWidthMax' => 'S', + 'minLeftSideBearing' => 's', + 'minRightSideBearing' => 's', + 'xMaxExtent' => 's', + 'caretSlopeRise' => 's', + 'caretSlopeRun' => 's', + 'metricDataFormat' => '+10s', + 'numberOfHMetrics' => 'S'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory as instance variables + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + init unless defined $fields{'Ascender'}; + $self->{' INFILE'}->read($dat, 36); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $self->{'numberOfHMetrics'} = $self->{' PARENT'}{'hmtx'}->numMetrics || $self->{'numberOfHMetrics'}; + $fh->print(TTF_Out_Fields($self, \%fields, 36)); + $self; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 36; +} + + +=head2 $t->update + +Updates various parameters in the hhea table from the hmtx table. + +=cut + +sub update +{ + my ($self) = @_; + my ($hmtx) = $self->{' PARENT'}{'hmtx'}; + my ($glyphs); + my ($num, $res); + my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext); + + return undef unless ($self->SUPER::update); + return undef unless (defined $hmtx && defined $self->{' PARENT'}{'loca'}); + + $hmtx->read->update; + $self->{' PARENT'}{'loca'}->read->update; + $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'}; + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + for ($i = 0; $i < $num; $i++) + { + $aw = $hmtx->{'advance'}[$i]; + $lsb = $hmtx->{'lsb'}[$i]; + if (defined $glyphs->[$i]) + { $ext = $lsb + $glyphs->[$i]->read->{'xMax'} - $glyphs->[$i]{'xMin'}; } + else + { $ext = $aw; } + $maw = $aw if ($aw > $maw); + $mlsb = $lsb if ($lsb < $mlsb or $i == 0); + $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0); + $mext = $ext if ($ext > $mext); + } + $self->{'advanceWidthMax'} = $maw; + $self->{'minLeftSideBearing'} = $mlsb; + $self->{'minRightSideBearing'} = $mrsb; + $self->{'xMaxExtent'} = $mext; + $self->{'numberOfHMetrics'} = $hmtx->numMetrics; + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hmtx.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hmtx.pm new file mode 100644 index 0000000000..9fba573ba4 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Hmtx.pm @@ -0,0 +1,224 @@ +package Font::TTF::Hmtx; + +=head1 NAME + +Font::TTF::Hmtx - Horizontal Metrics + +=head1 DESCRIPTION + +Contains the advance width and left side bearing for each glyph. Given the +compressability of the data onto disk, this table uses information from +other tables, and thus must do part of its output during the output of +other tables + +=head1 INSTANCE VARIABLES + +The horizontal metrics are kept in two arrays by glyph id. The variable names +do not start with a space + +=over 4 + +=item advance + +An array containing the advance width for each glyph + +=item lsb + +An array containing the left side bearing for each glyph + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the horizontal metrics from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($numh, $numg); + + $numh = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'}; + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + $self->_read($numg, $numh, "advance", "lsb"); +} + +sub _read +{ + my ($self, $numg, $numh, $tAdv, $tLsb) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($i, $dat); + + for ($i = 0; $i < $numh; $i++) + { + $fh->read($dat, 4); + ($self->{$tAdv}[$i], $self->{$tLsb}[$i]) = unpack("nn", $dat); + $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768); + } + + $i--; + while (++$i < $numg) + { + $fh->read($dat, 2); + $self->{$tAdv}[$i] = $self->{$tAdv}[$numh - 1]; + $self->{$tLsb}[$i] = unpack("n", $dat); + $self->{$tLsb}[$i] -= 65536 if ($self->{$tLsb}[$i] >= 32768); + } + $self; +} + +=head2 $t->numMetrics + +Calculates again the number of long metrics required to store the information +here. Returns undef if the table has not been read. + +=cut + +sub numMetrics +{ + my ($self) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($i); + + return undef unless $self->{' read'}; + + for ($i = $numg - 2; $i >= 0; $i--) + { last if ($self->{'advance'}[$i] != $self->{'advance'}[$i + 1]); } + + return $i + 2; +} + + +=head2 $t->out($fh) + +Writes the metrics to a TTF file. Assumes that the C has updated the +numHMetrics from here + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($numh) = $self->{' PARENT'}{'hhea'}->read->{'numberOfHMetrics'}; + $self->_out($fh, $numg, $numh, "advance", "lsb"); +} + +sub _out +{ + my ($self, $fh, $numg, $numh, $tAdv, $tLsb) = @_; + my ($i, $lsb); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + for ($i = 0; $i < $numg; $i++) + { + $lsb = $self->{$tLsb}[$i]; + $lsb += 65536 if $lsb < 0; + if ($i >= $numh) + { $fh->print(pack("n", $lsb)); } + else + { $fh->print(pack("n2", $self->{$tAdv}[$i], $lsb)); } + } + $self; +} + + +=head2 $t->update + +Updates the lsb values from the xMin from the each glyph + +=cut + +sub update +{ + my ($self) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($i); + + return undef unless ($self->SUPER::update); +# lsb & xMin must always be the same, regardless of any flags! +# return $self unless ($self->{' PARENT'}{'head'}{'flags'} & 2); # lsb & xMin the same + + $self->{' PARENT'}{'loca'}->update; + for ($i = 0; $i < $numg; $i++) + { + my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i]; + if ($g) + { $self->{'lsb'}[$i] = $g->read->update_bbox->{'xMin'}; } + else + { $self->{'lsb'}[$i] = 0; } + } + $self->{' PARENT'}{'head'}{'flags'} |= 2; + $self; +} + + +=head2 $t->out_xml($context, $depth) + +Outputs the table in XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($addr) = ($self =~ m/\((.+)\)$/o); + my ($i); + + if ($context->{'addresses'}{$addr}) + { + $fh->printf("%s<%s id_ref='%s'/>\n", $depth, $context->{'name'}, $addr); + return $self; + } + else + { $fh->printf("%s<%s id='%s'>\n", $depth, $context->{'name'}, $addr); } + + $self->read; + + for ($i = 0; $i < $numg; $i++) + { $fh->print("$depth$context->{'indent'}\n"); } + + $fh->print("$depth{'name'}>\n"); + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern.pm new file mode 100644 index 0000000000..1ff2728ead --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern.pm @@ -0,0 +1,364 @@ +package Font::TTF::Kern; + +=head1 NAME + +Font::TTF::Kern - Kerning tables + +=head1 DESCRIPTION + +Kerning tables are held as an ordered collection of subtables each giving +incremental information regarding the kerning of various pairs of glyphs. + +The basic structure of the kerning data structure is: + + $kern = $f->{'kern'}{'tables'}[$tnum]{'kerns'}{$leftnum}{$rightnum}; + +Due to the possible complexity of some kerning tables the above information +is insufficient. Reference also needs to be made to the type of the table and +the coverage field. + +=head1 INSTANCE VARIABLES + +The instance variables for a kerning table are relatively straightforward. + +=over 4 + +=item Version + +Version number of the kerning table + +=item Num + +Number of subtables in the kerning table + +=item tables + +Array of subtables in the kerning table + +Each subtable has a number of instance variables. + +=over 4 + +=item kern + +A two level hash array containing kerning values. The indexing is left +is via left class and right class. It may seem using hashes is strange, +but most tables are not type 2 and this method saves empty array values. + +=item type + +Stores the table type. Only type 0 and type 2 tables are specified for +TrueType so far. + +=item coverage + +A bit field of coverage information regarding the kerning value. See the +TrueType specification for details. + +=item Version + +Contains the version number of the table. + +=item Num + +Number of kerning pairs in this type 0 table. + +=item left + +An array indexed by glyph - left_first which returns a class number for +the glyph in type 2 tables. + +=item right + +An array indexed by glyph - right_first which returns a class number for +the glyph in type 2 tables. + +=item left_first + +the glyph number of the first element in the left array for type 2 tables. + +=item right_first + +the glyph number of the first element in the right array for type 2 tables. + +=item num_left + +Number of left classes + +=item num_right + +Number of right classes + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::Table; +use Font::TTF::Kern::Subtable; + +@ISA = qw(Font::TTF::Table); +my @subtables = qw(OrderedList StateTable ClassArray CompactClassArray); + +=head2 $t->read + +Reads the whole kerning table into structures + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($dat, $i, $numt, $len, $cov, $t); + + $fh->read($dat, 4); + ($self->{'Version'}, $numt) = unpack("n2", $dat); + if ($self->{'Version'} > 0) + { + $fh->read($dat, 4, 4); + ($self->{'Version'}, $numt) = TTF_Unpack("vL", $dat); + } + $self->{'Num'} = $numt; + + for ($i = 0; $i < $numt; $i++) + { + if ($self->{'Version'} > 0) + { + $fh->read($dat, 8); + my ($length, $coverage, $index) = unpack("Nnn", $dat); + my ($type) = $coverage & 0xFF; + $t = Font::TTF::Kern::Subtable->create($type, $coverage, $length); + $t->read($fh); + } + else + { + $t = $self->read_subtable($fh); + } + push (@{$self->{'tables'}}, $t); + } + $self; +} + +sub read_subtable +{ + my ($self, $fh) = @_; + my ($dat, $len, $cov, $t); + + $t = {}; + $fh->read($dat, 6); + ($t->{'Version'}, $len, $cov) = unpack("n3", $dat); + $t->{'coverage'} = $cov & 255; + $t->{'type'} = $cov >> 8; + if ($t->{'Version'} == 0) + { + # NB: Cambria is an example of a font that plays an unsual trick: The + # kern table is much larger than can be represented by the header $len + # would allow. So we use the number of pairs to figure out how much to read. + $fh->read($dat, 8); + $t->{'Num'} = unpack("n", $dat); + $fh->read($dat, $t->{'Num'} * 6); + my (@vals) = unpack("n*", $dat); + for (0 .. ($t->{'Num'} - 1)) + { + my ($f, $l, $v); + $f = shift @vals; + $l = shift @vals; + $v = shift @vals; + $v -= 65536 if ($v > 32767); + $t->{'kern'}{$f}{$l} = $v; + } + } elsif ($t->{'Version'} == 2) + { + my ($wid, $off, $numg, $maxl, $maxr, $j); + + $fh->read($dat, $len - 6); + $wid = unpack("n", $dat); + $off = unpack("n", substr($dat, 2)); + ($t->{'left_first'}, $numg) = unpack("n2", substr($dat, $off)); + $t->{'left'} = [unpack("n$numg", substr($dat, $off + 4))]; + foreach (@{$t->{'left'}}) + { + $_ /= $wid; + $maxl = $_ if ($_ > $maxl); + } + $t->{'left_max'} = $maxl; + + $off = unpack("n", substr($dat, 4)); + ($t->{'right_first'}, $numg) = unpack("n2", substr($dat, $off)); + $t->{'right'} = [unpack("n$numg", substr($dat, $off + 4))]; + foreach (@{$t->{'right'}}) + { + $_ >>= 1; + $maxr = $_ if ($_ > $maxr); + } + $t->{'right_max'} = $maxr; + + $off = unpack("n", substr($dat, 6)); + for ($j = 0; $j <= $maxl; $j++) + { + my ($k) = 0; + + map { $t->{'kern'}{$j}{$k} = $_ if $_; $k++; } + unpack("n$maxr", substr($dat, $off + $wid * $j)); + } + } + return $t; +} + + +=head2 $t->out($fh) + +Outputs the kerning tables to the given file + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i, $l, $r, $t); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + if ($self->{'Version'} > 0) + { $fh->print(TTF_Pack("vL", $self->{'Version'}, $self->{'Num'})); } + else + { $fh->print(pack("n2", $self->{'Version'}, $self->{'Num'})); } + + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $t = $self->{'tables'}[$i]; + + if ($self->{'Version'} > 0) + { $t->out($fh); } + else + { $self->out_subtable($fh, $t); } + } + $self; +} + + +sub out_subtable +{ + my ($self, $fh, $t) = @_; + my ($loc) = $fh->tell(); + my ($loc1, $l, $r); + + $fh->print(pack("nnn", $t->{'Version'}, 0, $t->{'coverage'})); + if ($t->{'Version'} == 0) + { + my ($dat); + foreach $l (sort {$a <=> $b} keys %{$t->{'kern'}}) + { + foreach $r (sort {$a <=> $b} keys %{$t->{'kern'}{$l}}) + { $dat .= TTF_Pack("SSs", $l, $r, $t->{'kern'}{$l}{$r}); } + } + $fh->print(TTF_Pack("SSSS", Font::TTF::Utils::TTF_bininfo(length($dat) / 6, 6))); + $fh->print($dat); + } elsif ($t->{'Version'} == 2) + { + my ($arr); + + $fh->print(pack("nnnn", $t->{'right_max'} << 1, 8, ($#{$t->{'left'}} + 7) << 1, + ($#{$t->{'left'}} + $#{$t->{'right'}} + 10) << 1)); + + $fh->print(pack("nn", $t->{'left_first'}, $#{$t->{'left'}} + 1)); + foreach (@{$t->{'left'}}) + { $fh->print(pack("C", $_ * (($t->{'left_max'} + 1) << 1))); } + + $fh->print(pack("nn", $t->{'right_first'}, $#{$t->{'right'}} + 1)); + foreach (@{$t->{'right'}}) + { $fh->print(pack("C", $_ << 1)); } + + $arr = "\000\000" x (($t->{'left_max'} + 1) * ($t->{'right_max'} + 1)); + foreach $l (keys %{$t->{'kern'}}) + { + foreach $r (keys %{$t->{'kern'}{$l}}) + { substr($arr, ($l * ($t->{'left_max'} + 1) + $r) << 1, 2) + = pack("n", $t->{'kern'}{$l}{$r}); } + } + $fh->print($arr); + } + $loc1 = $fh->tell(); + $fh->seek($loc + 2, 0); + $fh->print(pack("n", $loc1 - $loc)); + $fh->seek($loc1, 0); +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Handles outputting the kern hash into XML a little more tidily + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($f, $l); + + return $self->SUPER::XML_element(@_) unless ($key eq 'kern'); + $fh->print("$depth\n"); + foreach $f (sort {$a <=> $b} keys %{$value}) + { + foreach $l (sort {$a <=> $b} keys %{$value->{$f}}) + { $fh->print("$depth$context->{'indent'}\n"); } + } + $fh->print("$depth\n"); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +Only supports kerning table types 0 & 2. + +=item * + +No real support functions to I anything with the kerning tables yet. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/ClassArray.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/ClassArray.pm new file mode 100644 index 0000000000..c43446da9c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/ClassArray.pm @@ -0,0 +1,163 @@ +package Font::TTF::Kern::ClassArray; + +=head1 NAME + +Font::TTF::Kern::ClassArray - ClassArray Kern Subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + my $subtableStart = $fh->tell() - 8; + my $dat; + $fh->read($dat, 8); + my ($rowWidth, $leftClassTable, $rightClassTable, $array) = unpack("nnnn", $dat); + + $fh->seek($subtableStart + $leftClassTable, IO::File::SEEK_SET); + $fh->read($dat, 4); + my ($firstGlyph, $nGlyphs) = unpack("nn", $dat); + $fh->read($dat, $nGlyphs * 2); + my $leftClasses = []; + foreach (TTF_Unpack("S*", $dat)) { + push @{$leftClasses->[($_ - $array) / $rowWidth]}, $firstGlyph++; + } + + $fh->seek($subtableStart + $rightClassTable, IO::File::SEEK_SET); + $fh->read($dat, 4); + ($firstGlyph, $nGlyphs) = unpack("nn", $dat); + $fh->read($dat, $nGlyphs * 2); + my $rightClasses = []; + foreach (TTF_Unpack("S*", $dat)) { + push @{$rightClasses->[$_ / 2]}, $firstGlyph++; + } + + $fh->seek($subtableStart + $array, IO::File::SEEK_SET); + $fh->read($dat, $self->{'length'} - $array); + + my $offset = 0; + my $kernArray = []; + while ($offset < length($dat)) { + push @$kernArray, [ TTF_Unpack("s*", substr($dat, $offset, $rowWidth)) ]; + $offset += $rowWidth; + } + + $self->{'leftClasses'} = $leftClasses; + $self->{'rightClasses'} = $rightClasses; + $self->{'kernArray'} = $kernArray; + + $fh->seek($subtableStart + $self->{'length'}, IO::File::SEEK_SET); + + $self; +} + +=head2 $t->out_sub($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + +} + +sub dumpXML +{ + my ($self, $fh) = @_; + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + $fh->printf("\n"); + $self->dumpClasses($self->{'leftClasses'}, $fh); + $fh->printf("\n"); + + $fh->printf("\n"); + $self->dumpClasses($self->{'rightClasses'}, $fh); + $fh->printf("\n"); + + $fh->printf("\n"); + my $kernArray = $self->{'kernArray'}; + foreach (0 .. $#$kernArray) { + $fh->printf("\n", $_); + my $row = $kernArray->[$_]; + foreach (0 .. $#$row) { + $fh->printf("\n", $_, $row->[$_]); + } + $fh->printf("\n"); + } + $fh->printf("\n"); +} + +sub type +{ + return 'kernClassArray'; +} + + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/CompactClassArray.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/CompactClassArray.pm new file mode 100644 index 0000000000..a2f23453c6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/CompactClassArray.pm @@ -0,0 +1,103 @@ +package Font::TTF::Kern::CompactClassArray; + +=head1 NAME + +Font::TTF::Kern::CompactClassArray - Compact Class Array kern subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + die "incomplete"; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ + my ($self, $fh) = @_; + + die "incomplete"; + + $self; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + die "incomplete"; +} + + +sub type +{ + return 'kernCompactClassArray'; +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/OrderedList.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/OrderedList.pm new file mode 100644 index 0000000000..512693e2fe --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/OrderedList.pm @@ -0,0 +1,118 @@ +package Font::TTF::Kern::OrderedList; + +=head1 NAME + +Font::TTF::Kern::OrderedList - Ordered List Kern subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class, @options) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + my $dat; + $fh->read($dat, 8); + my ($nPairs, $searchRange, $entrySelector, $rangeShift) = unpack("nnnn", $dat); + + my $pairs = []; + foreach (1 .. $nPairs) { + $fh->read($dat, 6); + my ($left, $right, $kern) = TTF_Unpack("SSs", $dat); + push @$pairs, { 'left' => $left, 'right' => $right, 'kern' => $kern } if $kern != 0; + } + + $self->{'kernPairs'} = $pairs; + + $self; +} + +=head2 $t->out_sub($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ + my ($self, $fh) = @_; + + my $pairs = $self->{'kernPairs'}; + $fh->print(pack("nnnn", TTF_bininfo(scalar @$pairs, 6))); + + foreach (sort { $a->{'left'} <=> $b->{'left'} or $a->{'right'} <=> $b->{'right'} } @$pairs) { + $fh->print(TTF_Pack("SSs", $_->{'left'}, $_->{'right'}, $_->{'kern'})); + } +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub out_xml +{ + my ($self, $context, $depth, $k, $val) = @_; + my ($fh) = $context->{'fh'}; + + my $postVal = $self->post()->{'VAL'}; + + $fh = 'STDOUT' unless defined $fh; + foreach (@{$self->{'kernPairs'}}) { + $fh->printf("$depth$context->{'indent'}\n", $postVal->[$_->{'left'}], $postVal->[$_->{'right'}], $_->{'kern'}); + } +} + + +sub type +{ + return 'kernOrderedList'; +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/StateTable.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/StateTable.pm new file mode 100644 index 0000000000..6183130f96 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/StateTable.pm @@ -0,0 +1,153 @@ +package Font::TTF::Kern::StateTable; + +=head1 NAME + +Font::TTF::Kern::StateTable - State Table Kern subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Kern::Subtable; +use IO::File; + +@ISA = qw(Font::TTF::Kern::Subtable); + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $stTableStart = $fh->tell(); + + my ($classes, $states, $entries) = AAT_read_state_table($fh, 0); + + foreach (@$entries) { + my $flags = $_->{'flags'}; + delete $_->{'flags'}; + $_->{'push'} = 1 if $flags & 0x8000; + $_->{'noAdvance'} = 1 if $flags & 0x4000; + $flags &= ~0xC000; + if ($flags != 0) { + my $kernList = []; + $fh->seek($stTableStart + $flags, IO::File::SEEK_SET); + while (1) { + $fh->read($dat, 2); + my $k = TTF_Unpack("s", $dat); + push @$kernList, ($k & ~1); + last if ($k & 1) != 0; + } + $_->{'kernList'} = $kernList; + } + } + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'entries'} = $entries; + + $fh->seek($stTableStart - 8 + $self->{'length'}, IO::File::SEEK_SET); + + $self; +} + +=head2 $t->out_sub($fh) + +Writes the table to a file + +=cut + +sub out_sub +{ +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ +} + +sub dumpXML +{ + my ($self, $fh) = @_; + + $fh->printf("\n"); + $self->dumpClasses($self->{'classes'}, $fh); + $fh->printf("\n"); + + $fh->printf("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\n", $_); + my $members = $states->[$_]; + foreach (0 .. $#$members) { + my $m = $members->[$_]; + $fh->printf("{'nextState'}); + $fh->printf(" push=\"1\"") if $m->{'push'}; + $fh->printf(" noAdvance=\"1\"") if $m->{'noAdvance'}; + if (exists $m->{'kernList'}) { + $fh->printf(">"); + foreach (@{$m->{'kernList'}}) { + $fh->printf("", $_); + } + $fh->printf("\n"); + } + else { + $fh->printf("/>\n"); + } + } + $fh->printf("\n"); + } + $fh->printf("\n"); +} + +sub type +{ + return 'kernStateTable'; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/Subtable.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/Subtable.pm new file mode 100644 index 0000000000..cbe6df3e94 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Kern/Subtable.pm @@ -0,0 +1,185 @@ +package Font::TTF::Kern::Subtable; + +=head1 NAME + +Font::TTF::Kern::Subtable - Kern Subtable superclass for AAT + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +require Font::TTF::Kern::OrderedList; +require Font::TTF::Kern::StateTable; +require Font::TTF::Kern::ClassArray; +require Font::TTF::Kern::CompactClassArray; + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + + bless $self, $class; +} + +sub create +{ + my ($class, $type, $coverage, $length) = @_; + + $class = ref($class) || $class; + + my $subclass; + if ($type == 0) { + $subclass = 'Font::TTF::Kern::OrderedList'; + } + elsif ($type == 1) { + $subclass = 'Font::TTF::Kern::StateTable'; + } + elsif ($type == 2) { + $subclass = 'Font::TTF::Kern::ClassArray'; + } + elsif ($type == 3) { + $subclass = 'Font::TTF::Kern::CompactClassArray'; + } + + my @options; + push @options,'vertical' if ($coverage & 0x8000) != 0; + push @options,'crossStream' if ($coverage & 0x4000) != 0; + push @options,'variation' if ($coverage & 0x2000) != 0; + + my ($subTable) = $subclass->new(@options); + + map { $subTable->{$_} = 1 } @options; + + $subTable->{'type'} = $type; + $subTable->{'length'} = $length; + + $subTable; +} + +=head2 $t->out($fh) + +Writes the table to a file + +=cut + +sub out +{ + my ($self, $fh) = @_; + + my $subtableStart = $fh->tell(); + my $type = $self->{'type'}; + my $coverage = $type; + $coverage += 0x8000 if $self->{'vertical'}; + $coverage += 0x4000 if $self->{'crossStream'}; + $coverage += 0x2000 if $self->{'variation'}; + + $fh->print(TTF_Pack("LSS", 0, $coverage, $self->{'tupleIndex'})); # placeholder for length + + $self->out_sub($fh); + + my $length = $fh->tell() - $subtableStart; + my $padBytes = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + $fh->seek($subtableStart, IO::File::SEEK_SET); + $fh->print(pack("N", $length)); + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub post +{ + my ($self) = @_; + + my $post = $self->{' PARENT'}{' PARENT'}{'post'}; + if (defined $post) { + $post->read; + } + else { + $post = {}; + } + + return $post; +} + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + $fh = 'STDOUT' unless defined $fh; +} + +=head2 $t->print_classes($fh) + +Prints a human-readable representation of the table + +=cut + +sub print_classes +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + my $classes = $self->{'classes'}; + foreach (0 .. $#$classes) { + my $class = $classes->[$_]; + if (defined $class) { + $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class)); + } + } +} + +sub dumpClasses +{ + my ($self, $classes, $fh) = @_; + my $post = $self->post(); + + foreach (0 .. $#$classes) { + my $c = $classes->[$_]; + if ($#$c > -1) { + $fh->printf("\n", $_); + foreach (@$c) { + $fh->printf("\n", $_, $post->{'VAL'}[$_]); + } + $fh->printf("\n"); + } + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/LTSH.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/LTSH.pm new file mode 100644 index 0000000000..9f59eb9062 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/LTSH.pm @@ -0,0 +1,110 @@ +package Font::TTF::LTSH; + +=head1 NAME + +Font::TTF::LTSH - Linear Threshold table + +=head1 DESCRIPTION + +Holds the linear threshold for each glyph. This is the ppem value at which a +glyph's metrics become linear. The value is set to 1 if a glyph's metrics are +always linear. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item glyphs + +An array of ppem values. One value per glyph + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($numg, $dat); + + $fh->read($dat, 4); + ($self->{'Version'}, $numg) = unpack("nn", $dat); + $self->{'Num'} = $numg; + + $fh->read($dat, $numg); + $self->{'glyphs'} = [unpack("C$numg", $dat)]; + $self; +} + + +=head2 $t->out($fh) + +Outputs the LTSH to the given fh. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + $fh->print(pack("nn", 0, $numg)); + $fh->print(pack("C$numg", @{$self->{'glyphs'}})); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Loca.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Loca.pm new file mode 100644 index 0000000000..8cddd0c6f9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Loca.pm @@ -0,0 +1,197 @@ +package Font::TTF::Loca; + +=head1 NAME + +Font::TTF::Loca - the Locations table, which is intimately tied to the glyf table + +=head1 DESCRIPTION + +The location table holds the directory of locations of each glyph within the +glyf table. Due to this relationship and the unimportance of the actual locations +when it comes to holding glyphs in memory, reading the location table results +in the creation of glyph objects for each glyph and stores them here. +So if you are looking for glyphs, do not look in the C table, look here +instead. + +Things get complicated if you try to change the glyph list within the one table. +The recommendation is to create another clean location object to replace this +table in the font, ensuring that the old table is read first and to transfer +or copy glyphs across from the read table to the new table. + +=head1 INSTANCE VARIABLES + +The instance variables do not start with a space + +=over 4 + +=item glyphs + +An array of glyph objects for each glyph. + +=item glyphtype + +A string containing the class name to create for each new glyph. If empty, +defaults to L. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +@ISA = qw(Font::TTF::Table); + +require Font::TTF::Glyph; + + +=head2 $t->new + +Creates a new location table making sure it has a glyphs array + +=cut + +sub new +{ + my ($class) = shift; + my ($res) = $class->SUPER::new(@_); + $res->{'glyphs'} = []; + $res; +} + +=head2 $t->read + +Reads the location table creating glyph objects (L) for each glyph +allowing their later reading. + +=cut + +sub read +{ + my ($self) = @_; + + # Do this before $self->SUPER::read because this can alter the file pointer: + my ($glyfLoc) = $self->{' PARENT'}{'glyf'}->_read->{' OFFSET'}; # May seek on $fh! + + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($locFmt) = $self->{' PARENT'}{'head'}{'indexToLocFormat'}; + my ($numGlyphs) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($dat, $last, $i, $loc); + + $fh->read($dat, $locFmt ? 4 : 2); + $last = unpack($locFmt ? "N" : "n", $dat); + for ($i = 0; $i < $numGlyphs; $i++) + { + $fh->read($dat, $locFmt ? 4 : 2); + $loc = unpack($locFmt ? "N" : "n", $dat); + $self->{'glyphs'}[$i] = ($self->{'glyphtype'} || "Font::TTF::Glyph")->new( + LOC => $last << ($locFmt ? 0 : 1), + OUTLOC => $last << ($locFmt ? 0 : 1), + PARENT => $self->{' PARENT'}, + INFILE => $self->{' PARENT'}{'glyf'}{' INFILE'}, + BASE => $glyfLoc, + OUTLEN => ($loc - $last) << ($locFmt ? 0 : 1), + LEN => ($loc - $last) << ($locFmt ? 0 : 1)) if ($loc != $last); + $last = $loc; + } + $self; +} + + +=head2 $t->out($fh) + +Writes the location table out to $fh. Notice that not having read the location +table implies that the glyf table has not been read either, so the numbers in +the location table are still valid. Let's hope that C and +C haven't changed otherwise we are in big trouble. + +The function uses the OUTLOC location in the glyph calculated when the glyf +table was attempted to be output. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($locFmt) = $self->{' PARENT'}{'head'}{'indexToLocFormat'}; + my ($numGlyphs) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($count, $i, $offset, $g); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + + $count = 0; + for ($i = 0; $i < $numGlyphs; $i++) + { + $g = ($self->{'glyphs'}[$i]) || ""; + unless ($g) + { + $count++; + next; + } else + { + if ($locFmt) + { $fh->print(pack("N", $g->{' OUTLOC'}) x ($count + 1)); } + else + { $fh->print(pack("n", $g->{' OUTLOC'} >> 1) x ($count + 1)); } + $count = 0; + $offset = $g->{' OUTLOC'} + $g->{' OUTLEN'}; + } + } + $fh->print(pack($locFmt ? "N" : "n", ($locFmt ? $offset: $offset >> 1)) x ($count + 1)); +} + + +=head2 $t->out_xml($context, $depth) + +No need to output a loca table, this is dynamically generated + +=cut + +sub out_xml +{ return $_[0]; } + + +=head2 $t->glyphs_do(&func) + +Calls func for each glyph in this location table in numerical order: + + &func($glyph, $glyph_num) + +=cut + +sub glyphs_do +{ + my ($self, $func) = @_; + my ($i); + + for ($i = 0; $i <= $#{$self->{'glyphs'}}; $i++) + { &$func($self->{'glyphs'}[$i], $i) if defined $self->{'glyphs'}[$i]; } + $self; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Manual.pod b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Manual.pod new file mode 100644 index 0000000000..ae07faaba0 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Manual.pod @@ -0,0 +1,220 @@ +=head1 NAME + +Font::TTF::Manual - Information regarding the whole module set + +=head1 INTRODUCTION + +This document looks at the whole issue of how the various modules in the +TrueType Font work together. As such it is partly information on this font +system and partly information on TrueType fonts in general. + +Due to the inter-relation between so many tables in a TrueType font, different +tables will make expectations as to which other tables exist. At the very least +a font should consist of a C table and a C table. The system has +been designed around the expectation that the necessary tables for font +rendering in the Windows environment exist. But inter table dependencies have +been kept to what are considered necessary. + +This module set is not meant as a simple to use, mindless, font editing suite, +but as a low-level, get your hands dirty, know what you are doing, set of +classes for those who understand the intricacies (and there are many) of +TrueType fonts. To this end, if you get something wrong in the data structures, +etc. then this module set won't tell you and will happily create fonts which +don't work. + +At the time of writing, not every TrueType table in existence has been +implemented! Only the core basic tables of TrueType 1.0 (i.e. no embedded bitmap +tables, no postscript type tables, no OpenType tables and no GX tables) have +been implemented. If you want to help by implementing another table or two, then +please go ahead and send me your code. For a full list of tables, see +L. + + +=head2 Design Principles + +PERL is not C++. C++ encourages methods to be written for changing and reading +each instance variable in a class. If we did this in this PERL program the +results would be rather large and slow. Instead, since most access will be read +access, we expose as much of the inner storage of an object to user access +directly via hash lookup. The advantage this gives are great. For example, by +following an instance variable chain, looking up the C parameter for a +particular glyph becomes: + + $f->{'loca'}{'glyphs'}[$glyph]{'yMax'} + +Or, if we are feeling very lazy and don't mind waiting: + + $f->{'loca'}{'glyphs'}[$f->{'cmap'}->ms_lookup(0x41)]{'yMax'} + +The disadvantage of this method is that it behoves module users to behave +themselves. Thus it does not hold your hand and ensure that if you make a change +to a table, that the table is marked as I, or that other tables are +updated accordingly. + +It is up to the application developer to understand the implications of the +changes they make to a font, and to take the necessary action to ensure that the +data they get out is what they want. Thus, you could go and change the C +value on a glyph and output a new font with this change, but it is up to you to +ensure that the font's bounding box details in the C table are correct, +and even that your changing C is well motivated. + +To help with using the system, each module (or table) will not only describe the +methods it supports, which are relatively few, but also the instance variables +it supports, which are many. Most of the variables directly reflect table +attributes as specified in the OpenType specification, available from Microsoft +(L), Adobe and Apple. A list of the names +used is also given in each module, but not necessarily with any further +description. After all, this code is not a TrueType manual as well! + + +=head2 Conventions + +There are various conventions used in this system. + +Firstly we consider the documentation conventions regarding instance variables. +Each instance variable is marked indicating whether it is a B<(P)>rivate +variable which users of the module are not expected to read and certainly not +write to or a B<(R)>ead only variable which users may well want to read but not +write to. + + +=head1 METHODS + +This section examines various methods and how the various modules work with +these methods. + + +=head2 read and read_dat + +Before the data structures for a table can be accessed, they need to be filled +in from somewhere. The usual way to do this is to read an existing TrueType +font. This may be achieved by: + + $f = Font::TTF::Font->open($filename) || die "Unable to read $filename"; + +This will open an existing font and read its directory header. Notice that at +this point, none of the tables in the font have been read. (Actually, the +C and C tables are read at this point too since they contain the +commonly required parameters of): + + $f->{'head'}{'unitsPerEm'} + $f->{'maxp'}{'numGlyphs'} + +In order to be able to access information from a table, it is first necessary to +C it. Consider trying to find the advance width of a space character +(U+0020). The following code should do it: + + $f = Font::TTF::Font->open($ARGV[0]); + $snum = $f->{'cmap'}->ms_lookup(0x0020); + $sadv = $f->{'hmtx'}{'advance'}[$snum]; + print $sadv; + +This would result in the value zero being printed, which is far from correct. +But why? The first line would correctly read the font directory. The second line +would, incidently, correctly locate the space character in the Windows cmap +(assuming a non symbol encoded font). The third line would not succeed in its +task since the C table has not been filled in from the font file. To +achieve what we want we would first need to cause it to be read: + + $f->{'hmtx'}->read; + $sadv = $f->{'hmtx'}{'advance'}[$snum]; + +Or for those who are too lazy to write multiple lines, C returns the +object it reads. Thus we could write: + + $sadv = $f->{'hmtx'}->read->{'advance'}[$snum]; + +Why, if we always have to read tables before accessing information from them, +did we not have to do this for the C table? The answer lies in the method +call. It senses that the table hasn't been read and reads it for us. This will +generally happen with all method calls, it is only when we do direct data access +that we have to take the responsibility to read the table first. + +Reading a table does not necessarily result in all the data being placed into +internal data structures. In the case of a simple table C is sufficient. +In fact, the normal case is that C reads the data from the file into +an instance variable called C<' dat'> (including the space) and not into the +data structures. + +This is true except for the C class which represents a single glyph. Here +the process is reversed. Reading a C reads the data for the glyph into +the C<' dat'> instance variable and sets various header attributes for the glyph +(C, C, etc.). The data is converted out of the variable into +data structures via the C method. + +The aim, therefore, is that C should do the natural thing (read into data +structures for those tables and elements for which it is helpful -- all except +C at present) and C should do the unnatural thing: read just +the binary data for normal tables and convert binary data to data structures for +Cs. + +In summary, therefore, use C unless you want to hack around with the +internals of glyphs in which case see L for more details. + + +=head2 update + +The aim of this method is to allow the various data elements in a C font +to update themselves. All tables know how to update themselves. All tables also +contain information which cannot be I but is new knowledge in the font. +As a result, certain tables do nothing when they are updated. We can, therefore, +build an update hierarchy of tables, with the independent tables at the bottom +and C at the top: + + +--loca + | + glyf--+--maxp + | + +---+--head + | + hmtx------+--hhea + + cmap-----OS/2 + + name-- + + post-- +There is an important universal dependency which it is up to the user to +keep up to date. This is C which is used to iterate over all +the glyphs. Note that the glyphs themselves are not held in the C table +but in the C table, so adding glyphs, etc. automatically involves keeping +the C table up to date. + +=head2 Creating fonts + +Suppose we were creating a font from scratch. How much information do we need +to supply and how much will C do for us? + +The following information is required: + + $f->{'loca'}{'glyphs'} + $f->{'head'}{'upem'} + $f->{'maxp'}{'numGlyphs'} (doesn't come from $f->{'loca'}{'glyphs'}) + $f->{'hmtx'}{'advance'} + $f->{'post'}['format'} + $f->{'post'}{'VAL'} + $f->{'cmap'} + $f->{'name'} + +Pretty much everything else is calculated for you. Details of what is needed +for a glyph may be found in L. Once we have all the +information we need (and there is lots more that you could add) then we simply + + $f->dirty; # mark all tables dirty + $f->update; # update the font + +=head1 AUTHOR + +Martin Hosken L. +(see CONTRIBUTORS for other authors). + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut + +1; diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Maxp.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Maxp.pm new file mode 100644 index 0000000000..ab67a0e700 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Maxp.pm @@ -0,0 +1,199 @@ +package Font::TTF::Maxp; + +=head1 NAME + +Font::TTF::Maxp - Maximum Profile table in a font + +=head1 DESCRIPTION + +A collection of useful instance variables following the TTF standard. Probably +the most used being C. Note that this particular value is +foundational and should be kept up to date by the application, it is not updated +by C. + +Handles table versions 0.5, 1.0 + +=head1 INSTANCE VARIABLES + +No others beyond those specified in the standard: + + numGlyphs + maxPoints + maxContours + maxCompositePoints + maxCompositeContours + maxZones + maxTwilightPoints + maxStorage + maxFunctionDefs + maxInstructionDefs + maxStackElements + maxSizeOfInstructions + maxComponentElements + maxComponentDepth + + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'numGlyphs' => 'S', + 'maxPoints' => 'S', + 'maxContours' => 'S', + 'maxCompositePoints' => 'S', + 'maxCompositeContours' => 'S', + 'maxZones' => 'S', + 'maxTwilightPoints' => 'S', + 'maxStorage' => 'S', + 'maxFunctionDefs' => 'S', + 'maxInstructionDefs' => 'S', + 'maxStackElements' => 'S', + 'maxSizeOfInstructions' => 'S', + 'maxComponentElements' => 'S', + 'maxComponentDepth' => 'S'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + + init unless defined $fields{'numGlyphs'}; # any key would do + $self->{' INFILE'}->read($dat, 4); + $self->{'version'} = TTF_Unpack("v", $dat); + + if ($self->{'version'} == 0.5) + { + $self->{' INFILE'}->read($dat, 2); + $self->{'numGlyphs'} = unpack("n", $dat); + } else + { + $self->{' INFILE'}->read($dat, 28); + TTF_Read_Fields($self, $dat, \%fields); + } + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + $fh->print(TTF_Pack("v", $self->{'version'})); + + if ($self->{'version'} == 0.5) + { $fh->print(pack("n", $self->{'numGlyphs'})); } + else + { $fh->print(TTF_Out_Fields($self, \%fields, 28)); } + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + + +=head2 $t->update + +Calculates all the maximum values for a font based on the glyphs in the font. +Only those fields which require hinting code interpretation are ignored and +left as they were read. + +=cut + +sub update +{ + my ($self) = @_; + my ($i, $num, @n, @m, $j); + my (@name) = qw(maxPoints maxContours maxCompositePoints maxCompositeContours + maxSizeOfInstructions maxComponentElements maxComponentDepth); + + return undef unless ($self->SUPER::update); + return undef if ($self->{'version'} == 0.5); # only got numGlyphs + return undef unless (defined $self->{' PARENT'}{'loca'}); + $self->{' PARENT'}{'loca'}->update; + $num = $self->{'numGlyphs'}; + + for ($i = 0; $i < $num; $i++) + { + my ($g) = $self->{' PARENT'}{'loca'}{'glyphs'}[$i] || next; + + @n = $g->maxInfo; + + for ($j = 0; $j <= $#n; $j++) + { $m[$j] = $n[$j] if $n[$j] > $m[$j]; } + } + + foreach ('prep', 'fpgm') + { $m[4] = length($self->{' PARENT'}{$_}{' dat'}) + if (defined $self->{' PARENT'}{$_} + && length($self->{' PARENT'}{$_}{' dat'}) > $m[4]); + } + + for ($j = 0; $j <= $#name; $j++) + { $self->{$name[$j]} = $m[$j]; } + $self; +} +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort.pm new file mode 100644 index 0000000000..d9196d755c --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort.pm @@ -0,0 +1,130 @@ +package Font::TTF::Mort; + +=head1 NAME + +Font::TTF::Mort - Glyph Metamorphosis table in a font + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Mort::Chain; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh, $numChains); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + + $fh->read($dat, 8); + ($self->{'version'}, $numChains) = TTF_Unpack("vL", $dat); + + my $chains = []; + foreach (1 .. $numChains) { + my $chain = new Font::TTF::Mort::Chain->new; + $chain->read($fh); + $chain->{' PARENT'} = $self; + push @$chains, $chain; + } + + $self->{'chains'} = $chains; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $chains = $self->{'chains'}; + $fh->print(TTF_Pack("vL", $self->{'version'}, scalar @$chains)); + + foreach (@$chains) { + $_->out($fh); + } +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read unless $self->{' read'}; + my $feat = $self->{' PARENT'}->{'feat'}; + $feat->read; + my $post = $self->{' PARENT'}->{'post'}; + $post->read; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\n", $self->{'version'}); + + my $chains = $self->{'chains'}; + foreach (@$chains) { + $_->print($fh); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Chain.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Chain.pm new file mode 100644 index 0000000000..c08ba7bfb7 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Chain.pm @@ -0,0 +1,206 @@ +package Font::TTF::Mort::Chain; + +=head1 NAME + +Font::TTF::Mort::Chain - Chain Mort subtable for AAT + +=cut + +use strict; +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Mort::Subtable; +use IO::File; + +=head2 $t->new + +=cut + +sub new +{ + my ($class, %parms) = @_; + my ($self) = {}; + my ($p); + + $class = ref($class) || $class; + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +=head2 $t->read($fh) + +Reads the chain into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $chainStart = $fh->tell(); + $fh->read($dat, 12); + my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat); + + my $featureEntries = []; + foreach (1 .. $nFeatureEntries) { + $fh->read($dat, 12); + my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat); + push @$featureEntries, { + 'type' => $featureType, + 'setting' => $featureSetting, + 'enable' => $enableFlags, + 'disable' => $disableFlags + }; + } + + my $subtables = []; + foreach (1 .. $nSubtables) { + my $subtableStart = $fh->tell(); + + $fh->read($dat, 8); + my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat); + my $type = $coverage & 0x0007; + + my $subtable = Font::TTF::Mort::Subtable->create($type, $coverage, $subFeatureFlags, $length); + $subtable->read($fh); + $subtable->{' PARENT'} = $self; + + push @$subtables, $subtable; + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); + } + + $self->{'defaultFlags'} = $defaultFlags; + $self->{'featureEntries'} = $featureEntries; + $self->{'subtables'} = $subtables; + + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + my $chainStart = $fh->tell(); + my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'}); + $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length + + foreach (@$featureEntries) { + $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'})); + } + + foreach (@$subtables) { + $_->out($fh); + } + + my $chainLength = $fh->tell() - $chainStart; + $fh->seek($chainStart + 4, IO::File::SEEK_SET); + $fh->print(pack("N", $chainLength)); + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the chain + +=cut + +sub feat +{ + my ($self) = @_; + + my $feat = $self->{' PARENT'}{' PARENT'}{'feat'}; + if (defined $feat) { + $feat->read; + } + else { + $feat = {}; + } + + return $feat; +} + +sub print +{ + my ($self, $fh) = @_; + + $fh->printf("version %f\n", $self->{'version'}); + + my $defaultFlags = $self->{'defaultFlags'}; + $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags); + + my $feat = $self->feat(); + my $featureEntries = $self->{'featureEntries'}; + foreach (@$featureEntries) { + $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n", + $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}, + $feat->settingName($_->{'type'}, $_->{'setting'})); + } + + my $subtables = $self->{'subtables'}; + foreach (@$subtables) { + my $type = $_->{'type'}; + my $subFeatureFlags = $_->{'subFeatureFlags'}; + $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n", + subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags, + "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"), + join(", ", + map { + join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) ) + } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries + ) ); + + $_->print($fh); + } +} + +sub subtable_type_ +{ + my ($val) = @_; + my ($res); + + my @types = ( + 'Rearrangement', + 'Contextual', + 'Ligature', + undef, + 'Non-contextual', + 'Insertion', + ); + $res = $types[$val] or ('Undefined (' . $val . ')'); + + $res; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Contextual.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Contextual.pm new file mode 100644 index 0000000000..1c70a19cd9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Contextual.pm @@ -0,0 +1,166 @@ +package Font::TTF::Mort::Contextual; + +=head1 NAME + +Font::TTF::Mort::Contextual - Contextual Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 10); + my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $self->{'length'} - 8]; + + foreach (@$entries) { + my $actions = $_->{'actions'}; + foreach (@$actions) { + $_ = $_ ? $_ - ($mappingTables / 2) : undef; + } + } + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))]; + + $self; +} + +=head2 $t->pack_sub() + +=cut + +sub pack_sub +{ + my ($self) = @_; + + my ($dat) = pack("nnnnn", (0) x 5); # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables + + my $classTable = length($dat); + my $classes = $self->{'classes'}; + $dat .= AAT_pack_classes($classes); + + my $stateArray = length($dat); + my $states = $self->{'states'}; + my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, + sub { + my $actions = $_->{'actions'}; + ( $_->{'flags'}, @$actions ) + } + ); + $dat .= $dat1; + + my $entryTable = length($dat); + my $offset = ($entryTable + 8 * @$entries) / 2; + foreach (@$entries) { + my ($nextState, $flags, @parts) = split /,/; + $dat .= pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts); + } + + my $mappingTables = length($dat); + my $mappings = $self->{'mappings'}; + $dat .= pack("n*", @$mappings); + + $dat1 = pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $mappings = $self->{'mappings'}; + foreach (0 .. $#$mappings) { + $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Insertion.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Insertion.pm new file mode 100644 index 0000000000..75d39aa6a8 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Insertion.pm @@ -0,0 +1,189 @@ +package Font::TTF::Mort::Insertion; + +=head1 NAME + +Font::TTF::Mort::Insertion - Insertion Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $subtableStart = $fh->tell(); + + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + my %insertListHash; + my $insertLists; + foreach (@$entries) { + my $flags = $_->{'flags'}; + my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f)); + my $actions = $_->{'actions'}; + foreach (0 .. 1) { + if ($insertCount[$_] > 0) { + $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET); + $fh->read($dat, $insertCount[$_] * 2); + if (not defined $insertListHash{$dat}) { + push @$insertLists, [unpack("n*", $dat)]; + $insertListHash{$dat} = $#$insertLists; + } + $actions->[$_] = $insertListHash{$dat}; + } + else { + $actions->[$_] = undef; + } + } + } + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'insertLists'} = $insertLists; + + $self; +} + +=head2 $t->pack_sub() + +=cut + +sub pack_sub +{ + my ($self) = @_; + + my ($dat) = pack("nnnn", (0) x 4); + + my $classTable = length($dat); + my $classes = $self->{'classes'}; + $dat .= AAT_pack_classes($classes); + + my $stateArray = length($dat); + my $states = $self->{'states'}; + my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, + sub { + my $actions = $_->{'actions'}; + ( $_->{'flags'}, @$actions ) + } + ); + $dat .= $dat1; + + my $entryTable = length($dat); + my $offset = ($entryTable + 8 * @$entries); + my @insListOffsets; + my $insertLists = $self->{'insertLists'}; + foreach (@$insertLists) { + push @insListOffsets, $offset; + $offset += 2 * scalar @$_; + } + foreach (@$entries) { + my ($nextState, $flags, @lists) = split /,/; + $flags &= ~0x03ff; + $flags |= (scalar @{$insertLists->[$lists[0]]}) << 5 if $lists[0] ne ''; + $flags |= (scalar @{$insertLists->[$lists[1]]}) if $lists[1] ne ''; + $dat .= pack("nnnn", $nextState, $flags, + map { $_ eq '' ? 0 : $insListOffsets[$_] } @lists); + } + + foreach (@$insertLists) { + $dat .= pack("n*", @$_); + } + + $dat1 = pack("nnnn", $stateSize, $classTable, $stateArray, $entryTable); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $insertLists = $self->{'insertLists'}; + foreach (0 .. $#$insertLists) { + my $insertList = $insertLists->[$_]; + $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList)); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Ligature.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Ligature.pm new file mode 100644 index 0000000000..c5f1a08d70 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Ligature.pm @@ -0,0 +1,256 @@ +package Font::TTF::Mort::Ligature; + +=head1 NAME + +Font::TTF::Mort::Ligature - Ligature Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 0); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 14); + my ($stateSize, $classTable, $stateArray, $entryTable, + $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $self->{'length'} - 8]; + + my %actions; + my $actionLists; + foreach (@$entries) { + my $offset = $_->{'flags'} & 0x3fff; + $_->{'flags'} &= ~0x3fff; + if ($offset != 0) { + if (not defined $actions{$offset}) { + $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET); + my $actionList; + while (1) { + $fh->read($dat, 4); + my $action = unpack("N", $dat); + my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff)); + $component -= 0x40000000 if $component > 0x1fffffff; + $component -= $componentTable / 2; + push @$actionList, { 'store' => $store, 'component' => $component }; + last if $last; + } + push @$actionLists, $actionList; + $actions{$offset} = $#$actionLists; + } + $_->{'actions'} = $actions{$offset}; + } + } + + $self->{'componentTable'} = $componentTable; + my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))]; + foreach (@$components) { + $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable; + } + $self->{'components'} = $components; + + $self->{'ligatureTable'} = $ligatureTable; + $self->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))]; + + $self->{'classes'} = $classes; + $self->{'states'} = $states; + $self->{'actionLists'} = $actionLists; + + $self; +} + +=head2 $t->pack_sub($fh) + +=cut + +sub pack_sub +{ + my ($self) = @_; + my ($dat); + + $dat .= pack("nnnnnnn", (0) x 7); # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures + + my $classTable = length($dat); + my $classes = $self->{'classes'}; + $dat .= AAT_pack_classes($classes); + + my $stateArray = length($dat); + my $states = $self->{'states'}; + + my ($dat1, $stateSize, $entries) = AAT_pack_states($classes, $stateArray, $states, + sub { + ( $_->{'flags'} & 0xc000, $_->{'actions'} ) + } + ); + $dat .= $dat1; + + my $actionLists = $self->{'actionLists'}; + my %actionListOffset; + my $actionListDataLength = 0; + my @actionListEntries; + foreach (0 .. $#$entries) { + my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]); + if ($offset eq "") { + $offset = undef; + } + else { + if (defined $actionListOffset{$offset}) { + $offset = $actionListOffset{$offset}; + } + else { + $actionListOffset{$offset} = $actionListDataLength; + my $list = $actionLists->[$offset]; + $actionListDataLength += 4 * @$list; + push @actionListEntries, $list; + $offset = $actionListOffset{$offset}; + } + } + $entries->[$_] = [ $nextState, $flags, $offset ]; + } + my $entryTable = length($dat); + my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3; + foreach (@$entries) { + $_->[2] += $ligActionLists if defined $_->[2]; + $dat .= pack("nn", $_->[0], $_->[1] + $_->[2]); + } + $dat .= pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4)); + + die "internal error" unless length($dat) == $ligActionLists; + + my $componentTable = length($dat) + $actionListDataLength; + my $actionList; + foreach $actionList (@actionListEntries) { + foreach (0 .. $#$actionList) { + my $action = $actionList->[$_]; + my $val = $action->{'component'} + $componentTable / 2; + $val += 0x40000000 if $val < 0; + $val &= 0x3fffffff; + $val |= 0x40000000 if $action->{'store'}; + $val |= 0x80000000 if $_ == $#$actionList; + $dat .= pack("N", $val); + } + } + + die "internal error" unless length($dat) == $componentTable; + + my $components = $self->{'components'}; + my $ligatureTable = $componentTable + @$components * 2; + $dat .= pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components); + + my $ligatures = $self->{'ligatures'}; + $dat .= pack("n*", @$ligatures); + + $dat1 = pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable); + substr($dat, 0, length($dat1)) = $dat1; + + return $dat; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "="); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $actionLists = $self->{'actionLists'}; + foreach (0 .. $#$actionLists) { + $fh->printf("\t\tList %d:\t", $_); + my $actionList = $actionLists->[$_]; + $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList)); + } + + my $ligatureTable = $self->{'ligatureTable'}; + + $fh->print("\n"); + my $components = $self->{'components'}; + foreach (0 .. $#$components) { + $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]); + } + + $fh->print("\n"); + my $ligatures = $self->{'ligatures'}; + foreach (0 .. $#$ligatures) { + $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Noncontextual.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Noncontextual.pm new file mode 100644 index 0000000000..52788cbaf7 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Noncontextual.pm @@ -0,0 +1,105 @@ +package Font::TTF::Mort::Noncontextual; + +=head1 NAME + +Font::TTF::Mort::Noncontextual - Noncontextual Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + my ($dat); + + my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{'length'} - 8, undef); + $self->{'format'} = $format; + $self->{'lookup'} = $lookup; + + $self; +} + +=head2 $t->pack_sub($fh) + +=cut + +sub pack_sub +{ + my ($self) = @_; + + return AAT_pack_lookup($self->{'format'}, $self->{'lookup'}, 2, undef); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + my $lookup = $self->{'lookup'}; + $fh->printf("\t\tLookup format %d\n", $self->{'format'}); + if (defined $lookup) { + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]); + } + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Rearrangement.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Rearrangement.pm new file mode 100644 index 0000000000..2e3d393c6d --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Rearrangement.pm @@ -0,0 +1,118 @@ +package Font::TTF::Mort::Rearrangement; + +=head1 NAME + +Font::TTF::Mort::Rearrangement - Rearrangement Mort subtable for AAT + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; + +@ISA = qw(Font::TTF::Mort::Subtable); + +sub new +{ + my ($class, $direction, $orientation, $subFeatureFlags) = @_; + my ($self) = { + 'direction' => $direction, + 'orientation' => $orientation, + 'subFeatureFlags' => $subFeatureFlags + }; + + $class = ref($class) || $class; + bless $self, $class; +} + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self, $fh) = @_; + + my ($classes, $states) = AAT_read_state_table($fh, 0); + $self->{'classes'} = $classes; + $self->{'states'} = $states; + + $self; +} + +=head2 $t->pack_sub() + +=cut + +sub pack_sub +{ + my ($self) = @_; + + return AAT_pack_state_table($self->{'classes'}, $self->{'states'}, 0); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + my $post = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + $self->print_classes($fh); + + $fh->print("\n"); + my $states = $self->{'states'}; + my @verbs = ( "0", "Ax->xA", "xD->Dx", "AxD->DxA", + "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx", + "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA", + "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA"); + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "<" if ($_->{'flags'} & 0x8000); + $flags .= ">" if ($_->{'flags'} & 0x2000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]); + } + $fh->print("\n"); + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Subtable.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Subtable.pm new file mode 100644 index 0000000000..c5497d7269 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Mort/Subtable.pm @@ -0,0 +1,210 @@ +package Font::TTF::Mort::Subtable; + +=head1 NAME + +Font::TTF::Mort::Subtable - Mort subtable superclass for AAT + +=head1 METHODS + +=cut + +use strict; +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +require Font::TTF::Mort::Rearrangement; +require Font::TTF::Mort::Contextual; +require Font::TTF::Mort::Ligature; +require Font::TTF::Mort::Noncontextual; +require Font::TTF::Mort::Insertion; + +sub new +{ + my ($class) = @_; + my ($self) = {}; + + $class = ref($class) || $class; + + bless $self, $class; +} + +sub create +{ + my ($class, $type, $coverage, $subFeatureFlags, $length) = @_; + + $class = ref($class) || $class; + + my $subclass; + if ($type == 0) { + $subclass = 'Font::TTF::Mort::Rearrangement'; + } + elsif ($type == 1) { + $subclass = 'Font::TTF::Mort::Contextual'; + } + elsif ($type == 2) { + $subclass = 'Font::TTF::Mort::Ligature'; + } + elsif ($type == 4) { + $subclass = 'Font::TTF::Mort::Noncontextual'; + } + elsif ($type == 5) { + $subclass = 'Font::TTF::Mort::Insertion'; + } + + my ($self) = $subclass->new( + (($coverage & 0x4000) ? 'RL' : 'LR'), + (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'), + $subFeatureFlags + ); + + $self->{'type'} = $type; + $self->{'length'} = $length; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file + +=cut + +sub out +{ + my ($self, $fh) = @_; + + my ($subtableStart) = $fh->tell(); + my ($type) = $self->{'type'}; + my ($coverage) = $type; + $coverage += 0x4000 if $self->{'direction'} eq 'RL'; + $coverage += 0x2000 if $self->{'orientation'} eq 'VH'; + $coverage += 0x8000 if $self->{'orientation'} eq 'V'; + + $fh->print(TTF_Pack("SSL", 0, $coverage, $self->{'subFeatureFlags'})); # placeholder for length + + my ($dat) = $self->pack_sub(); + $fh->print($dat); + + my ($length) = $fh->tell() - $subtableStart; + my ($padBytes) = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + $fh->seek($subtableStart, IO::File::SEEK_SET); + $fh->print(pack("n", $length)); + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub post +{ + my ($self) = @_; + + my ($post) = $self->{' PARENT'}{' PARENT'}{' PARENT'}{'post'}; + if (defined $post) { + $post->read; + } + else { + $post = {}; + } + + return $post; +} + +sub feat +{ + my ($self) = @_; + + return $self->{' PARENT'}->feat(); +} + +sub print +{ + my ($self, $fh) = @_; + + my ($feat) = $self->feat(); + my ($post) = $self->post(); + + $fh = 'STDOUT' unless defined $fh; + + my ($type) = $self->{'type'}; + my ($subFeatureFlags) = $self->{'subFeatureFlags'}; + my ($defaultFlags) = $self->{' PARENT'}{'defaultFlags'}; + my ($featureEntries) = $self->{' PARENT'}{'featureEntries'}; + $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n", + subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags, + "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"), + join(", ", + map { + join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) ) + } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries + ) ); +} + +sub subtable_type_ +{ + my ($val) = @_; + my ($res); + + my (@types) = ( + 'Rearrangement', + 'Contextual', + 'Ligature', + undef, + 'Non-contextual', + 'Insertion', + ); + $res = $types[$val] or ('Undefined (' . $val . ')'); + + $res; +} + +=head2 $t->print_classes($fh) + +Prints a human-readable representation of the table + +=cut + +sub print_classes +{ + my ($self, $fh) = @_; + + my ($post) = $self->post(); + + my ($classes) = $self->{'classes'}; + foreach (0 .. $#$classes) { + my $class = $classes->[$_]; + if (defined $class) { + $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class)); + } + } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Name.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Name.pm new file mode 100644 index 0000000000..73b6a163b9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Name.pm @@ -0,0 +1,916 @@ +package Font::TTF::Name; + +=head1 NAME + +Font::TTF::Name - String table for a TTF font + +=head1 DESCRIPTION + +Strings are held by number, platform, encoding and language. Strings are +accessed as: + + $f->{'name'}{'strings'}[$number][$platform_id][$encoding_id]{$language_id} + +Notice that the language is held in an associative array due to its sparse +nature on some platforms such as Microsoft ($pid = 3). Notice also that the +array order is different from the stored array order (platform, encoding, +language, number) to allow for easy manipulation of strings by number (which is +what I guess most people will want to do). + +By default, C<$Font::TTF::Name::utf8> is set to 1, and strings will be stored as UTF8 wherever +possible. The method C can be used to find out if a string in a particular +platform and encoding will be returned as UTF8. Unicode strings are always +converted if utf8 is requested. Otherwise, strings are stored according to platform: + +You now have to set <$Font::TTF::Name::utf8> to 0 to get the old behaviour. + +=over 4 + +=item Apple Unicode (platform id = 0) + +Data is stored as network ordered UCS2. There is no encoding id for this platform +but there are language ids as per Mac language ids. + +=item Mac (platform id = 1) + +Data is stored as 8-bit binary data, leaving the interpretation to the user +according to encoding id. + +=item Unicode (platform id = 2) + +Currently stored as 16-bit network ordered UCS2. Upon release of Perl 5.005 this +will change to utf8 assuming current UCS2 semantics for all encoding ids. + +=item Windows (platform id = 3) + +As per Unicode, the data is currently stored as 16-bit network ordered UCS2. Upon +release of Perl 5.005 this will change to utf8 assuming current UCS2 semantics for +all encoding ids. + +=back + +=head1 INSTANCE VARIABLES + +=over 4 + +=item strings + +An array of arrays, etc. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA $VERSION @apple_encs @apple_encodings $utf8 $cp_1252 @cp_1252 %win_langs %langs_win %langs_mac @ms_langids @mac_langs); +use Font::TTF::Table; +use Font::TTF::Utils; +@ISA = qw(Font::TTF::Table); + +$utf8 = 1; + +{ + my ($count, $i); + eval {require Compress::Zlib;}; + unless ($@) + { + for ($i = 0; $i <= $#apple_encs; $i++) + { + $apple_encodings[0][$i] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $apple_encs[$i])))] + if (defined $apple_encs[$i]); + foreach (0 .. 127) + { $apple_encodings[0][$i][$_] = $_; } + $count = 0; + $apple_encodings[1][$i] = {map {$_ => $count++} @{$apple_encodings[0][$i]}}; + } + $cp_1252[0] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $cp_1252)))]; + $count = 0; + $cp_1252[1] = {map({$_ => $count++} @{$cp_1252[0]})}; + } + for ($i = 0; $i < $#ms_langids; $i++) + { + if (defined $ms_langids[$i][1]) + { + my ($j); + for ($j = 0; $j < $#{$ms_langids[$i][1]}; $j++) + { + my ($v) = $ms_langids[$i][1][$j]; + if ($v =~ m/^-/o) + { $win_langs{(($j + 1) << 10) + $i} = $ms_langids[$i][0] . $v; } + else + { $win_langs{(($j + 1) << 10) + $i} = $v; } + } + } + else + { $win_langs{$i + 0x400} = $ms_langids[$i][0]; } + } + %langs_win = map {my ($t) = $win_langs{$_}; my (@res) = ($t => $_); push (@res, $t => $_) if ($t =~ s/-.*$//o && ($_ & 0xFC00) == 0x400); @res} keys %win_langs; + $i = 0; + %langs_mac = map {$_ => $i++} @mac_langs; +} + + +$VERSION = 1.1; # MJPH 17-JUN-2000 Add utf8 support +# $VERSION = 1.001; # MJPH 10-AUG-1998 Put $number first in list + +=head2 $t->read + +Reads all the names into memory + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($fh) = $self->{' INFILE'}; + my ($dat, $num, $stroff, $i, $pid, $eid, $lid, $nid, $len, $off, $here); + + $fh->read($dat, 6); + ($num, $stroff) = unpack("x2nn", $dat); + for ($i = 0; $i < $num; $i++) + { + use bytes; # hack to fix bugs in 5.8.7 + read($fh, $dat, 12); + ($pid, $eid, $lid, $nid, $len, $off) = unpack("n6", $dat); + $here = $fh->tell(); + $fh->seek($self->{' OFFSET'} + $stroff + $off, 0); + $fh->read($dat, $len); + if ($utf8) + { + if ($pid == 1 && defined $apple_encodings[0][$eid]) + { $dat = TTF_word_utf8(pack("n*", map({$apple_encodings[0][$eid][$_]} unpack("C*", $dat)))); } + elsif ($pid == 2 && $eid == 2 && @cp_1252) + { $dat = TTF_word_utf8(pack("n*", map({$cp_1252[0][$_]} unpack("C*", $dat)))); } + elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1)) + { $dat = TTF_word_utf8($dat); } + } + $self->{'strings'}[$nid][$pid][$eid]{$lid} = $dat; + $fh->seek($here, 0); + } + $self; +} + + +=head2 $t->out($fh) + +Writes out all the strings + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($pid, $eid, $lid, $nid, $todo, @todo); + my ($len, $loc, $stroff, $endloc, $str_trans); + my (%dedup, @strings, @offsets, $strcount); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $strcount = 0; + $offsets[0] = 0; + $loc = $fh->tell(); + $fh->print(pack("n3", 0, 0, 0)); + foreach $nid (0 .. $#{$self->{'strings'}}) + { + foreach $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + foreach $lid (sort keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + $str_trans = $self->{'strings'}[$nid][$pid][$eid]{$lid}; + if ($utf8) + { + if ($pid == 1 && defined $apple_encodings[1][$eid]) + { $str_trans = pack("C*", + map({$apple_encodings[1][$eid]{$_} || 0x3F} unpack("n*", + TTF_utf8_word($str_trans)))); } + elsif ($pid == 2 && $eid == 2 && @cp_1252) + { $str_trans = pack("C*", + map({$cp_1252[1][$eid]{$_} || 0x3F} unpack("n*", + TTF_utf8_word($str_trans)))); } + elsif ($pid == 2 && $eid == 0) + { $str_trans =~ s/[\xc0-\xff][\x80-\xbf]+/?/og; } + elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1)) + { $str_trans = TTF_utf8_word($str_trans); } + } + my ($str_ind); + unless (defined $dedup{$str_trans}) + { + use bytes; + $dedup{$str_trans} = $strcount; + $strings[$strcount] = $str_trans; + $strcount++; + $offsets[$strcount] = $offsets[$strcount-1] + bytes::length($str_trans); + } + $str_ind = $dedup{$str_trans}; + push (@todo, [$pid, $eid, $lid, $nid, $str_ind]); + } + } + } + } + + @todo = (sort {$a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] + || $a->[3] <=> $b->[3]} @todo); + foreach $todo (@todo) + { $fh->print(pack("n6", @{$todo}[0..3], $offsets[$todo->[4]+1] - $offsets[$todo->[4]], $offsets[$todo->[4]])); } + + $stroff = $fh->tell() - $loc; + foreach my $str (@strings) + { $fh->print($str); } + + $endloc = $fh->tell(); + $fh->seek($loc, 0); + $fh->print(pack("n3", 0, $#todo + 1, $stroff)); + $fh->seek($endloc, 0); + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Outputs the string element in nice XML (which is all the table really!) + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + my ($nid, $pid, $eid, $lid); + + return $self->SUPER::XML_element(@_) unless ($key eq 'strings'); + + foreach $nid (0 .. $#{$self->{'strings'}}) + { + next unless ref($self->{'strings'}[$nid]); +# $fh->print("$depth\n"); + foreach $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + foreach $lid (sort {$a <=> $b} keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + my ($lang) = $self->get_lang($pid, $lid) || $lid; + $fh->printf("%s\n%s%s%s\n%s\n", + $depth, $nid, $pid, $eid, $lang, $depth, + $context->{'indent'}, $self->{'strings'}[$nid][$pid][$eid]{$lid}, $depth); + } + } + } +# $fh->print("$depth\n"); + } + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Store strings in the right place + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'string') + { + my ($lid) = $self->find_name($attrs{'platform'}, $attrs{'language'}) || $attrs{'language'}; + $self->{'strings'}[$attrs{'id'}][$attrs{'platform'}][$attrs{'encoding'}]{$lid} + = $context->{'text'}; + return $context; + } + else + { return $self->SUPER::XML_end(@_); } +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + +=head2 is_utf8($pid, $eid) + +Returns whether a string of a given platform and encoding is going to be in UTF8 + +=cut + +sub is_utf8 +{ + my ($self, $pid, $eid) = @_; + + return ($utf8 && ($pid == 0 || $pid == 3 || ($pid == 2 && ($eid != 2 || @cp_1252)) + || ($pid == 1 && defined $apple_encodings[$eid]))); +} + + +=head2 find_name($nid) + +Hunts down a name in all the standard places and returns the string and for an +array context the pid, eid & lid as well + +=cut + +sub find_name +{ + my ($self, $nid) = @_; + my ($res, $pid, $eid, $lid, $look, $k); + + my (@lookup) = ([3, 1, 1033], [3, 1, -1], [3, 0, 1033], [3, 0, -1], [2, 1, -1], [2, 2, -1], [2, 0, -1], + [0, 0, 0], [1, 0, 0]); + foreach $look (@lookup) + { + ($pid, $eid, $lid) = @$look; + if ($lid == -1) + { + foreach $k (keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + if (($res = $self->{strings}[$nid][$pid][$eid]{$k}) ne '') + { + $lid = $k; + last; + } + } + } else + { $res = $self->{strings}[$nid][$pid][$eid]{$lid} } + if ($res ne '') + { return wantarray ? ($res, $pid, $eid, $lid) : $res; } + } + return ''; +} + + +=head2 remove_name($nid) + +Removes all strings with the given name id from the table. + +=cut + +sub remove_name +{ + my ($self, $nid) = @_; + + delete $self->{'strings'}[$nid]; +} + +=head2 set_name($nid, $str[, $lang[, @cover]]) + +Sets the given name id string to $str for all platforms and encodings that +this module can handle. If $lang is set, it is interpretted as a language +tag and if the particular language of a string is found to match, then +that string is changed, otherwise no change occurs. + +If supplied, @cover should be a list of references to two-element arrays +containing pid,eid pairs that should be added to the name table if not already present. + +This function does not add any names to the table unless @cover is supplied. + +=cut + +sub set_name +{ + my ($self, $nid, $str, $lang, @cover) = @_; + my ($pid, $eid, $lid, $c); + + foreach $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + my $strNL = $str; + $strNL =~ s/(?:\r?)\n/\r\n/og if $pid == 3; + $strNL =~ s/(?:\r?)\n/\r/og if $pid == 1; + foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + if (defined $self->{'strings'}[$nid][$pid][$eid]) + { + my ($isincover) = 0; + foreach $c (@cover) + { + if ($c->[0] == $pid && $c->[1] == $eid) + { + $isincover = 1; + last; + } + } + push(@cover, [$pid, $eid]) if (!$isincover); + } + foreach $lid (keys %{$self->{'strings'}[$nid][$pid][$eid]}) + { + next unless (!defined $lang || $self->match_lang($pid, $lid, $lang)); + $self->{'strings'}[$nid][$pid][$eid]{$lid} = $strNL; + foreach $c (0 .. $#cover) + { + next unless (defined $cover[$c] && $cover[$c][0] == $pid && $cover[$c][1] == $eid); + delete $cover[$c]; + last; + } + } + } + } + foreach $c (@cover) + { + next unless (defined $c && scalar @$c); + my ($pid, $eid) = @{$c}; + my ($lid) = $self->find_lang($pid, $lang); + my $strNL = $str; + $strNL =~ s/\n/\r\n/og if $pid == 3; + $strNL =~ s/\n/\r/og if $pid == 1; + $self->{'strings'}[$nid][$pid][$eid]{$lid} = $strNL; + } + return $self; +} + +=head2 Font::TTF::Name->match_lang($pid, $lid, $lang) + +Compares the language associated to the string of given platform and language +with the given language tag. If the language matches the tag (i.e. is equal +or more defined than the given language tag) returns true. This is calculated +by finding whether the associated language tag starts with the given language +tag. + +=cut + +sub match_lang +{ + my ($self, $pid, $lid, $lang) = @_; + my ($langid) = $self->get_lang($pid, $lid); + + return 1 if ($pid == 0); # all languages are equal in unicode since nothing defined + return ($lid == $lang) if ($lang != 0 || $lang eq '0'); + return !index(lc($langid), lc($lang)) || !index(lc($lang), lc($langid)); +} + +=head2 Font::TTF::Name->get_lang($pid, $lid) + +Returns the language tag associated with a particular platform and language id + +=cut + +sub get_lang +{ + my ($self, $pid, $lid) = @_; + + if ($pid == 3) + { return $win_langs{$lid}; } + elsif ($pid == 1) + { return $mac_langs[$lid]; } + return ''; +} + + +=head2 Font::TTF::Name->find_lang($pid, $lang) + +Looks up the language name and returns a lang id if one exists + +=cut + +sub find_lang +{ + my ($self, $pid, $lang) = @_; + + if ($pid == 3) + { return $langs_win{$lang}; } + elsif ($pid == 1) + { return $langs_mac{$lang}; } + return undef; +} + +=head2 Font::TTF::Name->pe_list() + +Returns an array of references to two-element arrays +containing pid,eid pairs that already exist in this name table. +Useful for creating @cover parameter to set_name(). + +=cut + +sub pe_list +{ + my ($self) = @_; + my (@cover, %ids); + + foreach my $nid (0 .. $#{$self->{'strings'}}) + { + if (defined $self->{'strings'}[$nid]) + { + foreach my $pid (0 .. $#{$self->{'strings'}[$nid]}) + { + if (defined $self->{'strings'}[$nid][$pid]) + { + foreach my $eid (0 .. $#{$self->{'strings'}[$nid][$pid]}) + { + if (defined $self->{'strings'}[$nid][$pid][$eid] && !$ids{$pid}{$eid}) + { + $ids{$pid}{$eid} = 1; + push @cover, [$pid, $eid]; + } + } + } + } + } + } + return @cover; +} + + +BEGIN { +@apple_encs = ( +<<'EOT', +M>)RES==NCW$`@.'G_S5Q*L(!#?+K1VO4:.W6IJA-:\^BM?>L>1&NP(A0Q$BL +M<*!62ZV8Z1)[K]BE$MR#O,=/7OW]7T&*6"NMI4K31EOMM)>N@XXZZ2Q#IBZZ +MZJ:['GKJ)4NVWOKHJ]\_/\!`@PR68XBAALDUW`@CC3+:&&.-,UZ>?!-,-,ED +M4TPUS70SS#3+;`7FF&N>0D7F6V"A119;8JEEEEMAI5566V.M==;;H-A&FVRV +MQ5;;_OTONJ3<%;?<5^NQ1YYXYJGG7GKME3?>>N^=#S[ZY(O/OOKNFU]^JO<[ +M!$?LLMO>$#OAH4-*4F+'[(L+E*F,6SH:%\9%]C@>1W&CN&%2:9QNO]-))5ZH +M<]9.!^/DQ/8X-V[@@#,AS0ZE+KB7R$ODA\:A26@>6H2FH9D?J17^)(I#3C@8 +MLD)V?:(^"BE.AN30,F0XK\(Y5UUVW0TW77/'W;H_;JM6HRJ1&95%M0Y'E5%5 +.5.U4]""JB`?E$` +EOT + +undef, +undef, +undef, +<<'EOT', +M>)RES[=/%```1O$WO8G_@$'J';W70Z2WHS>5WJN%8D6%D;BZ,3*P,;#C2D(8 +M,9&)08V)+4*(1((X2'(#[.:;7[[\*./_%D,L<<230"(!@B213`JII)%.!IED +MD4T.N>213P&%%%%,B!)N4LJMR[Z<"BJIHIH::JFCG@;"--)$,RVTTD8['732 +M13>WN<-=>NBECWX&&&2(848898QQ)IADBFEFF.4>]WG`0^:89X%%'O&8)SSE +M&<]9X@4O><4R*Y?_.ZRSRQ[[''#(1S[PB<]NL\D7OO&5[_S@9TR`(XXYX1=O +M.>4W9_SAG`O^7OF=O>XW*N)WV!%''7/<"2>=S?<\K5O(G[7?/Y>'``` +EOT + +<<'EOT', +M>)RED$LSEW$`A9_-^00L,H-^(=>4Y%^2J'1Q*Y+[I2(BHA`B?!%J6EM1*28S +M;9II[/PI*7*_%TUN\_*VZ%W:FN9LSYEGGD,\_Q?#$?SP)X"C!!)$,"&$$L8Q +MPCG."2(X222GB,+%:XR"42N,P5KG*-1))()H54KG.# +M--*Y20:WR"2+;'+()8]\"BBDB-O$PM +M==3SA`8::>(IS;3PC%;::'?X'^W#?&(0-Z-,,,,TL\PSQP)+K+#,*C]9XQ?K +M_.8/FVRPQ0[;[+&+S=_]_J;KX/Y6I?&U.JQ.Z[GU0@-VBNTR@;Q4G]ZI5V_U +MQG@83^-M?,PAXV6'VF'ZH&Z]4H_>J]]IO=:0W!K6B#[KBT;U56/ZIN\:UX1^ +?:%)3FM:,9C6G>2UH44M:UHI6'?)RES5=OSG$`0.$CYR.(A(3DUS]J4WOO59O6;&F+UMY[7R&(V'N^4ETZ=*"J +M:M:H=>E*0D1B)7HC1KC0[R#G^LEA,/]7((Z(EK2B-?&TH2WM:$\'.M*)SG0A +M@:YTHSL]Z$DO>M.'OO2C/P,8R*`&/X2A#&,X(QC)*$:3R!C&,H[Q3&`BDYC, +M%))(9BK3F,X,9C*+%%*9S1S22">#NN(MWO.>#.\GG(Y_YQ!>^DAT7 +M\8WZ$%$3$OC.#W(IYC=_^!N"1SWF*<]ZP1AO*:'`;*^0%V502J6'*8LRHRQR +M/.)Q3WC2TY[QG+D6FF^!19ZGR(M>BA*]3"'5(9Z8.>:YVSV-DD/CT"0T#RU" +MT]",G^YUG_L]8+$E7O6%!WUIF>4^]9K7?6R%E59YQUM6>]L:[WK/5][WH;7> +4M,X'/O&1-WSF_\` +EOT + +<<'EOT', +M>)RERT=.%5``0-&+7K'&!B(@X/L/^/3>ZZ?SZ=*K@`KVWOL:U!68.#!&8G2@ +M$Q?F5/=@SOB0XO\$$D2**:&4)&644T$E55130RUUU--`(TTTTT(K;;3302== +M=--#[[_?1S\###+$,".,DF:,<2:89(II9KC`+'/,L\`B2RRSPBIKK+/!13;9 +M8IM+7.8*.^QRE6M]SG`0]YQ&.>\)1G/.<%+WG%:][PEI0G +M/>5IL\SVC#F>-=<\\SUG@846>=Y@PFBQ)9::M,QR*ZRTRFIKK+4N!+[[CD]\ +M#I%?9O*-+XGH/N?BMON=CT7\B#MQUR5^^MY#ZH('7?:PJQYQS14/L!?S,S[$ +M=,SD*[]#DH\>==UC;K@8LD)V*`B%(3?D\2<4>=Q-3[B5R#'#66>LM\%&FVRV +GQ5;;;+?#3KOLML=>4_;9[X"##CGLB*.F'7/<"2>=)RED-DVUG$`1;=:U*Y%0C)5O^^/SSS/F>>9#"$JE7D>"D6\3S=>Q^MPU^JF +M&^M"2JJHIH9:ZJBG@4:::*:%M[32 +M1CL==_TNNNFAES[Z&6"0(889890QQIE@DG=,,% +MF;XTRVQSS#7/5[[VC<&8D?D66&C<(HLML=0RRZVPTBJ7K;;&6NNLM\%&FVRV +L):388:===MMCKP,..F2_(XXZYK#CMKGZS[YU-]QTRVUWW'7/?0]N`4(?0WT` +EOT + +<<'EOT', +M>)RED,5.0U$415=(D.X!$"ANMX^VN+M#D>+N[H4"Q5W^APF_PZ\PY.9-"`-& +MY.3LG>-"#_\3@P^'8OP$"%)"*6644T$E55130RUUU--`(TTTTT(K;;3302== +M=-OZ7OH(T<\`@PP19I@11AECG`DFF6*:&6:98YX%%EEBF15666.=#3;98IL= +M=MECGP,.B7#$,5%...6,&.=<<,D5U]QPRQWW//#($\^\\,J;G?_II)ETXS79 +M)L<$C<,['S[GYSY=?FWK6E>Z^?L'BK,:KP0E*DD>R?6E*-7E='DM9BA36A49XKI_!M<9D8J +EOT + +<<'EOT', +M>)RED,E3SW$8QU_77@<''+A]^Y5(2-F7+"%92\B^ES5ES]H,)L(8&21E*UNH +M&"8T8ZS3I(FS_T"$_`L^-^/D8)YY/^]Y/\L\"Y/Y/XN()T8"B0P@B8$,(IG! +MI#"$H0PCE>&DDG,((N99#.+VM8SP8**&0CF]C,%K:RC2*V +M4TP).]C)+G:SA[WLHY3]'.`@ASC,$-(*3WG:,R%ZSDK/!K[@1<][R2HO6^T5:ZSUJM>\[@UO +M6F>]M[SM'>]ZSX90_\"'-MIDLX^">ASPQ*?!M_C,Y[ZP->KE*U_[QK>^\WW( +CM/O!ML"=?K3#3[Z,*_AKOR]V^=5O=OO='_ZTQU^_`2-%:*`` +EOT + +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +<<'EOT', +M>)REC]=.E&$`1(\%&W@4004%_7:!I?>.Z-+[TJL*=K"`BH`*J,_"+2'A!7PW +MX;\2[LG<3#*9G!F2G$V!&'$***2(!,644$H9Y5102175U%!+'?4TT$@3S;30 +M2AN/:.\HSG +M+++$"U[RBM>\X2WO6&:%]WS@(Y]898W/?.$KZWQC@TVV^,X/?K+-#KO\XC=_ +M(OX!?T/"`0<=-$T+WG9 +M*U[UFNEF>%V]X4TSO666V=[VCG?-,==[WC?/?!_XT&#,N`466F3"8DLLMLD&W2#COMLML>>^V+=IX\2<7BCCGNA)-. +0.>V,L\XY[P*'[!\#D^='L@`` +EOT + +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +undef, +); + +$cp_1252 = ( +<<'EOT', +M>)P-SD-B'5```,#YJ6VE>DEM&[\VD]JVF?H./4'-U+93V[9M:SV;$141(Y74 +MTD@KG?0RR"B3S++(*IOL:%9-$0&YD?BH22(82XF)10.3(@U(DDB$;F_/]% +M0_Y0(!0*A4-\R!5RQ]R*BX\,#'4CB?]];B3)`@LMLM@22RVSW`HKK;):LC76 +M6F>]#3;:9+,MMMIFNQUVVF6W/?;:9[\##CKDL"-2''7,<2><=,II9YQUSGD7 +M7'3)95=<=0@` +EOT +); + + +@ms_langids = ( [""], + ['ar', ["-SA", "-IQ", "-EG", "-LY", "-DZ", "-MA", "-TN", + "-OM", "-YE", "-SY", "-JO", "-LB", "-KW", "-AE", + "-BH", "-QA", "-Ploc-SA", "-145"]], + ['bg-BG'], + ['ca-ES'], + ['zh', ['-TW', '-CN', '-HK', '-SG', '-MO', "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "zh", "-Hant"]], + ["cs-CZ"], + ["da-DK"], + ["de", ["-DE", "-CH", "-AT", "-LU", "-LI"]], + ["el-GR"], + ["en", ["-US", "-UK", "-AU", "-CA", "-NZ", "-IE", "-ZA", + "-JM", "029", "-BZ", "-TT", "-ZW", "-PH", "-ID", + "-HK", "-IN", "-MY", "-SG", "-AE", "-BH", "-EG", + "-JO", "-KW", "-TR", "-YE"]], + ["es", ["-ES", "-MX", "-ES", "-GT", "-CR", "-PA", "-DO", + "-VE", "-CO", "-PE", "-AR", "-EC", "-CL", "-UY", + "-PY", "-BO", "-SV", "-HN", "-NI", "-PR", "-US"]], + ["fi-FI"], + ["fr", ["-FR", "-BE", "-CA", "-CH", "-LU", "-MC", "", + "-RE", "-CG", "-SN", "-CM", "-CI", "-ML", "-MA", + "-HT"]], + ["he-IL"], + ["hu-HU"], + ["is-IS"], +# 0010 + ["it", ["-IT", "-CH"]], + ["ja-JP"], + ["ko-KR"], + ["nl", ["-NL", "-BE"]], + ["no", ["-bok-NO", "-nyn-NO", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "nn", "nb"]], + ["pl-PL"], + ["pt", ["-BR", "-PT"]], + ["rm-CH"], + ["ro", ["-RO", "_MD"]], + ["ru-RU"], + ["hr", ["-HR", "-Latn-CS", "Cyrl-CS", "-BA", "", "-Latn-BA", "-Cyrl-BA", + "", "". "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "bs-Cyrl", "bs-Latn", "sr-Cyrl", "sr-Latn", "", "bs", "sr"]], + ["sk-SK"], + ["sq-AL"], + ["sv", ["-SE", "-FI"]], + ["th-TH"], + ["tr-TR"], +# 0020 + ["ur", ["-PK", "tr-IN"]], + ["id-ID"], + ["uk-UA"], + ["be-BY"], + ["sl-SL"], + ["et-EE"], + ["lv-LV"], + ["lt-LT"], + ["tg", ["-Cyrl-TJ", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "-Cyrl"]], + ["fa-IR"], + ["vi-VN"], + ["hy-AM"], + ["az", ["-Latn-AZ", "-Cyrl-AZ", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "-Cyrl", "-Latn"]], + ["eu-ES"], + ["wen". ["wen-DE", "dsb-DE", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "dsb"]], + ["mk-MK"], +# 0030 + ["st"], + ["ts"], + ["tn-ZA"], + ["ven"], + ["xh-ZA"], + ["zu-ZA"], + ["af-ZA"], + ["ka-GE"], + ["fo-FO"], + ["hi-IN"], + ["mt"], + ["se", ["-NO", "-SE", "-FI", "smj-NO", "smj-SE", "sma-NO", "sma-SE", + "", "smn-FI", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "smn", "sms", "smj"]], + ["ga-IE"], + ["yi"], + ["ms", ["-MY", "-BN"]], + ["kk-KZ"], +# 0040 + ["ky-KG"], + ["sw-KE"], + ["tk-TM"], + ["uz", ["-Latn-UZ", "-Cyrl-UZ", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "-Cyrl", "-Latn"]], + ["tt-RU"], + ["bn", ["-IN", "-BD"]], + ["pa", ["-IN", "-Arab-PK", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "-Arab"]], + ["gu-IN"], + ["or-IN"], + ["ta-IN"], + ["te-IN"], + ["kn-IN"], + ["ml-IN"], + ["as-IN"], + ["mr-IN"], + ["sa-IN"], +# 0050 + ["mn", ["-Cyrl-MN", "-Mong-CN", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "-Cyrl", "-Mong"]], + ["bo", ["-CN", "-BT"]], + ["cy-GB"], + ["km-KH"], + ["lo-LA"], + ["my"], + ["gl-ES"], + ["kok-IN"], + ["mni"], + ["sd", ["-IN", "-PK", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Arab"]], + ["syr-SY"], + ["si-LK"], + ["chr", ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Cher"]], + ["iu", ["-Cans-CA", "-Latn-CA", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "-Cans", "-Latn"]], + ["am-ET"], + ["tmz", ["-Arab", "-Latn-DZ", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "-Latn"]], +# 0060 + ["ks"], + ["ne", ["-NP", "-IN"]], + ["fy-NL"], + ["ps-AF"], + ["fil-PH"], + ["dv-MV"], + ["bin-NG"], + ["fuv", ["-NG", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ff-Latn"]], + ["ha", ["-Latn-NG", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Latn"]], + ["ibb-NG"], + ["yo-NG"], + ["quz", ["-BO", "-EC", "-PE"]], + ["ns-ZA"], + ["ba-RU"], + ["lb-LU"], + ["kl-GL"], +# 0070 + ["ig-NG"], + ["kau"], + ["om"], + ["ti", ["-ET". "-ER"]], + ["gn"], + ["haw"], + ["la"], + ["so"], + ["ii-CN"], + ["pap"], + ["arn-CL"], + [""], # (unassigned) + ["moh-CA"], + [""], # (unassigned) + ["br-FR"], + [""], # (unassigned) +# 0080 + ["ug-CN"], + ["mi-NZ"], + ["oc-FR"], + ["co-FR"], + ["gsw-FR"], + ["sah-RU"], + ["qut-GT"], + ["rw-RW"], + ["wo-SN"], + [""], # (unassigned) + [""], # (unassigned) + [""], # (unassigned) + ["gbz-AF"], + [""], # (unassigned) + [""], # (unassigned) + [""], # (unassigned) +# 0090 + [""], # (unassigned) + ["gd-GB"], + ["ku", ["-Arab-IQ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "-Arab"]], + ["quc-CO"], +); +# 0501 = qps-ploc +# 05fe = qps-ploca +# 09ff = qps-plocm + +@mac_langs = ( + 'en', 'fr', 'de', 'it', 'nl', 'sv', 'es', 'da', 'pt', 'no', + 'he', 'ja', 'ar', 'fi', 'el', 'is', 'mt', 'tr', 'hr', 'zh-Hant', + 'ur', 'hi', 'th', 'ko', 'lt', 'pl', 'hu', 'et', 'lv', 'se', + 'fo', 'ru' ,'zh-Hans', 'nl', 'ga', 'sq', 'ro', 'cs', 'sk', + 'sl', 'yi', 'sr', 'mk', 'bg', 'uk', 'be', 'uz', 'kk', 'az-Cyrl', + 'az-Latn', 'hy', 'ka', 'mo', 'ky', 'abh', 'tuk', 'mn-Mong', 'mn-Cyrl', 'pst', + 'ku', 'ks', 'sd', 'bo', 'ne', 'sa', 'mr', 'bn', 'as', 'gu', + 'pa', 'or', 'ml', 'kn', 'ta', 'te', 'si', 'my', 'km', 'lo', + 'vi', 'id', 'tl', 'ms-Latn', 'ms-Arab', 'am', 'ti', 'tga', 'so', 'sw', + 'rw', 'rn', 'ny', 'mg', 'eo', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', 'cy', 'eu', + 'la', 'qu', 'gn', 'ay', 'tt', 'ug', 'dz', 'jv-Latn', 'su-Latn', + 'gl', 'af', 'br', 'iu', 'gd', 'gv', 'gd-IR-x-dotabove', 'to', 'el-polyton', 'kl', + 'az-Latn' +); + +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +Unicode type strings will be stored in utf8 for all known platforms, +once Perl 5.6 has been released and I can find all the mapping tables, etc. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OS_2.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OS_2.pm new file mode 100644 index 0000000000..b52312e184 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OS_2.pm @@ -0,0 +1,1036 @@ +package Font::TTF::OS_2; + +=head1 NAME + +Font::TTF::OS_2 - the OS/2 table in a TTF font + +=head1 DESCRIPTION + +The OS/2 table has two versions and forms, one an extension of the other. This +module supports both forms and the switching between them. + +=head1 INSTANCE VARIABLES + +No other variables than those in table and those in the standard: + + Version + xAvgCharWidth + usWeightClass + usWidthClass + fsType + ySubscriptXSize + ySubScriptYSize + ySubscriptXOffset + ySubscriptYOffset + ySuperscriptXSize + ySuperscriptYSize + ySuperscriptXOffset + ySuperscriptYOffset + yStrikeoutSize + yStrikeoutPosition + sFamilyClass + bFamilyType + bSerifStyle + bWeight + bProportion + bContrast + bStrokeVariation + bArmStyle + bLetterform + bMidline + bXheight + ulUnicodeRange1 + ulUnicodeRange2 + ulUnicodeRange3 + ulUnicodeRange4 + achVendID + fsSelection + usFirstCharIndex + usLastCharIndex + sTypoAscender + sTypoDescender + sTypoLineGap + usWinAscent + usWinDescent + ulCodePageRange1 + ulCodePageRange2 + xHeight + CapHeight + defaultChar + breakChar + maxLookups + +Notice that versions 0, 1, 2 & 3 of the table are supported. Notice also that the +Panose variable has been broken down into its elements. + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA @fields @lens @field_info @weights @ranges @codepages); +use Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'xAvgCharWidth' => 's', + 'usWeightClass' => 'S', + 'usWidthClass' => 'S', + 'fsType' => 's', + 'ySubscriptXSize' => 's', + 'ySubScriptYSize' => 's', + 'ySubscriptXOffset' => 's', + 'ySubscriptYOffset' => 's', + 'ySuperscriptXSize' => 's', + 'ySuperscriptYSize' => 's', + 'ySuperscriptXOffset' => 's', + 'ySuperscriptYOffset' => 's', + 'yStrikeoutSize' => 's', + 'yStrikeoutPosition' => 's', + 'sFamilyClass' => 's', + 'bFamilyType' => 'C', + 'bSerifStyle' => 'C', + 'bWeight' => 'C', + 'bProportion' => 'C', + 'bContrast' => 'C', + 'bStrokeVariation' => 'C', + 'bArmStyle' => 'C', + 'bLetterform' => 'C', + 'bMidline' => 'C', + 'bXheight' => 'C', + 'ulUnicodeRange1' => 'L', + 'ulUnicodeRange2' => 'L', + 'ulUnicodeRange3' => 'L', + 'ulUnicodeRange4' => 'L', + 'achVendID' => 'L', + 'fsSelection' => 'S', + 'usFirstCharIndex' => 'S', + 'usLastCharIndex' => 'S', + 'sTypoAscender' => 'S', + 'sTypoDescender' => 's', + 'sTypoLineGap' => 'S', + 'usWinAscent' => 'S', + 'usWinDescent' => 'S', + '' => '', + 'ulCodePageRange1' => 'L', + 'ulCodePageRange2' => 'L', + '' => '', + 'xHeight' => 's', + 'CapHeight' => 's', + 'defaultChar' => 'S', + 'breakChar' => 'S', + 'maxLookups' => 's', + '' => '', # i.e. v3 is basically same as v2 + '' => '' # i.e. v4 is structurally identical to v3 + ); + +@weights = qw(64 14 27 35 100 20 14 42 63 3 6 35 20 56 56 17 4 49 56 71 31 10 18 3 18 2 166); + +use Font::TTF::Utils; + +sub init +{ + my ($k, $v, $c, $n, $i, $t, $j); + + $n = 0; + @lens = (76, 84, 94, 94, 94); + for ($j = 0; $j < $#field_info; $j += 2) + { + if ($field_info[$j] eq '') + { + $n++; + next; + } + ($k, $v, $c) = TTF_Init_Fields($field_info[$j], $c, $field_info[$j+1]); + next unless defined $k && $k ne ""; + for ($i = $n; $i < 5; $i++) + { $fields[$i]{$k} = $v; } + } +} + + +=head2 $t->read + +Reads in the various values from disk (see details of OS/2 table) + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $ver); + + $self->SUPER::read or return $self; + + init unless defined $fields[2]{'xAvgCharWidth'}; + $self->{' INFILE'}->read($dat, 2); + $ver = unpack("n", $dat); + $self->{'Version'} = $ver; + if ($ver < 5) + { + $self->{' INFILE'}->read($dat, $lens[$ver]); + TTF_Read_Fields($self, $dat, $fields[$ver]); + } + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($ver); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $ver = $self->{'Version'}; + $fh->print(pack("n", $ver)); + $fh->print(TTF_Out_Fields($self, $fields[$ver], $lens[$ver])); + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $value) + +Tidies up the hex values to output them in hex + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $value) = @_; + my ($fh) = $context->{'fh'}; + + if ($key =~ m/^ul(?:Unicode|CodePage)Range\d$/o) + { $fh->printf("%s<%s>%08X\n", $depth, $key, $value, $key); } + elsif ($key eq 'achVendID') + { $fh->printf("%s<%s name='%s'/>\n", $depth, $key, pack('N', $value)); } + else + { return $self->SUPER::XML_element(@_); } + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Now handle them on the way back in + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag =~ m/^ul(?:Unicode|CodePage)Range\d$/o) + { return hex($context->{'text'}); } + elsif ($tag eq 'achVendID') + { return unpack('N', $attrs{'name'}); } + else + { return $self->SUPER::XML_end(@_); } +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 78; +} + +=head2 $t->update + +Updates the OS/2 table by getting information from other sources: + +Updates the C and C values based on the MS table in the +cmap. + +Updates the sTypoAscender, sTypoDescender & sTypoLineGap to be the same values +as Ascender, Descender and Linegap from the hhea table (assuming it is dirty) +and also sets usWinAscent to be the sum of Ascender+Linegap and usWinDescent to +be the negative of Descender. + +=cut + +sub update +{ + my ($self) = @_; + my ($map, @keys, $table, $i, $avg, $hmtx); + + return undef unless ($self->SUPER::update); + + $self->{' PARENT'}{'cmap'}->update; + $map = $self->{' PARENT'}{'cmap'}->find_ms || return undef; + $hmtx = $self->{' PARENT'}{'hmtx'}->read; + + @keys = sort {$a <=> $b} grep {$_ < 0x10000} keys %{$map->{'val'}}; + + $self->{'usFirstCharIndex'} = $keys[0]; + $self->{'usLastCharIndex'} = $keys[-1]; + + $table = $self->{' PARENT'}{'hhea'}->read; + + # try any way we can to get some real numbers passed around! + if (($self->{'fsSelection'} & 128) != 0) + { + # assume the user knows what they are doing and has sensible values already + } + elsif ($table->{'Ascender'} != 0 || $table->{'Descender'} != 0) + { + $self->{'sTypoAscender'} = $table->{'Ascender'}; + $self->{'sTypoDescender'} = $table->{'Descender'}; + $self->{'sTypoLineGap'} = $table->{'LineGap'}; + $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'}; + $self->{'usWinDescent'} = -$self->{'sTypoDescender'}; + } + elsif ($self->{'sTypoAscender'} != 0 || $self->{'sTypoDescender'} != 0) + { + $table->{'Ascender'} = $self->{'sTypoAscender'}; + $table->{'Descender'} = $self->{'sTypoDescender'}; + $table->{'LineGap'} = $self->{'sTypoLineGap'}; + $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'}; + $self->{'usWinDescent'} = -$self->{'sTypoDescender'}; + } + elsif ($self->{'usWinAscent'} != 0 || $self->{'usWinDescent'} != 0) + { + $self->{'sTypoAscender'} = $table->{'Ascender'} = $self->{'usWinAscent'}; + $self->{'sTypoDescender'} = $table->{'Descender'} = -$self->{'usWinDescent'}; + $self->{'sTypoLineGap'} = $table->{'LineGap'} = 0; + } + + if ($self->{'Version'} < 3) + { + for ($i = 0; $i < 26; $i++) + { $avg += $hmtx->{'advance'}[$map->{'val'}{$i + 0x0061}] * $weights[$i]; } + $avg += $hmtx->{'advance'}[$map->{'val'}{0x0020}] * $weights[-1]; + $self->{'xAvgCharWidth'} = $avg / 1000; + } + elsif ($self->{'Version'} > 2) + { + $i = 0; $avg = 0; + foreach (@{$hmtx->{'advance'}}) + { + next unless ($_); + $i++; + $avg += $_; + } + $avg /= $i if ($i); + $self->{'xAvgCharWidth'} = $avg; + } + + $self->{'ulUnicodeRange2'} &= ~0x2000000; + foreach $i (keys %{$map->{'val'}}) + { + if ($i >= 0x10000) + { + $self->{'ulUnicodeRange2'} |= 0x2000000; + last; + } + } + + $self->{'Version'} = 1 if (defined $self->{'ulCodePageRange1'} && $self->{'Version'} < 1); + $self->{'Version'} = 2 if (defined $self->{'maxLookups'} && $self->{'Version'} < 2); + + if ((exists $self->{' PARENT'}{'GPOS'} && $self->{' PARENT'}{'GPOS'}{' read'}) || + (exists $self->{' PARENT'}{'GSUB'} && $self->{' PARENT'}{'GSUB'}{' read'})) + { + # one or both of GPOS & GSUB exist and have been read or modified; so update usMaxContexts + my ($lp, $ls); + $lp = $self->{' PARENT'}{'GPOS'}->maxContext if exists $self->{' PARENT'}{'GPOS'}; + $ls = $self->{' PARENT'}{'GSUB'}->maxContext if exists $self->{' PARENT'}{'GSUB'}; + $self->{'maxLookups'} = $lp > $ls ? $lp : $ls; + } + + $self; +} + + +=head2 $t->guessRangeBits (\%map, [$cp_threshold, [%u_threshold]]) + +Set the ulCodePageRange and ulUnicodeRange fields based on characters actually present in the font. + +%map is a hash keyed by USV returning non-zero for characters present (e.g. use {'val'} +a from Unicode cmap). + +The two optional parameters are percentage of characters within the codepage or unicode range that need +to be present to constitute coverage. A threshold of 0 causes corresponding range bits to +be set if any characters are present at all, while a negative value causes the corresponding +range bits to be unchanged. Defaults are 50 and 0, respectively. + +For codepage bits, the threshold is percentage of characters between 0xC0 and 0xFF that need +to be present to constitute coverage). For codepages other than 1252, +characters (e.g., punctuation) that are defined identically to cp1252 are ignored +for the purposes of this percentage calculation. Looks only for SBCS codepages, not DBCS. + +For Unicode range bits that represent multiple ranges, e.g., bit 29 represents: + + Latin Extended Additional 1E00-1EFF + Latin Extended-C 2C60-2C7F + Latin Extended-D A720-A7FF + +the bit will be set if any of these ranges meet the threshold requirement. + +=cut + +sub guessRangeBits +{ + my ($self, $ucmap, $cp_threshold, $u_threshold) = @_; + $cp_threshold = 50 unless defined ($cp_threshold); + $u_threshold = 0 unless defined ($u_threshold); + my $j; # index into codepages or ranges + my $u; # USV + + unless (ref($codepages[0])) + { + # One-time work to convert range data + + # unpack codepages. But first make sure we have Zlib + eval {require Compress::Zlib} || croak("Cannot unpack codepage data Compress::Zlib not available"); + + for ($j = 0; $j <= $#codepages; $j++) + { + next unless $codepages[$j]; + $codepages[$j] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $codepages[$j])))]; + warn ("Got nothing for codepage # $j\n") if $#{$codepages[$j]} < 128; + } + + # convert Unicode array data to hash + my @newRanges; + for ($j = 0; $j <= $#ranges; $j++) + { + next unless $ranges[$j][2] =~ m/^([0-9a-f]{4,6})-([0-9a-f]{4,6})$/oi; + my $s = hex ($1); + my $e = hex ($2); + next unless $e > $s; + push @newRanges, {start => $s, end => $e, bit => $ranges[$j][0], name => $ranges[$j][1]}; + } + @ranges = sort {$a->{'end'} <=> $b->{'end'}} (@newRanges); + } + + if ($cp_threshold >= 0) + { + my $cpr; # codepage range vector + $cp_threshold = 100 if $cp_threshold > 100; + vec($cpr, 63 ,1) = 0; # Get all 64 bits into the vector + for $j (0 .. $#codepages) # For each codepage + { + # Count the number of chars from @range part of codepage that are present in the font + my $present = 0; + my $total = 0; + foreach (0x20 .. 0xFF) + { + $u = $codepages[$j][$_]; + next if $u == 0xFFFD; # Ignore undefined things in codepage + # For codepage 1252, ignore upper ansi altogether + # For other codepages, ignore characters that are same as in 1252. + next if $j > 0 ? $u == $codepages[0][$_] : $u > 0x007F; + $total++; + $present++ if exists $ucmap->{$u} && $ucmap->{$u} > 0; + } + #printf STDERR "DBG: Got $present / $total (%0.3f%%) in codepage bit $j\n", $present * 100 / $total; + #print STDERR "DBG: setting bit $j\n" if $cp_threshold == 0 ? ($present > 0) : (($present * 100 / $total) >= $cp_threshold); + vec($cpr, $j, 1) = 1 if $cp_threshold == 0 ? ($present > 0) : (($present * 100 / $total) >= $cp_threshold); + #print STDERR "\n"; + } + ($self->{'ulCodePageRange1'}, $self->{'ulCodePageRange2'}) = unpack ('V2', $cpr); + } + + if ($u_threshold >= 0) + { + my $ucr; # Unicode range vector + my @count; # Count of chars present in each range + $u_threshold = 100 if $u_threshold > 100; + vec($ucr, 127,1) = 0; # Get all 128 bits into the vector + $j = 0; +CHAR: for $u (sort {$a <=> $b} keys %{$ucmap}) + { + while ($u > $ranges[$j]{'end'}) + { + last CHAR if ++$j > $#ranges; + } + next if $u < $ranges[$j]{'start'}; + $count[$j]++ if $ucmap->{$u}; + } + foreach $j (0 .. $#ranges) + { + vec($ucr, $ranges[$j]{'bit'}, 1) = 1 if $u_threshold == 0 ? + ($count[$j] > 0) : + (($count[$j] * 100 / ($ranges[$j]{'end'} - $ranges[$j]{'start'} + 1)) >= $u_threshold); + } + ($self->{'ulUnicodeRange1'},$self->{'ulUnicodeRange2'},$self->{'ulUnicodeRange3'},$self->{'ulUnicodeRange4'}) = + unpack ('V4', $ucr); + } +} + +BEGIN { + +@codepages = ( +<<'EOT', # Bit 0: cp1252 +M>)P-R>-B%E```-#S+1O+O%NU;-MVRURV[7?H"3*7;2_;M6S;K=7Y>Q`1)8VT +MTDDO@XPRR2R+K++)+H><\"BJJI+(JJJJFNAIJJJ6V.NJJI[X&&FJDL2:::J:Y%EIJI;4VVFJGO0XZ +MZJ2S+KKJ)EYW/?342V]]]-5/?P,,-$B"P888:ICA1AAIE-'&&&N<\2:8:)+) +MIIAJFNEFF&F6V>:8:Y[Y%E@8$E-30J'(HE`LQ(408J*20I5(0J@;Z9::$IF? +MFO)_"X2"H4@H&F)#=,@3E1P3&QD><=\%% +MEUQVQ5777'?#3;?<=D>RN^ZY[X&''GGLB:>>>>Z%EUYY[8VWWGGO@X\^^>R+ +3K[[Y[H>??OGMCQ1_I?X#Q@N!>@`` +EOT + +<<'EOT', # Bit 1: cp1250 +M>)P-Q^=+U'$`Q_'WY^>LW%K=G:/OG6:VM4R[*RU'.7.EY2BW5E:.MOM?Z8%8 +MXB#!,O"1$8A$/2G:$D40$?6D2)`.NP=O>+T!8>&'/P$$$D0P&]C()D(()8QP +M(H@DBFABV,P6MF+#CH-8XH@G@6T8G+A()(GM)+.#%':RB]WL82_[V$\J:1S@ +M(.D<(H-,#N/&PQ&.DD4VQSA.#KGDD<\)3E)`(4444T(IIRBCG`HJJ>(TU=1P +MAK/44D<]#9SC/(TTT4P+K;313@>=7.`BE^CB,E>X2C<]]-+'-:YS@YO`08889H11,[7N-0Y?"2;9&./T*57-QJUZM6M8_;ZW&;N),_'&9:)-S+K7 +MZ5*+\:A!'1K1`'>M)>NM1XK +M0$TL*,M:4;:&5,TB3V3Q5&X%LJ00EF7CF1P\YX7"%*$\%?"25ZK@-6]4JV[> +MJY>/K*B53ZKA,U_DQU=Y%,0WA?)==GXHEI_\4K@BE:]"?O-'E?QE577J84U] ++_,.K-NO=?_3I:`(` +EOT + +<<'EOT', # Bit 2: cp1251 +M>)P%P=52%5``0-$-;!KISG,OW=W=#=(IV-W=_H+^@0^.CB,Z^J`^^&V.K@7$ +M$$L<$D\"B2213`JII'&*=#+()(ML#3;;89H==]MCG@$/.<,0Q9SG'>2YPD4MYQWT>\)!'/.8)3WG&\YHVQQH5B-T)YJ`DA1,)):#,Y])MB +MFJEFN!X*0U$H#64A&G)"[K^_D:A[8F>V02'WS+1SX9PV?E"R=\ +MY9N)?.>'"6[[CI_\XK=KD7PW^>.N\6ZY8Z999IMCKGGF6V"A119;8JEEEEMA +M,&+42JNLML9:ZZRWP4:;;+;%5MMLM\-.N^RVQU[[['?`08<<=L11QQQWPDFG +3G';&6>><=\%%EUQVQ=7_+3E$L0`` +EOT + +<<'EOT', # Bit 3: cp1253 +M>)PUB>^."+'_X$ +M,(U`@@AF.B&$$L8,#`ZYPESSCLBT3[%%HPDR$,<;AMF@WL;8U,A-H@DR("35.XVO\;,OA=+>XD9=R +M%>@>%512134UU%+GKO6X:*#1^--,"ZVT*9]V.NC4?3W00[KUB!X]UA,]U3,5 +MJDC%>JX2O5"I7JI,K_1:;_16[U2N][:E"E6J2M6J4:WJ]$'UN+>O15O>K3-_7KNW[HIW[IM_YH0(,:TK#^ZI]M_0=K +#AH5\ +EOT + +<<'EOT', # Bit 4: cp1254 +M>)PER6-ST'$``.#GOVPLM]9OJY9KR\NV[99M^SOT";)MV[S,NVQ=]JWKNN?E +M@TB,##+*)+,LLLHFNQQRRB6W//+*)[]8!1142&%%%%5,<7%*B%=2D"!1*:65 +MD:2L\ +M"2::9+(IIIIFNAEFFF6V.>::9[X%%H;UZ7]"L6A1B`])(82$F),A.4H+J5'7 +M]#__A2*A:(@+)4)BB`T%8NXE)$:#0]VHV[^+9EELB:6666Z%E599;8VUUEEO +M@XTVV6R+K;;9;H>==MEMC[WVV>^`@PXY[(BCCCGNA)-..>V,L\XY[X*++D7Q +M+KOBJFNNN^&F6VZ[XZY[47(TT'T///3(8T\\])Q%C]=7#@`X;L\3_X"Z)3*4E[G)9Q +MCFLR(MDK71'GN/K.)\[I.,_=\]X\+^"%@T$,1@QA*,/P9C@C&,DH?/!E-&,8 +MBQ_^C&,\$P@@D""""2&4,"9B.'$QB6DR_B?.X![``"[00"S67^9F_H]OI +MZG?Q`RL%7.<&A59&$<64<)-2.KE%.;>IX`Z55%%-#;7444\#C33QFV9::*6- +M=E6J2M6J4:WJ5*\&-:K)XU:S6M2J-K7KKN[IOA[HNWZH3S_UZW_97_1(C]6A +M)WJJ9WJN3KW02W7IE;KU6F_T5N_T7A_T49_T65_T53WZIMY_OWS,U^/^`\"V +"EBL` +EOT + +<<'EOT', # Bit 6: cp1256 +M>)P%P;=/%``8A^'W$'\J'*`"2N>[`XX.1^?.1N_UL``*=A'L8$,4-^.J$R,1 +M&Q$%%+N2N/@'N+@:%UN"BXDA./@\@(,@5A',:L0:UK*.$$)Q$D8X$:QG`QN) +M)(IH-K&9&&*)(YX$$DDB&<.%FQ122<-#.AEDDD4V.>221SY>"BBDB&)***6, +MXS"A7&.,J +MUQCGNLUHW.(LK5P#>^\X.?_%*CFECBMYK5HE:U\4?MZN"O.EE6@!7^6;A% +'Z--_?PY;L``` +EOT + +<<'EOT', # Bit 7: cp1257 +M>)P-B4=/%&``1-^L%`M86(1=FM\N106E]R)2;6`7%"P@%CI([_X5HT8E8N]1 +M.5GBV2@22;P("6G"S?HK"""0(()9S1K6LHX00EG/!C:RB3"< +MA+.9"")QX2:*:&*()8XM&#QXB2>!1)+8RC:VDTP*.]A)*FFDDT$F66230RYY +MY%-`(4444\(N2ME-&>544$D5U>QA+_O8SP%JJ.4@ASC,$8YRC..XR"4NTTH;[73021?=]-#+%?KH9X!!AAAFA%'&&&>" +M2::X:F;\/A-EB3-)QAB/M71+@=_''<='7EIW&;>),;'&:YPFW._S>.U6:/\' +MCN\VKUFN\HSGO.`OKU3/:][PEEF6 +M%*!4H2#>\5XNA2F$3QI5A+S*5;**U*0*5?%9-7SA*W/J4YD:U,Z"QC7)#P4J +M35(P/UF46TZ%LJPQ12I>>4I1L9I5J6I^J9;?K/!'_2I7HSKXIPE-.>;_`YNL +";XP` +EOT + +<<'EOT', # Bit 8: cp1258 +M>)PER>5.EF$`@.'KY;,[,%#1!U3L[NYNL+N[$_LR&;.= +M.J>S&>K<_>^Z$8D3DT=>^>170$&%%%9$4<445T))I906KXRRRBDO004559*H +MLBJ"),FJJJ:Z%#745$MM==153WT---1(8TTTU4QS+;342FMMM-5.>QUTU$EG +M773537<]]-1+;WWTU4]_`PPT2*HT@PTQU###C3#2**.-,=8XXTTPT22333'5 +M--/-,-,LL\TQUSSS+;#0(HLML=0RZ99;8:555EMC;=B9FQ,J1.M"Y9`20DB* +MRPH-_TJK*#4WYW^A?$@(E4)B2`ZE0WQ<=E+R7VL=I?U[4;H,F=;;8*---MMB +MJVVVVV&G77;;8Z]]]CO@H$,..^*H8XX[X:133COCK'/.1W$NN"C+)9==<=6U +M&-?=<#,JX5:LH-ON1!GNNN>^!QYZ)#O:$XMY[(FGGD4QS[WPTBNOO?'6NUCD +@O0\^1B5]BE7UV9)Q=C=52&U``!1?W11(@@00N`8*[4\'=W>KN[OHK_8#^8J=]Z.0!9E_.S,Z< +M!;+()H=<\LBG@$****:$4LJ0JH)T&2!AH)-)&BF19: +M2=-&.QUTTD4W/?321S\###+$,".,,L8X$TQRB^QSP"%'''/"*6=\X2G +M/.,Y+WC)*U[SAK>\XST?^,@G/O.%KWSC.S_X&7[__?.?D,ZL\X18B(=$2(94 +MB(3H1^"BRZY +@[(JKKKGNAIMNN>V.N^ZY[X&''GGLB:>>91[^`:-3=+0` +EOT + +undef, # Bit 17: Reserved +undef, # Bit 18: Reserved +undef, # Bit 19: Reserved +undef, # Bit 20: Reserved +undef, # Bit 21: Reserved +undef, # Bit 22: Reserved +undef, # Bit 23: Reserved +undef, # Bit 24: Reserved +undef, # Bit 25: Reserved +undef, # Bit 26: Reserved +undef, # Bit 27: Reserved +undef, # Bit 28: Reserved +undef, # Bit 29: Reserved +undef, # Bit 30: Reserved +undef, # Bit 31: Reserved +undef, # Bit 32: Reserved +undef, # Bit 33: Reserved +undef, # Bit 34: Reserved +undef, # Bit 35: Reserved +undef, # Bit 36: Reserved +undef, # Bit 37: Reserved +undef, # Bit 38: Reserved +undef, # Bit 39: Reserved +undef, # Bit 40: Reserved +undef, # Bit 41: Reserved +undef, # Bit 42: Reserved +undef, # Bit 43: Reserved +undef, # Bit 44: Reserved +undef, # Bit 45: Reserved +undef, # Bit 46: Reserved +undef, # Bit 47: Reserved + +<<'EOT', # Bit 48: cp869 +M>)Q%R>=7#0`]I+*/_:1Q@(.DX2OY`_W^Z/M!/-ZTT.!W.0!4Y`W1#-_58Q?_VEEIH5@F==*F5.K7IB9[J +MITK5I]\J4[GG5/E;308V56;F[S,I?NJTK5>F#IEF#)EJJ'JC$_ +M\[<("[=@PR+E4:VE6))E6H:E6;QEJ4Z/5*\&-:I)S>I0I[K,83Y69`5ZIN=V +M32_4K9=ZI=?JT1OUZJW>Z;T^Z),^ZK,*:*-#7_15WVC4=Q723I-^Z)?:]<<\ +'>/X"GB5Z;@`` +EOT + +<<'EOT', # Bit 49: cp866 +M>)P%P45#$P``AN$7_!0#<=088]381XYN&-W=#:,;N]N#!P\>C#_`P1_@S;_G +M\P`II'(#<9-;I'&;.]SE'NG<)X,'!,@DBVQRR"5('B'R"5-`A$****:$4J*4 +M$<.44T$E55130YQ:ZJBG@4:::*:%5MIHIX-.NN@F00^]]-'/`(,,,.<"RZY +MXB&/>,P3GO*,Y[S@):]XS1O>\H[W?.`CG_BL@#*5I6SE*%=!Y2FD?(55H(@* +M5:1BE:A4494I)JM<%:I4E:I5H[AJ5:=Z-:A136I6BUK5IG9UJ%-=ZE9"/>I5 +MGW_ZEW\[U3'O^\"K7O&A%[SF'6][RP'GN,5Q1XP33GK7FU[VN4^\YWE?^=1G +M/O*Q-[SN12_YTA<..=W?_-7?_<-?U*\!#6I(PQK1J,8TK@E-:DK3FM&LYI2B +:!4G+2M.:,I3D;S2??]%P:9`_ON;Z/\R_26T` +EOT + +<<'EOT', # Bit 50: cp865 +M>)P%P3=,%&``AN$7?FR(>BH@W>,_/A%%;-BQ*V*G]W9P1[=W:0X.#@P(BR,& +M([$,8B0F1J.)B'%D,0XD*K$W@AHIDNCS`#[X8O!C$I.9PE2FX<]T`IC!3&;A +M8#9SF$L@000SCQ!""2.<""*)8CY.HK&XB$$L():%Q+&(Q<2SA`26LHSEK&`E +MB:QB-6M8RSK6LX$D-K*)S6QA*]O8S@YVDLPN4MC-'O:RC_T213P&%%%%,":6X*:,<#UXJJ*2*:FJHI8Y#'.8(1SG&<4YPDE.^\)5/#/&#;_3RC!=\H(_?_.$G?QGC'R\9 +M8)1.7CF[?-IXRW=^,O8N16F;*5I7*E +M*4=%*E2!'`I4HN(5(92D8I4H7YFJ5H5*E:HZ5:I*'GF5IURE*T.UJE&(`G1) +M%]6B5ETPW;PV[>:)Z31/Z3&]YKJY8FZ8>S;*])D>&V?==%NO];B)P=R'EHSW$<#J$<(/NK3`*,AC6A,$YKBIQG-:4$H +M+6E%:\)H0UO:$4X$D40137MBB"6.#GAT)-Z*Z$1GNM"5;G0G@1[TI!>]Z4-? +M^I%(?P8PD$$,9@A#26(8PQE!,B-)812C&<-84DEC'..9P$0F,9DI3"6=:4QG +M!C.9Q6SF,)=YS&WYOP=T4$=UW/PZH5,Z:QF6:5F6 +M;3F6:WF6;P56J*<6I4I=TW6+Y;1V:*=V:Z_N:9_VZY".Z)A*=%)E.J\+*E>% +M+NFJJE2MF[JEV[JOQYSC(G74ZJXEZYEJ]5*O]5;O]5&?]44_5*,'>J2'>J-B +<2]<[?=`G?=5W/=%S_=0OO=(+?7.EP<`_%"[`E0`` +EOT + +<<'EOT', # Bit 52: cp863 +M>)P%P4E0#7``Q_%O_9&E>!(M4J__ZQJ_=4I;L.3@X=$A= +M'!N9:#+3HF+&,@W&.L/%Q3##N%3,<&#&6`X^'\`'7PS3F,X,_)C)+&8S!W\" +MF,L\',PGD`4$L9!%!!-"*&$L)IPE1!")DR@L+J(1,2QE&;$L)XYX5K"25220 +MR&K6D,1:UK&>#6QD$YM)9@M;V48*V]G!3G:QFU322">#/>QE'_LYP$$RR2*; +M''+)(Y\""BFBF!)**:.<"BIQ4T4U'KS44$L=]3302!.'.,P1CM),"\;,YAQ;O""Y[SD)Z]XPU]^ +M"UR\$M'G"?A_1S3U?4J2[Y*EIN52E? +M>:I6E@I4IE*5R*$@)2E>X4+)*E>%BI6K>M6H4IEJ4JWJY)%712I4MG+4J`:% +MR%^7=4GMZM!%,\1'TV7&38]YS*AY8GK-5=-G1FR$>6I&;:QU,V2]UN-RNJ+X +39=,9M*')P%P3=,U'$KHMBQ8V_8Z;T=W-'MO<+@X,"@L#BB +M1(UE$",QL403C;/8.V+7Q,$XF#CY/$`$D3CZ8?1G``,9Q&"&$,50AC$<'R,8 +MR2BB&O9P$8VL9DM9))%-CGDDD<^ +M!1121#$EE%)&.154$J2*:D*$J:&6.NIIH)$FMK*-[>Q@)[O8S1[VLH_]'.`@ +MASC,$8YRC&9[9#WVV)[84WMFS^V%O;17]MK>V%M[9^^MUSY8GWVT3_;9OMA7 +M^V;?[8?]Y"R=G/-?B&BCCU_\X1^_Z>$2-[D;\'&%.]SF#)>YI5-J4[LBE:R@ +MJI2O/%4K2P4J4ZE*Y%.TTI2J>*%TE:M"Q)P%P4=(%7``Q_&O_FU;O4K+W?/__%6F;=NVRZRTW'L]?<_=WD/MT*&#!]-+ +M1T,H)`\928<,C4SI$`2!1)@-VB($185F]/D`/OAB\&,2DYG"5*8QG1GX,Y-9 +MS,;!'.8RCP`"F<\"@@@FA%#""">"A3B)Q.(B"K&(Q2PAFJ7$$,LREK."E:QB +M-6N(8RWK6,\&-K*)S<2SA:UL8SL[V,DN=K.'!/:2R#[VO)1302555%-#+8T>-RT,%#NKG!;1[HFIK5(E]%R:U292E3 +M94I5M@I5H'PY%*`XQ2I,*%Y%*E:>,E2E6-:3*]I,X_I,GWFIKENVLT]&V'Z39>-MFXZK==Z7$Y7)+]M +2(G=L,/=MB+.!NVJE]3^&>7'F +EOT + +<<'EOT', # Bit 55: cp860 +M>)P%P4E0#7``Q_&O_G8A*MKD]7_]4F2/0F07*NW[]NJ]=DOVO0X=.CB@BV,T +MPU@.931FJ"DR6:8.%0?&#.I@&0[(&,;!YP-,P`O#1"8QF2E,91K3F8$W,YG% +M;'R8PUQ\\<.?>221SX%%%)$,264XJ*,\(E!7O*5/A[SG%Z>,FJE6A4J6J3I6JDEL>Y2E7Z)P-RE-W%W```-#[7[:6E_O%Y67;7BUKM5HMVSWTT&OU!;)MVSR9YV3K9)_: +MZST7$5'22"N=]#+(*)/,LL@JF^QRR"F7W/*(EE<^^1504"&%Q2BBJ&***Z&D +M4DH+RBBKG/(JJ"A6)955454UU=40IZ9::JNCKGKJ:Z"A1AIKHJEFFFNAI59: +M:Z.M=MKKH*-..NNBJVZZB]=#3PEZZ:V/OOKI;X"!!AELB$1##9-DN!&2C31* +MBM'&&&N<\2:8:)+)IIAJFNEFF&F6V>:8Z[0_7GGLJ8>>>>&U-U[ZX'VDFA-. +M.NNY4[[XYI/??D:JNNF^'Y:['1D0&>B1=S[[Y:,KD:*18@[;9(.##EAJO?UA +M85@4%H>H4-I1QQRQ-B2&KB$A]+?,RI`S1(>X$!MB@M#`$\=#GQ`?DD-2&!2Z +MA!0K[+/..>>=^??719=<#@5"UK`@S+?*A3#/-0]<=]57-^Q,/;?<=<\=;_VS +)P%P<52$``40-$+7$`%*>D&>3327=)("4A(HU@H=K<+%V[5'V#AC`O'+_#G +M/`=(()$D))D44CG#6+;7;898]]#CCD!C\9@G/.49SWG!2U[QFC>\Y1WO^F.F2EYRST3:S;#?;:6OM,M=N\YRTQDXO\(=_ +M\3U^Q,](C!JG#/LLC*-8BM,=\.\QQP>:J?/XZ +8;Y.]%CAKO8NV>,4&9ZSC=YQR^A\'$$.V +EOT + +<<'EOT', # Bit 58: cp852 +M>)P%P=M/S@$%)Z.1%^BG',HG8M2#L^C)]63ZJFG(M+!N;,+ +M%]WB'^C"QH:MBRYLKIBMF7'#*H=FS&9FN6%LIJW7"Q`.88030211+&,Y*UB) +MBVABB,5-'*N()X'5K&$M'A))(ID44DEC'>M)9P,;R<#8Q&8RV<)6LLAF&]O9 +MP4YVL9L]Y+"7?>SG`+GD<9!\"BBDB&)***6,<@YQF`HJ.4(5U1SE&,!@(T;B[00R]]]'.12USF +M"E>YQG4&&&2(848898QI_O.=+WQ5KZ+XIE)^R"L?/S7`JDSEJE10K?+S7K7J8Y%YA9CBD3/O?'"FG3GN\9?' +13'+?>:=^U:O!)IA8`NR$89P` +EOT + +<<'EOT', # Bit 59: cp775 +M>)P%PQ@)[LHHYP**@D09#=[V$L5^ZBFAOT@[30(A&CA"FB:,TO87YUJ\/"5F_MUF81J[4N#2I&"?(H785J48\Z-61N +M<]F8C=IUNV$C?."KJE7!;^9XHDH5JT2E\BNH9`4<#S,\6Q33#Q'V@>75\` +EOT + +<<'EOT', # Bit 60: cp737 +M>)P%P65W#@``AN';'FT8AFV&>>V1T]/3-;WN[M*=\\%QQMG!-IVOH]LFIKOK +M[_CJNH`.A"`ZTHG.=*$KW>A.#T+I22]Z$T8?^M*/*8RC>G,8":SF$T"][&,_]6I2LUIT0B=U +M2J=U1F=U3N=U01=U29<5U!5=U35=UPW=U"W=5JO:]%A/]%3/U*[G>J&7>J77 +M>J.W>J?W^J!/^JC/^J*O^J;O;G*S6QSB6!>[Q!E.=ZF3G>E\YSG780YWO.,< +M;9S@`A12(I#T0%5-/FX,$_P-K +#(&Q0 +EOT + +undef, # Bit 61: cp708 (unknown) + +<<'EOT', # Bit 62: cp850 +M>)P%P5-C$&```,#;UC&5[JV6WW++=0P^]5G\@V[9MV[;M.T2(E$QR +M*:242FIII)5.E/0RR"B3S++(*IOL@@XXZZ:R+KKKIKH>>>NFMC[X2]=/?``,-,M@00R499K@11AIE +MM#'&&F>\"2::9+(IIIIFNAF.^>V%AQZ[[XEG7GKEN7?>>NVP(TYXZJC/OOKH +MEQ_^N>JV[Q:Y[EK$7`^\\2+/;>>2>=)P%P3=,%&``AN$7?FR(>BH@(.#Q'Y^*(C;LV!LJ*+VW@SNZO1?`P<&!`6%Q +M1`D8RR!&8H(03$2,HXN3B4#LC5@B`4GT>0`??#'X,8G)3&$JT_!G.@',8":S +M<#";.TED'_LY0!+)'.00*:221CH9 +M9))%-CGDDD<^!1121#$EN"FE#`]>RJF@DBJJJ:&6PQSA*,`Y$WQBF+<,\HX/?.8+'QGA.U_IYQDO>,\`O_G#3_XRQC]> +M\9J;M-'NO.73S!#?^,4X/WC)';KIWS4,;:09,EXVQ;CJMUWI<3E<4HS:1 +1^S:41S;,V<`#M=+Z'T-Z<84` +EOT + +); + +# The following taken directly from OT Spec: + +@ranges = ( + [ 0, "Basic Latin", "0000-007F" ], + [ 1, "Latin-1 Supplement", "0080-00FF" ], + [ 2, "Latin Extended-A", "0100-017F" ], + [ 3, "Latin Extended-B", "0180-024F" ], + [ 4, "IPA Extensions", "0250-02AF" ], + [ 4, "Phonetic Extensions", "1D00-1D7F" ], + [ 4, "Phonetic Extensions Supplement", "1D80-1DBF" ], + [ 5, "Spacing Modifier Letters", "02B0-02FF" ], + [ 5, "Modifier Tone Letters", "A700-A71F" ], + [ 6, "Combining Diacritical Marks", "0300-036F" ], + [ 6, "Combining Diacritical Marks Supplement", "1DC0-1DFF" ], + [ 7, "Greek and Coptic", "0370-03FF" ], + [ 8, "Coptic", "2C80-2CFF" ], + [ 9, "Cyrillic", "0400-04FF" ], + [ 9, "Cyrillic Supplement", "0500-052F" ], + [ 9, "Cyrillic Extended-A", "2DE0-2DFF" ], + [ 9, "Cyrillic Extended-B", "A640-A69F" ], + [ 10, "Armenian", "0530-058F" ], + [ 11, "Hebrew", "0590-05FF" ], + [ 12, "Vai", "A500-A63F" ], + [ 13, "Arabic", "0600-06FF" ], + [ 13, "Arabic Supplement", "0750-077F" ], + [ 14, "NKo", "07C0-07FF" ], + [ 15, "Devanagari", "0900-097F" ], + [ 16, "Bengali", "0980-09FF" ], + [ 17, "Gurmukhi", "0A00-0A7F" ], + [ 18, "Gujarati", "0A80-0AFF" ], + [ 19, "Oriya", "0B00-0B7F" ], + [ 20, "Tamil", "0B80-0BFF" ], + [ 21, "Telugu", "0C00-0C7F" ], + [ 22, "Kannada", "0C80-0CFF" ], + [ 23, "Malayalam", "0D00-0D7F" ], + [ 24, "Thai", "0E00-0E7F" ], + [ 25, "Lao", "0E80-0EFF" ], + [ 26, "Georgian", "10A0-10FF" ], + [ 26, "Georgian Supplement", "2D00-2D2F" ], + [ 27, "Balinese", "1B00-1B7F" ], + [ 28, "Hangul Jamo", "1100-11FF" ], + [ 29, "Latin Extended Additional", "1E00-1EFF" ], + [ 29, "Latin Extended-C", "2C60-2C7F" ], + [ 29, "Latin Extended-D", "A720-A7FF" ], + [ 30, "Greek Extended", "1F00-1FFF" ], + [ 31, "General Punctuation", "2000-206F" ], + [ 31, "Supplemental Punctuation", "2E00-2E7F" ], + [ 32, "Superscripts And Subscripts", "2070-209F" ], + [ 33, "Currency Symbols", "20A0-20CF" ], + [ 34, "Combining Diacritical Marks For Symbols", "20D0-20FF" ], + [ 35, "Letterlike Symbols", "2100-214F" ], + [ 36, "Number Forms", "2150-218F" ], + [ 37, "Arrows", "2190-21FF" ], + [ 37, "Supplemental Arrows-A", "27F0-27FF" ], + [ 37, "Supplemental Arrows-B", "2900-297F" ], + [ 37, "Miscellaneous Symbols and Arrows", "2B00-2BFF" ], + [ 38, "Mathematical Operators", "2200-22FF" ], + [ 38, "Supplemental Mathematical Operators", "2A00-2AFF" ], + [ 38, "Miscellaneous Mathematical Symbols-A", "27C0-27EF" ], + [ 38, "Miscellaneous Mathematical Symbols-B", "2980-29FF" ], + [ 39, "Miscellaneous Technical", "2300-23FF" ], + [ 40, "Control Pictures", "2400-243F" ], + [ 41, "Optical Character Recognition", "2440-245F" ], + [ 42, "Enclosed Alphanumerics", "2460-24FF" ], + [ 43, "Box Drawing", "2500-257F" ], + [ 44, "Block Elements", "2580-259F" ], + [ 45, "Geometric Shapes", "25A0-25FF" ], + [ 46, "Miscellaneous Symbols", "2600-26FF" ], + [ 47, "Dingbats", "2700-27BF" ], + [ 48, "CJK Symbols And Punctuation", "3000-303F" ], + [ 49, "Hiragana", "3040-309F" ], + [ 50, "Katakana", "30A0-30FF" ], + [ 50, "Katakana Phonetic Extensions", "31F0-31FF" ], + [ 51, "Bopomofo", "3100-312F" ], + [ 51, "Bopomofo Extended", "31A0-31BF" ], + [ 52, "Hangul Compatibility Jamo", "3130-318F" ], + [ 53, "Phags-pa", "A840-A87F" ], + [ 54, "Enclosed CJK Letters And Months", "3200-32FF" ], + [ 55, "CJK Compatibility", "3300-33FF" ], + [ 56, "Hangul Syllables", "AC00-D7AF" ], + [ 57, "Non-Plane 0 * ", "D800-DFFF" ], + [ 58, "Phoenician", "10900-1091F" ], + [ 59, "CJK Unified Ideographs", "4E00-9FFF" ], + [ 59, "CJK Radicals Supplement", "2E80-2EFF" ], + [ 59, "Kangxi Radicals", "2F00-2FDF" ], + [ 59, "Ideographic Description Characters", "2FF0-2FFF" ], + [ 59, "CJK Unified Ideographs Extension A", "3400-4DBF" ], + [ 59, "CJK Unified Ideographs Extension B", "20000-2A6DF" ], + [ 59, "Kanbun", "3190-319F" ], + [ 60, "Private Use Area (plane 0)", "E000-F8FF" ], + [ 61, "CJK Strokes", "31C0-31EF" ], + [ 61, "CJK Compatibility Ideographs", "F900-FAFF" ], + [ 61, "CJK Compatibility Ideographs Supplement", "2F800-2FA1F" ], + [ 62, "Alphabetic Presentation Forms", "FB00-FB4F" ], + [ 63, "Arabic Presentation Forms-A", "FB50-FDFF" ], + [ 64, "Combining Half Marks", "FE20-FE2F" ], + [ 65, "Vertical Forms", "FE10-FE1F" ], + [ 65, "CJK Compatibility Forms", "FE30-FE4F" ], + [ 66, "Small Form Variants", "FE50-FE6F" ], + [ 67, "Arabic Presentation Forms-B", "FE70-FEFF" ], + [ 68, "Halfwidth And Fullwidth Forms", "FF00-FFEF" ], + [ 69, "Specials", "FFF0-FFFF" ], + [ 70, "Tibetan", "0F00-0FFF" ], + [ 71, "Syriac", "0700-074F" ], + [ 72, "Thaana", "0780-07BF" ], + [ 73, "Sinhala", "0D80-0DFF" ], + [ 74, "Myanmar", "1000-109F" ], + [ 75, "Ethiopic", "1200-137F" ], + [ 75, "Ethiopic Supplement", "1380-139F" ], + [ 75, "Ethiopic Extended", "2D80-2DDF" ], + [ 76, "Cherokee", "13A0-13FF" ], + [ 77, "Unified Canadian Aboriginal Syllabics", "1400-167F" ], + [ 78, "Ogham", "1680-169F" ], + [ 79, "Runic", "16A0-16FF" ], + [ 80, "Khmer", "1780-17FF" ], + [ 80, "Khmer Symbols", "19E0-19FF" ], + [ 81, "Mongolian", "1800-18AF" ], + [ 82, "Braille Patterns", "2800-28FF" ], + [ 83, "Yi Syllables", "A000-A48F" ], + [ 83, "Yi Radicals", "A490-A4CF" ], + [ 84, "Tagalog", "1700-171F" ], + [ 85, "Hanunoo", "1720-173F" ], + [ 85, "Buhid", "1740-175F" ], + [ 85, "Tagbanwa", "1760-177F" ], + [ 85, "Old Italic", "10300-1032F" ], + [ 86, "Gothic", "10330-1034F" ], + [ 87, "Deseret", "10400-1044F" ], + [ 88, "Byzantine Musical Symbols", "1D000-1D0FF" ], + [ 88, "Musical Symbols", "1D100-1D1FF" ], + [ 88, "Ancient Greek Musical Notation", "1D200-1D24F" ], + [ 89, "Mathematical Alphanumeric Symbols", "1D400-1D7FF" ], + [ 90, "Private Use (plane 15)", "FF000-FFFFD" ], + [ 90, "Private Use (plane 16)", "100000-10FFFD" ], + [ 91, "Variation Selectors", "FE00-FE0F" ], + [ 91, "Variation Selectors Supplement", "E0100-E01EF" ], + [ 92, "Tags", "E0000-E007F" ], + [ 93, "Limbu", "1900-194F" ], + [ 94, "Tai Le", "1950-197F" ], + [ 95, "New Tai Lue", "1980-19DF" ], + [ 96, "Buginese", "1A00-1A1F" ], + [ 97, "Glagolitic", "2C00-2C5F" ], + [ 98, "Tifinagh", "2D30-2D7F" ], + [ 99, "Yijing Hexagram Symbols", "4DC0-4DFF" ], + [ 100, "Syloti Nagri", "A800-A82F" ], + [ 101, "Linear B Syllabary", "10000-1007F" ], + [ 101, "Linear B Ideograms", "10080-100FF" ], + [ 101, "Aegean Numbers", "10100-1013F" ], + [ 102, "Ancient Greek Numbers", "10140-1018F" ], + [ 103, "Ugaritic", "10380-1039F" ], + [ 104, "Old Persian", "103A0-103DF" ], + [ 105, "Shavian", "10450-1047F" ], + [ 106, "Osmanya", "10480-104AF" ], + [ 107, "Cypriot Syllabary", "10800-1083F" ], + [ 108, "Kharoshthi", "10A00-10A5F" ], + [ 109, "Tai Xuan Jing Symbols", "1D300-1D35F" ], + [ 110, "Cuneiform", "12000-123FF" ], + [ 110, "Cuneiform Numbers and Punctuation", "12400-1247F" ], + [ 111, "Counting Rod Numerals", "1D360-1D37F" ], + [ 112, "Sundanese", "1B80-1BBF" ], + [ 113, "Lepcha", "1C00-1C4F" ], + [ 114, "Ol Chiki", "1C50-1C7F" ], + [ 115, "Saurashtra", "A880-A8DF" ], + [ 116, "Kayah Li", "A900-A92F" ], + [ 117, "Rejang", "A930-A95F" ], + [ 118, "Cham", "AA00-AA5F" ], + [ 119, "Ancient Symbols", "10190-101CF" ], + [ 120, "Phaistos Disc", "101D0-101FF" ], + [ 121, "Carian", "102A0-102DF" ], + [ 121, "Lycian", "10280-1029F" ], + [ 121, "Lydian", "10920-1093F" ], + [ 122, "Domino Tiles", "1F030-1F09F" ], + [ 122, "Mahjong Tiles", "1F000-1F02F" ], + [ 123-127, "Reserved", "" ], +); + +} + + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OTTags.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OTTags.pm new file mode 100644 index 0000000000..41f7703acd --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OTTags.pm @@ -0,0 +1,1698 @@ +use utf8; # NB: This file includes non-ASCII string constants in UTF-8 encoding + +package Font::TTF::OTTags; + +=head1 NAME + +Font::TTF::OTTags - Utilities for TrueType/OpenType tags + +=head1 SYNOPSIS + + use Font::TTF::OTTags qw( %tttags %ttnames %iso639 readtagsfile ); + + # Look at built-in stuff: + $script_tag = $tttags{'SCRIPT'}{'Cypriot Syllabary'}; # returns 'cprt' + $lang_name = $ttnames{'LANGUAGE'}{'ALT '}; # returns 'Altai' + + # Map iso639-2 tag to/from OT lang tag + @isotags = $iso639{'ALT '}; # returns [ 'atv', 'alt' ] + $lang_tag = $iso639{'atv'}; # returns 'ALT ' + + # Read latest tags file to add to built-in definitions + readtagsfile ("C:\\Program Files\\Microsoft VOLT\\TAGS.txt"); + +First-level keys to %tttags and %ttnames are: + +=over + +=item SCRIPT + +retrieve script tag or name + +=item LANGUAGE + +retrieve language tag or name + +=item FEATURE + +retrieve feature tag or name + +=back + +Built-in data has been derived from the 2014-07-11 draft of the +3rd edition of ISO/IEC 14496-22 +(Information technology - Coding of audio-visual objects - Part 22: Open Font Format) +which, when finalized and approved, will replace the second edition (ISO/IEC 14496-22:2009). + +=head1 METHODS + +=cut + +use strict; +use vars qw( %tttags %ttnames %iso639 @EXPORT_OK @ISA ); +require Exporter; +@ISA = qw( Exporter ); +@EXPORT_OK = qw( %tttags %ttnames %iso639 readtagsfile); + + +# All data below derived Microsoft OpenType specification 1.6 + +%tttags = ( + +'SCRIPT' => { + "Adlam" => 'adlm', + "Ahom" => 'ahom', + "Anatolian Hieroglyphs" => 'hluw', + "Arabic" => 'arab', + "Armenian" => 'armn', + "Avestan" => 'avst', + "Balinese" => 'bali', + "Bamum" => 'bamu', + "Bassa Vah" => 'bass', + "Batak" => 'batk', + "Bengali" => 'beng', + "Bengali v.2" => 'bng2', + "Bhaiksuki" => 'bhks', + "Bopomofo" => 'bopo', + "Brahmi" => 'brah', + "Braille" => 'brai', + "Buginese" => 'bugi', + "Buhid" => 'buhd', + "Byzantine Music" => 'byzm', + "Canadian Syllabics" => 'cans', + "Carian" => 'cari', + "Caucasian Albanian" => 'aghb', + "Chakma" => 'cakm', + "Cham" => 'cham', + "Cherokee" => 'cher', + "CJK Ideographic" => 'hani', + "Coptic" => 'copt', + "Cypriot Syllabary" => 'cprt', + "Cyrillic" => 'cyrl', + "Default" => 'DFLT', + "Deseret" => 'dsrt', + "Devanagari" => 'deva', + "Devanagari v.2" => 'dev2', + "Duployan" => 'dupl', + "Egyptian hieroglyphs" => 'egyp', + "Elbasan" => 'elba', + "Ethiopic" => 'ethi', + "Georgian" => 'geor', + "Glagolitic" => 'glag', + "Gothic" => 'goth', + "Grantha" => 'gran', + "Greek" => 'grek', + "Gujarati" => 'gujr', + "Gujarati v.2" => 'gjr2', + "Gurmukhi" => 'guru', + "Gurmukhi v.2" => 'gur2', + "Hangul" => 'hang', + "Hangul Jamo" => 'jamo', + "Hanunoo" => 'hano', + "Hatran" => 'hatr', + "Hebrew" => 'hebr', + "Hiragana" => 'kana', + "Imperial Aramaic" => 'armi', + "Inscriptional Pahlavi" => 'phli', + "Inscriptional Parthian" => 'prti', + "Javanese" => 'java', + "Kaithi" => 'kthi', + "Kannada" => 'knda', + "Kannada v.2" => 'knd2', + "Katakana" => 'kana', + "Kayah Li" => 'kali', + "Kharosthi" => 'khar', + "Khmer" => 'khmr', + "Khojki" => 'khoj', + "Khudawadi" => 'sind', + "Lao" => 'lao ', + "Latin" => 'latn', + "Lepcha" => 'lepc', + "Limbu" => 'limb', + "Linear A" => 'lina', + "Linear B" => 'linb', + "Lisu (Fraser)" => 'lisu', + "Lycian" => 'lyci', + "Lydian" => 'lydi', + "Mahajani" => 'mahj', + "Marchen" => 'marc', + "Malayalam" => 'mlym', + "Malayalam v.2" => 'mlm2', + "Mandaic, Mandaean" => 'mand', + "Manichaean" => 'mani', + "Mathematical Alphanumeric Symbols" => 'math', + "Meitei Mayek (Meithei, Meetei)" => 'mtei', + "Mende Kikakui" => 'mend', + "Meroitic Cursive" => 'merc', + "Meroitic Hieroglyphs" => 'mero', + "Miao" => 'plrd', + "Modi" => 'modi', + "Mongolian" => 'mong', + "Mro" => 'mroo', + "Multani" => 'mult', + "Musical Symbols" => 'musc', + "Myanmar" => 'mymr', + "Myanmar v.2" => 'mym2', + "Nabataean" => 'nbat', + "Newa" => 'newa', + "New Tai Lue" => 'talu', + "N'Ko" => 'nko ', + "Odia (formerly Oriya)" => 'orya', + "Odia (formerly Oriya) v.2" => 'ory2', + "Ogham" => 'ogam', + "Ol Chiki" => 'olck', + "Old Italic" => 'ital', + "Old Hungarian" => 'hung', + "Old North Arabian" => 'narb', + "Old Permic" => 'perm', + "Old Persian Cuneiform" => 'xpeo', + "Old South Arabian" => 'sarb', + "Old Turkic, Orkhon Runic" => 'orkh', + "Osage" => 'osge', + "Osmanya" => 'osma', + "Pahawh Hmong" => 'hmng', + "Palmyrene" => 'palm', + "Pau Cin Hau" => 'pauc', + "Phags-pa" => 'phag', + "Phoenician" => 'phnx', + "Psalter Pahlavi" => 'phlp', + "Rejang" => 'rjng', + "Runic" => 'runr', + "Samaritan" => 'samr', + "Saurashtra" => 'saur', + "Sharada" => 'shrd', + "Shavian" => 'shaw', + "Siddham" => 'sidd', + "Sign Writing" => 'sgnw', + "Sinhala" => 'sinh', + "Sora Sompeng" => 'sora', + "Sumero-Akkadian Cuneiform" => 'xsux', + "Sundanese" => 'sund', + "Syloti Nagri" => 'sylo', + "Syriac" => 'syrc', + "Tagalog" => 'tglg', + "Tagbanwa" => 'tagb', + "Tai Le" => 'tale', + "Tai Tham (Lanna)" => 'lana', + "Tai Viet" => 'tavt', + "Takri" => 'takr', + "Tamil" => 'taml', + "Tamil v.2" => 'tml2', + "Tangut" => 'tang', + "Telugu" => 'telu', + "Telugu v.2" => 'tel2', + "Thaana" => 'thaa', + "Thai" => 'thai', + "Tibetan" => 'tibt', + "Tifinagh" => 'tfng', + "Tirhuta" => 'tirh', + "Ugaritic Cuneiform" => 'ugar', + "Vai" => 'vai ', + "Warang Citi" => 'wara', + "Yi" => 'yi ', + }, + +'LANGUAGE' => { + "Aari" => 'ARI ', + "Abaza" => 'ABA ', + "Abkhazian" => 'ABK ', + "Achi" => 'ACR ', + "Acholi" => 'ACH ', + "Adyghe" => 'ADY ', + "Afar" => 'AFR ', + "Afrikaans" => 'AFK ', + "Agaw" => 'AGW ', + "Aiton" => 'AIO ', + "Akan" => 'AKA ', + "Albanian" => 'SQI ', + "Alsatian" => 'ALS ', + "Altai" => 'ALT ', + "Amharic" => 'AMH ', + "Anglo-Saxon" => 'ANG ', + "Arabic" => 'ARA ', + "Aragonese" => 'ARG ', + "Arakwal" => 'RKW ', + "Armenian East" => 'HYE0', + "Armenian" => 'HYE ', + "Aromanian" => 'RUP ', + "Arpitan" => 'FRP ', + "Assamese" => 'ASM ', + "Asturian" => 'AST ', + "Athapaskan" => 'ATH ', + "Avar" => 'AVR ', + "Awadhi" => 'AWA ', + "Aymara" => 'AYM ', + "Azerbaijani" => 'AZE ', + "Badaga" => 'BAD ', + "Baghelkhandi" => 'BAG ', + "Bagri" => 'BGQ ', + "Balante" => 'BLN ', + "Balinese" => 'BAN ', + "Balkar" => 'BAL ', + "Balti" => 'BLT ', + "Baluchi" => 'BLI ', + "Bambara (Bamanankan)" => 'BMB ', + "Bamileke" => 'BML ', + "Banda" => 'BAD0', + "Bandjalang" => 'BDY ', + "BaoulĂ©" => 'BAU ', + "Bashkir" => 'BSH ', + "Basque" => 'EUQ ', + "Batak Simalungun" => 'BTS ', + "Batak Toba" => 'BBC ', + "Bavarian" => 'BAR ', + "Belarusian" => 'BEL ', + "Bemba" => 'BEM ', + "Bench" => 'BCH ', + "Bengali" => 'BEN ', + "Berber" => 'BBR ', + "Beti" => 'BTI ', + "Bhili" => 'BHI ', + "Bhojpuri" => 'BHO ', + "Bible Cree" => 'BCR ', + "Bikol" => 'BIK ', + "Bilen" => 'BIL ', + "Bishnupriya Manipuri" => 'BPY ', + "Bislama" => 'BIS ', + "Blackfoot" => 'BKF ', + "Bodo" => 'BRX ', + "Bosnian" => 'BOS ', + "Bouyei" => 'PCC ', + "Brahui" => 'BRH ', + "Braj Bhasha" => 'BRI ', + "Breton" => 'BRE ', + "Bugis" => 'BUG ', + "Bulgarian" => 'BGR ', + "Burmese" => 'BRM ', + "Burushaski" => 'BSK ', + "Cajun French" => 'FRC ', + "Carrier" => 'CRR ', + "Catalan" => 'CAT ', + "Cebuano" => 'CEB ', + "Central Yupik" => 'ESU ', + "Chaha Gurage" => 'CHG ', + "Chamorro" => 'CHA ', + "Chattisgarhi" => 'CHH ', + "Chechen" => 'CHE ', + "Cherokee" => 'CHR ', + "Cheyenne" => 'CHY ', + "Chichewa (Chewa, Nyanja)" => 'CHI ', + "Chiga" => 'CGG ', + "Chin" => 'QIN ', + "Chinese Phonetic" => 'ZHP ', + "Chinese Simplified" => 'ZHS ', + "Chinese Traditional" => 'ZHT ', + "Chinese, Hong Kong SAR" => 'ZHH ', + "Chipewyan" => 'CHP ', + "Chittagonian" => 'CTG ', + "Choctaw" => 'CHO ', + "Chukchi" => 'CHK ', + "Church Slavonic" => 'CSL ', + "Chuukese" => 'CHK0', + "Chuvash" => 'CHU ', + "Comorian" => 'CMR ', + "Coptic" => 'COP ', + "Cornish" => 'COR ', + "Corsican" => 'COS ', + "Cree" => 'CRE ', + "Creoles" => 'CPP ', + "Crimean Tatar" => 'CRT ', + "Croatian" => 'HRV ', + "Czech" => 'CSY ', + "Dan" => 'DNJ ', + "Dangme" => 'DNG ', + "Danish" => 'DAN ', + "Dargwa" => 'DAR ', + "Dari" => 'DRI ', + "Dayi" => 'DAX ', + "Dehong Dai" => 'TDD ', + "Dhangu" => 'DHG ', + "Dhuwal" => 'DUJ ', + "Dimli" => 'DIQ ', + "Dinka" => 'DNK ', + "Divehi (Dhivehi, Maldivian) (deprecated)" => 'DHV ', + "Divehi (Dhivehi, Maldivian)" => 'DIV ', + "Djambarrpuyngu" => 'DJR0', + "Dogri" => 'DGO ', + "Dogri" => 'DGR ', + "Dungan" => 'DUN ', + "Dutch (Flemish)" => 'FLE ', + "Dutch" => 'NLD ', + "Dzongkha" => 'DZN ', + "Eastern Cree" => 'ECR ', + "Eastern Maninkakan" => 'EMK ', + "Eastern Pwo Karen" => 'KJP ', + "Ebira" => 'EBI ', + "Edo" => 'EDO ', + "Efik" => 'EFI ', + "English" => 'ENG ', + "Erzya" => 'ERZ ', + "Esperanto" => 'NTO ', + "Estonian" => 'ETI ', + "Even" => 'EVN ', + "Evenki" => 'EVK ', + "Ewe" => 'EWE ', + "Fang" => 'FAN0', + "Fanti" => 'FAT ', + "Faroese" => 'FOS ', + "Fe'fe'" => 'FMP ', + "Fijian" => 'FJI ', + "Filipino" => 'PIL ', + "Finnish" => 'FIN ', + "Fon" => 'FON ', + "Forest Nenets" => 'FNE ', + "French Antillean" => 'FAN ', + "French" => 'FRA ', + "Frisian" => 'FRI ', + "Friulian" => 'FRL ', + "Fulah" => 'FUL ', + "Futa" => 'FTA ', + "Ga" => 'GAD ', + "Gagauz" => 'GAG ', + "Galician" => 'GAL ', + "Ganda" => 'LUG ', + "Garhwali" => 'GAW ', + "Garo" => 'GRO ', + "Garshuni" => 'GAR ', + "Ge'ez" => 'GEZ ', + "Georgian" => 'KAT ', + "German" => 'DEU ', + "Gilaki" => 'GLK ', + "Gilyak" => 'GIL ', + "Githabul" => 'GIH ', + "Gogo" => 'GOG ', + "Gondi" => 'GON ', + "Greek" => 'ELL ', + "Greenlandic" => 'GRN ', + "Guarani" => 'GUA ', + "Gujarati" => 'GUJ ', + "Gumatj" => 'GNN ', + "Gumuz" => 'GMZ ', + "Gupapuyngu" => 'GUF ', + "Gusii" => 'GUZ ', + "Haitian (Haitian Creole)" => 'HAI ', + "Halam" => 'HAL ', + "Hammer-Banna" => 'HBN ', + "Harari" => 'HRI ', + "Harauti" => 'HAR ', + "Haryanvi" => 'BGC ', + "Hausa" => 'HAU ', + "Hawaiian" => 'HAW ', + "Haya" => 'HAY ', + "Hazaragi" => 'HAZ ', + "Hebrew" => 'IWR ', + "Herero" => 'HER ', + "High Mari" => 'HMA ', + "Hiligaynon" => 'HIL ', + "Hindi" => 'HIN ', + "Hindko" => 'HND ', + "Hiri Motu" => 'HMO ', + "Hmong Daw" => 'MWW ', + "Hmong" => 'HMN ', + "Ho" => 'HO ', + "Hungarian" => 'HUN ', + "Iban" => 'IBA ', + "Ibibio" => 'IBB ', + "Icelandic" => 'ISL ', + "Ido" => 'IDO ', + "Igbo" => 'IBO ', + "Ijo languages" => 'IJO ', + "Ilokano" => 'ILO ', + "Inari Sami" => 'ISM ', + "Indonesian" => 'IND ', + "Ingush" => 'ING ', + "Interlingua" => 'INA ', + "Interlingue" => 'ILE ', + "Inuktitut" => 'INU ', + "Inupiat" => 'IPK ', + "Irish Traditional" => 'IRT ', + "Irish" => 'IRI ', + "Italian" => 'ITA ', + "Jamaican Creole" => 'JAM ', + "Japanese" => 'JAN ', + "Javanese" => 'JAV ', + "Jula" => 'JUL ', + "Kabardian" => 'KAB ', + "Kabuverdianu (Crioulo)" => 'KEA ', + "Kabyle" => 'KAB0', + "Kachchi" => 'KAC ', + "Kalenjin" => 'KAL ', + "Kalmyk" => 'KLM ', + "Kamba" => 'KMB ', + "Kanauji" => 'BJJ ', + "Kannada" => 'KAN ', + "Kanuri" => 'KNR ', + "Kaqchikel" => 'CAK ', + "Karachay" => 'KAR ', + "Karaim" => 'KRM ', + "Karakalpak" => 'KRK ', + "Karelian" => 'KRL ', + "Karen" => 'KRN ', + "Kashmiri" => 'KSH ', + "Kashubian" => 'CSB ', + "Kazakh" => 'KAZ ', + "Kebena" => 'KEB ', + "Kekchi" => 'KEK ', + "Khakass" => 'KHA ', + "Khamti Shan" => 'KHT ', + "Khanty-Kazim" => 'KHK ', + "Khanty-Shurishkar" => 'KHS ', + "Khanty-Vakhi" => 'KHV ', + "Khasi" => 'KSI ', + "Khmer" => 'KHM ', + "Khorasani Turkic" => 'KMZ ', + "Khowar" => 'KHW ', + "Khutsuri Georgian" => 'KGE ', + "Kikongo" => 'KON ', + "Kikuyu (Gikuyu)" => 'KIK ', + "Kildin Sami" => 'KSM ', + "Kinyarwanda" => 'RUA ', + "Kirghiz (Kyrgyz)" => 'KIR ', + "Kiribati (Gilbertese)" => 'GIL0', + "Kirmanjki" => 'KIU ', + "Kisii" => 'KIS ', + "Kituba" => 'MKW ', + "Kodagu" => 'KOD ', + "Kokni" => 'KKN ', + "Komi" => 'KOM ', + "Komi-Permyak" => 'KOP ', + "Komi-Zyrian" => 'KOZ ', + "Komo" => 'KMO ', + "Komso" => 'KMS ', + "Kongo" => 'KON0', + "Konkani" => 'KOK ', + "Koorete" => 'KRT ', + "Korean Old Hangul" => 'KOH ', + "Korean" => 'KOR ', + "Koryak" => 'KYK ', + "Kosraean" => 'KOS ', + "Kpelle (Guinea)" => 'GKP ', + "Kpelle (Liberia)" => 'XPE ', + "Kpelle" => 'KPL ', + "Krio" => 'KRI ', + "Krymchak" => 'JCT ', + "Kuanyama" => 'KUA ', + "Kui" => 'KUI ', + "Kulvi" => 'KUL ', + "Kumaoni" => 'KMN ', + "Kumyk" => 'KUM ', + "Kurdish" => 'KUR ', + "Kurukh" => 'KUU ', + "Kuy" => 'KUY ', + "K'iche'" => 'QUC ', + "L-Cree" => 'LCR ', + "Ladakhi" => 'LDK ', + "Ladin" => 'LAD ', + "Ladino" => 'JUD ', + "Lahuli" => 'LAH ', + "Lak" => 'LAK ', + "Laki" => 'LKI ', + "Lambani" => 'LAM ', + "Lampung" => 'LJP ', + "Lao" => 'LAO ', + "Latin" => 'LAT ', + "Latvian" => 'LVI ', + "Laz" => 'LAZ ', + "Lezgi" => 'LEZ ', + "Ligurian" => 'LIJ ', + "Limbu" => 'LMB ', + "Limburgish" => 'LIM ', + "Lingala" => 'LIN ', + "Lisu" => 'LIS ', + "Lithuanian" => 'LTH ', + "Lojban" => 'JBO ', + "Loma" => 'LOM ', + "Lombard" => 'LMO ', + "Lomwe" => 'LMW ', + "Low Mari" => 'LMA ', + "Low Saxon" => 'NDS ', + "Lower Sorbian" => 'LSB ', + "Luba-Katanga" => 'LUB ', + "Luba-Lulua" => 'LUA ', + "Lule Sami" => 'LSM ', + "Luo" => 'LUO ', + "Luri" => 'LRC ', + "Luxembourgish" => 'LTZ ', + "Luyia" => 'LUH ', + "LĂĽ" => 'XBD ', + "Macedonian" => 'MKD ', + "Madura" => 'MAD ', + "Magahi" => 'MAG ', + "Maithili" => 'MTH ', + "Majang" => 'MAJ ', + "Makasar" => 'MKR ', + "Makhuwa" => 'MAK ', + "Makonde" => 'KDE ', + "Malagasy" => 'MLG ', + "Malay" => 'MLY ', + "Malayalam Reformed" => 'MLR ', + "Malayalam Traditional" => 'MAL ', + "Male" => 'MLE ', + "Malinke" => 'MLN ', + "Maltese" => 'MTS ', + "Mam" => 'MAM ', + "Manchu" => 'MCH ', + "Mandar" => 'MDR ', + "Mandinka" => 'MND ', + "Maninka" => 'MNK ', + "Manipuri" => 'MNI ', + "Mansi" => 'MAN ', + "Manx" => 'MNX ', + "Maori" => 'MRI ', + "Mapudungun" => 'MAP ', + "Marathi" => 'MAR ', + "Marshallese" => 'MAH ', + "Marwari" => 'MAW ', + "Mayan" => 'MYN ', + "Mazanderani" => 'MZN ', + "Mbembe Tigon" => 'NZA ', + "Mbo" => 'MBO ', + "Mbundu" => 'MBN ', + "Me'en" => 'MEN ', + "Medumba" => 'BYV ', + "Mende" => 'MDE ', + "Meru" => 'MER ', + "Mewati" => 'WTM ', + "Minangkabau" => 'MIN ', + "Minjangbal" => 'XJB ', + "Mirandese" => 'MWL ', + "Mizo" => 'MIZ ', + "Mohawk" => 'MOH ', + "Moksha" => 'MOK ', + "Moldavian" => 'MOL ', + "Mon" => 'MON ', + "Mongolian" => 'MNG ', + "Moose Cree" => 'MCR ', + "Morisyen" => 'MFE ', + "Moroccan" => 'MOR ', + "Mossi" => 'MOS ', + "Mundari" => 'MUN ', + "Muscogee" => 'MUS ', + "N'Ko" => 'NKO ', + "N-Cree" => 'NCR ', + "Naga-Assamese" => 'NAG ', + "Nagari" => 'NGR ', + "Nahuatl" => 'NAH ', + "Nanai" => 'NAN ', + "Naskapi" => 'NAS ', + "Nauruan" => 'NAU ', + "Navajo" => 'NAV ', + "Ndau" => 'NDC ', + "Ndebele" => 'NDB ', + "Ndonga" => 'NDG ', + "Neapolitan" => 'NAP ', + "Nepali" => 'NEP ', + "Newari" => 'NEW ', + "Ngbaka" => 'NGA ', + "Nigerian Fulfulde" => 'FUV ', + "Nimadi" => 'NOE ', + "Nisi" => 'NIS ', + "Niuean" => 'NIU ', + "Nogai" => 'NOG ', + "Norfolk" => 'PIH ', + "North Slavey" => 'SCS ', + "Northern Sami" => 'NSM ', + "Northern Thai" => 'NTA ', + "Norway House Cree" => 'NHC ', + "Norwegian Nynorsk (Nynorsk, Norwegian)" => 'NYN ', + "Norwegian" => 'NOR ', + "Novial" => 'NOV ', + "Nyamwezi" => 'NYM ', + "Nyankole" => 'NKL ', + "Occitan" => 'OCI ', + "Odia (formerly Oriya)" => 'ORI ', + "Oji-Cree" => 'OCR ', + "Ojibway" => 'OJB ', + "Old Irish" => 'SGA ', + "Oromo" => 'ORO ', + "Ossetian" => 'OSS ', + "Pa'o Karen" => 'BLK ', + "Palauan" => 'PAU ', + "Palaung" => 'PLG ', + "Palestinian Aramaic" => 'PAA ', + "Pali" => 'PAL ', + "Palpa" => 'PAP ', + "Pampangan" => 'PAM ', + "Pangasinan" => 'PAG ', + "Papiamentu" => 'PAP0', + "Pashto" => 'PAS ', + "Pennsylvania German" => 'PDC ', + "Persian" => 'FAR ', + "Phake" => 'PHK ', + "Phonetic transcription - Americanist conventions" => 'APPH', + "Phonetic transcription - IPA conventions" => 'IPPH', + "Picard" => 'PCD ', + "Piemontese" => 'PMS ', + "Pocomchi" => 'POH ', + "Pohnpeian" => 'PON ', + "Polish" => 'PLK ', + "Polytonic Greek" => 'PGR ', + "Portuguese" => 'PTG ', + "Provencal" => 'PRO ', + "Punjabi" => 'PAN ', + "Quechua (Bolivia)" => 'QUH ', + "Quechua (Ecuador)" => 'QVI ', + "Quechua (Peru)" => 'QWH ', + "Quechua" => 'QUZ ', + "R-Cree" => 'RCR ', + "Rajasthani" => 'RAJ ', + "Rakhine" => 'ARK ', + "Rarotongan" => 'RAR ', + "Rejang" => 'REJ ', + "Riang" => 'RIA ', + "Ripuarian" => 'KSH0', + "Ritarungo" => 'RIT ', + "Romanian" => 'ROM ', + "Romansh" => 'RMS ', + "Romany" => 'ROY ', + "Rotuman" => 'RTM ', + "Rundi" => 'RUN ', + "Russian Buriat" => 'RBU ', + "Russian" => 'RUS ', + "Rusyn" => 'RSY ', + "Sadri" => 'SAD ', + "Sakha" => 'YAK ', + "Samoan" => 'SMO ', + "Samogitian" => 'SGS ', + "San Blas Kuna" => 'CUK ', + "Sango" => 'SGO ', + "Sanskrit" => 'SAN ', + "Santali" => 'SAT ', + "Sardinian" => 'SRD ', + "Sasak" => 'SAS ', + "Saterland Frisian" => 'STQ ', + "Sayisi" => 'SAY ', + "Scots" => 'SCO ', + "Scottish Gaelic (Gaelic)" => 'GAE ', + "Sekota" => 'SEK ', + "Selkup" => 'SEL ', + "Sena" => 'SNA ', + "Seraiki" => 'SRK ', + "Serbian" => 'SRB ', + "Serer" => 'SRR ', + "Shan" => 'SHN ', + "Shona" => 'SNA0', + "Sibe" => 'SIB ', + "Sicilian" => 'SCN ', + "Sidamo" => 'SID ', + "Silesian" => 'SZL ', + "Silte Gurage" => 'SIG ', + "Sindhi" => 'SND ', + "Sinhala (Sinhalese)" => 'SNH ', + "Skolt Sami" => 'SKS ', + "Slavey" => 'SLA ', + "Slovak" => 'SKY ', + "Slovenian" => 'SLV ', + "Sodo Gurage" => 'SOG ', + "Soga" => 'XOG ', + "Somali" => 'SML ', + "Songe" => 'SOP ', + "Soninke" => 'SNK ', + "Sotho, Northern" => 'NSO ', + "Sotho, Southern" => 'SOT ', + "South Slavey" => 'SSL ', + "Southern Kiwai" => 'KJD ', + "Southern Sami" => 'SSM ', + "Spanish" => 'ESP ', + "Standard Morrocan Tamazigh" => 'ZGH ', + "Sukuma" => 'SUK ', + "Sundanese" => 'SUN ', + "Suri" => 'SUR ', + "Sutu" => 'SXT ', + "Svan" => 'SVA ', + "Swadaya Aramaic" => 'SWA ', + "Swahili" => 'SWK ', + "Swati" => 'SWZ ', + "Swedish" => 'SVE ', + "Sylheti" => 'SYL ', + "Syriac" => 'SYR ', + "S'gaw Karen" => 'KSW ', + "TH-Cree" => 'TCR ', + "Tabasaran" => 'TAB ', + "Tachelhit" => 'SHI ', + "Tagalog" => 'TGL ', + "Tahitian" => 'THT ', + "Tajik" => 'TAJ ', + "Tamashek" => 'TMH ', + "Tamazight" => 'TZM ', + "Tamil" => 'TAM ', + "Tarifit" => 'RIF ', + "Tatar" => 'TAT ', + "Telugu" => 'TEL ', + "Temne" => 'TMN ', + "Tetum" => 'TET ', + "Thai" => 'THA ', + "Tibetan" => 'TIB ', + "Tigre" => 'TGR ', + "Tigrinya" => 'TGY ', + "Tiv" => 'TIV ', + "Todo" => 'TOD ', + "Tok Pisin" => 'TPI ', + "Toma" => 'TOD0', + "Tonga" => 'TNG ', + "Tongan" => 'TGN ', + "Torki" => 'AZB ', + "Tsonga" => 'TSG ', + "Tswana" => 'TNA ', + "Tulu" => 'TUL ', + "Tumbuka" => 'TUM ', + "Tundra Nenets" => 'TNE ', + "Turkish" => 'TRK ', + "Turkmen" => 'TKM ', + "Turoyo Aramaic" => 'TUA ', + "Tuvalu" => 'TVL ', + "Tuvin" => 'TUV ', + "Twi" => 'TWI ', + "Tzotzil" => 'TZO ', + "TĂ y" => 'TYZ ', + "Udmurt" => 'UDM ', + "Ukrainian" => 'UKR ', + "Umbundu" => 'UMB ', + "Upper Saxon" => 'SXU ', + "Upper Sorbian" => 'USB ', + "Urdu" => 'URD ', + "Uyghur" => 'UYG ', + "Uzbek" => 'UZB ', + "Venda" => 'VEN ', + "Venetian" => 'VEC ', + "Vietnamese" => 'VIT ', + "Vlax Romani" => 'RMY ', + "VolapĂĽk" => 'VOL ', + "Võro" => 'VRO ', + "Wa" => 'WA ', + "Wagdi" => 'WAG ', + "Walloon" => 'WLN ', + "Waray-Waray" => 'WAR ', + "Wayuu" => 'GUC ', + "Welsh" => 'WEL ', + "West-Cree" => 'WCR ', + "Western Kayah" => 'KYU ', + "Western Panjabi" => 'PNB ', + "Western Pwo Karen" => 'PWO ', + "Wolof" => 'WLF ', + "Woods Cree" => 'DCR ', + "Xhosa" => 'XHS ', + "Y-Cree" => 'YCR ', + "Yao" => 'YAO ', + "Yapese" => 'YAP ', + "Yi Classic" => 'YIC ', + "Yi Modern" => 'YIM ', + "Yiddish" => 'JII ', + "Yoruba" => 'YBA ', + "Zamboanga Chavacano" => 'CBK ', + "Zande" => 'ZND ', + "Zarma" => 'DJR ', + "Zazaki" => 'ZZA ', + "Zealandic" => 'ZEA ', + "Zhuang" => 'ZHA ', + "Zulu" => 'ZUL ', + }, + +'FEATURE' => { + "Above-base Forms" => 'abvf', + "Above-base Mark Positioning" => 'abvm', + "Above-base Substitutions" => 'abvs', + "Access All Alternates" => 'aalt', + "Akhands" => 'akhn', + "Alternate Annotation Forms" => 'nalt', + "Alternate Half Widths" => 'halt', + "Alternate Vertical Half Metrics" => 'vhal', + "Alternate Vertical Metrics" => 'valt', + "Alternative Fractions" => 'afrc', + "Below-base Forms" => 'blwf', + "Below-base Mark Positioning" => 'blwm', + "Below-base Substitutions" => 'blws', + "Capital Spacing" => 'cpsp', + "Case-Sensitive Forms" => 'case', + "Centered CJK Punctuation" => 'cpct', + "Character Variants 01" => 'cv01', + "Character Variants 02" => 'cv02', + "Character Variants 03" => 'cv03', + "Character Variants 04" => 'cv04', + "Character Variants 05" => 'cv05', + "Character Variants 06" => 'cv06', + "Character Variants 07" => 'cv07', + "Character Variants 08" => 'cv08', + "Character Variants 09" => 'cv09', + "Character Variants 10" => 'cv10', + "Character Variants 11" => 'cv11', + "Character Variants 12" => 'cv12', + "Character Variants 13" => 'cv13', + "Character Variants 14" => 'cv14', + "Character Variants 15" => 'cv15', + "Character Variants 16" => 'cv16', + "Character Variants 17" => 'cv17', + "Character Variants 18" => 'cv18', + "Character Variants 19" => 'cv19', + "Character Variants 20" => 'cv20', + "Character Variants 21" => 'cv21', + "Character Variants 22" => 'cv22', + "Character Variants 23" => 'cv23', + "Character Variants 24" => 'cv24', + "Character Variants 25" => 'cv25', + "Character Variants 26" => 'cv26', + "Character Variants 27" => 'cv27', + "Character Variants 28" => 'cv28', + "Character Variants 29" => 'cv29', + "Character Variants 30" => 'cv30', + "Character Variants 31" => 'cv31', + "Character Variants 32" => 'cv32', + "Character Variants 33" => 'cv33', + "Character Variants 34" => 'cv34', + "Character Variants 35" => 'cv35', + "Character Variants 36" => 'cv36', + "Character Variants 37" => 'cv37', + "Character Variants 38" => 'cv38', + "Character Variants 39" => 'cv39', + "Character Variants 40" => 'cv40', + "Character Variants 41" => 'cv41', + "Character Variants 42" => 'cv42', + "Character Variants 43" => 'cv43', + "Character Variants 44" => 'cv44', + "Character Variants 45" => 'cv45', + "Character Variants 46" => 'cv46', + "Character Variants 47" => 'cv47', + "Character Variants 48" => 'cv48', + "Character Variants 49" => 'cv49', + "Character Variants 50" => 'cv50', + "Character Variants 51" => 'cv51', + "Character Variants 52" => 'cv52', + "Character Variants 53" => 'cv53', + "Character Variants 54" => 'cv54', + "Character Variants 55" => 'cv55', + "Character Variants 56" => 'cv56', + "Character Variants 57" => 'cv57', + "Character Variants 58" => 'cv58', + "Character Variants 59" => 'cv59', + "Character Variants 60" => 'cv60', + "Character Variants 61" => 'cv61', + "Character Variants 62" => 'cv62', + "Character Variants 63" => 'cv63', + "Character Variants 64" => 'cv64', + "Character Variants 65" => 'cv65', + "Character Variants 66" => 'cv66', + "Character Variants 67" => 'cv67', + "Character Variants 68" => 'cv68', + "Character Variants 69" => 'cv69', + "Character Variants 70" => 'cv70', + "Character Variants 71" => 'cv71', + "Character Variants 72" => 'cv72', + "Character Variants 73" => 'cv73', + "Character Variants 74" => 'cv74', + "Character Variants 75" => 'cv75', + "Character Variants 76" => 'cv76', + "Character Variants 77" => 'cv77', + "Character Variants 78" => 'cv78', + "Character Variants 79" => 'cv79', + "Character Variants 80" => 'cv80', + "Character Variants 81" => 'cv81', + "Character Variants 82" => 'cv82', + "Character Variants 83" => 'cv83', + "Character Variants 84" => 'cv84', + "Character Variants 85" => 'cv85', + "Character Variants 86" => 'cv86', + "Character Variants 87" => 'cv87', + "Character Variants 88" => 'cv88', + "Character Variants 89" => 'cv89', + "Character Variants 90" => 'cv90', + "Character Variants 91" => 'cv91', + "Character Variants 92" => 'cv92', + "Character Variants 93" => 'cv93', + "Character Variants 94" => 'cv94', + "Character Variants 95" => 'cv95', + "Character Variants 96" => 'cv96', + "Character Variants 97" => 'cv97', + "Character Variants 98" => 'cv98', + "Character Variants 99" => 'cv99', + "Conjunct Form After Ro" => 'cfar', + "Conjunct Forms" => 'cjct', + "Contextual Alternates" => 'calt', + "Contextual Ligatures" => 'clig', + "Contextual Swash" => 'cswh', + "Cursive Positioning" => 'curs', + "Denominators" => 'dnom', + "Discretionary Ligatures" => 'dlig', + "Distances" => 'dist', + "Dotless Forms" => 'dtls', + "Expert Forms" => 'expt', + "Final Glyph on Line Alternates" => 'falt', + "Flattened ascent forms" => 'flac', + "Fractions" => 'frac', + "Full Widths" => 'fwid', + "Glyph Composition / Decomposition" => 'ccmp', + "Halant Forms" => 'haln', + "Half Forms" => 'half', + "Half Widths" => 'hwid', + "Hangul" => 'hngl', + "Historical Forms" => 'hist', + "Historical Ligatures" => 'hlig', + "Hojo Kanji Forms (JIS X 0212-1990 Kanji Forms)" => 'hojo', + "Horizontal Kana Alternates" => 'hkna', + "Initial Forms" => 'init', + "Isolated Forms" => 'isol', + "Italics" => 'ital', + "JIS2004 Forms" => 'jp04', + "JIS78 Forms" => 'jp78', + "JIS83 Forms" => 'jp83', + "JIS90 Forms" => 'jp90', + "Justification Alternates" => 'jalt', + "Kerning" => 'kern', + "Leading Jamo Forms" => 'ljmo', + "Left Bounds" => 'lfbd', + "Left-to-right glyph alternates" => 'ltra', + "Left-to-right mirrored forms" => 'ltrm', + "Lining Figures" => 'lnum', + "Localized Forms" => 'locl', + "Mark Positioning via Substitution" => 'mset', + "Mark Positioning" => 'mark', + "Mark to Mark Positioning" => 'mkmk', + "Math script style alternates" => 'ssty', + "Mathematical Greek" => 'mgrk', + "Medial Forms #2" => 'med2', + "Medial Forms" => 'medi', + "NLC Kanji Forms" => 'nlck', + "Nukta Forms" => 'nukt', + "Numerators" => 'numr', + "Oldstyle Figures" => 'onum', + "Optical Bounds" => 'opbd', + "Optical size" => 'size', + "Ordinals" => 'ordn', + "Ornaments" => 'ornm', + "Petite Capitals From Capitals" => 'c2pc', + "Petite Capitals" => 'pcap', + "Post-base Forms" => 'pstf', + "Post-base Substitutions" => 'psts', + "Pre-Base Forms" => 'pref', + "Pre-base Substitutions" => 'pres', + "Proportional Alternate Vertical Metrics" => 'vpal', + "Proportional Alternate Widths" => 'palt', + "Proportional Figures" => 'pnum', + "Proportional Kana" => 'pkna', + "Proportional Widths" => 'pwid', + "Quarter Widths" => 'qwid', + "Rakar Forms" => 'rkrf', + "Randomize" => 'rand', + "Reph Forms" => 'rphf', + "Required Contextual Alternates" => 'rclt', + "Required Ligatures" => 'rlig', + "Right Bounds" => 'rtbd', + "Right-to-left alternates" => 'rtla', + "Right-to-left mirrored forms" => 'rtlm', + "Ruby Notation Forms" => 'ruby', + "Scientific Inferiors" => 'sinf', + "Simplified Forms" => 'smpl', + "Slashed Zero" => 'zero', + "Small Capitals From Capitals" => 'c2sc', + "Small Capitals" => 'smcp', + "Standard Ligatures" => 'liga', + "Stretching Glyph Decomposition" => 'stch', + "Stylistic Alternates" => 'salt', + "Stylistic Set 1" => 'ss01', + "Stylistic Set 10" => 'ss10', + "Stylistic Set 11" => 'ss11', + "Stylistic Set 12" => 'ss12', + "Stylistic Set 13" => 'ss13', + "Stylistic Set 14" => 'ss14', + "Stylistic Set 15" => 'ss15', + "Stylistic Set 16" => 'ss16', + "Stylistic Set 17" => 'ss17', + "Stylistic Set 18" => 'ss18', + "Stylistic Set 19" => 'ss19', + "Stylistic Set 2" => 'ss02', + "Stylistic Set 20" => 'ss20', + "Stylistic Set 3" => 'ss03', + "Stylistic Set 4" => 'ss04', + "Stylistic Set 5" => 'ss05', + "Stylistic Set 6" => 'ss06', + "Stylistic Set 7" => 'ss07', + "Stylistic Set 8" => 'ss08', + "Stylistic Set 9" => 'ss09', + "Subscript" => 'subs', + "Superscript" => 'sups', + "Swash" => 'swsh', + "Tabular Figures" => 'tnum', + "Terminal Forms #2" => 'fin2', + "Terminal Forms #3" => 'fin3', + "Terminal Forms" => 'fina', + "Third Widths" => 'twid', + "Titling" => 'titl', + "Traditional Forms" => 'trad', + "Traditional Name Forms" => 'tnam', + "Trailing Jamo Forms" => 'tjmo', + "Unicase" => 'unic', + "Vattu Variants" => 'vatu', + "Vertical Alternates and Rotation" => 'vrt2', + "Vertical Kana Alternates" => 'vkna', + "Vertical Kerning" => 'vkrn', + "Vertical Writing" => 'vert', + "Vowel Jamo Forms" => 'vjmo', + }, + +); + +%iso639 = ( + 'ABA ' => 'abq', + 'ABK ' => 'abk', + 'ACH ' => 'ach', + 'ACR ' => 'acr', + 'ADY ' => 'ady', + 'AFK ' => 'afr', + 'AFR ' => 'aar', + 'AGW ' => 'ahg', + 'AIO ' => 'aio', + 'AKA ' => 'aka', + 'ALS ' => 'gsw', + 'ALT ' => 'atv alt', + 'AMH ' => 'amh', + 'ANG ' => 'ang', + 'ARA ' => 'ara', + 'ARG ' => 'arg', + 'ARI ' => 'aiw', + 'ARK ' => 'mhv rmz rki', + 'ASM ' => 'asm', + 'AST ' => 'ast', + 'ATH ' => 'apk apj apl apm apw nav bea sek bcr caf crx clc gwi haa chp dgr scs xsl srs ing hoi koy hup ktw mvb wlk coq ctc gce tol tuu kkz tgx tht aht tfn taa tau tcb kuu tce ttm txc', + 'AVR ' => 'ava', + 'AWA ' => 'awa', + 'AYM ' => 'aym', + 'AZB ' => 'azb', + 'AZE ' => 'aze', + 'BAD ' => 'bfq', + 'BAD0' => 'bad', + 'BAG ' => 'bfy', + 'BAL ' => 'krc', + 'BAN ' => 'ban', + 'BAR ' => 'bar', + 'BAU ' => 'bci', + 'BBC ' => 'bbc', + 'BCH ' => 'bcq', + 'BDY ' => 'bdy', + 'BEL ' => 'bel', + 'BEM ' => 'bem', + 'BEN ' => 'ben', + 'BGC ' => 'bgc', + 'BGQ ' => 'bgq', + 'BGR ' => 'bul', + 'BHI ' => 'bhi bhb', + 'BHO ' => 'bho', + 'BIK ' => 'bik bhk bcl bto cts bln', + 'BIL ' => 'byn', + 'BIS ' => 'bis', + 'BJJ ' => 'bjj', + 'BKF ' => 'bla', + 'BLI ' => 'bal', + 'BLK ' => 'blk', + 'BLN ' => 'bjt ble', + 'BLT ' => 'bft', + 'BMB ' => 'bam', + 'BOS ' => 'bos', + 'BPY ' => 'bpy', + 'BRE ' => 'bre', + 'BRH ' => 'brh', + 'BRI ' => 'bra', + 'BRM ' => 'mya', + 'BRX ' => 'brx', + 'BSH ' => 'bak', + "BSK " => 'bsk', + 'BTI ' => 'btb', + 'BTS ' => 'bts', + 'BUG ' => 'bug', + "BYV " => 'byv', + 'CAK ' => 'cak', + 'CAT ' => 'cat', + 'CBK ' => 'cbk', + 'CEB ' => 'ceb', + 'CGG ' => 'cgg', + 'CHA ' => 'cha', + 'CHE ' => 'che', + 'CHG ' => 'sgw', + 'CHH ' => 'hne', + 'CHI ' => 'nya', + 'CHK ' => 'ckt', + 'CHK0' => 'chk', + 'CHO ' => 'cho', + 'CHP ' => 'chp', + 'CHR ' => 'chr', + 'CHU ' => 'chv', + 'CHY ' => 'chy', + 'CMR ' => 'swb wlc wni zdj', + 'COP ' => 'cop', + 'COR ' => 'cor', + 'COS ' => 'cos', + 'CPP ' => 'cpp', + 'CRE ' => 'cre', + 'CRR ' => 'crx caf', + 'CRT ' => 'crh', + 'CSB ' => 'csb', + 'CSL ' => 'chu', + 'CSY ' => 'ces', + 'CTG ' => 'ctg', + 'CUK ' => 'cuk', + 'DAN ' => 'dan', + 'DAR ' => 'dar', + 'DAX ' => 'dax', + 'DCR ' => 'cwd', + 'DEU ' => 'deu', + 'DGO ' => 'dgo', + 'DGR ' => 'doi', + 'DHG ' => 'dhg', + 'DHV ' => 'div', + 'DIQ ' => 'diq', + 'DIV ' => 'div', + 'DJR ' => 'dje', + 'DJR0' => 'djr', + 'DNG ' => 'ada', + 'DNJ ' => 'dnj', + 'DNK ' => 'din', + 'DRI ' => 'prs', + 'DUJ ' => 'duj', + 'DUN ' => 'dng', + 'DZN ' => 'dzo', + 'EBI ' => 'igb', + 'ECR ' => 'crj crl', + 'EDO ' => 'bin', + 'EFI ' => 'efi', + 'ELL ' => 'ell', + 'EMK ' => 'emk', + 'ENG ' => 'eng', + 'ERZ ' => 'myv', + 'ESP ' => 'spa', + 'ESU ' => 'esu', + 'ETI ' => 'est', + 'EUQ ' => 'eus', + 'EVK ' => 'evn', + 'EVN ' => 'eve', + 'EWE ' => 'ewe', + 'FAN ' => 'acf', + 'FAN0' => 'fan', + 'FAR ' => 'fas', + 'FAT ' => 'fat', + 'FIN ' => 'fin', + 'FJI ' => 'fij', + 'FLE ' => 'vls', + "FMP " => 'fmp', + 'FNE ' => 'enf', + 'FON ' => 'fon', + 'FOS ' => 'fao', + 'FRA ' => 'fra', + 'FRC ' => 'frc', + 'FRI ' => 'fry', + 'FRL ' => 'fur', + 'FRP ' => 'frp', + 'FTA ' => 'fuf', + 'FUL ' => 'ful', + 'FUV ' => 'fuv', + 'GAD ' => 'gaa', + 'GAE ' => 'gla', + 'GAG ' => 'gag', + 'GAL ' => 'glg', + 'GAW ' => 'gbm', + 'GEZ ' => 'gez', + 'GIH ' => 'gih', + 'GIL ' => 'niv', + 'GIL0' => 'gil', + 'GKP ' => 'gkp', + 'GLK ' => 'glk', + 'GMZ ' => 'guk', + 'GNN ' => 'gnn', + 'GOG ' => 'gog', + 'GON ' => 'gon gno ggo', + 'GRN ' => 'kal', + 'GRO ' => 'grt', + 'GUA ' => 'grn', + 'GUC ' => 'guc', + 'GUF ' => 'guf', + 'GUJ ' => 'guj', + 'GUZ ' => 'guz', + 'HAI ' => 'hat', + 'HAL ' => 'flm', + 'HAR ' => 'hoj', + 'HAU ' => 'hau', + 'HAW ' => 'haw', + 'HAY ' => 'hay', + 'HAZ ' => 'haz', + 'HBN ' => 'amf', + 'HER ' => 'her', + 'HIL ' => 'hil', + 'HIN ' => 'hin', + 'HMA ' => 'mrj', + 'HMN ' => 'hmn', + 'HMO ' => 'hmo', + 'HND ' => 'hno hnd', + 'HO ' => 'hoc', + 'HRI ' => 'har', + 'HRV ' => 'hrv', + 'HUN ' => 'hun', + 'HYE ' => 'hye', + 'HYE0' => 'hye', + 'IBA ' => 'iba', + 'IBB ' => 'ibb', + 'IBO ' => 'ibo', + 'IDO ' => 'ido', + 'IJO ' => 'ijc', + 'ILE ' => 'ile', + 'ILO ' => 'ilo', + 'INA ' => 'ina', + 'IND ' => 'ind', + 'ING ' => 'inh', + 'INU ' => 'iku', + 'IPK ' => 'ipk', + 'IRI ' => 'gle', + 'IRT ' => 'gle', + 'ISL ' => 'isl', + 'ISM ' => 'smn', + 'ITA ' => 'ita', + 'IWR ' => 'heb', + 'JAM ' => 'jam', + 'JAN ' => 'jpn', + 'JAV ' => 'jav', + 'JBO ' => 'jbo', + "JCT " => 'jct', + 'JII ' => 'yid', + 'JUD ' => 'lad', + 'JUL ' => 'dyu', + 'KAB ' => 'kbd', + 'KAB0' => 'kab', + 'KAC ' => 'kfr', + 'KAL ' => 'kln', + 'KAN ' => 'kan', + 'KAR ' => 'krc', + 'KAT ' => 'kat', + 'KAZ ' => 'kaz', + 'KDE ' => 'kde', + 'KEA ' => 'kea', + 'KEB ' => 'ktb', + 'KEK ' => 'kek', + 'KGE ' => 'kat', + 'KHA ' => 'kjh', + 'KHK ' => 'kca', + 'KHM ' => 'khm', + 'KHS ' => 'kca', + 'KHT ' => 'kht', + 'KHV ' => 'kca', + 'KHW ' => 'khw', + 'KIK ' => 'kik', + 'KIR ' => 'kir', + 'KIS ' => 'kqs kss', + 'KIU ' => 'kiu', + 'KJD ' => 'kjd', + 'KJP ' => 'kjp', + 'KKN ' => 'kex', + 'KLM ' => 'xal', + 'KMB ' => 'kam', + 'KMN ' => 'kfy', + 'KMO ' => 'kmw', + 'KMS ' => 'kxc', + "KMZ " => 'kmz', + 'KNR ' => 'kau', + 'KOD ' => 'kfa', + 'KOH ' => 'okm', + 'KOK ' => 'kok', + 'KOM ' => 'kom', + 'KON ' => 'ktu', + 'KON0' => 'kon', + 'KOP ' => 'koi', + 'KOR ' => 'kor', + 'KOS ' => 'kos', + 'KOZ ' => 'kpv', + 'KPL ' => 'kpe', + 'KRI ' => 'kri', + 'KRK ' => 'kaa', + 'KRL ' => 'krl', + 'KRM ' => 'kdr', + 'KRN ' => 'kar', + 'KRT ' => 'kqy', + 'KSH ' => 'kas', + 'KSH0' => 'ksh', + 'KSI ' => 'kha', + 'KSM ' => 'sjd', + 'KSW ' => 'ksw', + 'KUA ' => 'kua', + 'KUI ' => 'kxu', + 'KUL ' => 'kfx', + 'KUM ' => 'kum', + 'KUR ' => 'kur', + 'KUU ' => 'kru', + 'KUY ' => 'kdt', + 'KYK ' => 'kpy', + 'KYU ' => 'kyu', + 'LAD ' => 'lld', + 'LAH ' => 'bfu', + 'LAK ' => 'lbe', + 'LAM ' => 'lmn', + 'LAO ' => 'lao', + 'LAT ' => 'lat', + 'LAZ ' => 'lzz', + 'LCR ' => 'crm', + 'LDK ' => 'lbj', + 'LEZ ' => 'lez', + 'LIJ ' => 'lij', + 'LIM ' => 'lim', + 'LIN ' => 'lin', + 'LIS ' => 'lis', + 'LJP ' => 'ljp', + 'LKI ' => 'lki', + 'LMA ' => 'mhr', + 'LMB ' => 'lif', + 'LMO ' => 'lmo', + 'LMW ' => 'ngl', + 'LOM ' => 'lom', + 'LRC ' => 'lrc luz bqi zum', + 'LSB ' => 'dsb', + 'LSM ' => 'smj', + 'LTH ' => 'lit', + 'LTZ ' => 'ltz', + 'LUA ' => 'lua', + 'LUB ' => 'lub', + 'LUG ' => 'lug', + 'LUH ' => 'luy', + 'LUO ' => 'luo', + 'LVI ' => 'lav', + 'MAD ' => 'mad', + 'MAG ' => 'mag', + 'MAH ' => 'mah', + 'MAJ ' => 'mpe', + 'MAK ' => 'vmw', + 'MAL ' => 'mal', + 'MAM ' => 'mam', + 'MAN ' => 'mns', + 'MAP ' => 'arn', + 'MAR ' => 'mar', + 'MAW ' => 'mwr dhd rwr mve wry mtr swv', + 'MBN ' => 'kmb', + "MBO " => 'mbo', + 'MCH ' => 'mnc', + 'MCR ' => 'crm', + 'MDE ' => 'men', + 'MDR ' => 'mdr', + 'MEN ' => 'mym', + 'MER ' => 'mer', + 'MFE ' => 'mfe', + 'MIN ' => 'min', + 'MIZ ' => 'lus', + 'MKD ' => 'mkd', + 'MKR ' => 'mak', + 'MKW ' => 'mkw', + 'MLE ' => 'mdy', + 'MLG ' => 'mlg', + 'MLN ' => 'mlq', + 'MLR ' => 'mal', + 'MLY ' => 'msa', + 'MND ' => 'mnk', + 'MNG ' => 'mon', + 'MNI ' => 'mni', + 'MNK ' => 'man mnk myq mku msc emk mwk mlq', + 'MNX ' => 'glv', + 'MOH ' => 'mho', + 'MOK ' => 'mdf', + 'MOL ' => 'mol', + 'MON ' => 'mnw', + 'MOS ' => 'mos', + 'MRI ' => 'mri', + 'MTH ' => 'mai', + 'MTS ' => 'mlt', + 'MUN ' => 'unr', + 'MUS ' => 'mus', + 'MWL ' => 'mwl', + 'MWW ' => 'mww', + 'MYN ' => 'myn', + 'MZN ' => 'mzn', + 'NAG ' => 'nag', + 'NAH ' => 'nah', + 'NAN ' => 'gld', + 'NAP ' => 'nap', + 'NAS ' => 'nsk', + 'NAU ' => 'nau', + 'NAV ' => 'nav', + 'NCR ' => 'csw', + 'NDB ' => 'nbl nde', + 'NDC ' => 'ndc', + 'NDG ' => 'ndo', + 'NDS ' => 'nds', + 'NEP ' => 'nep', + 'NEW ' => 'new', + 'NGA ' => 'nga', + 'NHC ' => 'csw', + 'NIS ' => 'dap', + 'NIU ' => 'niu', + 'NKL ' => 'nyn', + 'NKO ' => 'ngo', + 'NLD ' => 'nld', + 'NOE ' => 'noe', + 'NOG ' => 'nog', + 'NOR ' => 'nob', + 'NOV ' => 'nov', + 'NSM ' => 'sme', + 'NSO ' => 'nso', + 'NTA ' => 'nod', + 'NTO ' => 'epo', + 'NYM ' => 'nym', + 'NYN ' => 'nno', + "NZA " => 'nza', + 'OCI ' => 'oci', + 'OCR ' => 'ojs', + 'OJB ' => 'oji', + 'ORI ' => 'ori', + 'ORO ' => 'orm', + 'OSS ' => 'oss', + 'PAA ' => 'sam', + 'PAG ' => 'pag', + 'PAL ' => 'pli', + 'PAM ' => 'pam', + 'PAN ' => 'pan', + 'PAP ' => 'plp', + 'PAP0' => 'pap', + 'PAS ' => 'pus', + 'PAU ' => 'pau', + 'PCC ' => 'pcc', + 'PCD ' => 'pcd', + 'PDC ' => 'pdc', + 'PGR ' => 'ell', + 'PHK ' => 'phk', + 'PIH ' => 'pih', + 'PIL ' => 'fil', + 'PLG ' => 'pce rbb pll', + 'PLK ' => 'pol', + 'PMS ' => 'pms', + 'PNB ' => 'pnb', + 'POH ' => 'poh', + 'PON ' => 'pon', + 'PRO ' => 'pro', + 'PTG ' => 'por', + 'PWO ' => 'pwo', + 'QIN ' => 'bgr cnh cnw czt sez tcp csy ctd flm pck tcz zom cmr dao hlt cka cnk mrh mwg cbl cnb csh', + 'QUC ' => 'quc', + 'QUH ' => 'quh', + 'QUZ ' => 'quz', + 'QVI ' => 'qvi', + 'QWH ' => 'qwh', + 'RAJ ' => 'raj', + 'RAR ' => 'rar', + 'RBU ' => 'bxr', + 'RCR ' => 'atj', + 'REJ ' => 'rej', + 'RIA ' => 'ria', + 'RIF ' => 'rif', + 'RIT ' => 'rit', + 'RKW ' => 'rkw', + 'RMS ' => 'roh', + 'RMY ' => 'rmy', + 'ROM ' => 'ron', + 'ROY ' => 'rom', + 'RSY ' => 'rue', + 'RTM ' => 'rtm', + 'RUA ' => 'kin', + 'RUN ' => 'run', + 'RUP ' => 'rup', + 'RUS ' => 'rus', + 'SAD ' => 'sck', + 'SAN ' => 'san', + 'SAS ' => 'sas', + 'SAT ' => 'sat', + 'SAY ' => 'chp', + 'SCN ' => 'scn', + 'SCO ' => 'sco', + "SCS " => 'scs', + 'SEK ' => 'xan', + 'SEL ' => 'sel', + 'SGA ' => 'sga', + 'SGO ' => 'sag', + 'SGS ' => 'sgs', + 'SHI ' => 'shi', + 'SHN ' => 'shn', + 'SIB ' => 'sjo', + 'SID ' => 'sid', + 'SIG ' => 'xst', + 'SKS ' => 'sms', + 'SKY ' => 'slk', + "SLA " => 'scs xsl', + 'SLV ' => 'slv', + 'SML ' => 'som', + 'SMO ' => 'smo', + 'SNA ' => 'she', + 'SNA0' => 'sna', + 'SND ' => 'snd', + 'SNH ' => 'sin', + 'SNK ' => 'snk', + 'SOG ' => 'gru', + 'SOP ' => 'sop', + 'SOT ' => 'sot', + 'SQI ' => 'gsw', + 'SRB ' => 'srp', + 'SRD ' => 'srd', + 'SRK ' => 'skr', + 'SRR ' => 'srr', + 'SSL ' => 'xsl', + 'SSM ' => 'sma', + 'STQ ' => 'stq', + 'SUK ' => 'suk', + 'SUN ' => 'sun', + 'SUR ' => 'suq', + 'SVA ' => 'sva', + 'SVE ' => 'swe', + 'SWA ' => 'aii', + 'SWK ' => 'swa', + 'SWZ ' => 'ssw', + 'SXT ' => 'ngo', + 'SXU ' => 'sxu', + 'SYL ' => 'syl', + 'SYR ' => 'syr', + 'SZL ' => 'szl', + 'TAB ' => 'tab', + 'TAJ ' => 'tgk', + 'TAM ' => 'tam', + 'TAT ' => 'tat', + 'TCR ' => 'cwd', + 'TDD ' => 'tdd', + 'TEL ' => 'tel', + 'TET ' => 'tet', + 'TGL ' => 'tgl', + 'TGN ' => 'ton', + 'TGR ' => 'tig', + 'TGY ' => 'tir', + 'THA ' => 'tha', + 'THT ' => 'tah', + 'TIB ' => 'bod', + 'TIV ' => 'tiv', + 'TKM ' => 'tuk', + 'TMH ' => 'tmh', + 'TMN ' => 'tem', + 'TNA ' => 'tsn', + 'TNE ' => 'enh', + 'TNG ' => 'toi', + 'TOD ' => 'xal', + 'TOD0' => 'tod', + 'TPI ' => 'tpi', + 'TRK ' => 'tur', + 'TSG ' => 'tso', + 'TUA ' => 'tru', + 'TUL ' => 'tcy', + 'TUM ' => 'tum', + 'TUV ' => 'tyv', + 'TVL ' => 'tvl', + 'TWI ' => 'twi', + 'TYZ ' => 'tyz', + 'TZM ' => 'tzm', + 'TZO ' => 'tzo', + 'UDM ' => 'udm', + 'UKR ' => 'ukr', + 'UMB ' => 'umb', + 'URD ' => 'urd', + 'USB ' => 'hsb', + 'UYG ' => 'uig', + 'UZB ' => 'uzb uzn uzs', + 'VEC ' => 'vec', + 'VEN ' => 'ven', + 'VIT ' => 'vie', + 'VOL ' => 'vol', + 'VRO ' => 'vro', + 'WA ' => 'wbm', + 'WAG ' => 'wbr', + 'WAR ' => 'war', + 'WCR ' => 'crk', + 'WEL ' => 'cym', + 'WLF ' => 'wol', + 'WLN ' => 'wln', + 'WTM ' => 'wtm', + 'XBD ' => 'khb', + 'XHS ' => 'xho', + 'XJB ' => 'xjb', + 'XOG ' => 'xog', + 'XPE ' => 'xpe', + 'YAK ' => 'sah', + 'YAO ' => 'yao', + 'YAP ' => 'yap', + 'YBA ' => 'yor', + 'YCR ' => 'cre', + 'YIM ' => 'iii', + 'ZEA ' => 'zea', + 'ZGH ' => 'zgh', + 'ZHA ' => 'zha', + 'ZHH ' => 'zho', + 'ZHP ' => 'zho', + 'ZHS ' => 'zho', + 'ZHT ' => 'zho', + 'ZND ' => 'zne', + 'ZUL ' => 'zul', + 'ZZA ' => 'zza', +); + +{ + foreach my $s (qw ( SCRIPT LANGUAGE FEATURE ) ) + { + map { $ttnames{$s}{$tttags{$s}{$_}} = $_ } keys %{$tttags{$s}}; + } + + # For ISO639 info, the raw data is a space-separated list of ISO639 + # language IDs. We convert that list to an array. + + foreach my $tag (keys %iso639) + { + my $list = $iso639{$tag}; + $iso639{$tag} = [ split(' ', $list) ]; + # Also set the reverse mapping: + map { $iso639{$_} = $tag } @{$iso639{$tag}}; + } +} + + +=head2 readtagsfile ( filename ) + +Read a file in the syntax of Tags.txt (included with Microsoft VOLT) to obtain additional/replacement tag definitions. + +Returns 0 if cannot open the file; else 1. + +=cut + +sub readtagsfile +{ + my $fname = shift; + open (TAGS, $fname) or return 0; + my ($what, $name, $tag); + while () + { + ($what, $name, $tag) = (m/"([^"]*)", "([^"]*)", "([^"]*)"/); #" + $ttnames{$what}{$tag} = $name; + $tttags{$what}{$name} = $tag; + } + close TAGS; + return 1; +} + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OldCmap.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OldCmap.pm new file mode 100644 index 0000000000..75091495b3 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OldCmap.pm @@ -0,0 +1,370 @@ +package Font::TTF::OldCmap; + +=head1 NAME + +Font::TTF::OldCmap - Character map table + +This module is deprecated + +=head1 DESCRIPTION + +Looks after the character map. The primary structure used for handling a cmap +is the L which handles the segmented arrays of format 4 tables, +and in a simpler form for format 0 tables. + +Due to the complexity of working with segmented arrays, most of the handling of +such arrays is via methods rather than via instance variables. + +One important feature of a format 4 table is that it always contains a segment +with a final address of 0xFFFF. If you are creating a table from scratch this is +important (although L can work quite happily without it). + + +=head1 INSTANCE VARIABLES + +The instance variables listed here are not preceded by a space due to their +emulating structural information in the font. + +=over 4 + +=item Num + +Number of subtables in this table + +=item Tables + +An array of subtables ([0..Num-1]) + +=back + +Each subtables also has its own instance variables which are, again, not +preceded by a space. + +=over 4 + +=item Platform + +The platform number for this subtable + +=item Encoding + +The encoding number for this subtable + +=item Format + +Gives the stored format of this subtable + +=item Ver + +Gives the version (or language) information for this subtable + +=item val + +This points to a L which contains the content of the particular +subtable. + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Table; +require Font::TTF::Segarr; + +@ISA = qw(Font::TTF::Table); + + +=head2 $t->read + +Reads the cmap into memory. Format 4 subtables read the whole subtable and +fill in the segmented array accordingly. + +Format 2 subtables are not read at all. + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $i, $j, $k, $id, @ids, $s); + my ($start, $end, $range, $delta, $form, $len, $num, $ver); + my ($fh) = $self->{' INFILE'}; + + $fh->read($dat, 4); + $self->{'Num'} = unpack("x2n", $dat); + $self->{'Tables'} = []; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = {}; + $fh->read($dat, 8); + ($s->{'Platform'}, $s->{'Encoding'}, $s->{'LOC'}) = (unpack("nnN", $dat)); + $s->{'LOC'} += $self->{' OFFSET'}; + push(@{$self->{'Tables'}}, $s); + } + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + $fh->seek($s->{'LOC'}, 0); + $fh->read($dat, 6); + ($form, $len, $ver) = (unpack("n3", $dat)); + + $s->{'Format'} = $form; + $s->{'Ver'} = $ver; + if ($form == 0) + { + $s->{'val'} = Font::TTF::Segarr->new; + $fh->read($dat, 256); + $s->{'val'}->fastadd_segment(0, 2, unpack("C*", $dat)); + $s->{'Start'} = 0; + $s->{'Num'} = 256; + } elsif ($form == 6) + { + my ($start, $ecount); + + $fh->read($dat, 4); + ($start, $ecount) = unpack("n2", $dat); + $fh->read($dat, $ecount << 1); + $s->{'val'} = Font::TTF::Segarr->new; + $s->{'val'}->fastadd_segment($start, 2, unpack("n*", $dat)); + $s->{'Start'} = $start; + $s->{'Num'} = $ecount; + } elsif ($form == 2) + { +# no idea what to do here yet + } elsif ($form == 4) + { + $fh->read($dat, 8); + $num = unpack("n", $dat); + $num >>= 1; + $fh->read($dat, $len - 14); + $s->{'val'} = Font::TTF::Segarr->new; + for ($j = 0; $j < $num; $j++) + { + $end = unpack("n", substr($dat, $j << 1, 2)); + $start = unpack("n", substr($dat, ($j << 1) + ($num << 1) + 2, 2)); + $delta = unpack("n", substr($dat, ($j << 1) + ($num << 2) + 2, 2)); + $delta -= 65536 if $delta > 32767; + $range = unpack("n", substr($dat, ($j << 1) + $num * 6 + 2, 2)); + @ids = (); + for ($k = $start; $k <= $end; $k++) + { + if ($range == 0) + { $id = $k + $delta; } + else + { $id = unpack("n", substr($dat, ($j << 1) + $num * 6 + + 2 + ($k - $start) * 2 + $range, 2)) + $delta; } + $id -= 65536 if $id > 65536; + push (@ids, $id); + } + $s->{'val'}->fastadd_segment($start, 0, @ids); + } + $s->{'val'}->tidy; + $s->{'Num'} = 0x10000; # always ends here + $s->{'Start'} = $s->{'val'}[0]{'START'}; + } + } + $self; +} + + +=head2 $t->ms_lookup($uni) + +Given a Unicode value in the MS table (Platform 3, Encoding 1) locates that +table and looks up the appropriate glyph number from it. + +=cut + +sub ms_lookup +{ + my ($self, $uni) = @_; + + $self->find_ms || return undef unless (defined $self->{' mstable'}); + return $self->{' mstable'}{'val'}->at($uni); +} + + +=head2 $t->find_ms + +Finds the Microsoft Unicode table and sets the C instance variable +to it if found. Returns the table it finds. + +=cut + +sub find_ms +{ + my ($self) = @_; + my ($i, $s, $alt); + + return $self->{' mstable'} if defined $self->{' mstable'}; + $self->read; + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + if ($s->{'Platform'} == 3) + { + $self->{' mstable'} = $s; + last if ($s->{'Encoding'} == 1); + } elsif ($s->{'Platform'} == 0 || ($s->{'Platform'} == 2 && $s->{'Encoding'} == 1)) + { $self->{' mstable'} = $s; } + } + $self->{' mstable'}; +} + + +=head2 $t->out($fh) + +Writes out a cmap table to a filehandle. If it has not been read, then +just copies from input file to output + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($loc, $s, $i, $base_loc, $j); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $base_loc = $fh->tell(); + $fh->print(pack("n2", 0, $self->{'Num'})); + + for ($i = 0; $i < $self->{'Num'}; $i++) + { $fh->print(pack("nnN", $self->{'Tables'}[$i]{'Platform'}, $self->{'Tables'}[$i]{'Encoding'}, 0)); } + + for ($i = 0; $i < $self->{'Num'}; $i++) + { + $s = $self->{'Tables'}[$i]; + $s->{'val'}->tidy; + $s->{' outloc'} = $fh->tell(); + $fh->print(pack("n3", $s->{'Format'}, 0, $s->{'Ver'})); # come back for length + if ($s->{'Format'} == 0) + { + $fh->print(pack("C256", $s->{'val'}->at(0, 256))); + } elsif ($s->{'Format'} == 6) + { + $fh->print(pack("n2", $s->{'Start'}, $s->{'Num'})); + $fh->print(pack("n*", $s->{'val'}->at($s->{'Start'}, $s->{'Num'}))); + } elsif ($s->{'Format'} == 2) + { + } elsif ($s->{'Format'} == 4) + { + my ($num, $sRange, $eSel); + my (@deltas, $delta, @range, $flat, $k, $segs, $count); + + $num = $#{$s->{'val'}} + 1; + $segs = $s->{'val'}; + for ($sRange = 1, $eSel = 0; $sRange <= $num; $eSel++) + { $sRange <<= 1;} + $eSel--; + $fh->print(pack("n4", $num * 2, $sRange, $eSel, ($num * 2) - $sRange)); + $fh->print(pack("n*", map {$_->{'START'} + $_->{'LEN'} - 1} @$segs)); + $fh->print(pack("n", 0)); + $fh->print(pack("n*", map {$_->{'START'}} @$segs)); + + for ($j = 0; $j < $num; $j++) + { + $delta = $segs->[$j]{'VAL'}[0]; $flat = 1; + for ($k = 1; $k < $segs->[$j]{'LEN'}; $k++) + { + if ($segs->[$j]{'VAL'}[$k] == 0) + { $flat = 0; } + if ($delta + $k != $segs->[$j]{'VAL'}[$k]) + { + $delta = 0; + last; + } + } + push (@range, $flat); + push (@deltas, ($delta ? $delta - $segs->[$j]{'START'} : 0)); + } + $fh->print(pack("n*", @deltas)); + + $count = 0; + for ($j = 0; $j < $num; $j++) + { + $delta = $deltas[$j]; + if ($delta != 0 && $range[$j] == 1) + { $range[$j] = 0; } + else + { + $range[$j] = ($count + $num - $j) << 1; + $count += $segs->[$j]{'LEN'}; + } + } + + $fh->print(pack("n*", @range)); + + for ($j = 0; $j < $num; $j++) + { + next if ($range[$j] == 0); + for ($k = 0; $k < $segs->[$j]{'LEN'}; $k++) + { $fh->print(pack("n", $segs->[$j]{'VAL'}[$k])); } + } + } + + $loc = $fh->tell(); + $fh->seek($s->{' outloc'} + 2, 0); + $fh->print(pack("n", $loc - $s->{' outloc'})); + $fh->seek($base_loc + 8 + ($i << 3), 0); + $fh->print(pack("N", $s->{' outloc'} - $base_loc)); + $fh->seek($loc, 0); + } + $self; +} + + +=head2 @map = $t->reverse([$num]) + +Returns a reverse map of the table of given number or the Microsoft +cmap. I.e. given a glyph gives the Unicode value for it. + +=cut + +sub reverse +{ + my ($self, $tnum) = @_; + my ($table) = defined $tnum ? $self->{'Tables'}[$tnum] : $self->find_ms; + my (@res, $i, $s, $first); + + foreach $s (@{$table->{'val'}}) + { + $first = $s->{'START'}; + map {$res[$_] = $first unless $res[$_]; $first++;} @{$s->{'VAL'}}; + } + @res; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +No support for format 2 tables (MBCS) + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OldMort.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OldMort.pm new file mode 100644 index 0000000000..517709c798 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/OldMort.pm @@ -0,0 +1,722 @@ +package Font::TTF::OldMort; + +=head1 NAME + +Font::TTF::OldMort - Glyph Metamorphosis table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +table version number (Fixed: currently 1.0) + +=item chains + +list of metamorphosis chains, each of which has its own fields: + +=over + +=item defaultFlags + +chain's default subfeature flags (UInt32) + +=item featureEntries + +list of feature entries, each of which has fields: + +=over + +=item type + +=item setting + +=item enable + +=item disable + +=back + +=item subtables + +list of metamorphosis subtables, each of which has fields: + +=over + +=item type + +subtable type (0: rearrangement; 1: contextual substitution; 2: ligature; +4: non-contextual substitution; 5: insertion) + +=item direction + +processing direction ('LR' or 'RL') + +=item orientation + +applies to text in which orientation ('VH', 'V', or 'H') + +=item subFeatureFlags + +the subfeature flags controlling whether the table is used (UInt32) + +=back + +Further fields depend on the type of subtable: + +=over + +Rearrangement table: + +=over + +=item classes + +array of lists of glyphs + +=item states + +array of arrays of hashes{'nextState', 'flags'} + +=back + +Contextual substitution table: + +=over + +=item classes + +array of lists of glyphs + +=item states + +array of array of hashes{'nextState', 'flags', 'actions'}, where C +is an array of two elements which are offsets to be added to [marked, current] +glyph to get index into C (or C if no mapping to be applied) + +=item mappings + +list of glyph codes mapped to through the state table mappings + +=back + +Ligature table: + +Non-contextual substitution table: + +Insertion table: + +=back + +=back + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use IO::File; + +@ISA = qw(Font::TTF::Table); + +=over + +=back + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh, $numChains); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + + $fh->read($dat, 8); + ($self->{'version'}, $numChains) = TTF_Unpack("fL", $dat); + + my $chains = []; + foreach (1 .. $numChains) { + my $chainStart = $fh->tell(); + $fh->read($dat, 12); + my ($defaultFlags, $chainLength, $nFeatureEntries, $nSubtables) = TTF_Unpack("LLSS", $dat); + my $featureEntries = []; + foreach (1 .. $nFeatureEntries) { + $fh->read($dat, 12); + my ($featureType, $featureSetting, $enableFlags, $disableFlags) = TTF_Unpack("SSLL", $dat); + push @$featureEntries, { + 'type' => $featureType, + 'setting' => $featureSetting, + 'enable' => $enableFlags, + 'disable' => $disableFlags + }; + } + my $subtables = []; + foreach (1 .. $nSubtables) { + my $subtableStart = $fh->tell(); + $fh->read($dat, 8); + my ($length, $coverage, $subFeatureFlags) = TTF_Unpack("SSL", $dat); + my $type = $coverage & 0x0007; + + my $subtable = { + 'type' => $type, + 'direction' => (($coverage & 0x4000) ? 'RL' : 'LR'), + 'orientation' => (($coverage & 0x2000) ? 'VH' : ($coverage & 0x8000) ? 'V' : 'H'), + 'subFeatureFlags' => $subFeatureFlags + }; + + if ($type == 0) { # rearrangement + my ($classes, $states) = AAT_read_state_table($fh, 0); + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + } + + elsif ($type == 1) { # contextual + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 10); + my ($stateSize, $classTable, $stateArray, $entryTable, $mappingTables) = unpack("nnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $mappingTables, $length - 8]; + + foreach (@$entries) { + my $actions = $_->{'actions'}; + foreach (@$actions) { + $_ = $_ ? $_ - ($mappingTables / 2) : undef; + } + } + + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + $subtable->{'mappings'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $mappingTables, $limits))]; + } + + elsif ($type == 2) { # ligature + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 0); + + $fh->seek($stateTableStart, IO::File::SEEK_SET); + $fh->read($dat, 14); + my ($stateSize, $classTable, $stateArray, $entryTable, + $ligActionTable, $componentTable, $ligatureTable) = unpack("nnnnnnn", $dat); + my $limits = [$classTable, $stateArray, $entryTable, $ligActionTable, $componentTable, $ligatureTable, $length - 8]; + + my %actions; + my $actionLists; + foreach (@$entries) { + my $offset = $_->{'flags'} & 0x3fff; + $_->{'flags'} &= ~0x3fff; + if ($offset != 0) { + if (not defined $actions{$offset}) { + $fh->seek($stateTableStart + $offset, IO::File::SEEK_SET); + my $actionList; + while (1) { + $fh->read($dat, 4); + my $action = unpack("N", $dat); + my ($last, $store, $component) = (($action & 0x80000000) != 0, ($action & 0xC0000000) != 0, ($action & 0x3fffffff)); + $component -= 0x40000000 if $component > 0x1fffffff; + $component -= $componentTable / 2; + push @$actionList, { 'store' => $store, 'component' => $component }; + last if $last; + } + push @$actionLists, $actionList; + $actions{$offset} = $#$actionLists; + } + $_->{'actions'} = $actions{$offset}; + } + } + + $subtable->{'componentTable'} = $componentTable; + my $components = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $componentTable, $limits))]; + foreach (@$components) { + $_ = ($_ - $ligatureTable) . " +" if $_ >= $ligatureTable; + } + $subtable->{'components'} = $components; + + $subtable->{'ligatureTable'} = $ligatureTable; + $subtable->{'ligatures'} = [unpack("n*", AAT_read_subtable($fh, $stateTableStart, $ligatureTable, $limits))]; + + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + $subtable->{'actionLists'} = $actionLists; + } + + elsif ($type == 4) { # non-contextual + my ($format, $lookup) = AAT_read_lookup($fh, 2, $length - 8, undef); + $subtable->{'format'} = $format; + $subtable->{'lookup'} = $lookup; + } + + elsif ($type == 5) { # insertion + my $stateTableStart = $fh->tell(); + my ($classes, $states, $entries) = AAT_read_state_table($fh, 2); + + my %insertListHash; + my $insertLists; + foreach (@$entries) { + my $flags = $_->{'flags'}; + my @insertCount = (($flags & 0x03e0) >> 5, ($flags & 0x001f)); + my $actions = $_->{'actions'}; + foreach (0 .. 1) { + if ($insertCount[$_] > 0) { + $fh->seek($stateTableStart + $actions->[$_], IO::File::SEEK_SET); + $fh->read($dat, $insertCount[$_] * 2); + if (not defined $insertListHash{$dat}) { + push @$insertLists, [unpack("n*", $dat)]; + $insertListHash{$dat} = $#$insertLists; + } + $actions->[$_] = $insertListHash{$dat}; + } + else { + $actions->[$_] = undef; + } + } + } + + $subtable->{'classes'} = $classes; + $subtable->{'states'} = $states; + $subtable->{'insertLists'} = $insertLists; + } + + else { + die "unknown subtable type"; + } + + push @$subtables, $subtable; + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); + } + + push @$chains, { + 'defaultFlags' => $defaultFlags, + 'featureEntries' => $featureEntries, + 'subtables' => $subtables + }; + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); + } + + $self->{'chains'} = $chains; + + $self; +} + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + my $chains = $self->{'chains'}; + $fh->print(TTF_Pack("fL", $self->{'version'}, scalar @$chains)); + + foreach (@$chains) { + my $chainStart = $fh->tell(); + my ($featureEntries, $subtables) = ($_->{'featureEntries'}, $_->{'subtables'}); + $fh->print(TTF_Pack("LLSS", $_->{'defaultFlags'}, 0, scalar @$featureEntries, scalar @$subtables)); # placeholder for length + + foreach (@$featureEntries) { + $fh->print(TTF_Pack("SSLL", $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'})); + } + + foreach (@$subtables) { + my $subtableStart = $fh->tell(); + my $type = $_->{'type'}; + my $coverage = $type; + $coverage += 0x4000 if $_->{'direction'} eq 'RL'; + $coverage += 0x2000 if $_->{'orientation'} eq 'VH'; + $coverage += 0x8000 if $_->{'orientation'} eq 'V'; + + $fh->print(TTF_Pack("SSL", 0, $coverage, $_->{'subFeatureFlags'})); # placeholder for length + + if ($type == 0) { # rearrangement + AAT_write_state_table($fh, $_->{'classes'}, $_->{'states'}, 0); + } + + elsif ($type == 1) { # contextual + my $stHeader = $fh->tell(); + $fh->print(pack("nnnnn", (0) x 5)); # placeholders for stateSize, classTable, stateArray, entryTable, mappingTables + + my $classTable = $fh->tell() - $stHeader; + my $classes = $_->{'classes'}; + AAT_write_classes($fh, $classes); + + my $stateArray = $fh->tell() - $stHeader; + my $states = $_->{'states'}; + my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states, + sub { + my $actions = $_->{'actions'}; + ( $_->{'flags'}, @$actions ) + } + ); + + my $entryTable = $fh->tell() - $stHeader; + my $offset = ($entryTable + 8 * @$entries) / 2; + foreach (@$entries) { + my ($nextState, $flags, @parts) = split /,/; + $fh->print(pack("nnnn", $nextState, $flags, map { $_ eq "" ? 0 : $_ + $offset } @parts)); + } + + my $mappingTables = $fh->tell() - $stHeader; + my $mappings = $_->{'mappings'}; + $fh->print(pack("n*", @$mappings)); + + my $loc = $fh->tell(); + $fh->seek($stHeader, IO::File::SEEK_SET); + $fh->print(pack("nnnnn", $stateSize, $classTable, $stateArray, $entryTable, $mappingTables)); + $fh->seek($loc, IO::File::SEEK_SET); + } + + elsif ($type == 2) { # ligature + my $stHeader = $fh->tell(); + $fh->print(pack("nnnnnnn", (0) x 7)); # placeholders for stateSize, classTable, stateArray, entryTable, actionLists, components, ligatures + + my $classTable = $fh->tell() - $stHeader; + my $classes = $_->{'classes'}; + AAT_write_classes($fh, $classes); + + my $stateArray = $fh->tell() - $stHeader; + my $states = $_->{'states'}; + + my ($stateSize, $entries) = AAT_write_states($fh, $classes, $stateArray, $states, + sub { + ( $_->{'flags'} & 0xc000, $_->{'actions'} ) + } + ); + + my $actionLists = $_->{'actionLists'}; + my %actionListOffset; + my $actionListDataLength = 0; + my @actionListEntries; + foreach (0 .. $#$entries) { + my ($nextState, $flags, $offset) = split(/,/, $entries->[$_]); + if ($offset eq "") { + $offset = undef; + } + else { + if (defined $actionListOffset{$offset}) { + $offset = $actionListOffset{$offset}; + } + else { + $actionListOffset{$offset} = $actionListDataLength; + my $list = $actionLists->[$offset]; + $actionListDataLength += 4 * @$list; + push @actionListEntries, $list; + $offset = $actionListOffset{$offset}; + } + } + $entries->[$_] = [ $nextState, $flags, $offset ]; + } + my $entryTable = $fh->tell() - $stHeader; + my $ligActionLists = ($entryTable + @$entries * 4 + 3) & ~3; + foreach (@$entries) { + $_->[2] += $ligActionLists if defined $_->[2]; + $fh->print(pack("nn", $_->[0], $_->[1] + $_->[2])); + } + $fh->print(pack("C*", (0) x ($ligActionLists - $entryTable - @$entries * 4))); + + die "internal error" if $fh->tell() != $ligActionLists + $stHeader; + + my $componentTable = $fh->tell() - $stHeader + $actionListDataLength; + my $actionList; + foreach $actionList (@actionListEntries) { + foreach (0 .. $#$actionList) { + my $action = $actionList->[$_]; + my $val = $action->{'component'} + $componentTable / 2; + $val += 0x40000000 if $val < 0; + $val &= 0x3fffffff; + $val |= 0x40000000 if $action->{'store'}; + $val |= 0x80000000 if $_ == $#$actionList; + $fh->print(pack("N", $val)); + } + } + + die "internal error" if $fh->tell() != $componentTable + $stHeader; + + my $components = $_->{'components'}; + my $ligatureTable = $componentTable + @$components * 2; + $fh->print(pack("n*", map { (index($_, '+') >= 0 ? $ligatureTable : 0) + $_ } @$components)); + + my $ligatures = $_->{'ligatures'}; + $fh->print(pack("n*", @$ligatures)); + + my $loc = $fh->tell(); + $fh->seek($stHeader, IO::File::SEEK_SET); + $fh->print(pack("nnnnnnn", $stateSize, $classTable, $stateArray, $entryTable, $ligActionLists, $componentTable, $ligatureTable)); + $fh->seek($loc, IO::File::SEEK_SET); + } + + elsif ($type == 4) { # non-contextual + AAT_write_lookup($fh, $_->{'format'}, $_->{'lookup'}, 2, undef); + } + + elsif ($type == 5) { # insertion + } + + else { + die "unknown subtable type"; + } + + my $length = $fh->tell() - $subtableStart; + my $padBytes = (4 - ($length & 3)) & 3; + $fh->print(pack("C*", (0) x $padBytes)); + $length += $padBytes; + $fh->seek($subtableStart, IO::File::SEEK_SET); + $fh->print(pack("n", $length)); + $fh->seek($subtableStart + $length, IO::File::SEEK_SET); + } + + my $chainLength = $fh->tell() - $chainStart; + $fh->seek($chainStart + 4, IO::File::SEEK_SET); + $fh->print(pack("N", $chainLength)); + $fh->seek($chainStart + $chainLength, IO::File::SEEK_SET); + } +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + + $self->read; + my $feat = $self->{' PARENT'}->{'feat'}; + $feat->read; + my $post = $self->{' PARENT'}->{'post'}; + $post->read; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\n", $self->{'version'}); + + my $chains = $self->{'chains'}; + foreach (@$chains) { + my $defaultFlags = $_->{'defaultFlags'}; + $fh->printf("chain: defaultFlags = %08x\n", $defaultFlags); + + my $featureEntries = $_->{'featureEntries'}; + foreach (@$featureEntries) { + $fh->printf("\tfeature %d, setting %d : enableFlags = %08x, disableFlags = %08x # '%s: %s'\n", + $_->{'type'}, $_->{'setting'}, $_->{'enable'}, $_->{'disable'}, + $feat->settingName($_->{'type'}, $_->{'setting'})); + } + + my $subtables = $_->{'subtables'}; + foreach (@$subtables) { + my $type = $_->{'type'}; + my $subFeatureFlags = $_->{'subFeatureFlags'}; + $fh->printf("\n\t%s table, %s, %s, subFeatureFlags = %08x # %s (%s)\n", + subtable_type_($type), $_->{'direction'}, $_->{'orientation'}, $subFeatureFlags, + "Default " . ((($subFeatureFlags & $defaultFlags) != 0) ? "On" : "Off"), + join(", ", + map { + join(": ", $feat->settingName($_->{'type'}, $_->{'setting'}) ) + } grep { ($_->{'enable'} & $subFeatureFlags) != 0 } @$featureEntries + ) ); + + if ($type == 0) { # rearrangement + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + my @verbs = ( "0", "Ax->xA", "xD->Dx", "AxD->DxA", + "ABx->xAB", "ABx->xBA", "xCD->CDx", "xCD->DCx", + "AxCD->CDxA", "AxCD->DCxA", "ABxD->DxAB", "ABxD->DxBA", + "ABxCD->CDxAB", "ABxCD->CDxBA", "ABxCD->DCxAB", "ABxCD->DCxBA"); + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "<" if ($_->{'flags'} & 0x8000); + $flags .= ">" if ($_->{'flags'} & 0x2000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, $verbs[($_->{'flags'} & 0x000f)]); + } + $fh->print("\n"); + } + } + + elsif ($type == 1) { # contextual + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $mappings = $_->{'mappings'}; + foreach (0 .. $#$mappings) { + $fh->printf("\t\tMapping %d: %d [%s]\n", $_, $mappings->[$_], $post->{'VAL'}[$mappings->[$_]]); + } + } + + elsif ($type == 2) { # ligature + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + $fh->printf("\t(%s%d,%s)", $flags, $_->{'nextState'}, defined $_->{'actions'} ? $_->{'actions'} : "="); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $actionLists = $_->{'actionLists'}; + foreach (0 .. $#$actionLists) { + $fh->printf("\t\tList %d:\t", $_); + my $actionList = $actionLists->[$_]; + $fh->printf("%s\n", join(", ", map { ($_->{'component'} . ($_->{'store'} ? "*" : "") ) } @$actionList)); + } + + my $ligatureTable = $_->{'ligatureTable'}; + + $fh->print("\n"); + my $components = $_->{'components'}; + foreach (0 .. $#$components) { + $fh->printf("\t\tComponent %d: %s\n", $_, $components->[$_]); + } + + $fh->print("\n"); + my $ligatures = $_->{'ligatures'}; + foreach (0 .. $#$ligatures) { + $fh->printf("\t\tLigature %d: %d [%s]\n", $_, $ligatures->[$_], $post->{'VAL'}[$ligatures->[$_]]); + } + } + + elsif ($type == 4) { # non-contextual + my $lookup = $_->{'lookup'}; + $fh->printf("\t\tLookup format %d\n", $_->{'format'}); + if (defined $lookup) { + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\t\t\t%d [%s] -> %d [%s])\n", $_, $post->{'VAL'}[$_], $lookup->{$_}, $post->{'VAL'}[$lookup->{$_}]); + } + } + } + + elsif ($type == 5) { # insertion + print_classes_($fh, $_, $post); + + $fh->print("\n"); + my $states = $_->{'states'}; + foreach (0 .. $#$states) { + $fh->printf("\t\tState %d:", $_); + my $state = $states->[$_]; + foreach (@$state) { + my $flags; + $flags .= "!" if ($_->{'flags'} & 0x4000); + $flags .= "*" if ($_->{'flags'} & 0x8000); + my $actions = $_->{'actions'}; + $fh->printf("\t(%s%d,%s,%s)", $flags, $_->{'nextState'}, map { defined $_ ? $_ : "=" } @$actions); + } + $fh->print("\n"); + } + + $fh->print("\n"); + my $insertLists = $_->{'insertLists'}; + foreach (0 .. $#$insertLists) { + my $insertList = $insertLists->[$_]; + $fh->printf("\t\tList %d: %s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$insertList)); + } + } + + else { + # unknown + } + } + } +} + +sub print_classes_ +{ + my ($fh, $subtable, $post) = @_; + + my $classes = $subtable->{'classes'}; + foreach (0 .. $#$classes) { + my $class = $classes->[$_]; + if (defined $class) { + $fh->printf("\t\tClass %d:\t%s\n", $_, join(", ", map { $_ . " [" . $post->{'VAL'}[$_] . "]" } @$class)); + } + } +} + +sub subtable_type_ +{ + my ($val) = @_; + my ($res); + + my @types = ( + 'Rearrangement', + 'Contextual', + 'Ligature', + undef, + 'Non-contextual', + 'Insertion', + ); + $res = $types[$val] or ('Undefined (' . $val . ')'); + + $res; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/PCLT.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/PCLT.pm new file mode 100644 index 0000000000..d9a2c6f19e --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/PCLT.pm @@ -0,0 +1,143 @@ +package Font::TTF::PCLT; + +=head1 NAME + +Font::TTF::PCLT - PCLT TrueType font table + +=head1 DESCRIPTION + +The PCLT table holds various pieces HP-PCL specific information. Information +here is generally not used by other software, except for the xHeight and +CapHeight which are stored here (if the table exists in a font). + +=head1 INSTANCE VARIABLES + +Only from table and the standard: + + version + FontNumber + Pitch + xHeight + Style + TypeFamily + CapHeight + SymbolSet + Typeface + CharacterComplement + FileName + StrokeWeight + WidthType + SerifStyle + +Notice that C, C and C return arrays +of unsigned characters of the appropriate length + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'FontNumber' => 'L', + 'Pitch' => 'S', + 'xHeight' => 'S', + 'Style' => 'S', + 'TypeFamily' => 'S', + 'CapHeight' => 'S', + 'SymbolSet' => 'S', + 'Typeface' => 'C16', + 'CharacterComplement' => 'C8', + 'FileName' => 'C6', + 'StrokeWeight' => 'C', + 'WidthType' => 'C', + 'SerifStyle' => 'c'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory thanks to some utility functions + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read || return $self; + + init unless defined $fields{'xHeight'}; + $self->{' INFILE'}->read($dat, 54); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + $fh->print(TTF_Out_Fields($self, \%fields, 54)); +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 54; +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/PSNames.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/PSNames.pm new file mode 100644 index 0000000000..686889e6b6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/PSNames.pm @@ -0,0 +1,4458 @@ +package Font::TTF::PSNames; + +=head1 NAME + +Font::TTF::PSNames - Utilities for Postscript glyph name processing + +=head1 SYNOPSIS + + use Font::TTF::PSNames qw(parse lookup); + $name = lookup($uni); + $uni = parse($name); + +=head1 METHODS + +=cut + +use strict; +use vars qw(%names %agl @EXPORT_OK @ISA); +require Exporter; +@ISA = qw( Exporter ); +@EXPORT_OK = qw( parse lookup); + +# Adobe Glyph List for New Fonts +# from http://partners.adobe.com/asn/tech/type/aglfn13.txt + +%names = ( + '0020' => 'space', + '0021' => 'exclam', + '0022' => 'quotedbl', + '0023' => 'numbersign', + '0024' => 'dollar', + '0025' => 'percent', + '0026' => 'ampersand', + '0027' => 'quotesingle', + '0028' => 'parenleft', + '0029' => 'parenright', + '002A' => 'asterisk', + '002B' => 'plus', + '002C' => 'comma', + '002D' => 'hyphen', + '002E' => 'period', + '002F' => 'slash', + '0030' => 'zero', + '0031' => 'one', + '0032' => 'two', + '0033' => 'three', + '0034' => 'four', + '0035' => 'five', + '0036' => 'six', + '0037' => 'seven', + '0038' => 'eight', + '0039' => 'nine', + '003A' => 'colon', + '003B' => 'semicolon', + '003C' => 'less', + '003D' => 'equal', + '003E' => 'greater', + '003F' => 'question', + '0040' => 'at', + '0041' => 'A', + '0042' => 'B', + '0043' => 'C', + '0044' => 'D', + '0045' => 'E', + '0046' => 'F', + '0047' => 'G', + '0048' => 'H', + '0049' => 'I', + '004A' => 'J', + '004B' => 'K', + '004C' => 'L', + '004D' => 'M', + '004E' => 'N', + '004F' => 'O', + '0050' => 'P', + '0051' => 'Q', + '0052' => 'R', + '0053' => 'S', + '0054' => 'T', + '0055' => 'U', + '0056' => 'V', + '0057' => 'W', + '0058' => 'X', + '0059' => 'Y', + '005A' => 'Z', + '005B' => 'bracketleft', + '005C' => 'backslash', + '005D' => 'bracketright', + '005E' => 'asciicircum', + '005F' => 'underscore', + '0060' => 'grave', + '0061' => 'a', + '0062' => 'b', + '0063' => 'c', + '0064' => 'd', + '0065' => 'e', + '0066' => 'f', + '0067' => 'g', + '0068' => 'h', + '0069' => 'i', + '006A' => 'j', + '006B' => 'k', + '006C' => 'l', + '006D' => 'm', + '006E' => 'n', + '006F' => 'o', + '0070' => 'p', + '0071' => 'q', + '0072' => 'r', + '0073' => 's', + '0074' => 't', + '0075' => 'u', + '0076' => 'v', + '0077' => 'w', + '0078' => 'x', + '0079' => 'y', + '007A' => 'z', + '007B' => 'braceleft', + '007C' => 'bar', + '007D' => 'braceright', + '007E' => 'asciitilde', +# '00A0' => 'space', + '00A1' => 'exclamdown', + '00A2' => 'cent', + '00A3' => 'sterling', + '00A4' => 'currency', + '00A5' => 'yen', + '00A6' => 'brokenbar', + '00A7' => 'section', + '00A8' => 'dieresis', + '00A9' => 'copyright', + '00AA' => 'ordfeminine', + '00AB' => 'guillemotleft', + '00AC' => 'logicalnot', +# '00AD' => 'hyphen', + '00AE' => 'registered', + '00AF' => 'macron', + '00B0' => 'degree', + '00B1' => 'plusminus', + '00B2' => 'twosuperior', + '00B3' => 'threesuperior', + '00B4' => 'acute', + '00B5' => 'mu', + '00B6' => 'paragraph', + '00B7' => 'periodcentered', + '00B8' => 'cedilla', + '00B9' => 'onesuperior', + '00BA' => 'ordmasculine', + '00BB' => 'guillemotright', + '00BC' => 'onequarter', + '00BD' => 'onehalf', + '00BE' => 'threequarters', + '00BF' => 'questiondown', + '00C0' => 'Agrave', + '00C1' => 'Aacute', + '00C2' => 'Acircumflex', + '00C3' => 'Atilde', + '00C4' => 'Adieresis', + '00C5' => 'Aring', + '00C6' => 'AE', + '00C7' => 'Ccedilla', + '00C8' => 'Egrave', + '00C9' => 'Eacute', + '00CA' => 'Ecircumflex', + '00CB' => 'Edieresis', + '00CC' => 'Igrave', + '00CD' => 'Iacute', + '00CE' => 'Icircumflex', + '00CF' => 'Idieresis', + '00D0' => 'Eth', + '00D1' => 'Ntilde', + '00D2' => 'Ograve', + '00D3' => 'Oacute', + '00D4' => 'Ocircumflex', + '00D5' => 'Otilde', + '00D6' => 'Odieresis', + '00D7' => 'multiply', + '00D8' => 'Oslash', + '00D9' => 'Ugrave', + '00DA' => 'Uacute', + '00DB' => 'Ucircumflex', + '00DC' => 'Udieresis', + '00DD' => 'Yacute', + '00DE' => 'Thorn', + '00DF' => 'germandbls', + '00E0' => 'agrave', + '00E1' => 'aacute', + '00E2' => 'acircumflex', + '00E3' => 'atilde', + '00E4' => 'adieresis', + '00E5' => 'aring', + '00E6' => 'ae', + '00E7' => 'ccedilla', + '00E8' => 'egrave', + '00E9' => 'eacute', + '00EA' => 'ecircumflex', + '00EB' => 'edieresis', + '00EC' => 'igrave', + '00ED' => 'iacute', + '00EE' => 'icircumflex', + '00EF' => 'idieresis', + '00F0' => 'eth', + '00F1' => 'ntilde', + '00F2' => 'ograve', + '00F3' => 'oacute', + '00F4' => 'ocircumflex', + '00F5' => 'otilde', + '00F6' => 'odieresis', + '00F7' => 'divide', + '00F8' => 'oslash', + '00F9' => 'ugrave', + '00FA' => 'uacute', + '00FB' => 'ucircumflex', + '00FC' => 'udieresis', + '00FD' => 'yacute', + '00FE' => 'thorn', + '00FF' => 'ydieresis', + '0100' => 'Amacron', + '0101' => 'amacron', + '0102' => 'Abreve', + '0103' => 'abreve', + '0104' => 'Aogonek', + '0105' => 'aogonek', + '0106' => 'Cacute', + '0107' => 'cacute', + '0108' => 'Ccircumflex', + '0109' => 'ccircumflex', + '010A' => 'Cdotaccent', + '010B' => 'cdotaccent', + '010C' => 'Ccaron', + '010D' => 'ccaron', + '010E' => 'Dcaron', + '010F' => 'dcaron', + '0110' => 'Dcroat', + '0111' => 'dcroat', + '0112' => 'Emacron', + '0113' => 'emacron', + '0114' => 'Ebreve', + '0115' => 'ebreve', + '0116' => 'Edotaccent', + '0117' => 'edotaccent', + '0118' => 'Eogonek', + '0119' => 'eogonek', + '011A' => 'Ecaron', + '011B' => 'ecaron', + '011C' => 'Gcircumflex', + '011D' => 'gcircumflex', + '011E' => 'Gbreve', + '011F' => 'gbreve', + '0120' => 'Gdotaccent', + '0121' => 'gdotaccent', + '0122' => 'Gcommaaccent', + '0123' => 'gcommaaccent', + '0124' => 'Hcircumflex', + '0125' => 'hcircumflex', + '0126' => 'Hbar', + '0127' => 'hbar', + '0128' => 'Itilde', + '0129' => 'itilde', + '012A' => 'Imacron', + '012B' => 'imacron', + '012C' => 'Ibreve', + '012D' => 'ibreve', + '012E' => 'Iogonek', + '012F' => 'iogonek', + '0130' => 'Idotaccent', + '0131' => 'dotlessi', + '0132' => 'IJ', + '0133' => 'ij', + '0134' => 'Jcircumflex', + '0135' => 'jcircumflex', + '0136' => 'Kcommaaccent', + '0137' => 'kcommaaccent', + '0138' => 'kgreenlandic', + '0139' => 'Lacute', + '013A' => 'lacute', + '013B' => 'Lcommaaccent', + '013C' => 'lcommaaccent', + '013D' => 'Lcaron', + '013E' => 'lcaron', + '013F' => 'Ldot', + '0140' => 'ldot', + '0141' => 'Lslash', + '0142' => 'lslash', + '0143' => 'Nacute', + '0144' => 'nacute', + '0145' => 'Ncommaaccent', + '0146' => 'ncommaaccent', + '0147' => 'Ncaron', + '0148' => 'ncaron', + '0149' => 'napostrophe', + '014A' => 'Eng', + '014B' => 'eng', + '014C' => 'Omacron', + '014D' => 'omacron', + '014E' => 'Obreve', + '014F' => 'obreve', + '0150' => 'Ohungarumlaut', + '0151' => 'ohungarumlaut', + '0152' => 'OE', + '0153' => 'oe', + '0154' => 'Racute', + '0155' => 'racute', + '0156' => 'Rcommaaccent', + '0157' => 'rcommaaccent', + '0158' => 'Rcaron', + '0159' => 'rcaron', + '015A' => 'Sacute', + '015B' => 'sacute', + '015C' => 'Scircumflex', + '015D' => 'scircumflex', + '015E' => 'Scedilla', + '015F' => 'scedilla', + '0160' => 'Scaron', + '0161' => 'scaron', + '0162' => 'Tcommaaccent', + '0163' => 'tcommaaccent', + '0164' => 'Tcaron', + '0165' => 'tcaron', + '0166' => 'Tbar', + '0167' => 'tbar', + '0168' => 'Utilde', + '0169' => 'utilde', + '016A' => 'Umacron', + '016B' => 'umacron', + '016C' => 'Ubreve', + '016D' => 'ubreve', + '016E' => 'Uring', + '016F' => 'uring', + '0170' => 'Uhungarumlaut', + '0171' => 'uhungarumlaut', + '0172' => 'Uogonek', + '0173' => 'uogonek', + '0174' => 'Wcircumflex', + '0175' => 'wcircumflex', + '0176' => 'Ycircumflex', + '0177' => 'ycircumflex', + '0178' => 'Ydieresis', + '0179' => 'Zacute', + '017A' => 'zacute', + '017B' => 'Zdotaccent', + '017C' => 'zdotaccent', + '017D' => 'Zcaron', + '017E' => 'zcaron', + '017F' => 'longs', + '0192' => 'florin', + '01A0' => 'Ohorn', + '01A1' => 'ohorn', + '01AF' => 'Uhorn', + '01B0' => 'uhorn', + '01E6' => 'Gcaron', + '01E7' => 'gcaron', + '01FA' => 'Aringacute', + '01FB' => 'aringacute', + '01FC' => 'AEacute', + '01FD' => 'aeacute', + '01FE' => 'Oslashacute', + '01FF' => 'oslashacute', + '0218' => 'Scommaaccent', + '0219' => 'scommaaccent', +# '021A' => 'Tcommaaccent', +# '021B' => 'tcommaaccent', + '02BC' => 'afii57929', + '02BD' => 'afii64937', + '02C6' => 'circumflex', + '02C7' => 'caron', +# '02C9' => 'macron', + '02D8' => 'breve', + '02D9' => 'dotaccent', + '02DA' => 'ring', + '02DB' => 'ogonek', + '02DC' => 'tilde', + '02DD' => 'hungarumlaut', + '0300' => 'gravecomb', + '0301' => 'acutecomb', + '0303' => 'tildecomb', + '0309' => 'hookabovecomb', + '0323' => 'dotbelowcomb', + '0384' => 'tonos', + '0385' => 'dieresistonos', + '0386' => 'Alphatonos', + '0387' => 'anoteleia', + '0388' => 'Epsilontonos', + '0389' => 'Etatonos', + '038A' => 'Iotatonos', + '038C' => 'Omicrontonos', + '038E' => 'Upsilontonos', + '038F' => 'Omegatonos', + '0390' => 'iotadieresistonos', + '0391' => 'Alpha', + '0392' => 'Beta', + '0393' => 'Gamma', +# '0394' => 'Delta', + '0395' => 'Epsilon', + '0396' => 'Zeta', + '0397' => 'Eta', + '0398' => 'Theta', + '0399' => 'Iota', + '039A' => 'Kappa', + '039B' => 'Lambda', + '039C' => 'Mu', + '039D' => 'Nu', + '039E' => 'Xi', + '039F' => 'Omicron', + '03A0' => 'Pi', + '03A1' => 'Rho', + '03A3' => 'Sigma', + '03A4' => 'Tau', + '03A5' => 'Upsilon', + '03A6' => 'Phi', + '03A7' => 'Chi', + '03A8' => 'Psi', +# '03A9' => 'Omega', + '03AA' => 'Iotadieresis', + '03AB' => 'Upsilondieresis', + '03AC' => 'alphatonos', + '03AD' => 'epsilontonos', + '03AE' => 'etatonos', + '03AF' => 'iotatonos', + '03B0' => 'upsilondieresistonos', + '03B1' => 'alpha', + '03B2' => 'beta', + '03B3' => 'gamma', + '03B4' => 'delta', + '03B5' => 'epsilon', + '03B6' => 'zeta', + '03B7' => 'eta', + '03B8' => 'theta', + '03B9' => 'iota', + '03BA' => 'kappa', + '03BB' => 'lambda', +# '03BC' => 'mu', + '03BD' => 'nu', + '03BE' => 'xi', + '03BF' => 'omicron', + '03C0' => 'pi', + '03C1' => 'rho', + '03C2' => 'sigma1', + '03C3' => 'sigma', + '03C4' => 'tau', + '03C5' => 'upsilon', + '03C6' => 'phi', + '03C7' => 'chi', + '03C8' => 'psi', + '03C9' => 'omega', + '03CA' => 'iotadieresis', + '03CB' => 'upsilondieresis', + '03CC' => 'omicrontonos', + '03CD' => 'upsilontonos', + '03CE' => 'omegatonos', + '03D1' => 'theta1', + '03D2' => 'Upsilon1', + '03D5' => 'phi1', + '03D6' => 'omega1', + '0401' => 'afii10023', + '0402' => 'afii10051', + '0403' => 'afii10052', + '0404' => 'afii10053', + '0405' => 'afii10054', + '0406' => 'afii10055', + '0407' => 'afii10056', + '0408' => 'afii10057', + '0409' => 'afii10058', + '040A' => 'afii10059', + '040B' => 'afii10060', + '040C' => 'afii10061', + '040E' => 'afii10062', + '040F' => 'afii10145', + '0410' => 'afii10017', + '0411' => 'afii10018', + '0412' => 'afii10019', + '0413' => 'afii10020', + '0414' => 'afii10021', + '0415' => 'afii10022', + '0416' => 'afii10024', + '0417' => 'afii10025', + '0418' => 'afii10026', + '0419' => 'afii10027', + '041A' => 'afii10028', + '041B' => 'afii10029', + '041C' => 'afii10030', + '041D' => 'afii10031', + '041E' => 'afii10032', + '041F' => 'afii10033', + '0420' => 'afii10034', + '0421' => 'afii10035', + '0422' => 'afii10036', + '0423' => 'afii10037', + '0424' => 'afii10038', + '0425' => 'afii10039', + '0426' => 'afii10040', + '0427' => 'afii10041', + '0428' => 'afii10042', + '0429' => 'afii10043', + '042A' => 'afii10044', + '042B' => 'afii10045', + '042C' => 'afii10046', + '042D' => 'afii10047', + '042E' => 'afii10048', + '042F' => 'afii10049', + '0430' => 'afii10065', + '0431' => 'afii10066', + '0432' => 'afii10067', + '0433' => 'afii10068', + '0434' => 'afii10069', + '0435' => 'afii10070', + '0436' => 'afii10072', + '0437' => 'afii10073', + '0438' => 'afii10074', + '0439' => 'afii10075', + '043A' => 'afii10076', + '043B' => 'afii10077', + '043C' => 'afii10078', + '043D' => 'afii10079', + '043E' => 'afii10080', + '043F' => 'afii10081', + '0440' => 'afii10082', + '0441' => 'afii10083', + '0442' => 'afii10084', + '0443' => 'afii10085', + '0444' => 'afii10086', + '0445' => 'afii10087', + '0446' => 'afii10088', + '0447' => 'afii10089', + '0448' => 'afii10090', + '0449' => 'afii10091', + '044A' => 'afii10092', + '044B' => 'afii10093', + '044C' => 'afii10094', + '044D' => 'afii10095', + '044E' => 'afii10096', + '044F' => 'afii10097', + '0451' => 'afii10071', + '0452' => 'afii10099', + '0453' => 'afii10100', + '0454' => 'afii10101', + '0455' => 'afii10102', + '0456' => 'afii10103', + '0457' => 'afii10104', + '0458' => 'afii10105', + '0459' => 'afii10106', + '045A' => 'afii10107', + '045B' => 'afii10108', + '045C' => 'afii10109', + '045E' => 'afii10110', + '045F' => 'afii10193', + '0462' => 'afii10146', + '0463' => 'afii10194', + '0472' => 'afii10147', + '0473' => 'afii10195', + '0474' => 'afii10148', + '0475' => 'afii10196', + '0490' => 'afii10050', + '0491' => 'afii10098', + '04D9' => 'afii10846', + '05B0' => 'afii57799', + '05B1' => 'afii57801', + '05B2' => 'afii57800', + '05B3' => 'afii57802', + '05B4' => 'afii57793', + '05B5' => 'afii57794', + '05B6' => 'afii57795', + '05B7' => 'afii57798', + '05B8' => 'afii57797', + '05B9' => 'afii57806', + '05BB' => 'afii57796', + '05BC' => 'afii57807', + '05BD' => 'afii57839', + '05BE' => 'afii57645', + '05BF' => 'afii57841', + '05C0' => 'afii57842', + '05C1' => 'afii57804', + '05C2' => 'afii57803', + '05C3' => 'afii57658', + '05D0' => 'afii57664', + '05D1' => 'afii57665', + '05D2' => 'afii57666', + '05D3' => 'afii57667', + '05D4' => 'afii57668', + '05D5' => 'afii57669', + '05D6' => 'afii57670', + '05D7' => 'afii57671', + '05D8' => 'afii57672', + '05D9' => 'afii57673', + '05DA' => 'afii57674', + '05DB' => 'afii57675', + '05DC' => 'afii57676', + '05DD' => 'afii57677', + '05DE' => 'afii57678', + '05DF' => 'afii57679', + '05E0' => 'afii57680', + '05E1' => 'afii57681', + '05E2' => 'afii57682', + '05E3' => 'afii57683', + '05E4' => 'afii57684', + '05E5' => 'afii57685', + '05E6' => 'afii57686', + '05E7' => 'afii57687', + '05E8' => 'afii57688', + '05E9' => 'afii57689', + '05EA' => 'afii57690', + '05F0' => 'afii57716', + '05F1' => 'afii57717', + '05F2' => 'afii57718', + '060C' => 'afii57388', + '061B' => 'afii57403', + '061F' => 'afii57407', + '0621' => 'afii57409', + '0622' => 'afii57410', + '0623' => 'afii57411', + '0624' => 'afii57412', + '0625' => 'afii57413', + '0626' => 'afii57414', + '0627' => 'afii57415', + '0628' => 'afii57416', + '0629' => 'afii57417', + '062A' => 'afii57418', + '062B' => 'afii57419', + '062C' => 'afii57420', + '062D' => 'afii57421', + '062E' => 'afii57422', + '062F' => 'afii57423', + '0630' => 'afii57424', + '0631' => 'afii57425', + '0632' => 'afii57426', + '0633' => 'afii57427', + '0634' => 'afii57428', + '0635' => 'afii57429', + '0636' => 'afii57430', + '0637' => 'afii57431', + '0638' => 'afii57432', + '0639' => 'afii57433', + '063A' => 'afii57434', + '0640' => 'afii57440', + '0641' => 'afii57441', + '0642' => 'afii57442', + '0643' => 'afii57443', + '0644' => 'afii57444', + '0645' => 'afii57445', + '0646' => 'afii57446', + '0647' => 'afii57470', + '0648' => 'afii57448', + '0649' => 'afii57449', + '064A' => 'afii57450', + '064B' => 'afii57451', + '064C' => 'afii57452', + '064D' => 'afii57453', + '064E' => 'afii57454', + '064F' => 'afii57455', + '0650' => 'afii57456', + '0651' => 'afii57457', + '0652' => 'afii57458', + '0660' => 'afii57392', + '0661' => 'afii57393', + '0662' => 'afii57394', + '0663' => 'afii57395', + '0664' => 'afii57396', + '0665' => 'afii57397', + '0666' => 'afii57398', + '0667' => 'afii57399', + '0668' => 'afii57400', + '0669' => 'afii57401', + '066A' => 'afii57381', + '066D' => 'afii63167', + '0679' => 'afii57511', + '067E' => 'afii57506', + '0686' => 'afii57507', + '0688' => 'afii57512', + '0691' => 'afii57513', + '0698' => 'afii57508', + '06A4' => 'afii57505', + '06AF' => 'afii57509', + '06BA' => 'afii57514', + '06D2' => 'afii57519', + '06D5' => 'afii57534', + '1E80' => 'Wgrave', + '1E81' => 'wgrave', + '1E82' => 'Wacute', + '1E83' => 'wacute', + '1E84' => 'Wdieresis', + '1E85' => 'wdieresis', + '1EF2' => 'Ygrave', + '1EF3' => 'ygrave', + '200C' => 'afii61664', + '200D' => 'afii301', + '200E' => 'afii299', + '200F' => 'afii300', + '2012' => 'figuredash', + '2013' => 'endash', + '2014' => 'emdash', + '2015' => 'afii00208', + '2017' => 'underscoredbl', + '2018' => 'quoteleft', + '2019' => 'quoteright', + '201A' => 'quotesinglbase', + '201B' => 'quotereversed', + '201C' => 'quotedblleft', + '201D' => 'quotedblright', + '201E' => 'quotedblbase', + '2020' => 'dagger', + '2021' => 'daggerdbl', + '2022' => 'bullet', + '2024' => 'onedotenleader', + '2025' => 'twodotenleader', + '2026' => 'ellipsis', + '202C' => 'afii61573', + '202D' => 'afii61574', + '202E' => 'afii61575', + '2030' => 'perthousand', + '2032' => 'minute', + '2033' => 'second', + '2039' => 'guilsinglleft', + '203A' => 'guilsinglright', + '203C' => 'exclamdbl', + '2044' => 'fraction', +# '2070' => 'zerosuperior', +# '2074' => 'foursuperior', +# '2075' => 'fivesuperior', +# '2076' => 'sixsuperior', +# '2077' => 'sevensuperior', +# '2078' => 'eightsuperior', +# '2079' => 'ninesuperior', +# '207D' => 'parenleftsuperior', +# '207E' => 'parenrightsuperior', +# '207F' => 'nsuperior', +# '2080' => 'zeroinferior', +# '2081' => 'oneinferior', +# '2082' => 'twoinferior', +# '2083' => 'threeinferior', +# '2084' => 'fourinferior', +# '2085' => 'fiveinferior', +# '2086' => 'sixinferior', +# '2087' => 'seveninferior', +# '2088' => 'eightinferior', +# '2089' => 'nineinferior', +# '208D' => 'parenleftinferior', +# '208E' => 'parenrightinferior', + '20A1' => 'colonmonetary', + '20A3' => 'franc', + '20A4' => 'lira', + '20A7' => 'peseta', + '20AA' => 'afii57636', + '20AB' => 'dong', + '20AC' => 'Euro', + '2105' => 'afii61248', + '2111' => 'Ifraktur', + '2113' => 'afii61289', + '2116' => 'afii61352', + '2118' => 'weierstrass', + '211C' => 'Rfraktur', + '211E' => 'prescription', + '2122' => 'trademark', + '2126' => 'Omega', + '212E' => 'estimated', + '2135' => 'aleph', + '2153' => 'onethird', + '2154' => 'twothirds', + '215B' => 'oneeighth', + '215C' => 'threeeighths', + '215D' => 'fiveeighths', + '215E' => 'seveneighths', + '2190' => 'arrowleft', + '2191' => 'arrowup', + '2192' => 'arrowright', + '2193' => 'arrowdown', + '2194' => 'arrowboth', + '2195' => 'arrowupdn', + '21A8' => 'arrowupdnbse', + '21B5' => 'carriagereturn', + '21D0' => 'arrowdblleft', + '21D1' => 'arrowdblup', + '21D2' => 'arrowdblright', + '21D3' => 'arrowdbldown', + '21D4' => 'arrowdblboth', + '2200' => 'universal', + '2202' => 'partialdiff', + '2203' => 'existential', + '2205' => 'emptyset', + '2206' => 'Delta', + '2207' => 'gradient', + '2208' => 'element', + '2209' => 'notelement', + '220B' => 'suchthat', + '220F' => 'product', + '2211' => 'summation', + '2212' => 'minus', +# '2215' => 'fraction', + '2217' => 'asteriskmath', +# '2219' => 'periodcentered', + '221A' => 'radical', + '221D' => 'proportional', + '221E' => 'infinity', + '221F' => 'orthogonal', + '2220' => 'angle', + '2227' => 'logicaland', + '2228' => 'logicalor', + '2229' => 'intersection', + '222A' => 'union', + '222B' => 'integral', + '2234' => 'therefore', + '223C' => 'similar', + '2245' => 'congruent', + '2248' => 'approxequal', + '2260' => 'notequal', + '2261' => 'equivalence', + '2264' => 'lessequal', + '2265' => 'greaterequal', + '2282' => 'propersubset', + '2283' => 'propersuperset', + '2284' => 'notsubset', + '2286' => 'reflexsubset', + '2287' => 'reflexsuperset', + '2295' => 'circleplus', + '2297' => 'circlemultiply', + '22A5' => 'perpendicular', + '22C5' => 'dotmath', + '2302' => 'house', + '2310' => 'revlogicalnot', + '2320' => 'integraltp', + '2321' => 'integralbt', + '2329' => 'angleleft', + '232A' => 'angleright', + '2500' => 'SF100000', + '2502' => 'SF110000', + '250C' => 'SF010000', + '2510' => 'SF030000', + '2514' => 'SF020000', + '2518' => 'SF040000', + '251C' => 'SF080000', + '2524' => 'SF090000', + '252C' => 'SF060000', + '2534' => 'SF070000', + '253C' => 'SF050000', + '2550' => 'SF430000', + '2551' => 'SF240000', + '2552' => 'SF510000', + '2553' => 'SF520000', + '2554' => 'SF390000', + '2555' => 'SF220000', + '2556' => 'SF210000', + '2557' => 'SF250000', + '2558' => 'SF500000', + '2559' => 'SF490000', + '255A' => 'SF380000', + '255B' => 'SF280000', + '255C' => 'SF270000', + '255D' => 'SF260000', + '255E' => 'SF360000', + '255F' => 'SF370000', + '2560' => 'SF420000', + '2561' => 'SF190000', + '2562' => 'SF200000', + '2563' => 'SF230000', + '2564' => 'SF470000', + '2565' => 'SF480000', + '2566' => 'SF410000', + '2567' => 'SF450000', + '2568' => 'SF460000', + '2569' => 'SF400000', + '256A' => 'SF540000', + '256B' => 'SF530000', + '256C' => 'SF440000', + '2580' => 'upblock', + '2584' => 'dnblock', + '2588' => 'block', + '258C' => 'lfblock', + '2590' => 'rtblock', + '2591' => 'ltshade', + '2592' => 'shade', + '2593' => 'dkshade', + '25A0' => 'filledbox', + '25A1' => 'H22073', + '25AA' => 'H18543', + '25AB' => 'H18551', + '25AC' => 'filledrect', + '25B2' => 'triagup', + '25BA' => 'triagrt', + '25BC' => 'triagdn', + '25C4' => 'triaglf', + '25CA' => 'lozenge', + '25CB' => 'circle', + '25CF' => 'H18533', + '25D8' => 'invbullet', + '25D9' => 'invcircle', + '25E6' => 'openbullet', + '263A' => 'smileface', + '263B' => 'invsmileface', + '263C' => 'sun', + '2640' => 'female', + '2642' => 'male', + '2660' => 'spade', + '2663' => 'club', + '2665' => 'heart', + '2666' => 'diamond', + '266A' => 'musicalnote', + '266B' => 'musicalnotedbl', + 'FB00' => 'ff', + 'FB01' => 'fi', + 'FB02' => 'fl', + 'FB03' => 'ffi', + 'FB04' => 'ffl', + 'FB1F' => 'afii57705', + 'FB2A' => 'afii57694', + 'FB2B' => 'afii57695', + 'FB35' => 'afii57723', + 'FB4B' => 'afii57700', +); + +# Adobe Glyph List 2.0 (sans those in glyph list for *new* fonts) -- thus +# these are all historic names that could occur in fonts +# from http://partners.adobe.com/asn/tech/type/glyphlist.txt + +%agl = ( + 'AEmacron' => "\x{01E2}", + 'AEsmall' => "\x{F7E6}", + 'Aacutesmall' => "\x{F7E1}", + 'Abreveacute' => "\x{1EAE}", + 'Abrevecyrillic' => "\x{04D0}", + 'Abrevedotbelow' => "\x{1EB6}", + 'Abrevegrave' => "\x{1EB0}", + 'Abrevehookabove' => "\x{1EB2}", + 'Abrevetilde' => "\x{1EB4}", + 'Acaron' => "\x{01CD}", + 'Acircle' => "\x{24B6}", + 'Acircumflexacute' => "\x{1EA4}", + 'Acircumflexdotbelow' => "\x{1EAC}", + 'Acircumflexgrave' => "\x{1EA6}", + 'Acircumflexhookabove' => "\x{1EA8}", + 'Acircumflexsmall' => "\x{F7E2}", + 'Acircumflextilde' => "\x{1EAA}", + 'Acute' => "\x{F6C9}", + 'Acutesmall' => "\x{F7B4}", + 'Acyrillic' => "\x{0410}", + 'Adblgrave' => "\x{0200}", + 'Adieresiscyrillic' => "\x{04D2}", + 'Adieresismacron' => "\x{01DE}", + 'Adieresissmall' => "\x{F7E4}", + 'Adotbelow' => "\x{1EA0}", + 'Adotmacron' => "\x{01E0}", + 'Agravesmall' => "\x{F7E0}", + 'Ahookabove' => "\x{1EA2}", + 'Aiecyrillic' => "\x{04D4}", + 'Ainvertedbreve' => "\x{0202}", + 'Amonospace' => "\x{FF21}", + 'Aringbelow' => "\x{1E00}", + 'Aringsmall' => "\x{F7E5}", + 'Asmall' => "\x{F761}", + 'Atildesmall' => "\x{F7E3}", + 'Aybarmenian' => "\x{0531}", + 'Bcircle' => "\x{24B7}", + 'Bdotaccent' => "\x{1E02}", + 'Bdotbelow' => "\x{1E04}", + 'Becyrillic' => "\x{0411}", + 'Benarmenian' => "\x{0532}", + 'Bhook' => "\x{0181}", + 'Blinebelow' => "\x{1E06}", + 'Bmonospace' => "\x{FF22}", + 'Brevesmall' => "\x{F6F4}", + 'Bsmall' => "\x{F762}", + 'Btopbar' => "\x{0182}", + 'Caarmenian' => "\x{053E}", + 'Caron' => "\x{F6CA}", + 'Caronsmall' => "\x{F6F5}", + 'Ccedillaacute' => "\x{1E08}", + 'Ccedillasmall' => "\x{F7E7}", + 'Ccircle' => "\x{24B8}", + 'Cdot' => "\x{010A}", + 'Cedillasmall' => "\x{F7B8}", + 'Chaarmenian' => "\x{0549}", + 'Cheabkhasiancyrillic' => "\x{04BC}", + 'Checyrillic' => "\x{0427}", + 'Chedescenderabkhasiancyrillic' => "\x{04BE}", + 'Chedescendercyrillic' => "\x{04B6}", + 'Chedieresiscyrillic' => "\x{04F4}", + 'Cheharmenian' => "\x{0543}", + 'Chekhakassiancyrillic' => "\x{04CB}", + 'Cheverticalstrokecyrillic' => "\x{04B8}", + 'Chook' => "\x{0187}", + 'Circumflexsmall' => "\x{F6F6}", + 'Cmonospace' => "\x{FF23}", + 'Coarmenian' => "\x{0551}", + 'Csmall' => "\x{F763}", + 'DZ' => "\x{01F1}", + 'DZcaron' => "\x{01C4}", + 'Daarmenian' => "\x{0534}", + 'Dafrican' => "\x{0189}", + 'Dcedilla' => "\x{1E10}", + 'Dcircle' => "\x{24B9}", + 'Dcircumflexbelow' => "\x{1E12}", + 'Ddotaccent' => "\x{1E0A}", + 'Ddotbelow' => "\x{1E0C}", + 'Decyrillic' => "\x{0414}", + 'Deicoptic' => "\x{03EE}", + 'Deltagreek' => "\x{0394}", + 'Dhook' => "\x{018A}", + 'Dieresis' => "\x{F6CB}", + 'DieresisAcute' => "\x{F6CC}", + 'DieresisGrave' => "\x{F6CD}", + 'Dieresissmall' => "\x{F7A8}", + 'Digammagreek' => "\x{03DC}", + 'Djecyrillic' => "\x{0402}", + 'Dlinebelow' => "\x{1E0E}", + 'Dmonospace' => "\x{FF24}", + 'Dotaccentsmall' => "\x{F6F7}", + 'Dslash' => "\x{0110}", + 'Dsmall' => "\x{F764}", + 'Dtopbar' => "\x{018B}", + 'Dz' => "\x{01F2}", + 'Dzcaron' => "\x{01C5}", + 'Dzeabkhasiancyrillic' => "\x{04E0}", + 'Dzecyrillic' => "\x{0405}", + 'Dzhecyrillic' => "\x{040F}", + 'Eacutesmall' => "\x{F7E9}", + 'Ecedillabreve' => "\x{1E1C}", + 'Echarmenian' => "\x{0535}", + 'Ecircle' => "\x{24BA}", + 'Ecircumflexacute' => "\x{1EBE}", + 'Ecircumflexbelow' => "\x{1E18}", + 'Ecircumflexdotbelow' => "\x{1EC6}", + 'Ecircumflexgrave' => "\x{1EC0}", + 'Ecircumflexhookabove' => "\x{1EC2}", + 'Ecircumflexsmall' => "\x{F7EA}", + 'Ecircumflextilde' => "\x{1EC4}", + 'Ecyrillic' => "\x{0404}", + 'Edblgrave' => "\x{0204}", + 'Edieresissmall' => "\x{F7EB}", + 'Edot' => "\x{0116}", + 'Edotbelow' => "\x{1EB8}", + 'Efcyrillic' => "\x{0424}", + 'Egravesmall' => "\x{F7E8}", + 'Eharmenian' => "\x{0537}", + 'Ehookabove' => "\x{1EBA}", + 'Eightroman' => "\x{2167}", + 'Einvertedbreve' => "\x{0206}", + 'Eiotifiedcyrillic' => "\x{0464}", + 'Elcyrillic' => "\x{041B}", + 'Elevenroman' => "\x{216A}", + 'Emacronacute' => "\x{1E16}", + 'Emacrongrave' => "\x{1E14}", + 'Emcyrillic' => "\x{041C}", + 'Emonospace' => "\x{FF25}", + 'Encyrillic' => "\x{041D}", + 'Endescendercyrillic' => "\x{04A2}", + 'Enghecyrillic' => "\x{04A4}", + 'Enhookcyrillic' => "\x{04C7}", + 'Eopen' => "\x{0190}", + 'Ercyrillic' => "\x{0420}", + 'Ereversed' => "\x{018E}", + 'Ereversedcyrillic' => "\x{042D}", + 'Escyrillic' => "\x{0421}", + 'Esdescendercyrillic' => "\x{04AA}", + 'Esh' => "\x{01A9}", + 'Esmall' => "\x{F765}", + 'Etarmenian' => "\x{0538}", + 'Ethsmall' => "\x{F7F0}", + 'Etilde' => "\x{1EBC}", + 'Etildebelow' => "\x{1E1A}", + 'Ezh' => "\x{01B7}", + 'Ezhcaron' => "\x{01EE}", + 'Ezhreversed' => "\x{01B8}", + 'Fcircle' => "\x{24BB}", + 'Fdotaccent' => "\x{1E1E}", + 'Feharmenian' => "\x{0556}", + 'Feicoptic' => "\x{03E4}", + 'Fhook' => "\x{0191}", + 'Fitacyrillic' => "\x{0472}", + 'Fiveroman' => "\x{2164}", + 'Fmonospace' => "\x{FF26}", + 'Fourroman' => "\x{2163}", + 'Fsmall' => "\x{F766}", + 'GBsquare' => "\x{3387}", + 'Gacute' => "\x{01F4}", + 'Gammaafrican' => "\x{0194}", + 'Gangiacoptic' => "\x{03EA}", + 'Gcedilla' => "\x{0122}", + 'Gcircle' => "\x{24BC}", + 'Gdot' => "\x{0120}", + 'Gecyrillic' => "\x{0413}", + 'Ghadarmenian' => "\x{0542}", + 'Ghemiddlehookcyrillic' => "\x{0494}", + 'Ghestrokecyrillic' => "\x{0492}", + 'Gheupturncyrillic' => "\x{0490}", + 'Ghook' => "\x{0193}", + 'Gimarmenian' => "\x{0533}", + 'Gjecyrillic' => "\x{0403}", + 'Gmacron' => "\x{1E20}", + 'Gmonospace' => "\x{FF27}", + 'Grave' => "\x{F6CE}", + 'Gravesmall' => "\x{F760}", + 'Gsmall' => "\x{F767}", + 'Gsmallhook' => "\x{029B}", + 'Gstroke' => "\x{01E4}", + 'HPsquare' => "\x{33CB}", + 'Haabkhasiancyrillic' => "\x{04A8}", + 'Hadescendercyrillic' => "\x{04B2}", + 'Hardsigncyrillic' => "\x{042A}", + 'Hbrevebelow' => "\x{1E2A}", + 'Hcedilla' => "\x{1E28}", + 'Hcircle' => "\x{24BD}", + 'Hdieresis' => "\x{1E26}", + 'Hdotaccent' => "\x{1E22}", + 'Hdotbelow' => "\x{1E24}", + 'Hmonospace' => "\x{FF28}", + 'Hoarmenian' => "\x{0540}", + 'Horicoptic' => "\x{03E8}", + 'Hsmall' => "\x{F768}", + 'Hungarumlaut' => "\x{F6CF}", + 'Hungarumlautsmall' => "\x{F6F8}", + 'Hzsquare' => "\x{3390}", + 'IAcyrillic' => "\x{042F}", + 'IUcyrillic' => "\x{042E}", + 'Iacutesmall' => "\x{F7ED}", + 'Icaron' => "\x{01CF}", + 'Icircle' => "\x{24BE}", + 'Icircumflexsmall' => "\x{F7EE}", + 'Icyrillic' => "\x{0406}", + 'Idblgrave' => "\x{0208}", + 'Idieresisacute' => "\x{1E2E}", + 'Idieresiscyrillic' => "\x{04E4}", + 'Idieresissmall' => "\x{F7EF}", + 'Idot' => "\x{0130}", + 'Idotbelow' => "\x{1ECA}", + 'Iebrevecyrillic' => "\x{04D6}", + 'Iecyrillic' => "\x{0415}", + 'Igravesmall' => "\x{F7EC}", + 'Ihookabove' => "\x{1EC8}", + 'Iicyrillic' => "\x{0418}", + 'Iinvertedbreve' => "\x{020A}", + 'Iishortcyrillic' => "\x{0419}", + 'Imacroncyrillic' => "\x{04E2}", + 'Imonospace' => "\x{FF29}", + 'Iniarmenian' => "\x{053B}", + 'Iocyrillic' => "\x{0401}", + 'Iotaafrican' => "\x{0196}", + 'Ismall' => "\x{F769}", + 'Istroke' => "\x{0197}", + 'Itildebelow' => "\x{1E2C}", + 'Izhitsacyrillic' => "\x{0474}", + 'Izhitsadblgravecyrillic' => "\x{0476}", + 'Jaarmenian' => "\x{0541}", + 'Jcircle' => "\x{24BF}", + 'Jecyrillic' => "\x{0408}", + 'Jheharmenian' => "\x{054B}", + 'Jmonospace' => "\x{FF2A}", + 'Jsmall' => "\x{F76A}", + 'KBsquare' => "\x{3385}", + 'KKsquare' => "\x{33CD}", + 'Kabashkircyrillic' => "\x{04A0}", + 'Kacute' => "\x{1E30}", + 'Kacyrillic' => "\x{041A}", + 'Kadescendercyrillic' => "\x{049A}", + 'Kahookcyrillic' => "\x{04C3}", + 'Kastrokecyrillic' => "\x{049E}", + 'Kaverticalstrokecyrillic' => "\x{049C}", + 'Kcaron' => "\x{01E8}", + 'Kcedilla' => "\x{0136}", + 'Kcircle' => "\x{24C0}", + 'Kdotbelow' => "\x{1E32}", + 'Keharmenian' => "\x{0554}", + 'Kenarmenian' => "\x{053F}", + 'Khacyrillic' => "\x{0425}", + 'Kheicoptic' => "\x{03E6}", + 'Khook' => "\x{0198}", + 'Kjecyrillic' => "\x{040C}", + 'Klinebelow' => "\x{1E34}", + 'Kmonospace' => "\x{FF2B}", + 'Koppacyrillic' => "\x{0480}", + 'Koppagreek' => "\x{03DE}", + 'Ksicyrillic' => "\x{046E}", + 'Ksmall' => "\x{F76B}", + 'LJ' => "\x{01C7}", + 'LL' => "\x{F6BF}", + 'Lcedilla' => "\x{013B}", + 'Lcircle' => "\x{24C1}", + 'Lcircumflexbelow' => "\x{1E3C}", + 'Ldotaccent' => "\x{013F}", + 'Ldotbelow' => "\x{1E36}", + 'Ldotbelowmacron' => "\x{1E38}", + 'Liwnarmenian' => "\x{053C}", + 'Lj' => "\x{01C8}", + 'Ljecyrillic' => "\x{0409}", + 'Llinebelow' => "\x{1E3A}", + 'Lmonospace' => "\x{FF2C}", + 'Lslashsmall' => "\x{F6F9}", + 'Lsmall' => "\x{F76C}", + 'MBsquare' => "\x{3386}", + 'Macron' => "\x{F6D0}", + 'Macronsmall' => "\x{F7AF}", + 'Macute' => "\x{1E3E}", + 'Mcircle' => "\x{24C2}", + 'Mdotaccent' => "\x{1E40}", + 'Mdotbelow' => "\x{1E42}", + 'Menarmenian' => "\x{0544}", + 'Mmonospace' => "\x{FF2D}", + 'Msmall' => "\x{F76D}", + 'Mturned' => "\x{019C}", + 'NJ' => "\x{01CA}", + 'Ncedilla' => "\x{0145}", + 'Ncircle' => "\x{24C3}", + 'Ncircumflexbelow' => "\x{1E4A}", + 'Ndotaccent' => "\x{1E44}", + 'Ndotbelow' => "\x{1E46}", + 'Nhookleft' => "\x{019D}", + 'Nineroman' => "\x{2168}", + 'Nj' => "\x{01CB}", + 'Njecyrillic' => "\x{040A}", + 'Nlinebelow' => "\x{1E48}", + 'Nmonospace' => "\x{FF2E}", + 'Nowarmenian' => "\x{0546}", + 'Nsmall' => "\x{F76E}", + 'Ntildesmall' => "\x{F7F1}", + 'OEsmall' => "\x{F6FA}", + 'Oacutesmall' => "\x{F7F3}", + 'Obarredcyrillic' => "\x{04E8}", + 'Obarreddieresiscyrillic' => "\x{04EA}", + 'Ocaron' => "\x{01D1}", + 'Ocenteredtilde' => "\x{019F}", + 'Ocircle' => "\x{24C4}", + 'Ocircumflexacute' => "\x{1ED0}", + 'Ocircumflexdotbelow' => "\x{1ED8}", + 'Ocircumflexgrave' => "\x{1ED2}", + 'Ocircumflexhookabove' => "\x{1ED4}", + 'Ocircumflexsmall' => "\x{F7F4}", + 'Ocircumflextilde' => "\x{1ED6}", + 'Ocyrillic' => "\x{041E}", + 'Odblacute' => "\x{0150}", + 'Odblgrave' => "\x{020C}", + 'Odieresiscyrillic' => "\x{04E6}", + 'Odieresissmall' => "\x{F7F6}", + 'Odotbelow' => "\x{1ECC}", + 'Ogoneksmall' => "\x{F6FB}", + 'Ogravesmall' => "\x{F7F2}", + 'Oharmenian' => "\x{0555}", + 'Ohm' => "\x{2126}", + 'Ohookabove' => "\x{1ECE}", + 'Ohornacute' => "\x{1EDA}", + 'Ohorndotbelow' => "\x{1EE2}", + 'Ohorngrave' => "\x{1EDC}", + 'Ohornhookabove' => "\x{1EDE}", + 'Ohorntilde' => "\x{1EE0}", + 'Oi' => "\x{01A2}", + 'Oinvertedbreve' => "\x{020E}", + 'Omacronacute' => "\x{1E52}", + 'Omacrongrave' => "\x{1E50}", + 'Omegacyrillic' => "\x{0460}", + 'Omegagreek' => "\x{03A9}", + 'Omegaroundcyrillic' => "\x{047A}", + 'Omegatitlocyrillic' => "\x{047C}", + 'Omonospace' => "\x{FF2F}", + 'Oneroman' => "\x{2160}", + 'Oogonek' => "\x{01EA}", + 'Oogonekmacron' => "\x{01EC}", + 'Oopen' => "\x{0186}", + 'Oslashsmall' => "\x{F7F8}", + 'Osmall' => "\x{F76F}", + 'Ostrokeacute' => "\x{01FE}", + 'Otcyrillic' => "\x{047E}", + 'Otildeacute' => "\x{1E4C}", + 'Otildedieresis' => "\x{1E4E}", + 'Otildesmall' => "\x{F7F5}", + 'Pacute' => "\x{1E54}", + 'Pcircle' => "\x{24C5}", + 'Pdotaccent' => "\x{1E56}", + 'Pecyrillic' => "\x{041F}", + 'Peharmenian' => "\x{054A}", + 'Pemiddlehookcyrillic' => "\x{04A6}", + 'Phook' => "\x{01A4}", + 'Piwrarmenian' => "\x{0553}", + 'Pmonospace' => "\x{FF30}", + 'Psicyrillic' => "\x{0470}", + 'Psmall' => "\x{F770}", + 'Qcircle' => "\x{24C6}", + 'Qmonospace' => "\x{FF31}", + 'Qsmall' => "\x{F771}", + 'Raarmenian' => "\x{054C}", + 'Rcedilla' => "\x{0156}", + 'Rcircle' => "\x{24C7}", + 'Rdblgrave' => "\x{0210}", + 'Rdotaccent' => "\x{1E58}", + 'Rdotbelow' => "\x{1E5A}", + 'Rdotbelowmacron' => "\x{1E5C}", + 'Reharmenian' => "\x{0550}", + 'Ringsmall' => "\x{F6FC}", + 'Rinvertedbreve' => "\x{0212}", + 'Rlinebelow' => "\x{1E5E}", + 'Rmonospace' => "\x{FF32}", + 'Rsmall' => "\x{F772}", + 'Rsmallinverted' => "\x{0281}", + 'Rsmallinvertedsuperior' => "\x{02B6}", + 'Sacutedotaccent' => "\x{1E64}", + 'Sampigreek' => "\x{03E0}", + 'Scarondotaccent' => "\x{1E66}", + 'Scaronsmall' => "\x{F6FD}", + 'Schwa' => "\x{018F}", + 'Schwacyrillic' => "\x{04D8}", + 'Schwadieresiscyrillic' => "\x{04DA}", + 'Scircle' => "\x{24C8}", + 'Sdotaccent' => "\x{1E60}", + 'Sdotbelow' => "\x{1E62}", + 'Sdotbelowdotaccent' => "\x{1E68}", + 'Seharmenian' => "\x{054D}", + 'Sevenroman' => "\x{2166}", + 'Shaarmenian' => "\x{0547}", + 'Shacyrillic' => "\x{0428}", + 'Shchacyrillic' => "\x{0429}", + 'Sheicoptic' => "\x{03E2}", + 'Shhacyrillic' => "\x{04BA}", + 'Shimacoptic' => "\x{03EC}", + 'Sixroman' => "\x{2165}", + 'Smonospace' => "\x{FF33}", + 'Softsigncyrillic' => "\x{042C}", + 'Ssmall' => "\x{F773}", + 'Stigmagreek' => "\x{03DA}", + 'Tcedilla' => "\x{0162}", + 'Tcircle' => "\x{24C9}", + 'Tcircumflexbelow' => "\x{1E70}", + 'Tdotaccent' => "\x{1E6A}", + 'Tdotbelow' => "\x{1E6C}", + 'Tecyrillic' => "\x{0422}", + 'Tedescendercyrillic' => "\x{04AC}", + 'Tenroman' => "\x{2169}", + 'Tetsecyrillic' => "\x{04B4}", + 'Thook' => "\x{01AC}", + 'Thornsmall' => "\x{F7FE}", + 'Threeroman' => "\x{2162}", + 'Tildesmall' => "\x{F6FE}", + 'Tiwnarmenian' => "\x{054F}", + 'Tlinebelow' => "\x{1E6E}", + 'Tmonospace' => "\x{FF34}", + 'Toarmenian' => "\x{0539}", + 'Tonefive' => "\x{01BC}", + 'Tonesix' => "\x{0184}", + 'Tonetwo' => "\x{01A7}", + 'Tretroflexhook' => "\x{01AE}", + 'Tsecyrillic' => "\x{0426}", + 'Tshecyrillic' => "\x{040B}", + 'Tsmall' => "\x{F774}", + 'Twelveroman' => "\x{216B}", + 'Tworoman' => "\x{2161}", + 'Uacutesmall' => "\x{F7FA}", + 'Ucaron' => "\x{01D3}", + 'Ucircle' => "\x{24CA}", + 'Ucircumflexbelow' => "\x{1E76}", + 'Ucircumflexsmall' => "\x{F7FB}", + 'Ucyrillic' => "\x{0423}", + 'Udblacute' => "\x{0170}", + 'Udblgrave' => "\x{0214}", + 'Udieresisacute' => "\x{01D7}", + 'Udieresisbelow' => "\x{1E72}", + 'Udieresiscaron' => "\x{01D9}", + 'Udieresiscyrillic' => "\x{04F0}", + 'Udieresisgrave' => "\x{01DB}", + 'Udieresismacron' => "\x{01D5}", + 'Udieresissmall' => "\x{F7FC}", + 'Udotbelow' => "\x{1EE4}", + 'Ugravesmall' => "\x{F7F9}", + 'Uhookabove' => "\x{1EE6}", + 'Uhornacute' => "\x{1EE8}", + 'Uhorndotbelow' => "\x{1EF0}", + 'Uhorngrave' => "\x{1EEA}", + 'Uhornhookabove' => "\x{1EEC}", + 'Uhorntilde' => "\x{1EEE}", + 'Uhungarumlautcyrillic' => "\x{04F2}", + 'Uinvertedbreve' => "\x{0216}", + 'Ukcyrillic' => "\x{0478}", + 'Umacroncyrillic' => "\x{04EE}", + 'Umacrondieresis' => "\x{1E7A}", + 'Umonospace' => "\x{FF35}", + 'Upsilonacutehooksymbolgreek' => "\x{03D3}", + 'Upsilonafrican' => "\x{01B1}", + 'Upsilondieresishooksymbolgreek' => "\x{03D4}", + 'Upsilonhooksymbol' => "\x{03D2}", + 'Ushortcyrillic' => "\x{040E}", + 'Usmall' => "\x{F775}", + 'Ustraightcyrillic' => "\x{04AE}", + 'Ustraightstrokecyrillic' => "\x{04B0}", + 'Utildeacute' => "\x{1E78}", + 'Utildebelow' => "\x{1E74}", + 'Vcircle' => "\x{24CB}", + 'Vdotbelow' => "\x{1E7E}", + 'Vecyrillic' => "\x{0412}", + 'Vewarmenian' => "\x{054E}", + 'Vhook' => "\x{01B2}", + 'Vmonospace' => "\x{FF36}", + 'Voarmenian' => "\x{0548}", + 'Vsmall' => "\x{F776}", + 'Vtilde' => "\x{1E7C}", + 'Wcircle' => "\x{24CC}", + 'Wdotaccent' => "\x{1E86}", + 'Wdotbelow' => "\x{1E88}", + 'Wmonospace' => "\x{FF37}", + 'Wsmall' => "\x{F777}", + 'Xcircle' => "\x{24CD}", + 'Xdieresis' => "\x{1E8C}", + 'Xdotaccent' => "\x{1E8A}", + 'Xeharmenian' => "\x{053D}", + 'Xmonospace' => "\x{FF38}", + 'Xsmall' => "\x{F778}", + 'Yacutesmall' => "\x{F7FD}", + 'Yatcyrillic' => "\x{0462}", + 'Ycircle' => "\x{24CE}", + 'Ydieresissmall' => "\x{F7FF}", + 'Ydotaccent' => "\x{1E8E}", + 'Ydotbelow' => "\x{1EF4}", + 'Yericyrillic' => "\x{042B}", + 'Yerudieresiscyrillic' => "\x{04F8}", + 'Yhook' => "\x{01B3}", + 'Yhookabove' => "\x{1EF6}", + 'Yiarmenian' => "\x{0545}", + 'Yicyrillic' => "\x{0407}", + 'Yiwnarmenian' => "\x{0552}", + 'Ymonospace' => "\x{FF39}", + 'Ysmall' => "\x{F779}", + 'Ytilde' => "\x{1EF8}", + 'Yusbigcyrillic' => "\x{046A}", + 'Yusbigiotifiedcyrillic' => "\x{046C}", + 'Yuslittlecyrillic' => "\x{0466}", + 'Yuslittleiotifiedcyrillic' => "\x{0468}", + 'Zaarmenian' => "\x{0536}", + 'Zcaronsmall' => "\x{F6FF}", + 'Zcircle' => "\x{24CF}", + 'Zcircumflex' => "\x{1E90}", + 'Zdot' => "\x{017B}", + 'Zdotbelow' => "\x{1E92}", + 'Zecyrillic' => "\x{0417}", + 'Zedescendercyrillic' => "\x{0498}", + 'Zedieresiscyrillic' => "\x{04DE}", + 'Zhearmenian' => "\x{053A}", + 'Zhebrevecyrillic' => "\x{04C1}", + 'Zhecyrillic' => "\x{0416}", + 'Zhedescendercyrillic' => "\x{0496}", + 'Zhedieresiscyrillic' => "\x{04DC}", + 'Zlinebelow' => "\x{1E94}", + 'Zmonospace' => "\x{FF3A}", + 'Zsmall' => "\x{F77A}", + 'Zstroke' => "\x{01B5}", + 'aabengali' => "\x{0986}", + 'aadeva' => "\x{0906}", + 'aagujarati' => "\x{0A86}", + 'aagurmukhi' => "\x{0A06}", + 'aamatragurmukhi' => "\x{0A3E}", + 'aarusquare' => "\x{3303}", + 'aavowelsignbengali' => "\x{09BE}", + 'aavowelsigndeva' => "\x{093E}", + 'aavowelsigngujarati' => "\x{0ABE}", + 'abbreviationmarkarmenian' => "\x{055F}", + 'abbreviationsigndeva' => "\x{0970}", + 'abengali' => "\x{0985}", + 'abopomofo' => "\x{311A}", + 'abreveacute' => "\x{1EAF}", + 'abrevecyrillic' => "\x{04D1}", + 'abrevedotbelow' => "\x{1EB7}", + 'abrevegrave' => "\x{1EB1}", + 'abrevehookabove' => "\x{1EB3}", + 'abrevetilde' => "\x{1EB5}", + 'acaron' => "\x{01CE}", + 'acircle' => "\x{24D0}", + 'acircumflexacute' => "\x{1EA5}", + 'acircumflexdotbelow' => "\x{1EAD}", + 'acircumflexgrave' => "\x{1EA7}", + 'acircumflexhookabove' => "\x{1EA9}", + 'acircumflextilde' => "\x{1EAB}", + 'acutebelowcmb' => "\x{0317}", + 'acutecmb' => "\x{0301}", + 'acutedeva' => "\x{0954}", + 'acutelowmod' => "\x{02CF}", + 'acutetonecmb' => "\x{0341}", + 'acyrillic' => "\x{0430}", + 'adblgrave' => "\x{0201}", + 'addakgurmukhi' => "\x{0A71}", + 'adeva' => "\x{0905}", + 'adieresiscyrillic' => "\x{04D3}", + 'adieresismacron' => "\x{01DF}", + 'adotbelow' => "\x{1EA1}", + 'adotmacron' => "\x{01E1}", + 'aekorean' => "\x{3150}", + 'aemacron' => "\x{01E3}", + 'afii08941' => "\x{20A4}", + 'afii10063' => "\x{F6C4}", + 'afii10064' => "\x{F6C5}", + 'afii10192' => "\x{F6C6}", + 'afii10831' => "\x{F6C7}", + 'afii10832' => "\x{F6C8}", + 'agujarati' => "\x{0A85}", + 'agurmukhi' => "\x{0A05}", + 'ahiragana' => "\x{3042}", + 'ahookabove' => "\x{1EA3}", + 'aibengali' => "\x{0990}", + 'aibopomofo' => "\x{311E}", + 'aideva' => "\x{0910}", + 'aiecyrillic' => "\x{04D5}", + 'aigujarati' => "\x{0A90}", + 'aigurmukhi' => "\x{0A10}", + 'aimatragurmukhi' => "\x{0A48}", + 'ainarabic' => "\x{0639}", + 'ainfinalarabic' => "\x{FECA}", + 'aininitialarabic' => "\x{FECB}", + 'ainmedialarabic' => "\x{FECC}", + 'ainvertedbreve' => "\x{0203}", + 'aivowelsignbengali' => "\x{09C8}", + 'aivowelsigndeva' => "\x{0948}", + 'aivowelsigngujarati' => "\x{0AC8}", + 'akatakana' => "\x{30A2}", + 'akatakanahalfwidth' => "\x{FF71}", + 'akorean' => "\x{314F}", + 'alef' => "\x{05D0}", + 'alefarabic' => "\x{0627}", + 'alefdageshhebrew' => "\x{FB30}", + 'aleffinalarabic' => "\x{FE8E}", + 'alefhamzaabovearabic' => "\x{0623}", + 'alefhamzaabovefinalarabic' => "\x{FE84}", + 'alefhamzabelowarabic' => "\x{0625}", + 'alefhamzabelowfinalarabic' => "\x{FE88}", + 'alefhebrew' => "\x{05D0}", + 'aleflamedhebrew' => "\x{FB4F}", + 'alefmaddaabovearabic' => "\x{0622}", + 'alefmaddaabovefinalarabic' => "\x{FE82}", + 'alefmaksuraarabic' => "\x{0649}", + 'alefmaksurafinalarabic' => "\x{FEF0}", + 'alefmaksurainitialarabic' => "\x{FEF3}", + 'alefmaksuramedialarabic' => "\x{FEF4}", + 'alefpatahhebrew' => "\x{FB2E}", + 'alefqamatshebrew' => "\x{FB2F}", + 'allequal' => "\x{224C}", + 'amonospace' => "\x{FF41}", + 'ampersandmonospace' => "\x{FF06}", + 'ampersandsmall' => "\x{F726}", + 'amsquare' => "\x{33C2}", + 'anbopomofo' => "\x{3122}", + 'angbopomofo' => "\x{3124}", + 'angkhankhuthai' => "\x{0E5A}", + 'anglebracketleft' => "\x{3008}", + 'anglebracketleftvertical' => "\x{FE3F}", + 'anglebracketright' => "\x{3009}", + 'anglebracketrightvertical' => "\x{FE40}", + 'angstrom' => "\x{212B}", + 'anudattadeva' => "\x{0952}", + 'anusvarabengali' => "\x{0982}", + 'anusvaradeva' => "\x{0902}", + 'anusvaragujarati' => "\x{0A82}", + 'apaatosquare' => "\x{3300}", + 'aparen' => "\x{249C}", + 'apostrophearmenian' => "\x{055A}", + 'apostrophemod' => "\x{02BC}", + 'apple' => "\x{F8FF}", + 'approaches' => "\x{2250}", + 'approxequalorimage' => "\x{2252}", + 'approximatelyequal' => "\x{2245}", + 'araeaekorean' => "\x{318E}", + 'araeakorean' => "\x{318D}", + 'arc' => "\x{2312}", + 'arighthalfring' => "\x{1E9A}", + 'aringbelow' => "\x{1E01}", + 'arrowdashdown' => "\x{21E3}", + 'arrowdashleft' => "\x{21E0}", + 'arrowdashright' => "\x{21E2}", + 'arrowdashup' => "\x{21E1}", + 'arrowdownleft' => "\x{2199}", + 'arrowdownright' => "\x{2198}", + 'arrowdownwhite' => "\x{21E9}", + 'arrowheaddownmod' => "\x{02C5}", + 'arrowheadleftmod' => "\x{02C2}", + 'arrowheadrightmod' => "\x{02C3}", + 'arrowheadupmod' => "\x{02C4}", + 'arrowhorizex' => "\x{F8E7}", + 'arrowleftdbl' => "\x{21D0}", + 'arrowleftdblstroke' => "\x{21CD}", + 'arrowleftoverright' => "\x{21C6}", + 'arrowleftwhite' => "\x{21E6}", + 'arrowrightdblstroke' => "\x{21CF}", + 'arrowrightheavy' => "\x{279E}", + 'arrowrightoverleft' => "\x{21C4}", + 'arrowrightwhite' => "\x{21E8}", + 'arrowtableft' => "\x{21E4}", + 'arrowtabright' => "\x{21E5}", + 'arrowupdownbase' => "\x{21A8}", + 'arrowupleft' => "\x{2196}", + 'arrowupleftofdown' => "\x{21C5}", + 'arrowupright' => "\x{2197}", + 'arrowupwhite' => "\x{21E7}", + 'arrowvertex' => "\x{F8E6}", + 'asciicircummonospace' => "\x{FF3E}", + 'asciitildemonospace' => "\x{FF5E}", + 'ascript' => "\x{0251}", + 'ascriptturned' => "\x{0252}", + 'asmallhiragana' => "\x{3041}", + 'asmallkatakana' => "\x{30A1}", + 'asmallkatakanahalfwidth' => "\x{FF67}", + 'asteriskaltonearabic' => "\x{066D}", + 'asteriskarabic' => "\x{066D}", + 'asteriskmonospace' => "\x{FF0A}", + 'asterisksmall' => "\x{FE61}", + 'asterism' => "\x{2042}", + 'asuperior' => "\x{F6E9}", + 'asymptoticallyequal' => "\x{2243}", + 'atmonospace' => "\x{FF20}", + 'atsmall' => "\x{FE6B}", + 'aturned' => "\x{0250}", + 'aubengali' => "\x{0994}", + 'aubopomofo' => "\x{3120}", + 'audeva' => "\x{0914}", + 'augujarati' => "\x{0A94}", + 'augurmukhi' => "\x{0A14}", + 'aulengthmarkbengali' => "\x{09D7}", + 'aumatragurmukhi' => "\x{0A4C}", + 'auvowelsignbengali' => "\x{09CC}", + 'auvowelsigndeva' => "\x{094C}", + 'auvowelsigngujarati' => "\x{0ACC}", + 'avagrahadeva' => "\x{093D}", + 'aybarmenian' => "\x{0561}", + 'ayin' => "\x{05E2}", + 'ayinaltonehebrew' => "\x{FB20}", + 'ayinhebrew' => "\x{05E2}", + 'babengali' => "\x{09AC}", + 'backslashmonospace' => "\x{FF3C}", + 'badeva' => "\x{092C}", + 'bagujarati' => "\x{0AAC}", + 'bagurmukhi' => "\x{0A2C}", + 'bahiragana' => "\x{3070}", + 'bahtthai' => "\x{0E3F}", + 'bakatakana' => "\x{30D0}", + 'barmonospace' => "\x{FF5C}", + 'bbopomofo' => "\x{3105}", + 'bcircle' => "\x{24D1}", + 'bdotaccent' => "\x{1E03}", + 'bdotbelow' => "\x{1E05}", + 'beamedsixteenthnotes' => "\x{266C}", + 'because' => "\x{2235}", + 'becyrillic' => "\x{0431}", + 'beharabic' => "\x{0628}", + 'behfinalarabic' => "\x{FE90}", + 'behinitialarabic' => "\x{FE91}", + 'behiragana' => "\x{3079}", + 'behmedialarabic' => "\x{FE92}", + 'behmeeminitialarabic' => "\x{FC9F}", + 'behmeemisolatedarabic' => "\x{FC08}", + 'behnoonfinalarabic' => "\x{FC6D}", + 'bekatakana' => "\x{30D9}", + 'benarmenian' => "\x{0562}", + 'bet' => "\x{05D1}", + 'betasymbolgreek' => "\x{03D0}", + 'betdagesh' => "\x{FB31}", + 'betdageshhebrew' => "\x{FB31}", + 'bethebrew' => "\x{05D1}", + 'betrafehebrew' => "\x{FB4C}", + 'bhabengali' => "\x{09AD}", + 'bhadeva' => "\x{092D}", + 'bhagujarati' => "\x{0AAD}", + 'bhagurmukhi' => "\x{0A2D}", + 'bhook' => "\x{0253}", + 'bihiragana' => "\x{3073}", + 'bikatakana' => "\x{30D3}", + 'bilabialclick' => "\x{0298}", + 'bindigurmukhi' => "\x{0A02}", + 'birusquare' => "\x{3331}", + 'blackcircle' => "\x{25CF}", + 'blackdiamond' => "\x{25C6}", + 'blackdownpointingtriangle' => "\x{25BC}", + 'blackleftpointingpointer' => "\x{25C4}", + 'blackleftpointingtriangle' => "\x{25C0}", + 'blacklenticularbracketleft' => "\x{3010}", + 'blacklenticularbracketleftvertical' => "\x{FE3B}", + 'blacklenticularbracketright' => "\x{3011}", + 'blacklenticularbracketrightvertical' => "\x{FE3C}", + 'blacklowerlefttriangle' => "\x{25E3}", + 'blacklowerrighttriangle' => "\x{25E2}", + 'blackrectangle' => "\x{25AC}", + 'blackrightpointingpointer' => "\x{25BA}", + 'blackrightpointingtriangle' => "\x{25B6}", + 'blacksmallsquare' => "\x{25AA}", + 'blacksmilingface' => "\x{263B}", + 'blacksquare' => "\x{25A0}", + 'blackstar' => "\x{2605}", + 'blackupperlefttriangle' => "\x{25E4}", + 'blackupperrighttriangle' => "\x{25E5}", + 'blackuppointingsmalltriangle' => "\x{25B4}", + 'blackuppointingtriangle' => "\x{25B2}", + 'blank' => "\x{2423}", + 'blinebelow' => "\x{1E07}", + 'bmonospace' => "\x{FF42}", + 'bobaimaithai' => "\x{0E1A}", + 'bohiragana' => "\x{307C}", + 'bokatakana' => "\x{30DC}", + 'bparen' => "\x{249D}", + 'bqsquare' => "\x{33C3}", + 'braceex' => "\x{F8F4}", + 'braceleftbt' => "\x{F8F3}", + 'braceleftmid' => "\x{F8F2}", + 'braceleftmonospace' => "\x{FF5B}", + 'braceleftsmall' => "\x{FE5B}", + 'bracelefttp' => "\x{F8F1}", + 'braceleftvertical' => "\x{FE37}", + 'bracerightbt' => "\x{F8FE}", + 'bracerightmid' => "\x{F8FD}", + 'bracerightmonospace' => "\x{FF5D}", + 'bracerightsmall' => "\x{FE5C}", + 'bracerighttp' => "\x{F8FC}", + 'bracerightvertical' => "\x{FE38}", + 'bracketleftbt' => "\x{F8F0}", + 'bracketleftex' => "\x{F8EF}", + 'bracketleftmonospace' => "\x{FF3B}", + 'bracketlefttp' => "\x{F8EE}", + 'bracketrightbt' => "\x{F8FB}", + 'bracketrightex' => "\x{F8FA}", + 'bracketrightmonospace' => "\x{FF3D}", + 'bracketrighttp' => "\x{F8F9}", + 'brevebelowcmb' => "\x{032E}", + 'brevecmb' => "\x{0306}", + 'breveinvertedbelowcmb' => "\x{032F}", + 'breveinvertedcmb' => "\x{0311}", + 'breveinverteddoublecmb' => "\x{0361}", + 'bridgebelowcmb' => "\x{032A}", + 'bridgeinvertedbelowcmb' => "\x{033A}", + 'bstroke' => "\x{0180}", + 'bsuperior' => "\x{F6EA}", + 'btopbar' => "\x{0183}", + 'buhiragana' => "\x{3076}", + 'bukatakana' => "\x{30D6}", + 'bulletinverse' => "\x{25D8}", + 'bulletoperator' => "\x{2219}", + 'bullseye' => "\x{25CE}", + 'caarmenian' => "\x{056E}", + 'cabengali' => "\x{099A}", + 'cadeva' => "\x{091A}", + 'cagujarati' => "\x{0A9A}", + 'cagurmukhi' => "\x{0A1A}", + 'calsquare' => "\x{3388}", + 'candrabindubengali' => "\x{0981}", + 'candrabinducmb' => "\x{0310}", + 'candrabindudeva' => "\x{0901}", + 'candrabindugujarati' => "\x{0A81}", + 'capslock' => "\x{21EA}", + 'careof' => "\x{2105}", + 'caronbelowcmb' => "\x{032C}", + 'caroncmb' => "\x{030C}", + 'cbopomofo' => "\x{3118}", + 'ccedillaacute' => "\x{1E09}", + 'ccircle' => "\x{24D2}", + 'ccurl' => "\x{0255}", + 'cdot' => "\x{010B}", + 'cdsquare' => "\x{33C5}", + 'cedillacmb' => "\x{0327}", + 'centigrade' => "\x{2103}", + 'centinferior' => "\x{F6DF}", + 'centmonospace' => "\x{FFE0}", + 'centoldstyle' => "\x{F7A2}", + 'centsuperior' => "\x{F6E0}", + 'chaarmenian' => "\x{0579}", + 'chabengali' => "\x{099B}", + 'chadeva' => "\x{091B}", + 'chagujarati' => "\x{0A9B}", + 'chagurmukhi' => "\x{0A1B}", + 'chbopomofo' => "\x{3114}", + 'cheabkhasiancyrillic' => "\x{04BD}", + 'checkmark' => "\x{2713}", + 'checyrillic' => "\x{0447}", + 'chedescenderabkhasiancyrillic' => "\x{04BF}", + 'chedescendercyrillic' => "\x{04B7}", + 'chedieresiscyrillic' => "\x{04F5}", + 'cheharmenian' => "\x{0573}", + 'chekhakassiancyrillic' => "\x{04CC}", + 'cheverticalstrokecyrillic' => "\x{04B9}", + 'chieuchacirclekorean' => "\x{3277}", + 'chieuchaparenkorean' => "\x{3217}", + 'chieuchcirclekorean' => "\x{3269}", + 'chieuchkorean' => "\x{314A}", + 'chieuchparenkorean' => "\x{3209}", + 'chochangthai' => "\x{0E0A}", + 'chochanthai' => "\x{0E08}", + 'chochingthai' => "\x{0E09}", + 'chochoethai' => "\x{0E0C}", + 'chook' => "\x{0188}", + 'cieucacirclekorean' => "\x{3276}", + 'cieucaparenkorean' => "\x{3216}", + 'cieuccirclekorean' => "\x{3268}", + 'cieuckorean' => "\x{3148}", + 'cieucparenkorean' => "\x{3208}", + 'cieucuparenkorean' => "\x{321C}", + 'circleot' => "\x{2299}", # Actual Adobe glyph list entry -- identified as typo, May 2008 + 'circledot' => "\x{2299}", # What it should have been + 'circlepostalmark' => "\x{3036}", + 'circlewithlefthalfblack' => "\x{25D0}", + 'circlewithrighthalfblack' => "\x{25D1}", + 'circumflexbelowcmb' => "\x{032D}", + 'circumflexcmb' => "\x{0302}", + 'clear' => "\x{2327}", + 'clickalveolar' => "\x{01C2}", + 'clickdental' => "\x{01C0}", + 'clicklateral' => "\x{01C1}", + 'clickretroflex' => "\x{01C3}", + 'clubsuitblack' => "\x{2663}", + 'clubsuitwhite' => "\x{2667}", + 'cmcubedsquare' => "\x{33A4}", + 'cmonospace' => "\x{FF43}", + 'cmsquaredsquare' => "\x{33A0}", + 'coarmenian' => "\x{0581}", + 'colonmonospace' => "\x{FF1A}", + 'colonsign' => "\x{20A1}", + 'colonsmall' => "\x{FE55}", + 'colontriangularhalfmod' => "\x{02D1}", + 'colontriangularmod' => "\x{02D0}", + 'commaabovecmb' => "\x{0313}", + 'commaaboverightcmb' => "\x{0315}", + 'commaaccent' => "\x{F6C3}", + 'commaarabic' => "\x{060C}", + 'commaarmenian' => "\x{055D}", + 'commainferior' => "\x{F6E1}", + 'commamonospace' => "\x{FF0C}", + 'commareversedabovecmb' => "\x{0314}", + 'commareversedmod' => "\x{02BD}", + 'commasmall' => "\x{FE50}", + 'commasuperior' => "\x{F6E2}", + 'commaturnedabovecmb' => "\x{0312}", + 'commaturnedmod' => "\x{02BB}", + 'compass' => "\x{263C}", + 'contourintegral' => "\x{222E}", + 'control' => "\x{2303}", + 'controlACK' => "\x{0006}", + 'controlBEL' => "\x{0007}", + 'controlBS' => "\x{0008}", + 'controlCAN' => "\x{0018}", + 'controlCR' => "\x{000D}", + 'controlDC1' => "\x{0011}", + 'controlDC2' => "\x{0012}", + 'controlDC3' => "\x{0013}", + 'controlDC4' => "\x{0014}", + 'controlDEL' => "\x{007F}", + 'controlDLE' => "\x{0010}", + 'controlEM' => "\x{0019}", + 'controlENQ' => "\x{0005}", + 'controlEOT' => "\x{0004}", + 'controlESC' => "\x{001B}", + 'controlETB' => "\x{0017}", + 'controlETX' => "\x{0003}", + 'controlFF' => "\x{000C}", + 'controlFS' => "\x{001C}", + 'controlGS' => "\x{001D}", + 'controlHT' => "\x{0009}", + 'controlLF' => "\x{000A}", + 'controlNAK' => "\x{0015}", + 'controlRS' => "\x{001E}", + 'controlSI' => "\x{000F}", + 'controlSO' => "\x{000E}", + 'controlSOT' => "\x{0002}", + 'controlSTX' => "\x{0001}", + 'controlSUB' => "\x{001A}", + 'controlSYN' => "\x{0016}", + 'controlUS' => "\x{001F}", + 'controlVT' => "\x{000B}", + 'copyrightsans' => "\x{F8E9}", + 'copyrightserif' => "\x{F6D9}", + 'cornerbracketleft' => "\x{300C}", + 'cornerbracketlefthalfwidth' => "\x{FF62}", + 'cornerbracketleftvertical' => "\x{FE41}", + 'cornerbracketright' => "\x{300D}", + 'cornerbracketrighthalfwidth' => "\x{FF63}", + 'cornerbracketrightvertical' => "\x{FE42}", + 'corporationsquare' => "\x{337F}", + 'cosquare' => "\x{33C7}", + 'coverkgsquare' => "\x{33C6}", + 'cparen' => "\x{249E}", + 'cruzeiro' => "\x{20A2}", + 'cstretched' => "\x{0297}", + 'curlyand' => "\x{22CF}", + 'curlyor' => "\x{22CE}", + 'cyrBreve' => "\x{F6D1}", + 'cyrFlex' => "\x{F6D2}", + 'cyrbreve' => "\x{F6D4}", + 'cyrflex' => "\x{F6D5}", + 'daarmenian' => "\x{0564}", + 'dabengali' => "\x{09A6}", + 'dadarabic' => "\x{0636}", + 'dadeva' => "\x{0926}", + 'dadfinalarabic' => "\x{FEBE}", + 'dadinitialarabic' => "\x{FEBF}", + 'dadmedialarabic' => "\x{FEC0}", + 'dagesh' => "\x{05BC}", + 'dageshhebrew' => "\x{05BC}", + 'dagujarati' => "\x{0AA6}", + 'dagurmukhi' => "\x{0A26}", + 'dahiragana' => "\x{3060}", + 'dakatakana' => "\x{30C0}", + 'dalarabic' => "\x{062F}", + 'dalet' => "\x{05D3}", + 'daletdagesh' => "\x{FB33}", + 'daletdageshhebrew' => "\x{FB33}", + 'dalethatafpatah' => "\x{05D3}\x{05B2}", + 'dalethatafpatahhebrew' => "\x{05D3}\x{05B2}", + 'dalethatafsegol' => "\x{05D3}\x{05B1}", + 'dalethatafsegolhebrew' => "\x{05D3}\x{05B1}", + 'dalethebrew' => "\x{05D3}", + 'dalethiriq' => "\x{05D3}\x{05B4}", + 'dalethiriqhebrew' => "\x{05D3}\x{05B4}", + 'daletholam' => "\x{05D3}\x{05B9}", + 'daletholamhebrew' => "\x{05D3}\x{05B9}", + 'daletpatah' => "\x{05D3}\x{05B7}", + 'daletpatahhebrew' => "\x{05D3}\x{05B7}", + 'daletqamats' => "\x{05D3}\x{05B8}", + 'daletqamatshebrew' => "\x{05D3}\x{05B8}", + 'daletqubuts' => "\x{05D3}\x{05BB}", + 'daletqubutshebrew' => "\x{05D3}\x{05BB}", + 'daletsegol' => "\x{05D3}\x{05B6}", + 'daletsegolhebrew' => "\x{05D3}\x{05B6}", + 'daletsheva' => "\x{05D3}\x{05B0}", + 'daletshevahebrew' => "\x{05D3}\x{05B0}", + 'dalettsere' => "\x{05D3}\x{05B5}", + 'dalettserehebrew' => "\x{05D3}\x{05B5}", + 'dalfinalarabic' => "\x{FEAA}", + 'dammaarabic' => "\x{064F}", + 'dammalowarabic' => "\x{064F}", + 'dammatanaltonearabic' => "\x{064C}", + 'dammatanarabic' => "\x{064C}", + 'danda' => "\x{0964}", + 'dargahebrew' => "\x{05A7}", + 'dargalefthebrew' => "\x{05A7}", + 'dasiapneumatacyrilliccmb' => "\x{0485}", + 'dblGrave' => "\x{F6D3}", + 'dblanglebracketleft' => "\x{300A}", + 'dblanglebracketleftvertical' => "\x{FE3D}", + 'dblanglebracketright' => "\x{300B}", + 'dblanglebracketrightvertical' => "\x{FE3E}", + 'dblarchinvertedbelowcmb' => "\x{032B}", + 'dblarrowleft' => "\x{21D4}", + 'dblarrowright' => "\x{21D2}", + 'dbldanda' => "\x{0965}", + 'dblgrave' => "\x{F6D6}", + 'dblgravecmb' => "\x{030F}", + 'dblintegral' => "\x{222C}", + 'dbllowline' => "\x{2017}", + 'dbllowlinecmb' => "\x{0333}", + 'dbloverlinecmb' => "\x{033F}", + 'dblprimemod' => "\x{02BA}", + 'dblverticalbar' => "\x{2016}", + 'dblverticallineabovecmb' => "\x{030E}", + 'dbopomofo' => "\x{3109}", + 'dbsquare' => "\x{33C8}", + 'dcedilla' => "\x{1E11}", + 'dcircle' => "\x{24D3}", + 'dcircumflexbelow' => "\x{1E13}", + 'ddabengali' => "\x{09A1}", + 'ddadeva' => "\x{0921}", + 'ddagujarati' => "\x{0AA1}", + 'ddagurmukhi' => "\x{0A21}", + 'ddalarabic' => "\x{0688}", + 'ddalfinalarabic' => "\x{FB89}", + 'dddhadeva' => "\x{095C}", + 'ddhabengali' => "\x{09A2}", + 'ddhadeva' => "\x{0922}", + 'ddhagujarati' => "\x{0AA2}", + 'ddhagurmukhi' => "\x{0A22}", + 'ddotaccent' => "\x{1E0B}", + 'ddotbelow' => "\x{1E0D}", + 'decimalseparatorarabic' => "\x{066B}", + 'decimalseparatorpersian' => "\x{066B}", + 'decyrillic' => "\x{0434}", + 'dehihebrew' => "\x{05AD}", + 'dehiragana' => "\x{3067}", + 'deicoptic' => "\x{03EF}", + 'dekatakana' => "\x{30C7}", + 'deleteleft' => "\x{232B}", + 'deleteright' => "\x{2326}", + 'deltaturned' => "\x{018D}", + 'denominatorminusonenumeratorbengali' => "\x{09F8}", + 'dezh' => "\x{02A4}", + 'dhabengali' => "\x{09A7}", + 'dhadeva' => "\x{0927}", + 'dhagujarati' => "\x{0AA7}", + 'dhagurmukhi' => "\x{0A27}", + 'dhook' => "\x{0257}", + 'dialytikatonos' => "\x{0385}", + 'dialytikatonoscmb' => "\x{0344}", + 'diamondsuitwhite' => "\x{2662}", + 'dieresisacute' => "\x{F6D7}", + 'dieresisbelowcmb' => "\x{0324}", + 'dieresiscmb' => "\x{0308}", + 'dieresisgrave' => "\x{F6D8}", + 'dihiragana' => "\x{3062}", + 'dikatakana' => "\x{30C2}", + 'dittomark' => "\x{3003}", + 'divides' => "\x{2223}", + 'divisionslash' => "\x{2215}", + 'djecyrillic' => "\x{0452}", + 'dlinebelow' => "\x{1E0F}", + 'dlsquare' => "\x{3397}", + 'dmacron' => "\x{0111}", + 'dmonospace' => "\x{FF44}", + 'dochadathai' => "\x{0E0E}", + 'dodekthai' => "\x{0E14}", + 'dohiragana' => "\x{3069}", + 'dokatakana' => "\x{30C9}", + 'dollarinferior' => "\x{F6E3}", + 'dollarmonospace' => "\x{FF04}", + 'dollaroldstyle' => "\x{F724}", + 'dollarsmall' => "\x{FE69}", + 'dollarsuperior' => "\x{F6E4}", + 'dorusquare' => "\x{3326}", + 'dotaccentcmb' => "\x{0307}", + 'dotbelowcmb' => "\x{0323}", + 'dotkatakana' => "\x{30FB}", + 'dotlessj' => "\x{F6BE}", + 'dotlessjstrokehook' => "\x{0284}", + 'dottedcircle' => "\x{25CC}", + 'doubleyodpatah' => "\x{FB1F}", + 'doubleyodpatahhebrew' => "\x{FB1F}", + 'downtackbelowcmb' => "\x{031E}", + 'downtackmod' => "\x{02D5}", + 'dparen' => "\x{249F}", + 'dsuperior' => "\x{F6EB}", + 'dtail' => "\x{0256}", + 'dtopbar' => "\x{018C}", + 'duhiragana' => "\x{3065}", + 'dukatakana' => "\x{30C5}", + 'dz' => "\x{01F3}", + 'dzaltone' => "\x{02A3}", + 'dzcaron' => "\x{01C6}", + 'dzcurl' => "\x{02A5}", + 'dzeabkhasiancyrillic' => "\x{04E1}", + 'dzecyrillic' => "\x{0455}", + 'dzhecyrillic' => "\x{045F}", + 'earth' => "\x{2641}", + 'ebengali' => "\x{098F}", + 'ebopomofo' => "\x{311C}", + 'ecandradeva' => "\x{090D}", + 'ecandragujarati' => "\x{0A8D}", + 'ecandravowelsigndeva' => "\x{0945}", + 'ecandravowelsigngujarati' => "\x{0AC5}", + 'ecedillabreve' => "\x{1E1D}", + 'echarmenian' => "\x{0565}", + 'echyiwnarmenian' => "\x{0587}", + 'ecircle' => "\x{24D4}", + 'ecircumflexacute' => "\x{1EBF}", + 'ecircumflexbelow' => "\x{1E19}", + 'ecircumflexdotbelow' => "\x{1EC7}", + 'ecircumflexgrave' => "\x{1EC1}", + 'ecircumflexhookabove' => "\x{1EC3}", + 'ecircumflextilde' => "\x{1EC5}", + 'ecyrillic' => "\x{0454}", + 'edblgrave' => "\x{0205}", + 'edeva' => "\x{090F}", + 'edot' => "\x{0117}", + 'edotbelow' => "\x{1EB9}", + 'eegurmukhi' => "\x{0A0F}", + 'eematragurmukhi' => "\x{0A47}", + 'efcyrillic' => "\x{0444}", + 'egujarati' => "\x{0A8F}", + 'eharmenian' => "\x{0567}", + 'ehbopomofo' => "\x{311D}", + 'ehiragana' => "\x{3048}", + 'ehookabove' => "\x{1EBB}", + 'eibopomofo' => "\x{311F}", + 'eightarabic' => "\x{0668}", + 'eightbengali' => "\x{09EE}", + 'eightcircle' => "\x{2467}", + 'eightcircleinversesansserif' => "\x{2791}", + 'eightdeva' => "\x{096E}", + 'eighteencircle' => "\x{2471}", + 'eighteenparen' => "\x{2485}", + 'eighteenperiod' => "\x{2499}", + 'eightgujarati' => "\x{0AEE}", + 'eightgurmukhi' => "\x{0A6E}", + 'eighthackarabic' => "\x{0668}", + 'eighthangzhou' => "\x{3028}", + 'eighthnotebeamed' => "\x{266B}", + 'eightideographicparen' => "\x{3227}", + 'eightinferior' => "\x{2088}", + 'eightmonospace' => "\x{FF18}", + 'eightoldstyle' => "\x{F738}", + 'eightparen' => "\x{247B}", + 'eightperiod' => "\x{248F}", + 'eightpersian' => "\x{06F8}", + 'eightroman' => "\x{2177}", + 'eightsuperior' => "\x{2078}", + 'eightthai' => "\x{0E58}", + 'einvertedbreve' => "\x{0207}", + 'eiotifiedcyrillic' => "\x{0465}", + 'ekatakana' => "\x{30A8}", + 'ekatakanahalfwidth' => "\x{FF74}", + 'ekonkargurmukhi' => "\x{0A74}", + 'ekorean' => "\x{3154}", + 'elcyrillic' => "\x{043B}", + 'elevencircle' => "\x{246A}", + 'elevenparen' => "\x{247E}", + 'elevenperiod' => "\x{2492}", + 'elevenroman' => "\x{217A}", + 'ellipsisvertical' => "\x{22EE}", + 'emacronacute' => "\x{1E17}", + 'emacrongrave' => "\x{1E15}", + 'emcyrillic' => "\x{043C}", + 'emdashvertical' => "\x{FE31}", + 'emonospace' => "\x{FF45}", + 'emphasismarkarmenian' => "\x{055B}", + 'enbopomofo' => "\x{3123}", + 'encyrillic' => "\x{043D}", + 'endashvertical' => "\x{FE32}", + 'endescendercyrillic' => "\x{04A3}", + 'engbopomofo' => "\x{3125}", + 'enghecyrillic' => "\x{04A5}", + 'enhookcyrillic' => "\x{04C8}", + 'enspace' => "\x{2002}", + 'eokorean' => "\x{3153}", + 'eopen' => "\x{025B}", + 'eopenclosed' => "\x{029A}", + 'eopenreversed' => "\x{025C}", + 'eopenreversedclosed' => "\x{025E}", + 'eopenreversedhook' => "\x{025D}", + 'eparen' => "\x{24A0}", + 'equalmonospace' => "\x{FF1D}", + 'equalsmall' => "\x{FE66}", + 'equalsuperior' => "\x{207C}", + 'erbopomofo' => "\x{3126}", + 'ercyrillic' => "\x{0440}", + 'ereversed' => "\x{0258}", + 'ereversedcyrillic' => "\x{044D}", + 'escyrillic' => "\x{0441}", + 'esdescendercyrillic' => "\x{04AB}", + 'esh' => "\x{0283}", + 'eshcurl' => "\x{0286}", + 'eshortdeva' => "\x{090E}", + 'eshortvowelsigndeva' => "\x{0946}", + 'eshreversedloop' => "\x{01AA}", + 'eshsquatreversed' => "\x{0285}", + 'esmallhiragana' => "\x{3047}", + 'esmallkatakana' => "\x{30A7}", + 'esmallkatakanahalfwidth' => "\x{FF6A}", + 'esuperior' => "\x{F6EC}", + 'etarmenian' => "\x{0568}", + 'etilde' => "\x{1EBD}", + 'etildebelow' => "\x{1E1B}", + 'etnahtafoukhhebrew' => "\x{0591}", + 'etnahtafoukhlefthebrew' => "\x{0591}", + 'etnahtahebrew' => "\x{0591}", + 'etnahtalefthebrew' => "\x{0591}", + 'eturned' => "\x{01DD}", + 'eukorean' => "\x{3161}", + 'euro' => "\x{20AC}", + 'evowelsignbengali' => "\x{09C7}", + 'evowelsigndeva' => "\x{0947}", + 'evowelsigngujarati' => "\x{0AC7}", + 'exclamarmenian' => "\x{055C}", + 'exclamdownsmall' => "\x{F7A1}", + 'exclammonospace' => "\x{FF01}", + 'exclamsmall' => "\x{F721}", + 'ezh' => "\x{0292}", + 'ezhcaron' => "\x{01EF}", + 'ezhcurl' => "\x{0293}", + 'ezhreversed' => "\x{01B9}", + 'ezhtail' => "\x{01BA}", + 'fadeva' => "\x{095E}", + 'fagurmukhi' => "\x{0A5E}", + 'fahrenheit' => "\x{2109}", + 'fathaarabic' => "\x{064E}", + 'fathalowarabic' => "\x{064E}", + 'fathatanarabic' => "\x{064B}", + 'fbopomofo' => "\x{3108}", + 'fcircle' => "\x{24D5}", + 'fdotaccent' => "\x{1E1F}", + 'feharabic' => "\x{0641}", + 'feharmenian' => "\x{0586}", + 'fehfinalarabic' => "\x{FED2}", + 'fehinitialarabic' => "\x{FED3}", + 'fehmedialarabic' => "\x{FED4}", + 'feicoptic' => "\x{03E5}", + 'fifteencircle' => "\x{246E}", + 'fifteenparen' => "\x{2482}", + 'fifteenperiod' => "\x{2496}", + 'finalkaf' => "\x{05DA}", + 'finalkafdagesh' => "\x{FB3A}", + 'finalkafdageshhebrew' => "\x{FB3A}", + 'finalkafhebrew' => "\x{05DA}", + 'finalkafqamats' => "\x{05DA}\x{05B8}", + 'finalkafqamatshebrew' => "\x{05DA}\x{05B8}", + 'finalkafsheva' => "\x{05DA}\x{05B0}", + 'finalkafshevahebrew' => "\x{05DA}\x{05B0}", + 'finalmem' => "\x{05DD}", + 'finalmemhebrew' => "\x{05DD}", + 'finalnun' => "\x{05DF}", + 'finalnunhebrew' => "\x{05DF}", + 'finalpe' => "\x{05E3}", + 'finalpehebrew' => "\x{05E3}", + 'finaltsadi' => "\x{05E5}", + 'finaltsadihebrew' => "\x{05E5}", + 'firsttonechinese' => "\x{02C9}", + 'fisheye' => "\x{25C9}", + 'fitacyrillic' => "\x{0473}", + 'fivearabic' => "\x{0665}", + 'fivebengali' => "\x{09EB}", + 'fivecircle' => "\x{2464}", + 'fivecircleinversesansserif' => "\x{278E}", + 'fivedeva' => "\x{096B}", + 'fivegujarati' => "\x{0AEB}", + 'fivegurmukhi' => "\x{0A6B}", + 'fivehackarabic' => "\x{0665}", + 'fivehangzhou' => "\x{3025}", + 'fiveideographicparen' => "\x{3224}", + 'fiveinferior' => "\x{2085}", + 'fivemonospace' => "\x{FF15}", + 'fiveoldstyle' => "\x{F735}", + 'fiveparen' => "\x{2478}", + 'fiveperiod' => "\x{248C}", + 'fivepersian' => "\x{06F5}", + 'fiveroman' => "\x{2174}", + 'fivesuperior' => "\x{2075}", + 'fivethai' => "\x{0E55}", + 'fmonospace' => "\x{FF46}", + 'fmsquare' => "\x{3399}", + 'fofanthai' => "\x{0E1F}", + 'fofathai' => "\x{0E1D}", + 'fongmanthai' => "\x{0E4F}", + 'forall' => "\x{2200}", + 'fourarabic' => "\x{0664}", + 'fourbengali' => "\x{09EA}", + 'fourcircle' => "\x{2463}", + 'fourcircleinversesansserif' => "\x{278D}", + 'fourdeva' => "\x{096A}", + 'fourgujarati' => "\x{0AEA}", + 'fourgurmukhi' => "\x{0A6A}", + 'fourhackarabic' => "\x{0664}", + 'fourhangzhou' => "\x{3024}", + 'fourideographicparen' => "\x{3223}", + 'fourinferior' => "\x{2084}", + 'fourmonospace' => "\x{FF14}", + 'fournumeratorbengali' => "\x{09F7}", + 'fouroldstyle' => "\x{F734}", + 'fourparen' => "\x{2477}", + 'fourperiod' => "\x{248B}", + 'fourpersian' => "\x{06F4}", + 'fourroman' => "\x{2173}", + 'foursuperior' => "\x{2074}", + 'fourteencircle' => "\x{246D}", + 'fourteenparen' => "\x{2481}", + 'fourteenperiod' => "\x{2495}", + 'fourthai' => "\x{0E54}", + 'fourthtonechinese' => "\x{02CB}", + 'fparen' => "\x{24A1}", + 'gabengali' => "\x{0997}", + 'gacute' => "\x{01F5}", + 'gadeva' => "\x{0917}", + 'gafarabic' => "\x{06AF}", + 'gaffinalarabic' => "\x{FB93}", + 'gafinitialarabic' => "\x{FB94}", + 'gafmedialarabic' => "\x{FB95}", + 'gagujarati' => "\x{0A97}", + 'gagurmukhi' => "\x{0A17}", + 'gahiragana' => "\x{304C}", + 'gakatakana' => "\x{30AC}", + 'gammalatinsmall' => "\x{0263}", + 'gammasuperior' => "\x{02E0}", + 'gangiacoptic' => "\x{03EB}", + 'gbopomofo' => "\x{310D}", + 'gcedilla' => "\x{0123}", + 'gcircle' => "\x{24D6}", + 'gdot' => "\x{0121}", + 'gecyrillic' => "\x{0433}", + 'gehiragana' => "\x{3052}", + 'gekatakana' => "\x{30B2}", + 'geometricallyequal' => "\x{2251}", + 'gereshaccenthebrew' => "\x{059C}", + 'gereshhebrew' => "\x{05F3}", + 'gereshmuqdamhebrew' => "\x{059D}", + 'gershayimaccenthebrew' => "\x{059E}", + 'gershayimhebrew' => "\x{05F4}", + 'getamark' => "\x{3013}", + 'ghabengali' => "\x{0998}", + 'ghadarmenian' => "\x{0572}", + 'ghadeva' => "\x{0918}", + 'ghagujarati' => "\x{0A98}", + 'ghagurmukhi' => "\x{0A18}", + 'ghainarabic' => "\x{063A}", + 'ghainfinalarabic' => "\x{FECE}", + 'ghaininitialarabic' => "\x{FECF}", + 'ghainmedialarabic' => "\x{FED0}", + 'ghemiddlehookcyrillic' => "\x{0495}", + 'ghestrokecyrillic' => "\x{0493}", + 'gheupturncyrillic' => "\x{0491}", + 'ghhadeva' => "\x{095A}", + 'ghhagurmukhi' => "\x{0A5A}", + 'ghook' => "\x{0260}", + 'ghzsquare' => "\x{3393}", + 'gihiragana' => "\x{304E}", + 'gikatakana' => "\x{30AE}", + 'gimarmenian' => "\x{0563}", + 'gimel' => "\x{05D2}", + 'gimeldagesh' => "\x{FB32}", + 'gimeldageshhebrew' => "\x{FB32}", + 'gimelhebrew' => "\x{05D2}", + 'gjecyrillic' => "\x{0453}", + 'glottalinvertedstroke' => "\x{01BE}", + 'glottalstop' => "\x{0294}", + 'glottalstopinverted' => "\x{0296}", + 'glottalstopmod' => "\x{02C0}", + 'glottalstopreversed' => "\x{0295}", + 'glottalstopreversedmod' => "\x{02C1}", + 'glottalstopreversedsuperior' => "\x{02E4}", + 'glottalstopstroke' => "\x{02A1}", + 'glottalstopstrokereversed' => "\x{02A2}", + 'gmacron' => "\x{1E21}", + 'gmonospace' => "\x{FF47}", + 'gohiragana' => "\x{3054}", + 'gokatakana' => "\x{30B4}", + 'gparen' => "\x{24A2}", + 'gpasquare' => "\x{33AC}", + 'gravebelowcmb' => "\x{0316}", + 'gravecmb' => "\x{0300}", + 'gravedeva' => "\x{0953}", + 'gravelowmod' => "\x{02CE}", + 'gravemonospace' => "\x{FF40}", + 'gravetonecmb' => "\x{0340}", + 'greaterequalorless' => "\x{22DB}", + 'greatermonospace' => "\x{FF1E}", + 'greaterorequivalent' => "\x{2273}", + 'greaterorless' => "\x{2277}", + 'greateroverequal' => "\x{2267}", + 'greatersmall' => "\x{FE65}", + 'gscript' => "\x{0261}", + 'gstroke' => "\x{01E5}", + 'guhiragana' => "\x{3050}", + 'gukatakana' => "\x{30B0}", + 'guramusquare' => "\x{3318}", + 'gysquare' => "\x{33C9}", + 'haabkhasiancyrillic' => "\x{04A9}", + 'haaltonearabic' => "\x{06C1}", + 'habengali' => "\x{09B9}", + 'hadescendercyrillic' => "\x{04B3}", + 'hadeva' => "\x{0939}", + 'hagujarati' => "\x{0AB9}", + 'hagurmukhi' => "\x{0A39}", + 'haharabic' => "\x{062D}", + 'hahfinalarabic' => "\x{FEA2}", + 'hahinitialarabic' => "\x{FEA3}", + 'hahiragana' => "\x{306F}", + 'hahmedialarabic' => "\x{FEA4}", + 'haitusquare' => "\x{332A}", + 'hakatakana' => "\x{30CF}", + 'hakatakanahalfwidth' => "\x{FF8A}", + 'halantgurmukhi' => "\x{0A4D}", + 'hamzaarabic' => "\x{0621}", + 'hamzadammaarabic' => "\x{0621}\x{064F}", + 'hamzadammatanarabic' => "\x{0621}\x{064C}", + 'hamzafathaarabic' => "\x{0621}\x{064E}", + 'hamzafathatanarabic' => "\x{0621}\x{064B}", + 'hamzalowarabic' => "\x{0621}", + 'hamzalowkasraarabic' => "\x{0621}\x{0650}", + 'hamzalowkasratanarabic' => "\x{0621}\x{064D}", + 'hamzasukunarabic' => "\x{0621}\x{0652}", + 'hangulfiller' => "\x{3164}", + 'hardsigncyrillic' => "\x{044A}", + 'harpoonleftbarbup' => "\x{21BC}", + 'harpoonrightbarbup' => "\x{21C0}", + 'hasquare' => "\x{33CA}", + 'hatafpatah' => "\x{05B2}", + 'hatafpatah16' => "\x{05B2}", + 'hatafpatah23' => "\x{05B2}", + 'hatafpatah2f' => "\x{05B2}", + 'hatafpatahhebrew' => "\x{05B2}", + 'hatafpatahnarrowhebrew' => "\x{05B2}", + 'hatafpatahquarterhebrew' => "\x{05B2}", + 'hatafpatahwidehebrew' => "\x{05B2}", + 'hatafqamats' => "\x{05B3}", + 'hatafqamats1b' => "\x{05B3}", + 'hatafqamats28' => "\x{05B3}", + 'hatafqamats34' => "\x{05B3}", + 'hatafqamatshebrew' => "\x{05B3}", + 'hatafqamatsnarrowhebrew' => "\x{05B3}", + 'hatafqamatsquarterhebrew' => "\x{05B3}", + 'hatafqamatswidehebrew' => "\x{05B3}", + 'hatafsegol' => "\x{05B1}", + 'hatafsegol17' => "\x{05B1}", + 'hatafsegol24' => "\x{05B1}", + 'hatafsegol30' => "\x{05B1}", + 'hatafsegolhebrew' => "\x{05B1}", + 'hatafsegolnarrowhebrew' => "\x{05B1}", + 'hatafsegolquarterhebrew' => "\x{05B1}", + 'hatafsegolwidehebrew' => "\x{05B1}", + 'hbopomofo' => "\x{310F}", + 'hbrevebelow' => "\x{1E2B}", + 'hcedilla' => "\x{1E29}", + 'hcircle' => "\x{24D7}", + 'hdieresis' => "\x{1E27}", + 'hdotaccent' => "\x{1E23}", + 'hdotbelow' => "\x{1E25}", + 'he' => "\x{05D4}", + 'heartsuitblack' => "\x{2665}", + 'heartsuitwhite' => "\x{2661}", + 'hedagesh' => "\x{FB34}", + 'hedageshhebrew' => "\x{FB34}", + 'hehaltonearabic' => "\x{06C1}", + 'heharabic' => "\x{0647}", + 'hehebrew' => "\x{05D4}", + 'hehfinalaltonearabic' => "\x{FBA7}", + 'hehfinalalttwoarabic' => "\x{FEEA}", + 'hehfinalarabic' => "\x{FEEA}", + 'hehhamzaabovefinalarabic' => "\x{FBA5}", + 'hehhamzaaboveisolatedarabic' => "\x{FBA4}", + 'hehinitialaltonearabic' => "\x{FBA8}", + 'hehinitialarabic' => "\x{FEEB}", + 'hehiragana' => "\x{3078}", + 'hehmedialaltonearabic' => "\x{FBA9}", + 'hehmedialarabic' => "\x{FEEC}", + 'heiseierasquare' => "\x{337B}", + 'hekatakana' => "\x{30D8}", + 'hekatakanahalfwidth' => "\x{FF8D}", + 'hekutaarusquare' => "\x{3336}", + 'henghook' => "\x{0267}", + 'herutusquare' => "\x{3339}", + 'het' => "\x{05D7}", + 'hethebrew' => "\x{05D7}", + 'hhook' => "\x{0266}", + 'hhooksuperior' => "\x{02B1}", + 'hieuhacirclekorean' => "\x{327B}", + 'hieuhaparenkorean' => "\x{321B}", + 'hieuhcirclekorean' => "\x{326D}", + 'hieuhkorean' => "\x{314E}", + 'hieuhparenkorean' => "\x{320D}", + 'hihiragana' => "\x{3072}", + 'hikatakana' => "\x{30D2}", + 'hikatakanahalfwidth' => "\x{FF8B}", + 'hiriq' => "\x{05B4}", + 'hiriq14' => "\x{05B4}", + 'hiriq21' => "\x{05B4}", + 'hiriq2d' => "\x{05B4}", + 'hiriqhebrew' => "\x{05B4}", + 'hiriqnarrowhebrew' => "\x{05B4}", + 'hiriqquarterhebrew' => "\x{05B4}", + 'hiriqwidehebrew' => "\x{05B4}", + 'hlinebelow' => "\x{1E96}", + 'hmonospace' => "\x{FF48}", + 'hoarmenian' => "\x{0570}", + 'hohipthai' => "\x{0E2B}", + 'hohiragana' => "\x{307B}", + 'hokatakana' => "\x{30DB}", + 'hokatakanahalfwidth' => "\x{FF8E}", + 'holam' => "\x{05B9}", + 'holam19' => "\x{05B9}", + 'holam26' => "\x{05B9}", + 'holam32' => "\x{05B9}", + 'holamhebrew' => "\x{05B9}", + 'holamnarrowhebrew' => "\x{05B9}", + 'holamquarterhebrew' => "\x{05B9}", + 'holamwidehebrew' => "\x{05B9}", + 'honokhukthai' => "\x{0E2E}", + 'hookcmb' => "\x{0309}", + 'hookpalatalizedbelowcmb' => "\x{0321}", + 'hookretroflexbelowcmb' => "\x{0322}", + 'hoonsquare' => "\x{3342}", + 'horicoptic' => "\x{03E9}", + 'horizontalbar' => "\x{2015}", + 'horncmb' => "\x{031B}", + 'hotsprings' => "\x{2668}", + 'hparen' => "\x{24A3}", + 'hsuperior' => "\x{02B0}", + 'hturned' => "\x{0265}", + 'huhiragana' => "\x{3075}", + 'huiitosquare' => "\x{3333}", + 'hukatakana' => "\x{30D5}", + 'hukatakanahalfwidth' => "\x{FF8C}", + 'hungarumlautcmb' => "\x{030B}", + 'hv' => "\x{0195}", + 'hypheninferior' => "\x{F6E5}", + 'hyphenmonospace' => "\x{FF0D}", + 'hyphensmall' => "\x{FE63}", + 'hyphensuperior' => "\x{F6E6}", + 'hyphentwo' => "\x{2010}", + 'iacyrillic' => "\x{044F}", + 'ibengali' => "\x{0987}", + 'ibopomofo' => "\x{3127}", + 'icaron' => "\x{01D0}", + 'icircle' => "\x{24D8}", + 'icyrillic' => "\x{0456}", + 'idblgrave' => "\x{0209}", + 'ideographearthcircle' => "\x{328F}", + 'ideographfirecircle' => "\x{328B}", + 'ideographicallianceparen' => "\x{323F}", + 'ideographiccallparen' => "\x{323A}", + 'ideographiccentrecircle' => "\x{32A5}", + 'ideographicclose' => "\x{3006}", + 'ideographiccomma' => "\x{3001}", + 'ideographiccommaleft' => "\x{FF64}", + 'ideographiccongratulationparen' => "\x{3237}", + 'ideographiccorrectcircle' => "\x{32A3}", + 'ideographicearthparen' => "\x{322F}", + 'ideographicenterpriseparen' => "\x{323D}", + 'ideographicexcellentcircle' => "\x{329D}", + 'ideographicfestivalparen' => "\x{3240}", + 'ideographicfinancialcircle' => "\x{3296}", + 'ideographicfinancialparen' => "\x{3236}", + 'ideographicfireparen' => "\x{322B}", + 'ideographichaveparen' => "\x{3232}", + 'ideographichighcircle' => "\x{32A4}", + 'ideographiciterationmark' => "\x{3005}", + 'ideographiclaborcircle' => "\x{3298}", + 'ideographiclaborparen' => "\x{3238}", + 'ideographicleftcircle' => "\x{32A7}", + 'ideographiclowcircle' => "\x{32A6}", + 'ideographicmedicinecircle' => "\x{32A9}", + 'ideographicmetalparen' => "\x{322E}", + 'ideographicmoonparen' => "\x{322A}", + 'ideographicnameparen' => "\x{3234}", + 'ideographicperiod' => "\x{3002}", + 'ideographicprintcircle' => "\x{329E}", + 'ideographicreachparen' => "\x{3243}", + 'ideographicrepresentparen' => "\x{3239}", + 'ideographicresourceparen' => "\x{323E}", + 'ideographicrightcircle' => "\x{32A8}", + 'ideographicsecretcircle' => "\x{3299}", + 'ideographicselfparen' => "\x{3242}", + 'ideographicsocietyparen' => "\x{3233}", + 'ideographicspace' => "\x{3000}", + 'ideographicspecialparen' => "\x{3235}", + 'ideographicstockparen' => "\x{3231}", + 'ideographicstudyparen' => "\x{323B}", + 'ideographicsunparen' => "\x{3230}", + 'ideographicsuperviseparen' => "\x{323C}", + 'ideographicwaterparen' => "\x{322C}", + 'ideographicwoodparen' => "\x{322D}", + 'ideographiczero' => "\x{3007}", + 'ideographmetalcircle' => "\x{328E}", + 'ideographmooncircle' => "\x{328A}", + 'ideographnamecircle' => "\x{3294}", + 'ideographsuncircle' => "\x{3290}", + 'ideographwatercircle' => "\x{328C}", + 'ideographwoodcircle' => "\x{328D}", + 'ideva' => "\x{0907}", + 'idieresisacute' => "\x{1E2F}", + 'idieresiscyrillic' => "\x{04E5}", + 'idotbelow' => "\x{1ECB}", + 'iebrevecyrillic' => "\x{04D7}", + 'iecyrillic' => "\x{0435}", + 'ieungacirclekorean' => "\x{3275}", + 'ieungaparenkorean' => "\x{3215}", + 'ieungcirclekorean' => "\x{3267}", + 'ieungkorean' => "\x{3147}", + 'ieungparenkorean' => "\x{3207}", + 'igujarati' => "\x{0A87}", + 'igurmukhi' => "\x{0A07}", + 'ihiragana' => "\x{3044}", + 'ihookabove' => "\x{1EC9}", + 'iibengali' => "\x{0988}", + 'iicyrillic' => "\x{0438}", + 'iideva' => "\x{0908}", + 'iigujarati' => "\x{0A88}", + 'iigurmukhi' => "\x{0A08}", + 'iimatragurmukhi' => "\x{0A40}", + 'iinvertedbreve' => "\x{020B}", + 'iishortcyrillic' => "\x{0439}", + 'iivowelsignbengali' => "\x{09C0}", + 'iivowelsigndeva' => "\x{0940}", + 'iivowelsigngujarati' => "\x{0AC0}", + 'ikatakana' => "\x{30A4}", + 'ikatakanahalfwidth' => "\x{FF72}", + 'ikorean' => "\x{3163}", + 'ilde' => "\x{02DC}", + 'iluyhebrew' => "\x{05AC}", + 'imacroncyrillic' => "\x{04E3}", + 'imageorapproximatelyequal' => "\x{2253}", + 'imatragurmukhi' => "\x{0A3F}", + 'imonospace' => "\x{FF49}", + 'increment' => "\x{2206}", + 'iniarmenian' => "\x{056B}", + 'integralbottom' => "\x{2321}", + 'integralex' => "\x{F8F5}", + 'integraltop' => "\x{2320}", + 'intisquare' => "\x{3305}", + 'iocyrillic' => "\x{0451}", + 'iotalatin' => "\x{0269}", + 'iparen' => "\x{24A4}", + 'irigurmukhi' => "\x{0A72}", + 'ismallhiragana' => "\x{3043}", + 'ismallkatakana' => "\x{30A3}", + 'ismallkatakanahalfwidth' => "\x{FF68}", + 'issharbengali' => "\x{09FA}", + 'istroke' => "\x{0268}", + 'isuperior' => "\x{F6ED}", + 'iterationhiragana' => "\x{309D}", + 'iterationkatakana' => "\x{30FD}", + 'itildebelow' => "\x{1E2D}", + 'iubopomofo' => "\x{3129}", + 'iucyrillic' => "\x{044E}", + 'ivowelsignbengali' => "\x{09BF}", + 'ivowelsigndeva' => "\x{093F}", + 'ivowelsigngujarati' => "\x{0ABF}", + 'izhitsacyrillic' => "\x{0475}", + 'izhitsadblgravecyrillic' => "\x{0477}", + 'jaarmenian' => "\x{0571}", + 'jabengali' => "\x{099C}", + 'jadeva' => "\x{091C}", + 'jagujarati' => "\x{0A9C}", + 'jagurmukhi' => "\x{0A1C}", + 'jbopomofo' => "\x{3110}", + 'jcaron' => "\x{01F0}", + 'jcircle' => "\x{24D9}", + 'jcrossedtail' => "\x{029D}", + 'jdotlessstroke' => "\x{025F}", + 'jecyrillic' => "\x{0458}", + 'jeemarabic' => "\x{062C}", + 'jeemfinalarabic' => "\x{FE9E}", + 'jeeminitialarabic' => "\x{FE9F}", + 'jeemmedialarabic' => "\x{FEA0}", + 'jeharabic' => "\x{0698}", + 'jehfinalarabic' => "\x{FB8B}", + 'jhabengali' => "\x{099D}", + 'jhadeva' => "\x{091D}", + 'jhagujarati' => "\x{0A9D}", + 'jhagurmukhi' => "\x{0A1D}", + 'jheharmenian' => "\x{057B}", + 'jis' => "\x{3004}", + 'jmonospace' => "\x{FF4A}", + 'jparen' => "\x{24A5}", + 'jsuperior' => "\x{02B2}", + 'kabashkircyrillic' => "\x{04A1}", + 'kabengali' => "\x{0995}", + 'kacute' => "\x{1E31}", + 'kacyrillic' => "\x{043A}", + 'kadescendercyrillic' => "\x{049B}", + 'kadeva' => "\x{0915}", + 'kaf' => "\x{05DB}", + 'kafarabic' => "\x{0643}", + 'kafdagesh' => "\x{FB3B}", + 'kafdageshhebrew' => "\x{FB3B}", + 'kaffinalarabic' => "\x{FEDA}", + 'kafhebrew' => "\x{05DB}", + 'kafinitialarabic' => "\x{FEDB}", + 'kafmedialarabic' => "\x{FEDC}", + 'kafrafehebrew' => "\x{FB4D}", + 'kagujarati' => "\x{0A95}", + 'kagurmukhi' => "\x{0A15}", + 'kahiragana' => "\x{304B}", + 'kahookcyrillic' => "\x{04C4}", + 'kakatakana' => "\x{30AB}", + 'kakatakanahalfwidth' => "\x{FF76}", + 'kappasymbolgreek' => "\x{03F0}", + 'kapyeounmieumkorean' => "\x{3171}", + 'kapyeounphieuphkorean' => "\x{3184}", + 'kapyeounpieupkorean' => "\x{3178}", + 'kapyeounssangpieupkorean' => "\x{3179}", + 'karoriisquare' => "\x{330D}", + 'kashidaautoarabic' => "\x{0640}", + 'kashidaautonosidebearingarabic' => "\x{0640}", + 'kasmallkatakana' => "\x{30F5}", + 'kasquare' => "\x{3384}", + 'kasraarabic' => "\x{0650}", + 'kasratanarabic' => "\x{064D}", + 'kastrokecyrillic' => "\x{049F}", + 'katahiraprolongmarkhalfwidth' => "\x{FF70}", + 'kaverticalstrokecyrillic' => "\x{049D}", + 'kbopomofo' => "\x{310E}", + 'kcalsquare' => "\x{3389}", + 'kcaron' => "\x{01E9}", + 'kcedilla' => "\x{0137}", + 'kcircle' => "\x{24DA}", + 'kdotbelow' => "\x{1E33}", + 'keharmenian' => "\x{0584}", + 'kehiragana' => "\x{3051}", + 'kekatakana' => "\x{30B1}", + 'kekatakanahalfwidth' => "\x{FF79}", + 'kenarmenian' => "\x{056F}", + 'kesmallkatakana' => "\x{30F6}", + 'khabengali' => "\x{0996}", + 'khacyrillic' => "\x{0445}", + 'khadeva' => "\x{0916}", + 'khagujarati' => "\x{0A96}", + 'khagurmukhi' => "\x{0A16}", + 'khaharabic' => "\x{062E}", + 'khahfinalarabic' => "\x{FEA6}", + 'khahinitialarabic' => "\x{FEA7}", + 'khahmedialarabic' => "\x{FEA8}", + 'kheicoptic' => "\x{03E7}", + 'khhadeva' => "\x{0959}", + 'khhagurmukhi' => "\x{0A59}", + 'khieukhacirclekorean' => "\x{3278}", + 'khieukhaparenkorean' => "\x{3218}", + 'khieukhcirclekorean' => "\x{326A}", + 'khieukhkorean' => "\x{314B}", + 'khieukhparenkorean' => "\x{320A}", + 'khokhaithai' => "\x{0E02}", + 'khokhonthai' => "\x{0E05}", + 'khokhuatthai' => "\x{0E03}", + 'khokhwaithai' => "\x{0E04}", + 'khomutthai' => "\x{0E5B}", + 'khook' => "\x{0199}", + 'khorakhangthai' => "\x{0E06}", + 'khzsquare' => "\x{3391}", + 'kihiragana' => "\x{304D}", + 'kikatakana' => "\x{30AD}", + 'kikatakanahalfwidth' => "\x{FF77}", + 'kiroguramusquare' => "\x{3315}", + 'kiromeetorusquare' => "\x{3316}", + 'kirosquare' => "\x{3314}", + 'kiyeokacirclekorean' => "\x{326E}", + 'kiyeokaparenkorean' => "\x{320E}", + 'kiyeokcirclekorean' => "\x{3260}", + 'kiyeokkorean' => "\x{3131}", + 'kiyeokparenkorean' => "\x{3200}", + 'kiyeoksioskorean' => "\x{3133}", + 'kjecyrillic' => "\x{045C}", + 'klinebelow' => "\x{1E35}", + 'klsquare' => "\x{3398}", + 'kmcubedsquare' => "\x{33A6}", + 'kmonospace' => "\x{FF4B}", + 'kmsquaredsquare' => "\x{33A2}", + 'kohiragana' => "\x{3053}", + 'kohmsquare' => "\x{33C0}", + 'kokaithai' => "\x{0E01}", + 'kokatakana' => "\x{30B3}", + 'kokatakanahalfwidth' => "\x{FF7A}", + 'kooposquare' => "\x{331E}", + 'koppacyrillic' => "\x{0481}", + 'koreanstandardsymbol' => "\x{327F}", + 'koroniscmb' => "\x{0343}", + 'kparen' => "\x{24A6}", + 'kpasquare' => "\x{33AA}", + 'ksicyrillic' => "\x{046F}", + 'ktsquare' => "\x{33CF}", + 'kturned' => "\x{029E}", + 'kuhiragana' => "\x{304F}", + 'kukatakana' => "\x{30AF}", + 'kukatakanahalfwidth' => "\x{FF78}", + 'kvsquare' => "\x{33B8}", + 'kwsquare' => "\x{33BE}", + 'labengali' => "\x{09B2}", + 'ladeva' => "\x{0932}", + 'lagujarati' => "\x{0AB2}", + 'lagurmukhi' => "\x{0A32}", + 'lakkhangyaothai' => "\x{0E45}", + 'lamaleffinalarabic' => "\x{FEFC}", + 'lamalefhamzaabovefinalarabic' => "\x{FEF8}", + 'lamalefhamzaaboveisolatedarabic' => "\x{FEF7}", + 'lamalefhamzabelowfinalarabic' => "\x{FEFA}", + 'lamalefhamzabelowisolatedarabic' => "\x{FEF9}", + 'lamalefisolatedarabic' => "\x{FEFB}", + 'lamalefmaddaabovefinalarabic' => "\x{FEF6}", + 'lamalefmaddaaboveisolatedarabic' => "\x{FEF5}", + 'lamarabic' => "\x{0644}", + 'lambdastroke' => "\x{019B}", + 'lamed' => "\x{05DC}", + 'lameddagesh' => "\x{FB3C}", + 'lameddageshhebrew' => "\x{FB3C}", + 'lamedhebrew' => "\x{05DC}", + 'lamedholam' => "\x{05DC}\x{05B9}", + 'lamedholamdagesh' => "\x{05DC}\x{05B9}\x{05BC}", + 'lamedholamdageshhebrew' => "\x{05DC}\x{05B9}\x{05BC}", + 'lamedholamhebrew' => "\x{05DC}\x{05B9}", + 'lamfinalarabic' => "\x{FEDE}", + 'lamhahinitialarabic' => "\x{FCCA}", + 'laminitialarabic' => "\x{FEDF}", + 'lamjeeminitialarabic' => "\x{FCC9}", + 'lamkhahinitialarabic' => "\x{FCCB}", + 'lamlamhehisolatedarabic' => "\x{FDF2}", + 'lammedialarabic' => "\x{FEE0}", + 'lammeemhahinitialarabic' => "\x{FD88}", + 'lammeeminitialarabic' => "\x{FCCC}", + 'lammeemjeeminitialarabic' => "\x{FEDF}\x{FEE4}\x{FEA0}", + 'lammeemkhahinitialarabic' => "\x{FEDF}\x{FEE4}\x{FEA8}", + 'largecircle' => "\x{25EF}", + 'lbar' => "\x{019A}", + 'lbelt' => "\x{026C}", + 'lbopomofo' => "\x{310C}", + 'lcedilla' => "\x{013C}", + 'lcircle' => "\x{24DB}", + 'lcircumflexbelow' => "\x{1E3D}", + 'ldotaccent' => "\x{0140}", + 'ldotbelow' => "\x{1E37}", + 'ldotbelowmacron' => "\x{1E39}", + 'leftangleabovecmb' => "\x{031A}", + 'lefttackbelowcmb' => "\x{0318}", + 'lessequalorgreater' => "\x{22DA}", + 'lessmonospace' => "\x{FF1C}", + 'lessorequivalent' => "\x{2272}", + 'lessorgreater' => "\x{2276}", + 'lessoverequal' => "\x{2266}", + 'lesssmall' => "\x{FE64}", + 'lezh' => "\x{026E}", + 'lhookretroflex' => "\x{026D}", + 'liwnarmenian' => "\x{056C}", + 'lj' => "\x{01C9}", + 'ljecyrillic' => "\x{0459}", + 'll' => "\x{F6C0}", + 'lladeva' => "\x{0933}", + 'llagujarati' => "\x{0AB3}", + 'llinebelow' => "\x{1E3B}", + 'llladeva' => "\x{0934}", + 'llvocalicbengali' => "\x{09E1}", + 'llvocalicdeva' => "\x{0961}", + 'llvocalicvowelsignbengali' => "\x{09E3}", + 'llvocalicvowelsigndeva' => "\x{0963}", + 'lmiddletilde' => "\x{026B}", + 'lmonospace' => "\x{FF4C}", + 'lmsquare' => "\x{33D0}", + 'lochulathai' => "\x{0E2C}", + 'logicalnotreversed' => "\x{2310}", + 'lolingthai' => "\x{0E25}", + 'lowlinecenterline' => "\x{FE4E}", + 'lowlinecmb' => "\x{0332}", + 'lowlinedashed' => "\x{FE4D}", + 'lparen' => "\x{24A7}", + 'lsquare' => "\x{2113}", + 'lsuperior' => "\x{F6EE}", + 'luthai' => "\x{0E26}", + 'lvocalicbengali' => "\x{098C}", + 'lvocalicdeva' => "\x{090C}", + 'lvocalicvowelsignbengali' => "\x{09E2}", + 'lvocalicvowelsigndeva' => "\x{0962}", + 'lxsquare' => "\x{33D3}", + 'mabengali' => "\x{09AE}", + 'macronbelowcmb' => "\x{0331}", + 'macroncmb' => "\x{0304}", + 'macronlowmod' => "\x{02CD}", + 'macronmonospace' => "\x{FFE3}", + 'macute' => "\x{1E3F}", + 'madeva' => "\x{092E}", + 'magujarati' => "\x{0AAE}", + 'magurmukhi' => "\x{0A2E}", + 'mahapakhhebrew' => "\x{05A4}", + 'mahapakhlefthebrew' => "\x{05A4}", + 'mahiragana' => "\x{307E}", + 'maichattawalowleftthai' => "\x{F895}", + 'maichattawalowrightthai' => "\x{F894}", + 'maichattawathai' => "\x{0E4B}", + 'maichattawaupperleftthai' => "\x{F893}", + 'maieklowleftthai' => "\x{F88C}", + 'maieklowrightthai' => "\x{F88B}", + 'maiekthai' => "\x{0E48}", + 'maiekupperleftthai' => "\x{F88A}", + 'maihanakatleftthai' => "\x{F884}", + 'maihanakatthai' => "\x{0E31}", + 'maitaikhuleftthai' => "\x{F889}", + 'maitaikhuthai' => "\x{0E47}", + 'maitholowleftthai' => "\x{F88F}", + 'maitholowrightthai' => "\x{F88E}", + 'maithothai' => "\x{0E49}", + 'maithoupperleftthai' => "\x{F88D}", + 'maitrilowleftthai' => "\x{F892}", + 'maitrilowrightthai' => "\x{F891}", + 'maitrithai' => "\x{0E4A}", + 'maitriupperleftthai' => "\x{F890}", + 'maiyamokthai' => "\x{0E46}", + 'makatakana' => "\x{30DE}", + 'makatakanahalfwidth' => "\x{FF8F}", + 'mansyonsquare' => "\x{3347}", + 'maqafhebrew' => "\x{05BE}", + 'mars' => "\x{2642}", + 'masoracirclehebrew' => "\x{05AF}", + 'masquare' => "\x{3383}", + 'mbopomofo' => "\x{3107}", + 'mbsquare' => "\x{33D4}", + 'mcircle' => "\x{24DC}", + 'mcubedsquare' => "\x{33A5}", + 'mdotaccent' => "\x{1E41}", + 'mdotbelow' => "\x{1E43}", + 'meemarabic' => "\x{0645}", + 'meemfinalarabic' => "\x{FEE2}", + 'meeminitialarabic' => "\x{FEE3}", + 'meemmedialarabic' => "\x{FEE4}", + 'meemmeeminitialarabic' => "\x{FCD1}", + 'meemmeemisolatedarabic' => "\x{FC48}", + 'meetorusquare' => "\x{334D}", + 'mehiragana' => "\x{3081}", + 'meizierasquare' => "\x{337E}", + 'mekatakana' => "\x{30E1}", + 'mekatakanahalfwidth' => "\x{FF92}", + 'mem' => "\x{05DE}", + 'memdagesh' => "\x{FB3E}", + 'memdageshhebrew' => "\x{FB3E}", + 'memhebrew' => "\x{05DE}", + 'menarmenian' => "\x{0574}", + 'merkhahebrew' => "\x{05A5}", + 'merkhakefulahebrew' => "\x{05A6}", + 'merkhakefulalefthebrew' => "\x{05A6}", + 'merkhalefthebrew' => "\x{05A5}", + 'mhook' => "\x{0271}", + 'mhzsquare' => "\x{3392}", + 'middledotkatakanahalfwidth' => "\x{FF65}", + 'middot' => "\x{00B7}", + 'mieumacirclekorean' => "\x{3272}", + 'mieumaparenkorean' => "\x{3212}", + 'mieumcirclekorean' => "\x{3264}", + 'mieumkorean' => "\x{3141}", + 'mieumpansioskorean' => "\x{3170}", + 'mieumparenkorean' => "\x{3204}", + 'mieumpieupkorean' => "\x{316E}", + 'mieumsioskorean' => "\x{316F}", + 'mihiragana' => "\x{307F}", + 'mikatakana' => "\x{30DF}", + 'mikatakanahalfwidth' => "\x{FF90}", + 'minusbelowcmb' => "\x{0320}", + 'minuscircle' => "\x{2296}", + 'minusmod' => "\x{02D7}", + 'minusplus' => "\x{2213}", + 'miribaarusquare' => "\x{334A}", + 'mirisquare' => "\x{3349}", + 'mlonglegturned' => "\x{0270}", + 'mlsquare' => "\x{3396}", + 'mmcubedsquare' => "\x{33A3}", + 'mmonospace' => "\x{FF4D}", + 'mmsquaredsquare' => "\x{339F}", + 'mohiragana' => "\x{3082}", + 'mohmsquare' => "\x{33C1}", + 'mokatakana' => "\x{30E2}", + 'mokatakanahalfwidth' => "\x{FF93}", + 'molsquare' => "\x{33D6}", + 'momathai' => "\x{0E21}", + 'moverssquare' => "\x{33A7}", + 'moverssquaredsquare' => "\x{33A8}", + 'mparen' => "\x{24A8}", + 'mpasquare' => "\x{33AB}", + 'mssquare' => "\x{33B3}", + 'msuperior' => "\x{F6EF}", + 'mturned' => "\x{026F}", + 'mu1' => "\x{00B5}", + 'muasquare' => "\x{3382}", + 'muchgreater' => "\x{226B}", + 'muchless' => "\x{226A}", + 'mufsquare' => "\x{338C}", + 'mugreek' => "\x{03BC}", + 'mugsquare' => "\x{338D}", + 'muhiragana' => "\x{3080}", + 'mukatakana' => "\x{30E0}", + 'mukatakanahalfwidth' => "\x{FF91}", + 'mulsquare' => "\x{3395}", + 'mumsquare' => "\x{339B}", + 'munahhebrew' => "\x{05A3}", + 'munahlefthebrew' => "\x{05A3}", + 'musicflatsign' => "\x{266D}", + 'musicsharpsign' => "\x{266F}", + 'mussquare' => "\x{33B2}", + 'muvsquare' => "\x{33B6}", + 'muwsquare' => "\x{33BC}", + 'mvmegasquare' => "\x{33B9}", + 'mvsquare' => "\x{33B7}", + 'mwmegasquare' => "\x{33BF}", + 'mwsquare' => "\x{33BD}", + 'nabengali' => "\x{09A8}", + 'nabla' => "\x{2207}", + 'nadeva' => "\x{0928}", + 'nagujarati' => "\x{0AA8}", + 'nagurmukhi' => "\x{0A28}", + 'nahiragana' => "\x{306A}", + 'nakatakana' => "\x{30CA}", + 'nakatakanahalfwidth' => "\x{FF85}", + 'nasquare' => "\x{3381}", + 'nbopomofo' => "\x{310B}", + 'nbspace' => "\x{00A0}", + 'ncedilla' => "\x{0146}", + 'ncircle' => "\x{24DD}", + 'ncircumflexbelow' => "\x{1E4B}", + 'ndotaccent' => "\x{1E45}", + 'ndotbelow' => "\x{1E47}", + 'nehiragana' => "\x{306D}", + 'nekatakana' => "\x{30CD}", + 'nekatakanahalfwidth' => "\x{FF88}", + 'newsheqelsign' => "\x{20AA}", + 'nfsquare' => "\x{338B}", + 'ngabengali' => "\x{0999}", + 'ngadeva' => "\x{0919}", + 'ngagujarati' => "\x{0A99}", + 'ngagurmukhi' => "\x{0A19}", + 'ngonguthai' => "\x{0E07}", + 'nhiragana' => "\x{3093}", + 'nhookleft' => "\x{0272}", + 'nhookretroflex' => "\x{0273}", + 'nieunacirclekorean' => "\x{326F}", + 'nieunaparenkorean' => "\x{320F}", + 'nieuncieuckorean' => "\x{3135}", + 'nieuncirclekorean' => "\x{3261}", + 'nieunhieuhkorean' => "\x{3136}", + 'nieunkorean' => "\x{3134}", + 'nieunpansioskorean' => "\x{3168}", + 'nieunparenkorean' => "\x{3201}", + 'nieunsioskorean' => "\x{3167}", + 'nieuntikeutkorean' => "\x{3166}", + 'nihiragana' => "\x{306B}", + 'nikatakana' => "\x{30CB}", + 'nikatakanahalfwidth' => "\x{FF86}", + 'nikhahitleftthai' => "\x{F899}", + 'nikhahitthai' => "\x{0E4D}", + 'ninearabic' => "\x{0669}", + 'ninebengali' => "\x{09EF}", + 'ninecircle' => "\x{2468}", + 'ninecircleinversesansserif' => "\x{2792}", + 'ninedeva' => "\x{096F}", + 'ninegujarati' => "\x{0AEF}", + 'ninegurmukhi' => "\x{0A6F}", + 'ninehackarabic' => "\x{0669}", + 'ninehangzhou' => "\x{3029}", + 'nineideographicparen' => "\x{3228}", + 'nineinferior' => "\x{2089}", + 'ninemonospace' => "\x{FF19}", + 'nineoldstyle' => "\x{F739}", + 'nineparen' => "\x{247C}", + 'nineperiod' => "\x{2490}", + 'ninepersian' => "\x{06F9}", + 'nineroman' => "\x{2178}", + 'ninesuperior' => "\x{2079}", + 'nineteencircle' => "\x{2472}", + 'nineteenparen' => "\x{2486}", + 'nineteenperiod' => "\x{249A}", + 'ninethai' => "\x{0E59}", + 'nj' => "\x{01CC}", + 'njecyrillic' => "\x{045A}", + 'nkatakana' => "\x{30F3}", + 'nkatakanahalfwidth' => "\x{FF9D}", + 'nlegrightlong' => "\x{019E}", + 'nlinebelow' => "\x{1E49}", + 'nmonospace' => "\x{FF4E}", + 'nmsquare' => "\x{339A}", + 'nnabengali' => "\x{09A3}", + 'nnadeva' => "\x{0923}", + 'nnagujarati' => "\x{0AA3}", + 'nnagurmukhi' => "\x{0A23}", + 'nnnadeva' => "\x{0929}", + 'nohiragana' => "\x{306E}", + 'nokatakana' => "\x{30CE}", + 'nokatakanahalfwidth' => "\x{FF89}", + 'nonbreakingspace' => "\x{00A0}", + 'nonenthai' => "\x{0E13}", + 'nonuthai' => "\x{0E19}", + 'noonarabic' => "\x{0646}", + 'noonfinalarabic' => "\x{FEE6}", + 'noonghunnaarabic' => "\x{06BA}", + 'noonghunnafinalarabic' => "\x{FB9F}", + 'noonhehinitialarabic' => "\x{FEE7}\x{FEEC}", + 'nooninitialarabic' => "\x{FEE7}", + 'noonjeeminitialarabic' => "\x{FCD2}", + 'noonjeemisolatedarabic' => "\x{FC4B}", + 'noonmedialarabic' => "\x{FEE8}", + 'noonmeeminitialarabic' => "\x{FCD5}", + 'noonmeemisolatedarabic' => "\x{FC4E}", + 'noonnoonfinalarabic' => "\x{FC8D}", + 'notcontains' => "\x{220C}", + 'notelementof' => "\x{2209}", + 'notgreater' => "\x{226F}", + 'notgreaternorequal' => "\x{2271}", + 'notgreaternorless' => "\x{2279}", + 'notidentical' => "\x{2262}", + 'notless' => "\x{226E}", + 'notlessnorequal' => "\x{2270}", + 'notparallel' => "\x{2226}", + 'notprecedes' => "\x{2280}", + 'notsucceeds' => "\x{2281}", + 'notsuperset' => "\x{2285}", + 'nowarmenian' => "\x{0576}", + 'nparen' => "\x{24A9}", + 'nssquare' => "\x{33B1}", + 'nsuperior' => "\x{207F}", + 'nuhiragana' => "\x{306C}", + 'nukatakana' => "\x{30CC}", + 'nukatakanahalfwidth' => "\x{FF87}", + 'nuktabengali' => "\x{09BC}", + 'nuktadeva' => "\x{093C}", + 'nuktagujarati' => "\x{0ABC}", + 'nuktagurmukhi' => "\x{0A3C}", + 'numbersignmonospace' => "\x{FF03}", + 'numbersignsmall' => "\x{FE5F}", + 'numeralsigngreek' => "\x{0374}", + 'numeralsignlowergreek' => "\x{0375}", + 'numero' => "\x{2116}", + 'nun' => "\x{05E0}", + 'nundagesh' => "\x{FB40}", + 'nundageshhebrew' => "\x{FB40}", + 'nunhebrew' => "\x{05E0}", + 'nvsquare' => "\x{33B5}", + 'nwsquare' => "\x{33BB}", + 'nyabengali' => "\x{099E}", + 'nyadeva' => "\x{091E}", + 'nyagujarati' => "\x{0A9E}", + 'nyagurmukhi' => "\x{0A1E}", + 'oangthai' => "\x{0E2D}", + 'obarred' => "\x{0275}", + 'obarredcyrillic' => "\x{04E9}", + 'obarreddieresiscyrillic' => "\x{04EB}", + 'obengali' => "\x{0993}", + 'obopomofo' => "\x{311B}", + 'ocandradeva' => "\x{0911}", + 'ocandragujarati' => "\x{0A91}", + 'ocandravowelsigndeva' => "\x{0949}", + 'ocandravowelsigngujarati' => "\x{0AC9}", + 'ocaron' => "\x{01D2}", + 'ocircle' => "\x{24DE}", + 'ocircumflexacute' => "\x{1ED1}", + 'ocircumflexdotbelow' => "\x{1ED9}", + 'ocircumflexgrave' => "\x{1ED3}", + 'ocircumflexhookabove' => "\x{1ED5}", + 'ocircumflextilde' => "\x{1ED7}", + 'ocyrillic' => "\x{043E}", + 'odblacute' => "\x{0151}", + 'odblgrave' => "\x{020D}", + 'odeva' => "\x{0913}", + 'odieresiscyrillic' => "\x{04E7}", + 'odotbelow' => "\x{1ECD}", + 'oekorean' => "\x{315A}", + 'ogonekcmb' => "\x{0328}", + 'ogujarati' => "\x{0A93}", + 'oharmenian' => "\x{0585}", + 'ohiragana' => "\x{304A}", + 'ohookabove' => "\x{1ECF}", + 'ohornacute' => "\x{1EDB}", + 'ohorndotbelow' => "\x{1EE3}", + 'ohorngrave' => "\x{1EDD}", + 'ohornhookabove' => "\x{1EDF}", + 'ohorntilde' => "\x{1EE1}", + 'oi' => "\x{01A3}", + 'oinvertedbreve' => "\x{020F}", + 'okatakana' => "\x{30AA}", + 'okatakanahalfwidth' => "\x{FF75}", + 'okorean' => "\x{3157}", + 'olehebrew' => "\x{05AB}", + 'omacronacute' => "\x{1E53}", + 'omacrongrave' => "\x{1E51}", + 'omdeva' => "\x{0950}", + 'omegacyrillic' => "\x{0461}", + 'omegalatinclosed' => "\x{0277}", + 'omegaroundcyrillic' => "\x{047B}", + 'omegatitlocyrillic' => "\x{047D}", + 'omgujarati' => "\x{0AD0}", + 'omonospace' => "\x{FF4F}", + 'onearabic' => "\x{0661}", + 'onebengali' => "\x{09E7}", + 'onecircle' => "\x{2460}", + 'onecircleinversesansserif' => "\x{278A}", + 'onedeva' => "\x{0967}", + 'onefitted' => "\x{F6DC}", + 'onegujarati' => "\x{0AE7}", + 'onegurmukhi' => "\x{0A67}", + 'onehackarabic' => "\x{0661}", + 'onehangzhou' => "\x{3021}", + 'oneideographicparen' => "\x{3220}", + 'oneinferior' => "\x{2081}", + 'onemonospace' => "\x{FF11}", + 'onenumeratorbengali' => "\x{09F4}", + 'oneoldstyle' => "\x{F731}", + 'oneparen' => "\x{2474}", + 'oneperiod' => "\x{2488}", + 'onepersian' => "\x{06F1}", + 'oneroman' => "\x{2170}", + 'onethai' => "\x{0E51}", + 'oogonek' => "\x{01EB}", + 'oogonekmacron' => "\x{01ED}", + 'oogurmukhi' => "\x{0A13}", + 'oomatragurmukhi' => "\x{0A4B}", + 'oopen' => "\x{0254}", + 'oparen' => "\x{24AA}", + 'option' => "\x{2325}", + 'oshortdeva' => "\x{0912}", + 'oshortvowelsigndeva' => "\x{094A}", + 'osmallhiragana' => "\x{3049}", + 'osmallkatakana' => "\x{30A9}", + 'osmallkatakanahalfwidth' => "\x{FF6B}", + 'ostrokeacute' => "\x{01FF}", + 'osuperior' => "\x{F6F0}", + 'otcyrillic' => "\x{047F}", + 'otildeacute' => "\x{1E4D}", + 'otildedieresis' => "\x{1E4F}", + 'oubopomofo' => "\x{3121}", + 'overline' => "\x{203E}", + 'overlinecenterline' => "\x{FE4A}", + 'overlinecmb' => "\x{0305}", + 'overlinedashed' => "\x{FE49}", + 'overlinedblwavy' => "\x{FE4C}", + 'overlinewavy' => "\x{FE4B}", + 'overscore' => "\x{00AF}", + 'ovowelsignbengali' => "\x{09CB}", + 'ovowelsigndeva' => "\x{094B}", + 'ovowelsigngujarati' => "\x{0ACB}", + 'paampssquare' => "\x{3380}", + 'paasentosquare' => "\x{332B}", + 'pabengali' => "\x{09AA}", + 'pacute' => "\x{1E55}", + 'padeva' => "\x{092A}", + 'pagedown' => "\x{21DF}", + 'pageup' => "\x{21DE}", + 'pagujarati' => "\x{0AAA}", + 'pagurmukhi' => "\x{0A2A}", + 'pahiragana' => "\x{3071}", + 'paiyannoithai' => "\x{0E2F}", + 'pakatakana' => "\x{30D1}", + 'palatalizationcyrilliccmb' => "\x{0484}", + 'palochkacyrillic' => "\x{04C0}", + 'pansioskorean' => "\x{317F}", + 'parallel' => "\x{2225}", + 'parenleftaltonearabic' => "\x{FD3E}", + 'parenleftbt' => "\x{F8ED}", + 'parenleftex' => "\x{F8EC}", + 'parenleftinferior' => "\x{208D}", + 'parenleftmonospace' => "\x{FF08}", + 'parenleftsmall' => "\x{FE59}", + 'parenleftsuperior' => "\x{207D}", + 'parenlefttp' => "\x{F8EB}", + 'parenleftvertical' => "\x{FE35}", + 'parenrightaltonearabic' => "\x{FD3F}", + 'parenrightbt' => "\x{F8F8}", + 'parenrightex' => "\x{F8F7}", + 'parenrightinferior' => "\x{208E}", + 'parenrightmonospace' => "\x{FF09}", + 'parenrightsmall' => "\x{FE5A}", + 'parenrightsuperior' => "\x{207E}", + 'parenrighttp' => "\x{F8F6}", + 'parenrightvertical' => "\x{FE36}", + 'paseqhebrew' => "\x{05C0}", + 'pashtahebrew' => "\x{0599}", + 'pasquare' => "\x{33A9}", + 'patah' => "\x{05B7}", + 'patah11' => "\x{05B7}", + 'patah1d' => "\x{05B7}", + 'patah2a' => "\x{05B7}", + 'patahhebrew' => "\x{05B7}", + 'patahnarrowhebrew' => "\x{05B7}", + 'patahquarterhebrew' => "\x{05B7}", + 'patahwidehebrew' => "\x{05B7}", + 'pazerhebrew' => "\x{05A1}", + 'pbopomofo' => "\x{3106}", + 'pcircle' => "\x{24DF}", + 'pdotaccent' => "\x{1E57}", + 'pe' => "\x{05E4}", + 'pecyrillic' => "\x{043F}", + 'pedagesh' => "\x{FB44}", + 'pedageshhebrew' => "\x{FB44}", + 'peezisquare' => "\x{333B}", + 'pefinaldageshhebrew' => "\x{FB43}", + 'peharabic' => "\x{067E}", + 'peharmenian' => "\x{057A}", + 'pehebrew' => "\x{05E4}", + 'pehfinalarabic' => "\x{FB57}", + 'pehinitialarabic' => "\x{FB58}", + 'pehiragana' => "\x{307A}", + 'pehmedialarabic' => "\x{FB59}", + 'pekatakana' => "\x{30DA}", + 'pemiddlehookcyrillic' => "\x{04A7}", + 'perafehebrew' => "\x{FB4E}", + 'percentarabic' => "\x{066A}", + 'percentmonospace' => "\x{FF05}", + 'percentsmall' => "\x{FE6A}", + 'periodarmenian' => "\x{0589}", + 'periodhalfwidth' => "\x{FF61}", + 'periodinferior' => "\x{F6E7}", + 'periodmonospace' => "\x{FF0E}", + 'periodsmall' => "\x{FE52}", + 'periodsuperior' => "\x{F6E8}", + 'perispomenigreekcmb' => "\x{0342}", + 'pfsquare' => "\x{338A}", + 'phabengali' => "\x{09AB}", + 'phadeva' => "\x{092B}", + 'phagujarati' => "\x{0AAB}", + 'phagurmukhi' => "\x{0A2B}", + 'phieuphacirclekorean' => "\x{327A}", + 'phieuphaparenkorean' => "\x{321A}", + 'phieuphcirclekorean' => "\x{326C}", + 'phieuphkorean' => "\x{314D}", + 'phieuphparenkorean' => "\x{320C}", + 'philatin' => "\x{0278}", + 'phinthuthai' => "\x{0E3A}", + 'phisymbolgreek' => "\x{03D5}", + 'phook' => "\x{01A5}", + 'phophanthai' => "\x{0E1E}", + 'phophungthai' => "\x{0E1C}", + 'phosamphaothai' => "\x{0E20}", + 'pieupacirclekorean' => "\x{3273}", + 'pieupaparenkorean' => "\x{3213}", + 'pieupcieuckorean' => "\x{3176}", + 'pieupcirclekorean' => "\x{3265}", + 'pieupkiyeokkorean' => "\x{3172}", + 'pieupkorean' => "\x{3142}", + 'pieupparenkorean' => "\x{3205}", + 'pieupsioskiyeokkorean' => "\x{3174}", + 'pieupsioskorean' => "\x{3144}", + 'pieupsiostikeutkorean' => "\x{3175}", + 'pieupthieuthkorean' => "\x{3177}", + 'pieuptikeutkorean' => "\x{3173}", + 'pihiragana' => "\x{3074}", + 'pikatakana' => "\x{30D4}", + 'pisymbolgreek' => "\x{03D6}", + 'piwrarmenian' => "\x{0583}", + 'plusbelowcmb' => "\x{031F}", + 'pluscircle' => "\x{2295}", + 'plusmod' => "\x{02D6}", + 'plusmonospace' => "\x{FF0B}", + 'plussmall' => "\x{FE62}", + 'plussuperior' => "\x{207A}", + 'pmonospace' => "\x{FF50}", + 'pmsquare' => "\x{33D8}", + 'pohiragana' => "\x{307D}", + 'pointingindexdownwhite' => "\x{261F}", + 'pointingindexleftwhite' => "\x{261C}", + 'pointingindexrightwhite' => "\x{261E}", + 'pointingindexupwhite' => "\x{261D}", + 'pokatakana' => "\x{30DD}", + 'poplathai' => "\x{0E1B}", + 'postalmark' => "\x{3012}", + 'postalmarkface' => "\x{3020}", + 'pparen' => "\x{24AB}", + 'precedes' => "\x{227A}", + 'primemod' => "\x{02B9}", + 'primereversed' => "\x{2035}", + 'projective' => "\x{2305}", + 'prolongedkana' => "\x{30FC}", + 'propellor' => "\x{2318}", + 'proportion' => "\x{2237}", + 'psicyrillic' => "\x{0471}", + 'psilipneumatacyrilliccmb' => "\x{0486}", + 'pssquare' => "\x{33B0}", + 'puhiragana' => "\x{3077}", + 'pukatakana' => "\x{30D7}", + 'pvsquare' => "\x{33B4}", + 'pwsquare' => "\x{33BA}", + 'qadeva' => "\x{0958}", + 'qadmahebrew' => "\x{05A8}", + 'qafarabic' => "\x{0642}", + 'qaffinalarabic' => "\x{FED6}", + 'qafinitialarabic' => "\x{FED7}", + 'qafmedialarabic' => "\x{FED8}", + 'qamats' => "\x{05B8}", + 'qamats10' => "\x{05B8}", + 'qamats1a' => "\x{05B8}", + 'qamats1c' => "\x{05B8}", + 'qamats27' => "\x{05B8}", + 'qamats29' => "\x{05B8}", + 'qamats33' => "\x{05B8}", + 'qamatsde' => "\x{05B8}", + 'qamatshebrew' => "\x{05B8}", + 'qamatsnarrowhebrew' => "\x{05B8}", + 'qamatsqatanhebrew' => "\x{05B8}", + 'qamatsqatannarrowhebrew' => "\x{05B8}", + 'qamatsqatanquarterhebrew' => "\x{05B8}", + 'qamatsqatanwidehebrew' => "\x{05B8}", + 'qamatsquarterhebrew' => "\x{05B8}", + 'qamatswidehebrew' => "\x{05B8}", + 'qarneyparahebrew' => "\x{059F}", + 'qbopomofo' => "\x{3111}", + 'qcircle' => "\x{24E0}", + 'qhook' => "\x{02A0}", + 'qmonospace' => "\x{FF51}", + 'qof' => "\x{05E7}", + 'qofdagesh' => "\x{FB47}", + 'qofdageshhebrew' => "\x{FB47}", + 'qofhatafpatah' => "\x{05E7}\x{05B2}", + 'qofhatafpatahhebrew' => "\x{05E7}\x{05B2}", + 'qofhatafsegol' => "\x{05E7}\x{05B1}", + 'qofhatafsegolhebrew' => "\x{05E7}\x{05B1}", + 'qofhebrew' => "\x{05E7}", + 'qofhiriq' => "\x{05E7}\x{05B4}", + 'qofhiriqhebrew' => "\x{05E7}\x{05B4}", + 'qofholam' => "\x{05E7}\x{05B9}", + 'qofholamhebrew' => "\x{05E7}\x{05B9}", + 'qofpatah' => "\x{05E7}\x{05B7}", + 'qofpatahhebrew' => "\x{05E7}\x{05B7}", + 'qofqamats' => "\x{05E7}\x{05B8}", + 'qofqamatshebrew' => "\x{05E7}\x{05B8}", + 'qofqubuts' => "\x{05E7}\x{05BB}", + 'qofqubutshebrew' => "\x{05E7}\x{05BB}", + 'qofsegol' => "\x{05E7}\x{05B6}", + 'qofsegolhebrew' => "\x{05E7}\x{05B6}", + 'qofsheva' => "\x{05E7}\x{05B0}", + 'qofshevahebrew' => "\x{05E7}\x{05B0}", + 'qoftsere' => "\x{05E7}\x{05B5}", + 'qoftserehebrew' => "\x{05E7}\x{05B5}", + 'qparen' => "\x{24AC}", + 'quarternote' => "\x{2669}", + 'qubuts' => "\x{05BB}", + 'qubuts18' => "\x{05BB}", + 'qubuts25' => "\x{05BB}", + 'qubuts31' => "\x{05BB}", + 'qubutshebrew' => "\x{05BB}", + 'qubutsnarrowhebrew' => "\x{05BB}", + 'qubutsquarterhebrew' => "\x{05BB}", + 'qubutswidehebrew' => "\x{05BB}", + 'questionarabic' => "\x{061F}", + 'questionarmenian' => "\x{055E}", + 'questiondownsmall' => "\x{F7BF}", + 'questiongreek' => "\x{037E}", + 'questionmonospace' => "\x{FF1F}", + 'questionsmall' => "\x{F73F}", + 'quotedblmonospace' => "\x{FF02}", + 'quotedblprime' => "\x{301E}", + 'quotedblprimereversed' => "\x{301D}", + 'quoteleftreversed' => "\x{201B}", + 'quoterightn' => "\x{0149}", + 'quotesinglemonospace' => "\x{FF07}", + 'raarmenian' => "\x{057C}", + 'rabengali' => "\x{09B0}", + 'radeva' => "\x{0930}", + 'radicalex' => "\x{F8E5}", + 'radoverssquare' => "\x{33AE}", + 'radoverssquaredsquare' => "\x{33AF}", + 'radsquare' => "\x{33AD}", + 'rafe' => "\x{05BF}", + 'rafehebrew' => "\x{05BF}", + 'ragujarati' => "\x{0AB0}", + 'ragurmukhi' => "\x{0A30}", + 'rahiragana' => "\x{3089}", + 'rakatakana' => "\x{30E9}", + 'rakatakanahalfwidth' => "\x{FF97}", + 'ralowerdiagonalbengali' => "\x{09F1}", + 'ramiddlediagonalbengali' => "\x{09F0}", + 'ramshorn' => "\x{0264}", + 'ratio' => "\x{2236}", + 'rbopomofo' => "\x{3116}", + 'rcedilla' => "\x{0157}", + 'rcircle' => "\x{24E1}", + 'rdblgrave' => "\x{0211}", + 'rdotaccent' => "\x{1E59}", + 'rdotbelow' => "\x{1E5B}", + 'rdotbelowmacron' => "\x{1E5D}", + 'referencemark' => "\x{203B}", + 'registersans' => "\x{F8E8}", + 'registerserif' => "\x{F6DA}", + 'reharabic' => "\x{0631}", + 'reharmenian' => "\x{0580}", + 'rehfinalarabic' => "\x{FEAE}", + 'rehiragana' => "\x{308C}", + 'rehyehaleflamarabic' => "\x{0631}\x{FEF3}\x{FE8E}\x{0644}", + 'rekatakana' => "\x{30EC}", + 'rekatakanahalfwidth' => "\x{FF9A}", + 'resh' => "\x{05E8}", + 'reshdageshhebrew' => "\x{FB48}", + 'reshhatafpatah' => "\x{05E8}\x{05B2}", + 'reshhatafpatahhebrew' => "\x{05E8}\x{05B2}", + 'reshhatafsegol' => "\x{05E8}\x{05B1}", + 'reshhatafsegolhebrew' => "\x{05E8}\x{05B1}", + 'reshhebrew' => "\x{05E8}", + 'reshhiriq' => "\x{05E8}\x{05B4}", + 'reshhiriqhebrew' => "\x{05E8}\x{05B4}", + 'reshholam' => "\x{05E8}\x{05B9}", + 'reshholamhebrew' => "\x{05E8}\x{05B9}", + 'reshpatah' => "\x{05E8}\x{05B7}", + 'reshpatahhebrew' => "\x{05E8}\x{05B7}", + 'reshqamats' => "\x{05E8}\x{05B8}", + 'reshqamatshebrew' => "\x{05E8}\x{05B8}", + 'reshqubuts' => "\x{05E8}\x{05BB}", + 'reshqubutshebrew' => "\x{05E8}\x{05BB}", + 'reshsegol' => "\x{05E8}\x{05B6}", + 'reshsegolhebrew' => "\x{05E8}\x{05B6}", + 'reshsheva' => "\x{05E8}\x{05B0}", + 'reshshevahebrew' => "\x{05E8}\x{05B0}", + 'reshtsere' => "\x{05E8}\x{05B5}", + 'reshtserehebrew' => "\x{05E8}\x{05B5}", + 'reversedtilde' => "\x{223D}", + 'reviahebrew' => "\x{0597}", + 'reviamugrashhebrew' => "\x{0597}", + 'rfishhook' => "\x{027E}", + 'rfishhookreversed' => "\x{027F}", + 'rhabengali' => "\x{09DD}", + 'rhadeva' => "\x{095D}", + 'rhook' => "\x{027D}", + 'rhookturned' => "\x{027B}", + 'rhookturnedsuperior' => "\x{02B5}", + 'rhosymbolgreek' => "\x{03F1}", + 'rhotichookmod' => "\x{02DE}", + 'rieulacirclekorean' => "\x{3271}", + 'rieulaparenkorean' => "\x{3211}", + 'rieulcirclekorean' => "\x{3263}", + 'rieulhieuhkorean' => "\x{3140}", + 'rieulkiyeokkorean' => "\x{313A}", + 'rieulkiyeoksioskorean' => "\x{3169}", + 'rieulkorean' => "\x{3139}", + 'rieulmieumkorean' => "\x{313B}", + 'rieulpansioskorean' => "\x{316C}", + 'rieulparenkorean' => "\x{3203}", + 'rieulphieuphkorean' => "\x{313F}", + 'rieulpieupkorean' => "\x{313C}", + 'rieulpieupsioskorean' => "\x{316B}", + 'rieulsioskorean' => "\x{313D}", + 'rieulthieuthkorean' => "\x{313E}", + 'rieultikeutkorean' => "\x{316A}", + 'rieulyeorinhieuhkorean' => "\x{316D}", + 'rightangle' => "\x{221F}", + 'righttackbelowcmb' => "\x{0319}", + 'righttriangle' => "\x{22BF}", + 'rihiragana' => "\x{308A}", + 'rikatakana' => "\x{30EA}", + 'rikatakanahalfwidth' => "\x{FF98}", + 'ringbelowcmb' => "\x{0325}", + 'ringcmb' => "\x{030A}", + 'ringhalfleft' => "\x{02BF}", + 'ringhalfleftarmenian' => "\x{0559}", + 'ringhalfleftbelowcmb' => "\x{031C}", + 'ringhalfleftcentered' => "\x{02D3}", + 'ringhalfright' => "\x{02BE}", + 'ringhalfrightbelowcmb' => "\x{0339}", + 'ringhalfrightcentered' => "\x{02D2}", + 'rinvertedbreve' => "\x{0213}", + 'rittorusquare' => "\x{3351}", + 'rlinebelow' => "\x{1E5F}", + 'rlongleg' => "\x{027C}", + 'rlonglegturned' => "\x{027A}", + 'rmonospace' => "\x{FF52}", + 'rohiragana' => "\x{308D}", + 'rokatakana' => "\x{30ED}", + 'rokatakanahalfwidth' => "\x{FF9B}", + 'roruathai' => "\x{0E23}", + 'rparen' => "\x{24AD}", + 'rrabengali' => "\x{09DC}", + 'rradeva' => "\x{0931}", + 'rragurmukhi' => "\x{0A5C}", + 'rreharabic' => "\x{0691}", + 'rrehfinalarabic' => "\x{FB8D}", + 'rrvocalicbengali' => "\x{09E0}", + 'rrvocalicdeva' => "\x{0960}", + 'rrvocalicgujarati' => "\x{0AE0}", + 'rrvocalicvowelsignbengali' => "\x{09C4}", + 'rrvocalicvowelsigndeva' => "\x{0944}", + 'rrvocalicvowelsigngujarati' => "\x{0AC4}", + 'rsuperior' => "\x{F6F1}", + 'rturned' => "\x{0279}", + 'rturnedsuperior' => "\x{02B4}", + 'ruhiragana' => "\x{308B}", + 'rukatakana' => "\x{30EB}", + 'rukatakanahalfwidth' => "\x{FF99}", + 'rupeemarkbengali' => "\x{09F2}", + 'rupeesignbengali' => "\x{09F3}", + 'rupiah' => "\x{F6DD}", + 'ruthai' => "\x{0E24}", + 'rvocalicbengali' => "\x{098B}", + 'rvocalicdeva' => "\x{090B}", + 'rvocalicgujarati' => "\x{0A8B}", + 'rvocalicvowelsignbengali' => "\x{09C3}", + 'rvocalicvowelsigndeva' => "\x{0943}", + 'rvocalicvowelsigngujarati' => "\x{0AC3}", + 'sabengali' => "\x{09B8}", + 'sacutedotaccent' => "\x{1E65}", + 'sadarabic' => "\x{0635}", + 'sadeva' => "\x{0938}", + 'sadfinalarabic' => "\x{FEBA}", + 'sadinitialarabic' => "\x{FEBB}", + 'sadmedialarabic' => "\x{FEBC}", + 'sagujarati' => "\x{0AB8}", + 'sagurmukhi' => "\x{0A38}", + 'sahiragana' => "\x{3055}", + 'sakatakana' => "\x{30B5}", + 'sakatakanahalfwidth' => "\x{FF7B}", + 'sallallahoualayhewasallamarabic' => "\x{FDFA}", + 'samekh' => "\x{05E1}", + 'samekhdagesh' => "\x{FB41}", + 'samekhdageshhebrew' => "\x{FB41}", + 'samekhhebrew' => "\x{05E1}", + 'saraaathai' => "\x{0E32}", + 'saraaethai' => "\x{0E41}", + 'saraaimaimalaithai' => "\x{0E44}", + 'saraaimaimuanthai' => "\x{0E43}", + 'saraamthai' => "\x{0E33}", + 'saraathai' => "\x{0E30}", + 'saraethai' => "\x{0E40}", + 'saraiileftthai' => "\x{F886}", + 'saraiithai' => "\x{0E35}", + 'saraileftthai' => "\x{F885}", + 'saraithai' => "\x{0E34}", + 'saraothai' => "\x{0E42}", + 'saraueeleftthai' => "\x{F888}", + 'saraueethai' => "\x{0E37}", + 'saraueleftthai' => "\x{F887}", + 'sarauethai' => "\x{0E36}", + 'sarauthai' => "\x{0E38}", + 'sarauuthai' => "\x{0E39}", + 'sbopomofo' => "\x{3119}", + 'scarondotaccent' => "\x{1E67}", + 'schwa' => "\x{0259}", + 'schwacyrillic' => "\x{04D9}", + 'schwadieresiscyrillic' => "\x{04DB}", + 'schwahook' => "\x{025A}", + 'scircle' => "\x{24E2}", + 'sdotaccent' => "\x{1E61}", + 'sdotbelow' => "\x{1E63}", + 'sdotbelowdotaccent' => "\x{1E69}", + 'seagullbelowcmb' => "\x{033C}", + 'secondtonechinese' => "\x{02CA}", + 'seenarabic' => "\x{0633}", + 'seenfinalarabic' => "\x{FEB2}", + 'seeninitialarabic' => "\x{FEB3}", + 'seenmedialarabic' => "\x{FEB4}", + 'segol' => "\x{05B6}", + 'segol13' => "\x{05B6}", + 'segol1f' => "\x{05B6}", + 'segol2c' => "\x{05B6}", + 'segolhebrew' => "\x{05B6}", + 'segolnarrowhebrew' => "\x{05B6}", + 'segolquarterhebrew' => "\x{05B6}", + 'segoltahebrew' => "\x{0592}", + 'segolwidehebrew' => "\x{05B6}", + 'seharmenian' => "\x{057D}", + 'sehiragana' => "\x{305B}", + 'sekatakana' => "\x{30BB}", + 'sekatakanahalfwidth' => "\x{FF7E}", + 'semicolonarabic' => "\x{061B}", + 'semicolonmonospace' => "\x{FF1B}", + 'semicolonsmall' => "\x{FE54}", + 'semivoicedmarkkana' => "\x{309C}", + 'semivoicedmarkkanahalfwidth' => "\x{FF9F}", + 'sentisquare' => "\x{3322}", + 'sentosquare' => "\x{3323}", + 'sevenarabic' => "\x{0667}", + 'sevenbengali' => "\x{09ED}", + 'sevencircle' => "\x{2466}", + 'sevencircleinversesansserif' => "\x{2790}", + 'sevendeva' => "\x{096D}", + 'sevengujarati' => "\x{0AED}", + 'sevengurmukhi' => "\x{0A6D}", + 'sevenhackarabic' => "\x{0667}", + 'sevenhangzhou' => "\x{3027}", + 'sevenideographicparen' => "\x{3226}", + 'seveninferior' => "\x{2087}", + 'sevenmonospace' => "\x{FF17}", + 'sevenoldstyle' => "\x{F737}", + 'sevenparen' => "\x{247A}", + 'sevenperiod' => "\x{248E}", + 'sevenpersian' => "\x{06F7}", + 'sevenroman' => "\x{2176}", + 'sevensuperior' => "\x{2077}", + 'seventeencircle' => "\x{2470}", + 'seventeenparen' => "\x{2484}", + 'seventeenperiod' => "\x{2498}", + 'seventhai' => "\x{0E57}", + 'sfthyphen' => "\x{00AD}", + 'shaarmenian' => "\x{0577}", + 'shabengali' => "\x{09B6}", + 'shacyrillic' => "\x{0448}", + 'shaddaarabic' => "\x{0651}", + 'shaddadammaarabic' => "\x{FC61}", + 'shaddadammatanarabic' => "\x{FC5E}", + 'shaddafathaarabic' => "\x{FC60}", + 'shaddafathatanarabic' => "\x{0651}\x{064B}", + 'shaddakasraarabic' => "\x{FC62}", + 'shaddakasratanarabic' => "\x{FC5F}", + 'shadedark' => "\x{2593}", + 'shadelight' => "\x{2591}", + 'shademedium' => "\x{2592}", + 'shadeva' => "\x{0936}", + 'shagujarati' => "\x{0AB6}", + 'shagurmukhi' => "\x{0A36}", + 'shalshelethebrew' => "\x{0593}", + 'shbopomofo' => "\x{3115}", + 'shchacyrillic' => "\x{0449}", + 'sheenarabic' => "\x{0634}", + 'sheenfinalarabic' => "\x{FEB6}", + 'sheeninitialarabic' => "\x{FEB7}", + 'sheenmedialarabic' => "\x{FEB8}", + 'sheicoptic' => "\x{03E3}", + 'sheqel' => "\x{20AA}", + 'sheqelhebrew' => "\x{20AA}", + 'sheva' => "\x{05B0}", + 'sheva115' => "\x{05B0}", + 'sheva15' => "\x{05B0}", + 'sheva22' => "\x{05B0}", + 'sheva2e' => "\x{05B0}", + 'shevahebrew' => "\x{05B0}", + 'shevanarrowhebrew' => "\x{05B0}", + 'shevaquarterhebrew' => "\x{05B0}", + 'shevawidehebrew' => "\x{05B0}", + 'shhacyrillic' => "\x{04BB}", + 'shimacoptic' => "\x{03ED}", + 'shin' => "\x{05E9}", + 'shindagesh' => "\x{FB49}", + 'shindageshhebrew' => "\x{FB49}", + 'shindageshshindot' => "\x{FB2C}", + 'shindageshshindothebrew' => "\x{FB2C}", + 'shindageshsindot' => "\x{FB2D}", + 'shindageshsindothebrew' => "\x{FB2D}", + 'shindothebrew' => "\x{05C1}", + 'shinhebrew' => "\x{05E9}", + 'shinshindot' => "\x{FB2A}", + 'shinshindothebrew' => "\x{FB2A}", + 'shinsindot' => "\x{FB2B}", + 'shinsindothebrew' => "\x{FB2B}", + 'shook' => "\x{0282}", + 'sigmafinal' => "\x{03C2}", + 'sigmalunatesymbolgreek' => "\x{03F2}", + 'sihiragana' => "\x{3057}", + 'sikatakana' => "\x{30B7}", + 'sikatakanahalfwidth' => "\x{FF7C}", + 'siluqhebrew' => "\x{05BD}", + 'siluqlefthebrew' => "\x{05BD}", + 'sindothebrew' => "\x{05C2}", + 'siosacirclekorean' => "\x{3274}", + 'siosaparenkorean' => "\x{3214}", + 'sioscieuckorean' => "\x{317E}", + 'sioscirclekorean' => "\x{3266}", + 'sioskiyeokkorean' => "\x{317A}", + 'sioskorean' => "\x{3145}", + 'siosnieunkorean' => "\x{317B}", + 'siosparenkorean' => "\x{3206}", + 'siospieupkorean' => "\x{317D}", + 'siostikeutkorean' => "\x{317C}", + 'sixarabic' => "\x{0666}", + 'sixbengali' => "\x{09EC}", + 'sixcircle' => "\x{2465}", + 'sixcircleinversesansserif' => "\x{278F}", + 'sixdeva' => "\x{096C}", + 'sixgujarati' => "\x{0AEC}", + 'sixgurmukhi' => "\x{0A6C}", + 'sixhackarabic' => "\x{0666}", + 'sixhangzhou' => "\x{3026}", + 'sixideographicparen' => "\x{3225}", + 'sixinferior' => "\x{2086}", + 'sixmonospace' => "\x{FF16}", + 'sixoldstyle' => "\x{F736}", + 'sixparen' => "\x{2479}", + 'sixperiod' => "\x{248D}", + 'sixpersian' => "\x{06F6}", + 'sixroman' => "\x{2175}", + 'sixsuperior' => "\x{2076}", + 'sixteencircle' => "\x{246F}", + 'sixteencurrencydenominatorbengali' => "\x{09F9}", + 'sixteenparen' => "\x{2483}", + 'sixteenperiod' => "\x{2497}", + 'sixthai' => "\x{0E56}", + 'slashmonospace' => "\x{FF0F}", + 'slong' => "\x{017F}", + 'slongdotaccent' => "\x{1E9B}", + 'smonospace' => "\x{FF53}", + 'sofpasuqhebrew' => "\x{05C3}", + 'softhyphen' => "\x{00AD}", + 'softsigncyrillic' => "\x{044C}", + 'sohiragana' => "\x{305D}", + 'sokatakana' => "\x{30BD}", + 'sokatakanahalfwidth' => "\x{FF7F}", + 'soliduslongoverlaycmb' => "\x{0338}", + 'solidusshortoverlaycmb' => "\x{0337}", + 'sorusithai' => "\x{0E29}", + 'sosalathai' => "\x{0E28}", + 'sosothai' => "\x{0E0B}", + 'sosuathai' => "\x{0E2A}", + 'spacehackarabic' => "\x{0020}", + 'spadesuitblack' => "\x{2660}", + 'spadesuitwhite' => "\x{2664}", + 'sparen' => "\x{24AE}", + 'squarebelowcmb' => "\x{033B}", + 'squarecc' => "\x{33C4}", + 'squarecm' => "\x{339D}", + 'squarediagonalcrosshatchfill' => "\x{25A9}", + 'squarehorizontalfill' => "\x{25A4}", + 'squarekg' => "\x{338F}", + 'squarekm' => "\x{339E}", + 'squarekmcapital' => "\x{33CE}", + 'squareln' => "\x{33D1}", + 'squarelog' => "\x{33D2}", + 'squaremg' => "\x{338E}", + 'squaremil' => "\x{33D5}", + 'squaremm' => "\x{339C}", + 'squaremsquared' => "\x{33A1}", + 'squareorthogonalcrosshatchfill' => "\x{25A6}", + 'squareupperlefttolowerrightfill' => "\x{25A7}", + 'squareupperrighttolowerleftfill' => "\x{25A8}", + 'squareverticalfill' => "\x{25A5}", + 'squarewhitewithsmallblack' => "\x{25A3}", + 'srsquare' => "\x{33DB}", + 'ssabengali' => "\x{09B7}", + 'ssadeva' => "\x{0937}", + 'ssagujarati' => "\x{0AB7}", + 'ssangcieuckorean' => "\x{3149}", + 'ssanghieuhkorean' => "\x{3185}", + 'ssangieungkorean' => "\x{3180}", + 'ssangkiyeokkorean' => "\x{3132}", + 'ssangnieunkorean' => "\x{3165}", + 'ssangpieupkorean' => "\x{3143}", + 'ssangsioskorean' => "\x{3146}", + 'ssangtikeutkorean' => "\x{3138}", + 'ssuperior' => "\x{F6F2}", + 'sterlingmonospace' => "\x{FFE1}", + 'strokelongoverlaycmb' => "\x{0336}", + 'strokeshortoverlaycmb' => "\x{0335}", + 'subset' => "\x{2282}", + 'subsetnotequal' => "\x{228A}", + 'subsetorequal' => "\x{2286}", + 'succeeds' => "\x{227B}", + 'suhiragana' => "\x{3059}", + 'sukatakana' => "\x{30B9}", + 'sukatakanahalfwidth' => "\x{FF7D}", + 'sukunarabic' => "\x{0652}", + 'superset' => "\x{2283}", + 'supersetnotequal' => "\x{228B}", + 'supersetorequal' => "\x{2287}", + 'svsquare' => "\x{33DC}", + 'syouwaerasquare' => "\x{337C}", + 'tabengali' => "\x{09A4}", + 'tackdown' => "\x{22A4}", + 'tackleft' => "\x{22A3}", + 'tadeva' => "\x{0924}", + 'tagujarati' => "\x{0AA4}", + 'tagurmukhi' => "\x{0A24}", + 'taharabic' => "\x{0637}", + 'tahfinalarabic' => "\x{FEC2}", + 'tahinitialarabic' => "\x{FEC3}", + 'tahiragana' => "\x{305F}", + 'tahmedialarabic' => "\x{FEC4}", + 'taisyouerasquare' => "\x{337D}", + 'takatakana' => "\x{30BF}", + 'takatakanahalfwidth' => "\x{FF80}", + 'tatweelarabic' => "\x{0640}", + 'tav' => "\x{05EA}", + 'tavdages' => "\x{FB4A}", + 'tavdagesh' => "\x{FB4A}", + 'tavdageshhebrew' => "\x{FB4A}", + 'tavhebrew' => "\x{05EA}", + 'tbopomofo' => "\x{310A}", + 'tccurl' => "\x{02A8}", + 'tcedilla' => "\x{0163}", + 'tcheharabic' => "\x{0686}", + 'tchehfinalarabic' => "\x{FB7B}", + 'tchehinitialarabic' => "\x{FB7C}", + 'tchehmedialarabic' => "\x{FB7D}", + 'tchehmeeminitialarabic' => "\x{FB7C}\x{FEE4}", + 'tcircle' => "\x{24E3}", + 'tcircumflexbelow' => "\x{1E71}", + 'tdieresis' => "\x{1E97}", + 'tdotaccent' => "\x{1E6B}", + 'tdotbelow' => "\x{1E6D}", + 'tecyrillic' => "\x{0442}", + 'tedescendercyrillic' => "\x{04AD}", + 'teharabic' => "\x{062A}", + 'tehfinalarabic' => "\x{FE96}", + 'tehhahinitialarabic' => "\x{FCA2}", + 'tehhahisolatedarabic' => "\x{FC0C}", + 'tehinitialarabic' => "\x{FE97}", + 'tehiragana' => "\x{3066}", + 'tehjeeminitialarabic' => "\x{FCA1}", + 'tehjeemisolatedarabic' => "\x{FC0B}", + 'tehmarbutaarabic' => "\x{0629}", + 'tehmarbutafinalarabic' => "\x{FE94}", + 'tehmedialarabic' => "\x{FE98}", + 'tehmeeminitialarabic' => "\x{FCA4}", + 'tehmeemisolatedarabic' => "\x{FC0E}", + 'tehnoonfinalarabic' => "\x{FC73}", + 'tekatakana' => "\x{30C6}", + 'tekatakanahalfwidth' => "\x{FF83}", + 'telephone' => "\x{2121}", + 'telephoneblack' => "\x{260E}", + 'telishagedolahebrew' => "\x{05A0}", + 'telishaqetanahebrew' => "\x{05A9}", + 'tencircle' => "\x{2469}", + 'tenideographicparen' => "\x{3229}", + 'tenparen' => "\x{247D}", + 'tenperiod' => "\x{2491}", + 'tenroman' => "\x{2179}", + 'tesh' => "\x{02A7}", + 'tet' => "\x{05D8}", + 'tetdagesh' => "\x{FB38}", + 'tetdageshhebrew' => "\x{FB38}", + 'tethebrew' => "\x{05D8}", + 'tetsecyrillic' => "\x{04B5}", + 'tevirhebrew' => "\x{059B}", + 'tevirlefthebrew' => "\x{059B}", + 'thabengali' => "\x{09A5}", + 'thadeva' => "\x{0925}", + 'thagujarati' => "\x{0AA5}", + 'thagurmukhi' => "\x{0A25}", + 'thalarabic' => "\x{0630}", + 'thalfinalarabic' => "\x{FEAC}", + 'thanthakhatlowleftthai' => "\x{F898}", + 'thanthakhatlowrightthai' => "\x{F897}", + 'thanthakhatthai' => "\x{0E4C}", + 'thanthakhatupperleftthai' => "\x{F896}", + 'theharabic' => "\x{062B}", + 'thehfinalarabic' => "\x{FE9A}", + 'thehinitialarabic' => "\x{FE9B}", + 'thehmedialarabic' => "\x{FE9C}", + 'thereexists' => "\x{2203}", + 'thetasymbolgreek' => "\x{03D1}", + 'thieuthacirclekorean' => "\x{3279}", + 'thieuthaparenkorean' => "\x{3219}", + 'thieuthcirclekorean' => "\x{326B}", + 'thieuthkorean' => "\x{314C}", + 'thieuthparenkorean' => "\x{320B}", + 'thirteencircle' => "\x{246C}", + 'thirteenparen' => "\x{2480}", + 'thirteenperiod' => "\x{2494}", + 'thonangmonthothai' => "\x{0E11}", + 'thook' => "\x{01AD}", + 'thophuthaothai' => "\x{0E12}", + 'thothahanthai' => "\x{0E17}", + 'thothanthai' => "\x{0E10}", + 'thothongthai' => "\x{0E18}", + 'thothungthai' => "\x{0E16}", + 'thousandcyrillic' => "\x{0482}", + 'thousandsseparatorarabic' => "\x{066C}", + 'thousandsseparatorpersian' => "\x{066C}", + 'threearabic' => "\x{0663}", + 'threebengali' => "\x{09E9}", + 'threecircle' => "\x{2462}", + 'threecircleinversesansserif' => "\x{278C}", + 'threedeva' => "\x{0969}", + 'threegujarati' => "\x{0AE9}", + 'threegurmukhi' => "\x{0A69}", + 'threehackarabic' => "\x{0663}", + 'threehangzhou' => "\x{3023}", + 'threeideographicparen' => "\x{3222}", + 'threeinferior' => "\x{2083}", + 'threemonospace' => "\x{FF13}", + 'threenumeratorbengali' => "\x{09F6}", + 'threeoldstyle' => "\x{F733}", + 'threeparen' => "\x{2476}", + 'threeperiod' => "\x{248A}", + 'threepersian' => "\x{06F3}", + 'threequartersemdash' => "\x{F6DE}", + 'threeroman' => "\x{2172}", + 'threethai' => "\x{0E53}", + 'thzsquare' => "\x{3394}", + 'tihiragana' => "\x{3061}", + 'tikatakana' => "\x{30C1}", + 'tikatakanahalfwidth' => "\x{FF81}", + 'tikeutacirclekorean' => "\x{3270}", + 'tikeutaparenkorean' => "\x{3210}", + 'tikeutcirclekorean' => "\x{3262}", + 'tikeutkorean' => "\x{3137}", + 'tikeutparenkorean' => "\x{3202}", + 'tildebelowcmb' => "\x{0330}", + 'tildecmb' => "\x{0303}", + 'tildedoublecmb' => "\x{0360}", + 'tildeoperator' => "\x{223C}", + 'tildeoverlaycmb' => "\x{0334}", + 'tildeverticalcmb' => "\x{033E}", + 'timescircle' => "\x{2297}", + 'tipehahebrew' => "\x{0596}", + 'tipehalefthebrew' => "\x{0596}", + 'tippigurmukhi' => "\x{0A70}", + 'titlocyrilliccmb' => "\x{0483}", + 'tiwnarmenian' => "\x{057F}", + 'tlinebelow' => "\x{1E6F}", + 'tmonospace' => "\x{FF54}", + 'toarmenian' => "\x{0569}", + 'tohiragana' => "\x{3068}", + 'tokatakana' => "\x{30C8}", + 'tokatakanahalfwidth' => "\x{FF84}", + 'tonebarextrahighmod' => "\x{02E5}", + 'tonebarextralowmod' => "\x{02E9}", + 'tonebarhighmod' => "\x{02E6}", + 'tonebarlowmod' => "\x{02E8}", + 'tonebarmidmod' => "\x{02E7}", + 'tonefive' => "\x{01BD}", + 'tonesix' => "\x{0185}", + 'tonetwo' => "\x{01A8}", + 'tonsquare' => "\x{3327}", + 'topatakthai' => "\x{0E0F}", + 'tortoiseshellbracketleft' => "\x{3014}", + 'tortoiseshellbracketleftsmall' => "\x{FE5D}", + 'tortoiseshellbracketleftvertical' => "\x{FE39}", + 'tortoiseshellbracketright' => "\x{3015}", + 'tortoiseshellbracketrightsmall' => "\x{FE5E}", + 'tortoiseshellbracketrightvertical' => "\x{FE3A}", + 'totaothai' => "\x{0E15}", + 'tpalatalhook' => "\x{01AB}", + 'tparen' => "\x{24AF}", + 'trademarksans' => "\x{F8EA}", + 'trademarkserif' => "\x{F6DB}", + 'tretroflexhook' => "\x{0288}", + 'ts' => "\x{02A6}", + 'tsadi' => "\x{05E6}", + 'tsadidagesh' => "\x{FB46}", + 'tsadidageshhebrew' => "\x{FB46}", + 'tsadihebrew' => "\x{05E6}", + 'tsecyrillic' => "\x{0446}", + 'tsere' => "\x{05B5}", + 'tsere12' => "\x{05B5}", + 'tsere1e' => "\x{05B5}", + 'tsere2b' => "\x{05B5}", + 'tserehebrew' => "\x{05B5}", + 'tserenarrowhebrew' => "\x{05B5}", + 'tserequarterhebrew' => "\x{05B5}", + 'tserewidehebrew' => "\x{05B5}", + 'tshecyrillic' => "\x{045B}", + 'tsuperior' => "\x{F6F3}", + 'ttabengali' => "\x{099F}", + 'ttadeva' => "\x{091F}", + 'ttagujarati' => "\x{0A9F}", + 'ttagurmukhi' => "\x{0A1F}", + 'tteharabic' => "\x{0679}", + 'ttehfinalarabic' => "\x{FB67}", + 'ttehinitialarabic' => "\x{FB68}", + 'ttehmedialarabic' => "\x{FB69}", + 'tthabengali' => "\x{09A0}", + 'tthadeva' => "\x{0920}", + 'tthagujarati' => "\x{0AA0}", + 'tthagurmukhi' => "\x{0A20}", + 'tturned' => "\x{0287}", + 'tuhiragana' => "\x{3064}", + 'tukatakana' => "\x{30C4}", + 'tukatakanahalfwidth' => "\x{FF82}", + 'tusmallhiragana' => "\x{3063}", + 'tusmallkatakana' => "\x{30C3}", + 'tusmallkatakanahalfwidth' => "\x{FF6F}", + 'twelvecircle' => "\x{246B}", + 'twelveparen' => "\x{247F}", + 'twelveperiod' => "\x{2493}", + 'twelveroman' => "\x{217B}", + 'twentycircle' => "\x{2473}", + 'twentyhangzhou' => "\x{5344}", + 'twentyparen' => "\x{2487}", + 'twentyperiod' => "\x{249B}", + 'twoarabic' => "\x{0662}", + 'twobengali' => "\x{09E8}", + 'twocircle' => "\x{2461}", + 'twocircleinversesansserif' => "\x{278B}", + 'twodeva' => "\x{0968}", + 'twodotleader' => "\x{2025}", + 'twodotleadervertical' => "\x{FE30}", + 'twogujarati' => "\x{0AE8}", + 'twogurmukhi' => "\x{0A68}", + 'twohackarabic' => "\x{0662}", + 'twohangzhou' => "\x{3022}", + 'twoideographicparen' => "\x{3221}", + 'twoinferior' => "\x{2082}", + 'twomonospace' => "\x{FF12}", + 'twonumeratorbengali' => "\x{09F5}", + 'twooldstyle' => "\x{F732}", + 'twoparen' => "\x{2475}", + 'twoperiod' => "\x{2489}", + 'twopersian' => "\x{06F2}", + 'tworoman' => "\x{2171}", + 'twostroke' => "\x{01BB}", + 'twothai' => "\x{0E52}", + 'ubar' => "\x{0289}", + 'ubengali' => "\x{0989}", + 'ubopomofo' => "\x{3128}", + 'ucaron' => "\x{01D4}", + 'ucircle' => "\x{24E4}", + 'ucircumflexbelow' => "\x{1E77}", + 'ucyrillic' => "\x{0443}", + 'udattadeva' => "\x{0951}", + 'udblacute' => "\x{0171}", + 'udblgrave' => "\x{0215}", + 'udeva' => "\x{0909}", + 'udieresisacute' => "\x{01D8}", + 'udieresisbelow' => "\x{1E73}", + 'udieresiscaron' => "\x{01DA}", + 'udieresiscyrillic' => "\x{04F1}", + 'udieresisgrave' => "\x{01DC}", + 'udieresismacron' => "\x{01D6}", + 'udotbelow' => "\x{1EE5}", + 'ugujarati' => "\x{0A89}", + 'ugurmukhi' => "\x{0A09}", + 'uhiragana' => "\x{3046}", + 'uhookabove' => "\x{1EE7}", + 'uhornacute' => "\x{1EE9}", + 'uhorndotbelow' => "\x{1EF1}", + 'uhorngrave' => "\x{1EEB}", + 'uhornhookabove' => "\x{1EED}", + 'uhorntilde' => "\x{1EEF}", + 'uhungarumlautcyrillic' => "\x{04F3}", + 'uinvertedbreve' => "\x{0217}", + 'ukatakana' => "\x{30A6}", + 'ukatakanahalfwidth' => "\x{FF73}", + 'ukcyrillic' => "\x{0479}", + 'ukorean' => "\x{315C}", + 'umacroncyrillic' => "\x{04EF}", + 'umacrondieresis' => "\x{1E7B}", + 'umatragurmukhi' => "\x{0A41}", + 'umonospace' => "\x{FF55}", + 'underscoremonospace' => "\x{FF3F}", + 'underscorevertical' => "\x{FE33}", + 'underscorewavy' => "\x{FE4F}", + 'uparen' => "\x{24B0}", + 'upperdothebrew' => "\x{05C4}", + 'upsilonlatin' => "\x{028A}", + 'uptackbelowcmb' => "\x{031D}", + 'uptackmod' => "\x{02D4}", + 'uragurmukhi' => "\x{0A73}", + 'ushortcyrillic' => "\x{045E}", + 'usmallhiragana' => "\x{3045}", + 'usmallkatakana' => "\x{30A5}", + 'usmallkatakanahalfwidth' => "\x{FF69}", + 'ustraightcyrillic' => "\x{04AF}", + 'ustraightstrokecyrillic' => "\x{04B1}", + 'utildeacute' => "\x{1E79}", + 'utildebelow' => "\x{1E75}", + 'uubengali' => "\x{098A}", + 'uudeva' => "\x{090A}", + 'uugujarati' => "\x{0A8A}", + 'uugurmukhi' => "\x{0A0A}", + 'uumatragurmukhi' => "\x{0A42}", + 'uuvowelsignbengali' => "\x{09C2}", + 'uuvowelsigndeva' => "\x{0942}", + 'uuvowelsigngujarati' => "\x{0AC2}", + 'uvowelsignbengali' => "\x{09C1}", + 'uvowelsigndeva' => "\x{0941}", + 'uvowelsigngujarati' => "\x{0AC1}", + 'vadeva' => "\x{0935}", + 'vagujarati' => "\x{0AB5}", + 'vagurmukhi' => "\x{0A35}", + 'vakatakana' => "\x{30F7}", + 'vav' => "\x{05D5}", + 'vavdagesh' => "\x{FB35}", + 'vavdagesh65' => "\x{FB35}", + 'vavdageshhebrew' => "\x{FB35}", + 'vavhebrew' => "\x{05D5}", + 'vavholam' => "\x{FB4B}", + 'vavholamhebrew' => "\x{FB4B}", + 'vavvavhebrew' => "\x{05F0}", + 'vavyodhebrew' => "\x{05F1}", + 'vcircle' => "\x{24E5}", + 'vdotbelow' => "\x{1E7F}", + 'vecyrillic' => "\x{0432}", + 'veharabic' => "\x{06A4}", + 'vehfinalarabic' => "\x{FB6B}", + 'vehinitialarabic' => "\x{FB6C}", + 'vehmedialarabic' => "\x{FB6D}", + 'vekatakana' => "\x{30F9}", + 'venus' => "\x{2640}", + 'verticalbar' => "\x{007C}", + 'verticallineabovecmb' => "\x{030D}", + 'verticallinebelowcmb' => "\x{0329}", + 'verticallinelowmod' => "\x{02CC}", + 'verticallinemod' => "\x{02C8}", + 'vewarmenian' => "\x{057E}", + 'vhook' => "\x{028B}", + 'vikatakana' => "\x{30F8}", + 'viramabengali' => "\x{09CD}", + 'viramadeva' => "\x{094D}", + 'viramagujarati' => "\x{0ACD}", + 'visargabengali' => "\x{0983}", + 'visargadeva' => "\x{0903}", + 'visargagujarati' => "\x{0A83}", + 'vmonospace' => "\x{FF56}", + 'voarmenian' => "\x{0578}", + 'voicediterationhiragana' => "\x{309E}", + 'voicediterationkatakana' => "\x{30FE}", + 'voicedmarkkana' => "\x{309B}", + 'voicedmarkkanahalfwidth' => "\x{FF9E}", + 'vokatakana' => "\x{30FA}", + 'vparen' => "\x{24B1}", + 'vtilde' => "\x{1E7D}", + 'vturned' => "\x{028C}", + 'vuhiragana' => "\x{3094}", + 'vukatakana' => "\x{30F4}", + 'waekorean' => "\x{3159}", + 'wahiragana' => "\x{308F}", + 'wakatakana' => "\x{30EF}", + 'wakatakanahalfwidth' => "\x{FF9C}", + 'wakorean' => "\x{3158}", + 'wasmallhiragana' => "\x{308E}", + 'wasmallkatakana' => "\x{30EE}", + 'wattosquare' => "\x{3357}", + 'wavedash' => "\x{301C}", + 'wavyunderscorevertical' => "\x{FE34}", + 'wawarabic' => "\x{0648}", + 'wawfinalarabic' => "\x{FEEE}", + 'wawhamzaabovearabic' => "\x{0624}", + 'wawhamzaabovefinalarabic' => "\x{FE86}", + 'wbsquare' => "\x{33DD}", + 'wcircle' => "\x{24E6}", + 'wdotaccent' => "\x{1E87}", + 'wdotbelow' => "\x{1E89}", + 'wehiragana' => "\x{3091}", + 'wekatakana' => "\x{30F1}", + 'wekorean' => "\x{315E}", + 'weokorean' => "\x{315D}", + 'whitebullet' => "\x{25E6}", + 'whitecircle' => "\x{25CB}", + 'whitecircleinverse' => "\x{25D9}", + 'whitecornerbracketleft' => "\x{300E}", + 'whitecornerbracketleftvertical' => "\x{FE43}", + 'whitecornerbracketright' => "\x{300F}", + 'whitecornerbracketrightvertical' => "\x{FE44}", + 'whitediamond' => "\x{25C7}", + 'whitediamondcontainingblacksmalldiamond' => "\x{25C8}", + 'whitedownpointingsmalltriangle' => "\x{25BF}", + 'whitedownpointingtriangle' => "\x{25BD}", + 'whiteleftpointingsmalltriangle' => "\x{25C3}", + 'whiteleftpointingtriangle' => "\x{25C1}", + 'whitelenticularbracketleft' => "\x{3016}", + 'whitelenticularbracketright' => "\x{3017}", + 'whiterightpointingsmalltriangle' => "\x{25B9}", + 'whiterightpointingtriangle' => "\x{25B7}", + 'whitesmallsquare' => "\x{25AB}", + 'whitesmilingface' => "\x{263A}", + 'whitesquare' => "\x{25A1}", + 'whitestar' => "\x{2606}", + 'whitetelephone' => "\x{260F}", + 'whitetortoiseshellbracketleft' => "\x{3018}", + 'whitetortoiseshellbracketright' => "\x{3019}", + 'whiteuppointingsmalltriangle' => "\x{25B5}", + 'whiteuppointingtriangle' => "\x{25B3}", + 'wihiragana' => "\x{3090}", + 'wikatakana' => "\x{30F0}", + 'wikorean' => "\x{315F}", + 'wmonospace' => "\x{FF57}", + 'wohiragana' => "\x{3092}", + 'wokatakana' => "\x{30F2}", + 'wokatakanahalfwidth' => "\x{FF66}", + 'won' => "\x{20A9}", + 'wonmonospace' => "\x{FFE6}", + 'wowaenthai' => "\x{0E27}", + 'wparen' => "\x{24B2}", + 'wring' => "\x{1E98}", + 'wsuperior' => "\x{02B7}", + 'wturned' => "\x{028D}", + 'wynn' => "\x{01BF}", + 'xabovecmb' => "\x{033D}", + 'xbopomofo' => "\x{3112}", + 'xcircle' => "\x{24E7}", + 'xdieresis' => "\x{1E8D}", + 'xdotaccent' => "\x{1E8B}", + 'xeharmenian' => "\x{056D}", + 'xmonospace' => "\x{FF58}", + 'xparen' => "\x{24B3}", + 'xsuperior' => "\x{02E3}", + 'yaadosquare' => "\x{334E}", + 'yabengali' => "\x{09AF}", + 'yadeva' => "\x{092F}", + 'yaekorean' => "\x{3152}", + 'yagujarati' => "\x{0AAF}", + 'yagurmukhi' => "\x{0A2F}", + 'yahiragana' => "\x{3084}", + 'yakatakana' => "\x{30E4}", + 'yakatakanahalfwidth' => "\x{FF94}", + 'yakorean' => "\x{3151}", + 'yamakkanthai' => "\x{0E4E}", + 'yasmallhiragana' => "\x{3083}", + 'yasmallkatakana' => "\x{30E3}", + 'yasmallkatakanahalfwidth' => "\x{FF6C}", + 'yatcyrillic' => "\x{0463}", + 'ycircle' => "\x{24E8}", + 'ydotaccent' => "\x{1E8F}", + 'ydotbelow' => "\x{1EF5}", + 'yeharabic' => "\x{064A}", + 'yehbarreearabic' => "\x{06D2}", + 'yehbarreefinalarabic' => "\x{FBAF}", + 'yehfinalarabic' => "\x{FEF2}", + 'yehhamzaabovearabic' => "\x{0626}", + 'yehhamzaabovefinalarabic' => "\x{FE8A}", + 'yehhamzaaboveinitialarabic' => "\x{FE8B}", + 'yehhamzaabovemedialarabic' => "\x{FE8C}", + 'yehinitialarabic' => "\x{FEF3}", + 'yehmedialarabic' => "\x{FEF4}", + 'yehmeeminitialarabic' => "\x{FCDD}", + 'yehmeemisolatedarabic' => "\x{FC58}", + 'yehnoonfinalarabic' => "\x{FC94}", + 'yehthreedotsbelowarabic' => "\x{06D1}", + 'yekorean' => "\x{3156}", + 'yenmonospace' => "\x{FFE5}", + 'yeokorean' => "\x{3155}", + 'yeorinhieuhkorean' => "\x{3186}", + 'yerahbenyomohebrew' => "\x{05AA}", + 'yerahbenyomolefthebrew' => "\x{05AA}", + 'yericyrillic' => "\x{044B}", + 'yerudieresiscyrillic' => "\x{04F9}", + 'yesieungkorean' => "\x{3181}", + 'yesieungpansioskorean' => "\x{3183}", + 'yesieungsioskorean' => "\x{3182}", + 'yetivhebrew' => "\x{059A}", + 'yhook' => "\x{01B4}", + 'yhookabove' => "\x{1EF7}", + 'yiarmenian' => "\x{0575}", + 'yicyrillic' => "\x{0457}", + 'yikorean' => "\x{3162}", + 'yinyang' => "\x{262F}", + 'yiwnarmenian' => "\x{0582}", + 'ymonospace' => "\x{FF59}", + 'yod' => "\x{05D9}", + 'yoddagesh' => "\x{FB39}", + 'yoddageshhebrew' => "\x{FB39}", + 'yodhebrew' => "\x{05D9}", + 'yodyodhebrew' => "\x{05F2}", + 'yodyodpatahhebrew' => "\x{FB1F}", + 'yohiragana' => "\x{3088}", + 'yoikorean' => "\x{3189}", + 'yokatakana' => "\x{30E8}", + 'yokatakanahalfwidth' => "\x{FF96}", + 'yokorean' => "\x{315B}", + 'yosmallhiragana' => "\x{3087}", + 'yosmallkatakana' => "\x{30E7}", + 'yosmallkatakanahalfwidth' => "\x{FF6E}", + 'yotgreek' => "\x{03F3}", + 'yoyaekorean' => "\x{3188}", + 'yoyakorean' => "\x{3187}", + 'yoyakthai' => "\x{0E22}", + 'yoyingthai' => "\x{0E0D}", + 'yparen' => "\x{24B4}", + 'ypogegrammeni' => "\x{037A}", + 'ypogegrammenigreekcmb' => "\x{0345}", + 'yr' => "\x{01A6}", + 'yring' => "\x{1E99}", + 'ysuperior' => "\x{02B8}", + 'ytilde' => "\x{1EF9}", + 'yturned' => "\x{028E}", + 'yuhiragana' => "\x{3086}", + 'yuikorean' => "\x{318C}", + 'yukatakana' => "\x{30E6}", + 'yukatakanahalfwidth' => "\x{FF95}", + 'yukorean' => "\x{3160}", + 'yusbigcyrillic' => "\x{046B}", + 'yusbigiotifiedcyrillic' => "\x{046D}", + 'yuslittlecyrillic' => "\x{0467}", + 'yuslittleiotifiedcyrillic' => "\x{0469}", + 'yusmallhiragana' => "\x{3085}", + 'yusmallkatakana' => "\x{30E5}", + 'yusmallkatakanahalfwidth' => "\x{FF6D}", + 'yuyekorean' => "\x{318B}", + 'yuyeokorean' => "\x{318A}", + 'yyabengali' => "\x{09DF}", + 'yyadeva' => "\x{095F}", + 'zaarmenian' => "\x{0566}", + 'zadeva' => "\x{095B}", + 'zagurmukhi' => "\x{0A5B}", + 'zaharabic' => "\x{0638}", + 'zahfinalarabic' => "\x{FEC6}", + 'zahinitialarabic' => "\x{FEC7}", + 'zahiragana' => "\x{3056}", + 'zahmedialarabic' => "\x{FEC8}", + 'zainarabic' => "\x{0632}", + 'zainfinalarabic' => "\x{FEB0}", + 'zakatakana' => "\x{30B6}", + 'zaqefgadolhebrew' => "\x{0595}", + 'zaqefqatanhebrew' => "\x{0594}", + 'zarqahebrew' => "\x{0598}", + 'zayin' => "\x{05D6}", + 'zayindagesh' => "\x{FB36}", + 'zayindageshhebrew' => "\x{FB36}", + 'zayinhebrew' => "\x{05D6}", + 'zbopomofo' => "\x{3117}", + 'zcircle' => "\x{24E9}", + 'zcircumflex' => "\x{1E91}", + 'zcurl' => "\x{0291}", + 'zdot' => "\x{017C}", + 'zdotbelow' => "\x{1E93}", + 'zecyrillic' => "\x{0437}", + 'zedescendercyrillic' => "\x{0499}", + 'zedieresiscyrillic' => "\x{04DF}", + 'zehiragana' => "\x{305C}", + 'zekatakana' => "\x{30BC}", + 'zeroarabic' => "\x{0660}", + 'zerobengali' => "\x{09E6}", + 'zerodeva' => "\x{0966}", + 'zerogujarati' => "\x{0AE6}", + 'zerogurmukhi' => "\x{0A66}", + 'zerohackarabic' => "\x{0660}", + 'zeroinferior' => "\x{2080}", + 'zeromonospace' => "\x{FF10}", + 'zerooldstyle' => "\x{F730}", + 'zeropersian' => "\x{06F0}", + 'zerosuperior' => "\x{2070}", + 'zerothai' => "\x{0E50}", + 'zerowidthjoiner' => "\x{FEFF}", + 'zerowidthnonjoiner' => "\x{200C}", + 'zerowidthspace' => "\x{200B}", + 'zhbopomofo' => "\x{3113}", + 'zhearmenian' => "\x{056A}", + 'zhebrevecyrillic' => "\x{04C2}", + 'zhecyrillic' => "\x{0436}", + 'zhedescendercyrillic' => "\x{0497}", + 'zhedieresiscyrillic' => "\x{04DD}", + 'zihiragana' => "\x{3058}", + 'zikatakana' => "\x{30B8}", + 'zinorhebrew' => "\x{05AE}", + 'zlinebelow' => "\x{1E95}", + 'zmonospace' => "\x{FF5A}", + 'zohiragana' => "\x{305E}", + 'zokatakana' => "\x{30BE}", + 'zparen' => "\x{24B5}", + 'zretroflexhook' => "\x{0290}", + 'zstroke' => "\x{01B6}", + 'zuhiragana' => "\x{305A}", + 'zukatakana' => "\x{30BA}", + ); + +# Add to this list the glyphs for new fonts (from aglfn13): + +map { $agl{$names{$_}} = pack('U',hex ($_))} (keys %names); + + +# %doubles = (map{$_ => "uni$_"} qw(0394 03A9 0162 2215 00AD 02C9 03BC 2219 00A0 0163)); + +=head2 lookup ( $usv [, $noAlt [, $noUni] ]) + +return the Adobe-recommended glyph name for a specific Unicode codepoint (integer). By default +returns C names rather than C or C names + +If C<$noAlt> is true, C and C names are returned rather than C. + +if C<$noUni> is true, returns undef if it would have to resort to C or C +style names. Essentially this represents a straight lookup in the Adobe-recommended list. + +=cut + +sub lookup +{ + my ($num, $noalt, $noUni) = @_; + my ($val) = sprintf("%04X", $num); + + if (defined $names{$val}) + { + return $names{$val} if ($noalt || $names{$val} !~ m/^(?:afii|SF)/o); + } + return undef if $noUni; + if ($num > 0xFFFF) + { return "u$val"; } + elsif ($num) + { return "uni$val"; } + else + { return ".notdef"; } +} + +=head2 parse ( $glyphname ) + +Parse an Adobe-conformant glyph name, generating a Unicode codepoint sequence equivalent to the glyph (or +glyph components, should the name represent a ligature). In scalar context, returns a reference to an +array of Unicodes (decimal). Array is empty if the glyph name is non-conformant. +In list context, the first item returned is the same array reference as above. The second item +is a reference to an array containing the extensions (if any) present on the glyph name. +The '.' that precedes each extension is not included. + +=cut + +sub parse +{ + my ($gname, @USVs, @extensions); + ($gname, @extensions) = split('\.', $_[0]); + # if name originally started with . (e.g., .null) then $gname will now be '' ... need to fix that up: + $gname = '.' . shift(@extensions) if $gname eq ''; + if (defined $gname) + { + foreach $gname (split('_', $gname)) + { + if ($gname =~ /^u[0-9a-fA-F]{4,6}$/) + { + push @USVs, hex(substr($gname, 1)); + } + elsif ($gname =~ /^uni([0-9a-fA-F]{4,4})+$/) + { + push @USVs, map {hex($_)} ($gname =~ /([0-9a-fA-F]{4,4})/g) + } + elsif (exists $agl{$gname}) + { + push @USVs, unpack ('U*', $agl{$gname}); + } + } + } + return \@USVs unless wantarray; + my @res = (\@USVs, \@extensions); + return @res; +} + +#Code used to parse Adobe's agl file and generate text for %agl initialization: +#while () { +# chomp; +# next if m/^#/; +# my ($gname, @nums) = split(/[; ]/); +# if ($#nums > 0 or !defined ($Font::TTF::PSNames::names{$nums[0]}) or $Font::TTF::PSNames::names{$nums[0]} ne $gname) +# { +# print "\t'$gname' => \""; +# map {print "\\x{$_}" } @nums; +# print "\",\n"; +# } +# } + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Post.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Post.pm new file mode 100644 index 0000000000..a3f29e2705 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Post.pm @@ -0,0 +1,329 @@ +package Font::TTF::Post; + +=head1 NAME + +Font::TTF::Post - Holds the Postscript names for each glyph + +=head1 DESCRIPTION + +Holds the postscript names for glyphs. Note that they are not held as an +array, but as indexes into two lists. The first list is the standard Postscript +name list defined by the TrueType standard. The second comes from the font +directly. + +Looking up a glyph from a Postscript name or a name from a glyph number is +achieved through methods rather than variable lookup. + +This class handles PostScript table types of 1, 2, 2.5 & 3, but not version 4. +Support for version 2.5 is as per Apple spec rather than MS. + +The way to look up Postscript names or glyphs is: + + $pname = $f->{'post'}{'VAL'}[$gnum]; + $gnum = $f->{'post'}{'STRINGS'}{$pname}; + +=head1 INSTANCE VARIABLES + +Due to different systems having different limitations, there are various class +variables available to control what post table types can be written. + +=over 4 + +=item $Font::TTF::Post::no25 + +If set tells Font::TTF::Post::out to use table type 2 instead of 2.5 in case apps +cannot handle version 2.5. + +=item VAL + +Contains an array indexed by glyph number of Postscript names. This is used when +writing out a font. + +=item STRINGS + +An associative array of Postscript names mapping to the highest glyph with that +name. These may not be in sync with VAL. + +=back + +In addition there are the standard introductory variables defined in the +standard: + + FormatType + italicAngle + underlinePosition + underlineThickness + isFixedPitch + minMemType42 + maxMemType42 + minMemType1 + maxMemType1 + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA @base_set %base_set %fields $VERSION $no25 @field_info @base_set); +require Font::TTF::Table; +use Font::TTF::Utils; + +$no25 = 1; # officially deprecated format 2.5 tables in MS spec 1.3 + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'FormatType' => 'f', + 'italicAngle' => 'f', + 'underlinePosition' => 's', + 'underlineThickness' => 's', + 'isFixedPitch' => 'L', + 'minMemType42' => 'L', + 'maxMemType42' => 'L', + 'minMemType1' => 'L', + 'maxMemType1' => 'L'); +@base_set = qw(.notdef .null nonmarkingreturn space exclam quotedbl numbersign dollar percent ampersand quotesingle + parenleft parenright asterisk plus comma hyphen period slash zero one two three four five six + seven eight nine colon semicolon less equal greater question at A B C D E F G H I J K L M N O P Q + R S T U V W X Y Z bracketleft backslash bracketright asciicircum underscore grave a b c d e f g h + i j k l m n o p q r s t u v w x y z braceleft bar braceright asciitilde Adieresis Aring Ccedilla + Eacute Ntilde Odieresis Udieresis aacute agrave acircumflex adieresis atilde aring ccedilla eacute + egrave ecircumflex edieresis iacute igrave icircumflex idieresis ntilde oacute ograve ocircumflex + odieresis otilde uacute ugrave ucircumflex udieresis dagger degree cent sterling section bullet + paragraph germandbls registered copyright trademark acute dieresis notequal AE Oslash infinity + plusminus lessequal greaterequal yen mu partialdiff summation product pi integral ordfeminine + ordmasculine Omega ae oslash questiondown exclamdown logicalnot radical florin approxequal + Delta guillemotleft guillemotright ellipsis nonbreakingspace Agrave Atilde Otilde OE oe endash emdash + quotedblleft quotedblright quoteleft quoteright divide lozenge ydieresis Ydieresis fraction currency + guilsinglleft guilsinglright fi fl daggerdbl periodcentered quotesinglbase quotedblbase perthousand + Acircumflex Ecircumflex Aacute Edieresis Egrave Iacute Icircumflex Idieresis Igrave Oacute Ocircumflex + apple Ograve Uacute Ucircumflex Ugrave dotlessi circumflex tilde macron breve dotaccent + ring cedilla hungarumlaut ogonek caron Lslash lslash Scaron scaron Zcaron zcaron brokenbar Eth eth + Yacute yacute Thorn thorn minus multiply onesuperior twosuperior threesuperior onehalf onequarter + threequarters franc Gbreve gbreve Idotaccent Scedilla scedilla Cacute cacute Ccaron ccaron dcroat); + +$VERSION = 0.01; # MJPH 5-AUG-1998 Re-organise data structures + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } + $i = 0; + %base_set = map {$_ => $i++} @base_set; +} + + +=head2 $t->read + +Reads the Postscript table into memory from disk + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $dat1, $i, $off, $c, $maxoff, $form, $angle, $numGlyphs); + my ($fh) = $self->{' INFILE'}; + + $numGlyphs = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + init unless ($fields{'FormatType'}); + $fh->read($dat, 32); + TTF_Read_Fields($self, $dat, \%fields); + + if (int($self->{'FormatType'} + .5) == 1) + { + for ($i = 0; $i < 258; $i++) + { + $self->{'VAL'}[$i] = $base_set[$i]; + $self->{'STRINGS'}{$base_set[$i]} = $i unless (defined $self->{'STRINGS'}{$base_set[$i]}); + } + } elsif (int($self->{'FormatType'} * 2 + .1) == 5) + { + $fh->read($dat, 2); + $numGlyphs = unpack("n", $dat); + $fh->read($dat, $numGlyphs); + for ($i = 0; $i < $numGlyphs; $i++) + { + $off = unpack("c", substr($dat, $i, 1)); + $self->{'VAL'}[$i] = $base_set[$i + $off]; + $self->{'STRINGS'}{$base_set[$i + $off]} = $i unless (defined $self->{'STRINGS'}{$base_set[$i + $off]}); + } + } elsif (int($self->{'FormatType'} + .5) == 2) + { + my (@strings); + + $fh->read($dat, ($numGlyphs + 1) << 1); + for ($i = 0; $i < $numGlyphs; $i++) + { + $off = unpack("n", substr($dat, ($i + 1) << 1, 2)); + $maxoff = $off if (!defined $maxoff || $off > $maxoff); + } + for ($i = 0; $i < $maxoff - 257; $i++) + { + $fh->read($dat1, 1); + $off = unpack("C", $dat1); + $fh->read($dat1, $off); + $strings[$i] = $dat1; + } + for ($i = 0; $i < $numGlyphs; $i++) + { + $off = unpack("n", substr($dat, ($i + 1) << 1, 2)); + if ($off > 257) + { + $self->{'VAL'}[$i] = $strings[$off - 258]; + $self->{'STRINGS'}{$strings[$off - 258]} = $i; + } + else + { + $self->{'VAL'}[$i] = $base_set[$off]; + $self->{'STRINGS'}{$base_set[$off]} = $i unless (defined $self->{'STRINGS'}{$base_set[$off]}); + } + } + } + $self; +} + + +=head2 $t->out($fh) + +Writes out a new Postscript name table from memory or copies from disk + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i, $num); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + init unless ($fields{'FormatType'}); + + for ($i = $#{$self->{'VAL'}}; !defined $self->{'VAL'}[$i] && $i > 0; $i--) + { pop(@{$self->{'VAL'}}); } + if ($#{$self->{'VAL'}} < 0) + { $self->{'FormatType'} = 3; } + else + { + $self->{'FormatType'} = 1; + for ($i = 0; $i < $num; $i++) + { + if (!defined $base_set{$self->{'VAL'}[$i]}) + { + $self->{'FormatType'} = 2; + last; + } + elsif ($base_set{$self->{'VAL'}[$i]} != $i) + { $self->{'FormatType'} = ($no25 ? 2 : 2.5); } + } + } + + $fh->print(TTF_Out_Fields($self, \%fields, 32)); + + return $self if (int($self->{'FormatType'} + .4) == 3); + + if (int($self->{'FormatType'} + .5) == 2) + { + my (@ind); + my ($count) = 0; + + $fh->print(pack("n", $num)); + for ($i = 0; $i < $num; $i++) + { + if (defined $base_set{$self->{'VAL'}[$i]}) + { $fh->print(pack("n", $base_set{$self->{'VAL'}[$i]})); } + else + { + $fh->print(pack("n", $count + 258)); + $ind[$count++] = $i; + } + } + for ($i = 0; $i < $count; $i++) + { + $fh->print(pack("C", length($self->{'VAL'}[$ind[$i]]))); + $fh->print($self->{'VAL'}[$ind[$i]]); + } + } elsif (int($self->{'FormatType'} * 2 + .5) == 5) + { + $fh->print(pack("n", $num)); + for ($i = 0; $i < $num; $i++) + { $fh->print(pack("c", defined $base_set{$self->{'VAL'}[$i]} ? + $base_set{$self->{'VAL'}[$i]} - $i : -$i)); } + } + + $self; +} + + +=head2 $t->XML_element($context, $depth, $key, $val) + +Outputs the names as one block of XML + +=cut + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $val) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self->SUPER::XML_element(@_) unless ($key eq 'STRINGS' || $key eq 'VAL'); + return unless ($key eq 'VAL'); + + $fh->print("$depth\n"); + for ($i = 0; $i <= $#{$self->{'VAL'}}; $i++) + { $fh->print("$depth$context->{'indent'}\n"); } + $fh->print("$depth\n"); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 32; +} + +1; + +=head1 BUGS + +=over 4 + +=item * + +No support for type 4 tables + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Prep.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Prep.pm new file mode 100644 index 0000000000..dae719369e --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Prep.pm @@ -0,0 +1,99 @@ +package Font::TTF::Prep; + +=head1 NAME + +Font::TTF::Prep - Preparation hinting program. Called when ppem changes + +=head1 DESCRIPTION + +This is a minimal class adding nothing beyond a table, but is a repository +for prep type information for those processes brave enough to address hinting. + +=cut + +use strict; +use vars qw(@ISA $VERSION); +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); + +$VERSION = 0.0001; + + +=head2 $t->read + +Reads the data using C. + +=cut + +sub read +{ + $_[0]->read_dat; + $_[0]->{' read'} = 1; +} + + +=head2 $t->out_xml($context, $depth) + +Outputs Prep program as XML + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($fh) = $context->{'fh'}; + my ($dat); + + $self->read; + $dat = Font::TTF::Utils::XML_binhint($self->{' dat'}); + $dat =~ s/\n(?!$)/\n$depth$context->{'indent'}/omg; + $fh->print("$depth\n"); + $fh->print("$depth$context->{'indent'}$dat"); + $fh->print("$depth\n"); + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Parse all that hinting code + +=cut + +sub XML_end +{ + my ($self) = shift; + my ($context, $tag, %attrs) = @_; + + if ($tag eq 'code') + { + $self->{' dat'} = Font::TTF::Utils::XML_hintbin($context->{'text'}); + return $context; + } else + { return $self->SUPER::XML_end(@_); } +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Prop.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Prop.pm new file mode 100644 index 0000000000..16c4dcc723 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Prop.pm @@ -0,0 +1,179 @@ +package Font::TTF::Prop; + +=head1 NAME + +Font::TTF::Prop - Glyph Properties table in a font + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over + +=item version + +=item default + +=item lookup + +Hash of property values keyed by glyph number + +=item lookupFormat + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +use Font::TTF::Utils; +use Font::TTF::AATutils; +use Font::TTF::Segarr; + +@ISA = qw(Font::TTF::Table); + +=head2 $t->read + +Reads the table into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($dat, $fh); + my ($version, $lookupPresent, $default); + + $self->SUPER::read or return $self; + + $fh = $self->{' INFILE'}; + $fh->read($dat, 8); + ($version, $lookupPresent, $default) = TTF_Unpack("vSS", $dat); + + if ($lookupPresent) { + my ($format, $lookup) = AAT_read_lookup($fh, 2, $self->{' LENGTH'} - 8, $default); + $self->{'lookup'} = $lookup; + $self->{'format'} = $format; + } + + $self->{'version'} = $version; + $self->{'default'} = $default; + + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($default, $lookup); + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $default = $self->{'default'}; + $lookup = $self->{'lookup'}; + $fh->print(TTF_Pack("vSS", $self->{'version'}, (defined $lookup ? 1 : 0), $default)); + + AAT_write_lookup($fh, $self->{'format'}, $lookup, 2, $default) if (defined $lookup); +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 8; +} + +=head2 $t->print($fh) + +Prints a human-readable representation of the table + +=cut + +sub print +{ + my ($self, $fh) = @_; + my ($lookup); + + $self->read; + + $fh = 'STDOUT' unless defined $fh; + + $fh->printf("version %f\ndefault %04x # %s\n", $self->{'version'}, $self->{'default'}, meaning_($self->{'default'})); + $lookup = $self->{'lookup'}; + if (defined $lookup) { + $fh->printf("format %d\n", $self->{'format'}); + foreach (sort { $a <=> $b } keys %$lookup) { + $fh->printf("\t%d -> %04x # %s\n", $_, $lookup->{$_}, meaning_($lookup->{$_})); + } + } +} + +sub meaning_ +{ + my ($val) = @_; + my ($res); + + my @types = ( + "Strong left-to-right", + "Strong right-to-left", + "Arabic letter", + "European number", + "European number separator", + "European number terminator", + "Arabic number", + "Common number separator", + "Block separator", + "Segment separator", + "Whitespace", + "Other neutral"); + $res = $types[$val & 0x001f] or ("Undefined [" . ($val & 0x001f) . "]"); + + $res .= ", floater" if $val & 0x8000; + $res .= ", hang left" if $val & 0x4000; + $res .= ", hang right" if $val & 0x2000; + $res .= ", attaches on right" if $val & 0x0080; + $res .= ", pair" if $val & 0x1000; + my $pairOffset = ($val & 0x0f00) >> 8; + $pairOffset = $pairOffset - 16 if $pairOffset > 7; + $res .= $pairOffset > 0 ? " +" . $pairOffset : $pairOffset < 0 ? " " . $pairOffset : ""; + + $res; +} + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Jonathan Kew L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Segarr.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Segarr.pm new file mode 100644 index 0000000000..514b605e13 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Segarr.pm @@ -0,0 +1,385 @@ +package Font::TTF::Segarr; + +=head1 NAME + +Font::TTF::Segarr - Segmented array + +=head1 DESCRIPTION + +Holds data either directly or indirectly as a series of arrays. This class +looks after the set of arrays and masks the individual sub-arrays, thus saving +a class, we hope. + +=head1 INSTANCE VARIABLES + +All instance variables do not start with a space. + +The segmented array is simply an array of segments + +Each segment is a more complex affair: + +=over 4 + +=item START + +In terms of the array, the address for the 0th element in this segment. + +=item LEN + +Number of elements in this segment + +=item VAL + +The array which contains the elements + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@types $VERSION); +$VERSION = 0.0001; + +@types = ('', 'C', 'n', '', 'N'); + +=head2 Font::TTF::Segarr->new($size) + +Creates a new segmented array with a given data size + +=cut + +sub new +{ + my ($class) = @_; + my ($self) = []; + + bless $self, (ref($class) || $class); +} + + +=head2 $s->fastadd_segment($start, $is_sparse, @dat) + +Creates a new segment and adds it to the array assuming no overlap between +the new segment and any others in the array. $is_sparse indicates whether the +passed in array contains Cs or not. If false no checking is done (which +is faster, but riskier). If equal to 2 then 0 is considered undef as well. + +Returns the number of segments inserted. + +=cut + +sub fastadd_segment +{ + my ($self) = shift; + my ($start) = shift; + my ($sparse) = shift; + my ($p, $i, $seg, @seg); + + + if ($sparse) + { + for ($i = 0; $i <= $#_; $i++) + { + if (!defined $seg && (($sparse != 2 && defined $_[$i]) || $_[$i] != 0)) + { $seg->{'START'} = $start + $i; $seg->{'VAL'} = []; } + + if (defined $seg && (($sparse == 2 && $_[$i] == 0) || !defined $_[$i])) + { + $seg->{'LEN'} = $start + $i - $seg->{'START'}; + push(@seg, $seg); + $seg = undef; + } elsif (defined $seg) + { push (@{$seg->{'VAL'}}, $_[$i]); } + } + if (defined $seg) + { + push(@seg, $seg); + $seg->{'LEN'} = $start + $i - $seg->{'START'}; + } + } else + { + $seg->{'START'} = $start; + $seg->{'LEN'} = $#_ + 1; + $seg->{'VAL'} = [@_]; + @seg = ($seg); + } + + for ($i = 0; $i <= $#$self; $i++) + { + if ($self->[$i]{'START'} > $start) + { + splice(@$self, $i, 0, @seg); + return wantarray ? @seg : scalar(@seg); + } + } + push(@$self, @seg); + return wantarray ? @seg : scalar(@seg); +} + + +=head2 $s->add_segment($start, $overwrite, @dat) + +Creates a new segment and adds it to the array allowing for possible overlaps +between the new segment and the existing ones. In the case of overlaps, elements +from the new segment are deleted unless $overwrite is set in which case the +elements already there are over-written. + +This method also checks the data coming in to see if it is sparse (i.e. contains +undef values). Gaps cause new segments to be created or not to over-write existing +values. + +=cut + +sub add_segment +{ + my ($self) = shift; + my ($start) = shift; + my ($over) = shift; + my ($seg, $i, $s, $offset, $j, $newi); + + return $self->fastadd_segment($start, $over, @_) if ($#$self < 0); + $offset = 0; + for ($i = 0; $i <= $#$self && $offset <= $#_; $i++) + { + $s = $self->[$i]; + if ($s->{'START'} <= $start + $offset) # only < for $offset == 0 + { + if ($s->{'START'} + $s->{'LEN'} > $start + $#_) + { + for ($j = $offset; $j <= $#_; $j++) + { + if ($over) + { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; } + else + { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; } + } + $offset = $#_ + 1; + last; + } elsif ($s->{'START'} + $s->{'LEN'} > $start + $offset) # is $offset needed here? + { + for ($j = $offset; $j < $s->{'START'} + $s->{'LEN'} - $start; $j++) + { + if ($over) + { $s->{'VAL'}[$start - $s->{'START'} + $j] = $_[$j] if defined $_[$j]; } + else + { $s->{'VAL'}[$start - $s->{'START'} + $j] ||= $_[$j] if defined $_[$j]; } + } + $offset = $s->{'START'} + $s->{'LEN'} - $start; + } + } else # new seg please + { + if ($s->{'START'} > $start + $#_ + 1) + { + $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $#_]) - 1; + $offset = $#_ + 1; + } + else + { + $i += $self->fastadd_segment($start + $offset, 1, @_[$offset .. $s->{'START'} - $start]) - 1; + $offset = $s->{'START'} - $start + 1; + } + } + } + if ($offset <= $#_) + { + $seg->{'START'} = $start + $offset; + $seg->{'LEN'} = $#_ - $offset + 1; + $seg->{'VAL'} = [@_[$offset .. $#_]]; + push (@$self, $seg); + } + $self->tidy; +} + + +=head2 $s->tidy + +Merges any immediately adjacent segments + +=cut + +sub tidy +{ + my ($self) = @_; + my ($i, $sl, $s); + + for ($i = 1; $i <= $#$self; $i++) + { + $sl = $self->[$i - 1]; + $s = $self->[$i]; + if ($s->{'START'} == $sl->{'START'} + $sl->{'LEN'}) + { + $sl->{'LEN'} += $s->{'LEN'}; + push (@{$sl->{'VAL'}}, @{$s->{'VAL'}}); + splice(@$self, $i, 1); + $i--; + } + } + $self; +} + + +=head2 $s->at($addr, [$len]) + +Looks up the data held at the given address by locating the appropriate segment +etc. If $len > 1 then returns an array of values, spaces being filled with undef. + +=cut + +sub at +{ + my ($self, $addr, $len) = @_; + my ($i, $dat, $s, @res, $offset); + + $len = 1 unless defined $len; + $offset = 0; + for ($i = 0; $i <= $#$self; $i++) + { + $s = $self->[$i]; + next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset); # only fires on $offset == 0 + if ($s->{'START'} > $addr + $offset) + { + push (@res, (undef) x ($s->{'START'} > $addr + $len ? + $len - $offset : $s->{'START'} - $addr - $offset)); + $offset = $s->{'START'} - $addr; + } + last if ($s->{'START'} >= $addr + $len); + + if ($s->{'START'} + $s->{'LEN'} >= $addr + $len) + { + push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} .. + $addr + $len - $s->{'START'} - 1]); + $offset = $len; + last; + } else + { + push (@res, @{$s->{'VAL'}}[$addr + $offset - $s->{'START'} .. $s->{'LEN'} - 1]); + $offset = $s->{'START'} + $s->{'LEN'} - $addr; + } + } + push (@res, (undef) x ($len - $offset)) if ($offset < $len); + return wantarray ? @res : $res[0]; +} + + +=head2 $s->remove($addr, [$len]) + +Removes the item or items from addr returning them as an array or the first +value in a scalar context. This is very like C, including padding with +undef, but it deletes stuff as it goes. + +=cut + +sub remove +{ + my ($self, $addr, $len) = @_; + my ($i, $dat, $s, @res, $offset); + + $len = 1 unless defined $len; + $offset = 0; + for ($i = 0; $i <= $#$self; $i++) + { + $s = $self->[$i]; + next if ($s->{'START'} + $s->{'LEN'} < $addr + $offset); + if ($s->{'START'} > $addr + $offset) + { + push (@res, (undef) x ($s->{'START'} > $addr + $len ? + $len - $offset : $s->{'START'} - $addr - $offset)); + $offset = $s->{'START'} - $addr; + } + last if ($s->{'START'} >= $addr + $len); + + unless ($s->{'START'} == $addr + $offset) + { + my ($seg) = {}; + + $seg->{'START'} = $s->{'START'}; + $seg->{'LEN'} = $addr + $offset - $s->{'START'}; + $seg->{'VAL'} = [splice(@{$s->{'VAL'}}, 0, $addr + $offset - $s->{'START'})]; + $s->{'LEN'} -= $addr + $offset - $s->{'START'}; + $s->{'START'} = $addr + $offset; + + splice(@$self, $i, 0, $seg); + $i++; + } + + if ($s->{'START'} + $s->{'LEN'} >= $addr + $len) + { + push (@res, splice(@{$s->{'VAL'}}, 0, $len - $offset)); + $s->{'LEN'} -= $len - $offset; + $s->{'START'} += $len - $offset; + $offset = $len; + last; + } else + { + push (@res, @{$s->{'VAL'}}); + $offset = $s->{'START'} + $s->{'LEN'} - $addr; + splice(@$self, $i, 0); + $i--; + } + } + push (@res, (undef) x ($len - $offset)) if ($offset < $len); + return wantarray ? @res : $res[0]; +} + + +=head2 $s->copy + +Deep copies this array + +=cut + +sub copy +{ + my ($self) = @_; + my ($res, $p); + + $res = []; + foreach $p (@$self) + { push (@$res, $self->copy_seg($p)); } + $res; +} + + +=head2 $s->copy_seg($seg) + +Creates a deep copy of a segment + +=cut + +sub copy_seg +{ + my ($self, $seg) = @_; + my ($p, $res); + + $res = {}; + $res->{'VAL'} = [@{$seg->{'VAL'}}]; + foreach $p (keys %$seg) + { $res->{$p} = $seg->{$p} unless defined $res->{$p}; } + $res; +} + + +1; + +=head1 BUGS + +No known bugs. + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Silf.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Silf.pm new file mode 100644 index 0000000000..9244c68934 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Silf.pm @@ -0,0 +1,900 @@ +package Font::TTF::Silf; + +=head1 NAME + +Font::TTF::Silf - The main Graphite table + +=head1 DESCRIPTION + +The Silf table holds the core of the Graphite rules for a font. A Silf table has +potentially multiple silf subtables, although there is usually only one. Within a silf subtable, +there are a number of passes which contain the actual finite state machines to match rules +and the constraint and action code to be executed when a rule matches. + +=head1 INSTANCE VARIABLES + +=over 4 + +=item Version + +Silf table format version + +=item Compiler + +Lowest compiler version necessary to fully support the semantics expressed in this +Graphite description + +=item SILF + +An array of Silf subtables + +=over 4 + +=item maxGlyphID + +The maximum glyph id referenced including pseudo and non glyphs + +=item Ascent + +Extra ascent to be added to the font ascent. + +=item Descent + +Extra descent to be added to the font descent. Both values are assumed to be +positive for a descender below the base line. + +=item substPass + +Pass index into PASS of the first substitution pass. + +=item posPass + +Pass index into PASS of the first positioning pass. + +=item justPass + +Pass index into PASS of the first justification pass. + +=item bidiPass + +Pass index of the pass before which the bidirectional processing pass will be executed. +0xFF indicates that there is no bidi pass to be executed. + +=item Flags + +A bitfield of flags: + + 0 - Indicates there are line end contextual rules in one of the passes + +=item maxPreContext + +Maximum length of a context preceding a cross line boundary contextualisation. + +=item maxPostContext + +Maximum length of a context following a cross line boundary contextualsation. + +=item attrPseudo + +Glyph attribute for the actual glyph id associated with a pseudo glyph. + +=item attrBreakWeight + +Glyph attribute number of the attribute holding the default breakweight associated with a glyph. + +=item attrDirectionality + +Glyph attribute number of the attribute holding the default directionality value associated with a glyph. + +=item JUST + +The may be a number of justification levels each with their own property values. +This points to an array of hashes, one for each justification level. + +=over 4 + +=item attrStretch + +Glyph attribute number for the amount of stretch allowed before this glyph. + +=item attrShrink + +Glyph attribute number for the amount of shrink allowed before this glyph. + +=item attrStep + +Glyph attribute number specifying the minimum granularity of actual spacing associated with this glyph at this level. + +=item attrWeight + +Glyph attribute number giving the weight associated with spreading space across a run of glyphs. + +=item runto + +Which level starts the next stage. + +=back + +=item numLigComp + +Number of initial glyph attributes that represent ligature components + +=item numUserAttr + +Number of user defined slot attributes referenced. Tells the engine how much space to +allocate to a slot for user attributes. + +=item maxCompPerLig + +Maximum number of components per ligature. + +=item direction + +Supported directions for this writing system + +=item CRIT_FEATURE + +Array of critical features. + +=item scripts + +Array of script tags that indicate which set of GDL rules to execute if there is more than one in a font. + +=item lbGID + +Glyph ID of the linebreak pseudo glyph. + +=item pseudos + +Hash of Unicode values to pseduo glyph ids. + +=item classes + +This is an array of classes, each of which is an array of glyph ids in class order. + +=item PASS + +The details of rules and actions are stored in passes. This value is an array of pass subobjects one for each pass. + +=over 4 + +=item flags + +This is a bitfield: + + 0 - If true, this pass makes no change to the slot stream considered as a sequence of glyph ids. + Only slot attributes are expected to change (for example during positioning). + +=item maxRuleLoop + +How many times the engine will allow rules to be tested and run without the engine advancing through the +input slot stream. + +=item maxRuleContext + +Number of slots of input needed to run this pass. + +=item maxBackup + +Number of slots by which the following pass needs to trail this pass (i.e. the maximum this pass is allowed to back up). + +=item numRules + +Number of action code blocks, and so uncompressed rules, in this pass. + +=item numRows + +Number of rows in the finite state machine. + +=item numTransitional + +Number of rows in the finite state machine that are not final states. This specifies the number of rows in the fsm +element. + +=item numSuccess + +Number of success states. A success state may also be a transitional state. + +=item numColumns + +Number of columns in the finite state machine. + +=item colmap + +A hash, indexed by glyphid, that gives the fsm column number associated with that glyphid. If not present, then +the glyphid is not part of the fsm and will finish fsm processing if it occurs. + +=item rulemap + +An array of arrays, one for each success state. Each array holds a list of rule numbers associated with that state. + +=item minRulePreContext + +Minimum number of items in a rule's precontext. + +=item maxRulePreContext + +The maximum number of items in any rule's precontext. + +=item startStates + +Array of starting state numbers dependeing on the length of actual precontext. +There are maxRulePreContext - minRulePreContext + 1 of these. + +=item ruleSortKeys + +An array of sort keys one for each rule giving the length of the rule including its precontext. + +=item rulePreContexts + +An array of precontext lengths for each rule. + +=item fsm + +A two dimensional array such that $p->{'fsm'}[$row][$col] gives the row of the next node to try in the fsm. + +=item passConstraintLen + +Length in bytes of the passConstraint code. + +=item passConstraintCode + +A byte string holding the pass constraint code. + +=item constraintCode + +An array of byte strings holding the constraint code for each rule. + +=item actionCode + +An array of byte strings holding the action code for each rule. + +=back + +=back + +=back + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use strict; +use vars qw(@ISA); + +@ISA = qw(Font::TTF::Table); + +=head2 @opcodes + +Each array holds the name of the opcode, the number of operand bytes and a string describing the operands. +The characters in the string have the following meaning: + + c - lsb of class id + C - msb of class id + f - feature index + g - lsb of glyph attribute id + G - msb of glyph attribute id + l - lsb of a 32-bit extension to a 16-bit number + L - msb of a 32-bit number + m - glyph metric id + n - lsb of a number + N - msb of a 16-bit number + o - offset (jump) + s - slot reference + S - slot attribute id + v - variable number of following arguments + +=cut + +our @opcodes = ( ["nop", 0, ""], ["push_byte", 1, "n"], ["push_byte_u", 1, "n"], ["push_short", 2, "Nn"], + ["push_short_u", 2, "Nn"], ["push_long", 4, "LlNn"], ["add", 0, ""], ["sub", 0, ""], + ["mul", 0, ""], ["div", 0, ""], ["min", 0, ""], ["max", 0, ""], + ["neg", 0, ""], ["trunc8", 0, ""], ["trunc16", 0, ""], ["cond", 0, ""], + ["and", 0, ""], ["or", 0, ""], ["not", 0, ""], ["equal", 0, ""], # 16 + ["not_eq", 0, ""], ["less", 0, ""], ["gtr", 0, ""], ["less_eq", 0, ""], + ["gtr_eq", 0, ""], ["next", 0, ""], ["next_n", 1, "n"], ["copy_next", 0, ""], + ["put_glyph_8bit_obs", 1, "c"], ["put_subs_8bit_obs", 3, "scc"], ["put_copy", 1, "s"], ["insert", 0, ""], + ["delete", 0, ""], ["assoc", -1, "v"], ["cntxt_item", 2, "so"], ["attr_set", 1, "S"], # 32 + ["attr_add", 1, "S"], ["attr_sub", 1, "S"], ["attr_set_slot", 1, "S"], ["iattr_set_slot", 2, "Sn"], + ["push_slot_attr", 2, "Ss"], ["push_glyph_attr_obs", 2, "gs"], ["push_glyph_metric", 3, "msn"], ["push_feat", 2, "fs"], + ["push_att_to_gattr_obs", 2, "gs"], ["push_att_to_glyph_metric", 3, "msn"], ["push_islot_attr", 3, "Ssn"], ["push_iglyph_attr", 3, "gsn"], + ["pop_ret", 0, ""], ["ret_zero", 0, ""], ["ret_true", 0, ""], ["iattr_set", 2, "Sn"], # 48 + ["iattr_add", 2, "Sn"], ["iattr_sub", 2, "Sn"], ["push_proc_state", 1, "n"], ["push_version", 0, ""], + ["put_subs", 5, "sCcCc"], ["put_subs2", 4, "cscc"], ["put_subs3", 7, "scscscc"], ["put_glyph", 2, "Cc"], + ["push_glyph_attr", 3, "Ggs"], ["push_att_to_glyph_attr", 3, "Ggs"], ["bitand", 0, ""], ["bitor", 0, ""], + ["bitnot", 0, ""], ["setbits", 4, "NnNn"], ["setfeat", 2, "fs"] ); # 64 + +my ($i) = 0; +our %opnames = map {$_->[0] => $i++} @opcodes; + +=head2 read + +Reads the Silf table into the internal data structure + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $d); + my ($fh) = $self->{' INFILE'}; + my ($moff) = $self->{' OFFSET'}; + my ($numsilf, @silfo); + + $fh->read($dat, 4); + ($self->{'Version'}) = TTF_Unpack("v", $dat); + if ($self->{'Version'} >= 3) + { + $fh->read($dat, 4); + ($self->{'Compiler'}) = TTF_Unpack("v", $dat); + } + $fh->read($dat, 4); + ($numsilf) = TTF_Unpack("S", $dat); + $fh->read($dat, $numsilf * 4); + foreach my $i (0 .. $numsilf - 1) + { push (@silfo, TTF_Unpack("L", substr($dat, $i * 4, 4))); } + + foreach my $sili (0 .. $numsilf - 1) + { + my ($silf) = {}; + my (@passo, @classo, $classbase, $numJust, $numCritFeatures, $numScript, $numPasses, $numPseudo, $i); + + push (@{$self->{'SILF'}}, $silf); + $fh->seek($moff + $silfo[$sili], 0); + if ($self->{'Version'} >= 3) + { + $fh->read($dat, 8); + ($silf->{'Version'}) = TTF_Unpack("v", $dat); + } + $fh->read($dat, 20); + ($silf->{'maxGlyphID'}, $silf->{'Ascent'}, $silf->{'Descent'}, + $numPasses, $silf->{'substPass'}, $silf->{'posPass'}, $silf->{'justPass'}, $silf->{'bidiPass'}, + $silf->{'Flags'}, $silf->{'maxPreContext'}, $silf->{'maxPostContext'}, $silf->{'attrPseudo'}, + $silf->{'attrBreakWeight'}, $silf->{'attrDirectionality'}, $silf->{'attrMirror'}, $silf->{'passBits'}, $numJust) = + TTF_Unpack("SssCCCCCCCCCCCCCC", $dat); + if ($numJust) + { + foreach my $j (0 .. $silf->{'numJust'} - 1) + { + my ($just) = {}; + push (@{$silf->{'JUST'}}, $just); + $fh->read($dat, 8); + ($just->{'attrStretch'}, $just->{'attrShrink'}, $just->{'attrStep'}, $just->{'attrWeight'}, + $just->{'runto'}) = TTF_Unpack("CCCCC", $dat); + } + } + $fh->read($dat, 10); + ($silf->{'numLigComp'}, $silf->{'numUserAttr'}, $silf->{'maxCompPerLig'}, $silf->{'direction'}, + $silf->{'attCollisions'}, $d, $d, $d, $numCritFeatures) = TTF_Unpack("SCCCCCCCC", $dat); + if ($numCritFeatures) + { + $fh->read($dat, $numCritFeatures * 2); + $silf->{'CRIT_FEATURE'} = [TTF_Unpack("S$numCritFeatures", $dat)]; + } + $fh->read($dat, 2); + ($d, $numScript) = TTF_Unpack("CC", $dat); + if ($numScript) + { + $fh->read($dat, $numScript * 4); + foreach (0 .. $numScript - 1) + { push (@{$silf->{'scripts'}}, unpack('a4', substr($dat, $_ * 4, 4))); } + } + $fh->read($dat, 2); + ($silf->{'lbGID'}) = TTF_Unpack("S", $dat); + $fh->read($dat, $numPasses * 4 + 4); + @passo = unpack("N*", $dat); + $fh->read($dat, 8); + ($numPseudo) = TTF_Unpack("S", $dat); + if ($numPseudo) + { + $fh->read($dat, $numPseudo * 6); + foreach (0 .. $numPseudo - 1) + { + my ($uni, $gid) = TTF_Unpack("LS", substr($dat, $_ * 6, 6)); + $silf->{'pseudos'}{$uni} = $gid; + } + } + $classbase = $fh->tell(); + $fh->read($dat, 4); + my ($numClasses, $numLinearClasses) = TTF_Unpack("SS", $dat); + $silf->{'numLinearClasses'} = $numLinearClasses; + $fh->read($dat, ($numClasses + 1) * ($self->{'Version'} >= 4 ? 4 : 2)); + @classo = unpack($self->{'Version'} >= 4 ? "N*" : "n*", $dat); + $fh->read($dat, $classo[-1] - $classo[0]); + for ($i = 0; $i < $numLinearClasses; $i++) + { + push (@{$silf->{'classes'}}, [unpack("n*", substr($dat, $classo[$i] - $classo[0], + $classo[$i+1] - $classo[$i]))]) + } + for ($i = $numLinearClasses; $i < $numClasses; $i++) + { + my (@res); + my (@c) = unpack("n*", substr($dat, $classo[$i] - $classo[0] + 8, $classo[$i+1] - $classo[$i] - 8)); + for (my $j = 0; $j < @c; $j += 2) + { $res[$c[$j+1]] = $c[$j]; } + push (@{$silf->{'classes'}}, \@res); + } + foreach (0 .. $numPasses - 1) + { $self->read_pass($fh, $passo[$_], $moff + $silfo[$sili], $silf, $_); } + } + return $self; +} + +sub chopcode +{ + my ($dest, $dat, $offsets, $isconstraint) = @_; + my ($last) = $offsets->[-1]; + my ($i); + + for ($i = $#{$offsets} - 1; $i >= 0; $i--) + { + if ((!$isconstraint || $offsets->[$i]) && $offsets->[$i] != $last) + { + unshift(@{$dest}, substr($dat, $offsets->[$i], $last - $offsets->[$i])); + $last = $offsets->[$i]; + } + else + { unshift(@{$dest}, ""); } + } +} + + +sub read_pass +{ + my ($self, $fh, $offset, $base, $silf, $id) = @_; + my ($pass) = {'id' => $id}; + my ($d, $dat, $i, @orulemap, @oconstraints, @oactions, $numRanges); + + $fh->seek($offset + $base, 0); + # printf "pass base = %04X\n", $offset; + push (@{$silf->{'PASS'}}, $pass); + $fh->read($dat, 40); + ($pass->{'flags'}, $pass->{'maxRuleLoop'}, $pass->{'maxRuleContext'}, $pass->{'maxBackup'}, + $pass->{'numRules'}, $d, $d, $d, $d, $d, $pass->{'numRows'}, $pass->{'numTransitional'}, + $pass->{'numSuccess'}, $pass->{'numColumns'}, $numRanges) = + TTF_Unpack("CCCCSSLLLLSSSSS", $dat); + $fh->read($dat, $numRanges * 6); + foreach $i (0 .. $numRanges - 1) + { + my ($first, $last, $col) = TTF_Unpack('SSS', substr($dat, $i * 6, 6)); + foreach ($first .. $last) + { $pass->{'colmap'}{$_} = $col; } + } + $fh->read($dat, $pass->{'numSuccess'} * 2 + 2); + @orulemap = unpack("n*", $dat); + $fh->read($dat, $orulemap[-1] * 2); + foreach (0 .. $pass->{'numSuccess'} - 1) + { push (@{$pass->{'rulemap'}}, [unpack("n*", substr($dat, $orulemap[$_] * 2, ($orulemap[$_+1] - $orulemap[$_]) * 2))]); } + $fh->read($dat, 2); + ($pass->{'minRulePreContext'}, $pass->{'maxRulePreContext'}) = TTF_Unpack("CC", $dat); + $fh->read($dat, ($pass->{'maxRulePreContext'} - $pass->{'minRulePreContext'} + 1) * 2); + $pass->{'startStates'} = [unpack('n*', $dat)]; + $fh->read($dat, $pass->{'numRules'} * 2); + $pass->{'ruleSortKeys'} = [unpack('n*', $dat)]; + $fh->read($dat, $pass->{'numRules'}); + $pass->{'rulePreContexts'} = [unpack('C*', $dat)]; + $fh->read($dat, 3); + ($pass->{'collisionThreshold'}, $pass->{'passConstraintLen'}) = TTF_Unpack("CS", $dat); + $fh->read($dat, ($pass->{'numRules'} + 1) * 2); + @oconstraints = unpack('n*', $dat); + $fh->read($dat, ($pass->{'numRules'} + 1) * 2); + @oactions = unpack('n*', $dat); + foreach (0 .. $pass->{'numTransitional'} - 1) + { + $fh->read($dat, $pass->{'numColumns'} * 2); + push (@{$pass->{'fsm'}}, [unpack('n*', $dat)]); + } + $fh->read($dat, 1); + if ($pass->{'passConstraintLen'}) + { $fh->read($pass->{'passConstraintCode'}, $pass->{'passConstraintLen'}); } + $fh->read($dat, $oconstraints[-1]); + $pass->{'constraintCode'} = []; + chopcode($pass->{'constraintCode'}, $dat, \@oconstraints, 1); + $fh->read($dat, $oactions[-1]); + $pass->{'actionCode'} = []; + chopcode($pass->{'actionCode'}, $dat, \@oactions, 0); + return $pass; +} + +sub chopranges +{ + my ($map, $numg) = @_; + my ($dat, $numRanges); + my (@keys) = sort {$a <=> $b} keys %{$map}; + my ($first, $last, $col, $g); + + $first = -1; + $last = -1; + $col = -1; + foreach $g (@keys) + { + next unless ($g > 0 or $g eq '0'); + if ($g != $last + 1 || $map->{$g} != $col) + { + if ($col != -1) + { + $dat .= pack("nnn", $first, $last, $col); + $numRanges++; + } + $first = $last = $g; + $col = $map->{$g}; + } + else + { $last++; } + } + if ($col != -1) + { + $dat .= pack("nnn", $first, $last, $col); + $numRanges++; + } + return ($numRanges, $dat); +} + +sub unpack_code +{ + my ($self, $str) = @_; + my (@res, $i, $j); + my ($l) = length($str); + + for ($i = 0; $i < $l; ) + { + my ($a) = unpack('C', substr($str, $i, 1)); + my ($o) = $opcodes[$a]; + my (@args); + my (@types) = split('', $o->[2]); + ++$i; + for ($j = 0; $j < @types; ++$j) + { + my ($t) = $types[$j]; + if ($t eq 'v') + { + my ($n) = unpack('C', substr($str, $i, 1)); + push (@args, unpack('C*', substr($str, $i + 1, $n))); + $i += $n + 1; + } + elsif ($t eq 'L' or $t eq 'N' or $t eq 'G' or $t eq 'C') + { + push (@args, unpack('n', substr($str, $i, 2))); + $i += 2; + $j++; + } + else + { + push (@args, unpack($t eq 's' ? 'c' : 'C', substr($str, $i, 1))); + $i++; + } + } + push (@res, [$o->[0], @args]); + } + return @res; +} + +sub pack_code +{ + my ($self, $cmds) = @_; + my ($res); + + foreach my $c (@{$cmds}) + { + my ($ind) = $opnames{$c->[0]}; + my ($i) = 1; + $res .= pack('C', $ind); + # my (@types) = unpack('C*', $opcodes[$ind][2]); + my (@types) = split('', $opcodes[$ind][2]); + for (my $j = 0; $j < @types; $j++) + { + my ($t) = $types[$j]; + if ($t eq 'v') + { + my ($n) = scalar @{$c} - 1; + $res .= pack('C*', $n, @{$c}[1..$#{$c}]); + $i += $n; + } + elsif ($t eq 'C' or $t eq 'G' or $t eq 'L' or $t eq 'N') + { + $res .= pack('n', $c->[$i]); + $j++; + } + else + { $res .= pack($t eq 's' ? 'c' : 'C', $c->[$i]); } + $i++; + } + } + return $res; +} + +sub packcode +{ + my ($code, $isconstraint) = @_; + my ($dat, $c, $res); + + $c = 1; + $dat = "\000"; + foreach (@{$code}) + { + if ($_) + { + push(@{$res}, $c); + $dat .= $_; + $c += length($_); + } + else + { push(@{$res}, $isconstraint ? 0 : $c); } + } + push(@{$res}, $c); + return ($res, $dat); +} + +sub out_pass +{ + my ($self, $fh, $pass, $silf, $subbase) = @_; + my (@orulemap, $dat, $actiondat, $numRanges, $c); + my (@offsets, $res, $pbase); + + $pbase = $fh->tell(); + # printf "pass base = %04X, ", $pbase - $subbase; + $fh->print(TTF_Pack("CCCCSSLLLLSSSS", $pass->{'flags'}, $pass->{'maxRuleLoop'}, $pass->{'maxRuleContext'}, + $pass->{'maxBackup'}, $pass->{'numRules'}, 24, 0, 0, 0, 0, $pass->{'numRows'}, + $pass->{'numTransitional'}, $pass->{'numSuccess'}, $pass->{'numColumns'})); + ($numRanges, $dat) = chopranges($pass->{'colmap'}); +# print "numranges = $numRanges\n"; + $fh->print(TTF_Pack("SSSS", TTF_bininfo($numRanges, 6))); + $fh->print($dat); + $dat = ""; + $c = 0; +# print "transitions = $pass->{'numTransitional'}, success = $pass->{'numSuccess'}, rows = $pass->{'numRows'}\n"; + my ($sucbase) = $pass->{'numRows'} - $pass->{'numSuccess'}; + foreach (0 .. ($pass->{'numSuccess'} - 1)) + { + push(@orulemap, $c); + if (defined $pass->{'rulemap'}[$_]) + { + $dat .= pack("n*", @{$pass->{'rulemap'}[$_]}); + $c += @{$pass->{'rulemap'}[$_]}; + } + else + { + print "No rules for " . ($sucbase + $_); + if ($sucbase + $_ < $pass->{'numTransitional'}) + { print ": (" . join(",", @{$pass->{'fsm'}[$sucbase + $_]}) . ")"; } + print "\n"; + } + } + push (@orulemap, $c); + $fh->print(pack("n*", @orulemap)); + $fh->print($dat); + $fh->print(TTF_Pack("CC", $pass->{'minRulePreContext'}, $pass->{'maxRulePreContext'})); + $fh->print(pack("n*", @{$pass->{'startStates'}})); + $fh->print(pack("n*", @{$pass->{'ruleSortKeys'}})); + $fh->print(pack("C*", @{$pass->{'rulePreContexts'}})); + $fh->print(TTF_Pack("CS", 0, $pass->{'passConstraintLen'})); + my ($oconstraints, $oactions); + ($oconstraints, $dat) = packcode($pass->{'constraintCode'}, 1); + ($oactions, $actiondat) = packcode($pass->{'actionCode'}, 0); +# printf "constraint offsets @ %X\n", $fh->tell(); + $fh->print(pack("n*", @{$oconstraints})); +# printf "action offsets @ %X\n", $fh->tell(); + $fh->print(pack("n*", @{$oactions})); +# printf "fsm @ %X\n", $fh->tell(); + foreach (@{$pass->{'fsm'}}) + { $fh->print(pack("n*", @{$_})); } +# printf "end of fsm @ %X\n", $fh->tell(); + $fh->print(pack("C", $pass->{'collisionThreshold'})); + push(@offsets, $fh->tell() - $subbase); + $fh->print($pass->{'passConstraintCode'}); + push(@offsets, $fh->tell() - $subbase); + $fh->print($dat); + push(@offsets, $fh->tell() - $subbase); + $fh->print($actiondat); + push(@offsets, 0); + print join(", ", @offsets) . "\n"; + $res = $fh->tell(); + $fh->seek($pbase + 8, 0); + $fh->print(pack("N*", @offsets)); + $fh->seek($res, 0); +# printf "end = %04X\n", $res - $subbase; + return $res; +} + +=head2 out + +Outputs a Silf data structure to a font file in binary format + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($silf, $base, $subbase, $silfc, $end); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $base = $fh->tell(); + if ($self->{'Version'} >= 3) + { $fh->print(TTF_Pack("vvSS", $self->{'Version'}, $self->{'Compiler'}, $#{$self->{'SILF'}} + 1, 0)); } + else + { $fh->print(TTF_Pack("vSS", $self->{'Version'}, $#{$self->{'SILF'}} + 1, 0)); } + $fh->print(pack('N*', (0) x (@{$self->{'SILF'}}))); + foreach $silf (@{$self->{'SILF'}}) + { + my ($subbase) = $fh->tell(); + my ($numlin, $i, @opasses, $oPasses, $oPseudo, $ooPasses); + if ($self->{'Version'} >= 3) + { + $fh->seek($base + 12 + $silfc * 4, 0); + $fh->print(pack('N', $subbase - $base)); + $fh->seek($subbase, 0); + $fh->print(TTF_Pack("vSS", $silf->{'Version'}, $ooPasses, $oPseudo)); + } + else + { + $fh->seek($base + 8 + $silfc * 4, 0); + $fh->print(pack('N', $subbase - $base)); + $fh->seek($subbase, 0); + } + $fh->print(TTF_Pack("SssCCCCCCCCCCCCCC", + $silf->{'maxGlyphID'}, $silf->{'Ascent'}, $silf->{'Descent'}, + scalar @{$silf->{'PASS'}}, $silf->{'substPass'}, $silf->{'posPass'}, $silf->{'justPass'}, $silf->{'bidiPass'}, + $silf->{'Flags'}, $silf->{'maxPreContext'}, $silf->{'maxPostContext'}, $silf->{'attrPseudo'}, + $silf->{'attrBreakWeight'}, $silf->{'attrDirectionality'}, $silf->{'attrMirror'}, $silf->{'passBits'}, $#{$silf->{'JUST'}} + 1)); + foreach (@{$silf->{'JUST'}}) + { $fh->print(TTF_Pack("CCCCCCCC", $_->{'attrStretch'}, $_->{'attrShrink'}, $_->{'attrStep'}, + $_->{'attrWeight'}, $_->{'runto'}, 0, 0, 0)); } + + $fh->print(TTF_Pack("SCCCCCCCC", $silf->{'numLigComp'}, $silf->{'numUserAttr'}, $silf->{'maxCompPerLig'}, + $silf->{'direction'}, $silf->{'attCollisions'}, 0, 0, 0, $#{$silf->{'CRIT_FEATURE'}} + 1)); + $fh->print(pack("n*", @{$silf->{'CRIT_FEATURE'}})); + $fh->print(TTF_Pack("CC", 0, $#{$silf->{'scripts'}} + 1)); + foreach (@{$self->{'scripts'}}) + { $fh->print(pack("a4", $_)); } + $fh->print(TTF_Pack("S", $silf->{'lbGID'})); + $ooPasses = $fh->tell(); + if ($silf->{'PASS'}) { $fh->print(pack("N*", (0) x (@{$silf->{'PASS'}} + 1)));} + $oPseudo = $fh->tell() - $subbase; + my (@pskeys) = keys %{$silf->{'pseudos'}}; + $fh->print(TTF_Pack("SSSS", TTF_bininfo(scalar @pskeys, 6))); + foreach my $k (sort {$a <=> $b} @pskeys) + { $fh->print(TTF_Pack("Ls", $k, $silf->{'pseudos'}{$k})); } + $numlin = $silf->{'numLinearClasses'}; + $fh->print(TTF_Pack("SS", scalar @{$silf->{'classes'}}, $numlin)); + my (@coffsets); + # printf "%X, ", $fh->tell() - $base; + my ($cbase) = (scalar @{$silf->{'classes'}} + 1) * ($self->{'Version'} >= 4 ? 4 : 2) + 4; + for ($i = 0; $i < $numlin; $i++) + { + push (@coffsets, $cbase); + $cbase += 2 * scalar @{$silf->{'classes'}[$i]}; + } + my (@nonlinclasses); + for ($i = $numlin; $i < @{$silf->{'classes'}}; $i++) + { + my (@c, $d, @d); + my $c = $silf->{'classes'}[$i]; + push (@coffsets, $cbase); + @c = sort {$c->[$a] <=> $c->[$b]} (0 .. $#{$c}); + foreach $d (@c) + { push (@d, $c->[$d], $d); } + push (@nonlinclasses, [@d]); + my ($len) = scalar @d; + $cbase += 8 + 2 * $len; + } + push (@coffsets, $cbase); + $fh->print(pack(($self->{'Version'} >= 4 ? 'N*' : 'n*'), @coffsets)); + for ($i = 0; $i < $numlin; $i++) + { $fh->print(pack("n*", @{$silf->{'classes'}[$i]})); } + # printf "%X, ", $fh->tell() - $base; + for ($i = $numlin; $i < @{$silf->{'classes'}}; $i++) + { + + my ($num) = scalar @{$nonlinclasses[$i-$numlin]}; + my (@bin) = TTF_bininfo($num/2, 1); + $fh->print(TTF_Pack("SSSS", @bin)); + $fh->print(pack("n*", @{$nonlinclasses[$i-$numlin]})); + } + $oPasses = $fh->tell() - $subbase; +# printf "original pass = %04X\n", $oPasses; + push (@opasses, $oPasses); + foreach (@{$silf->{'PASS'}}) + { push(@opasses, $self->out_pass($fh, $_, $silf, $subbase) - $subbase); } + $end = $fh->tell(); + $fh->seek($ooPasses, 0); + $fh->print(pack("N*", @opasses)); + if ($self->{'Version'} >= 3) + { + $fh->seek($subbase + 4, 0); + $fh->print(TTF_Pack("SS", $ooPasses - $subbase, $oPseudo)); + } + $fh->seek($end, 0); + $silfc++; + } +} + +sub XML_element +{ + my ($self, $context, $depth, $k, $val, $ind) = @_; + my ($fh) = $context->{'fh'}; + my ($i); + + return $self if ($k eq 'LOC'); + + if ($k eq 'classes') + { + $fh->print("$depth\n"); + foreach $i (0 .. $#{$val}) + { + $fh->printf("$depth \n", $i); + $fh->printf("$depth " . join(" ", map{sprintf("%d", $_)} @{$val->[$i]})); + $fh->print("\n$depth \n"); + } + $fh->print("$depth\n"); + } + elsif ($k eq 'fsm') + { + $fh->print("$depth\n"); + my ($i) = 0; + foreach (@{$val}) + { $fh->print("$depth " . join(" ", @{$_}) . "\n"); $i++; } + $fh->print("$depth\n"); + } + elsif ($k eq 'colmap') + { + my ($i); + $fh->print("$depth"); + foreach my $k (sort {$a <=> $b} keys %{$val}) + { + if ($i++ % 8 == 0) + { $fh->print("\n$depth "); } + $fh->printf(" %d=%d", $k, $val->{$k}); + } + $fh->print("\n$depth\n"); + } + elsif ($k eq 'constraintCode' or $k eq 'actionCode') + { + $fh->print("$depth<$k>\n"); + foreach my $i (0 .. $#{$val}) + { + my (@rules) = $self->unpack_code($val->[$i]); + next unless (@rules); + $fh->print("$depth [$i])) . "'>\n"); + foreach my $r (@rules) + { $fh->print("$depth $r->[0]: ". join(", ", @{$r}[1..$#{$r}]) . "\n"); } + $fh->print("$depth \n"); + } + $fh->print("$depth\n"); + } + else + { return $self->SUPER::XML_element($context, $depth, $k, $val, $ind); } + + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 4; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Sill.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Sill.pm new file mode 100644 index 0000000000..1977709d68 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Sill.pm @@ -0,0 +1,143 @@ +package Font::TTF::Sill; + +=head1 NAME + +Font::TTF::Sill - Graphite language mapping table + +=head1 DESCRIPTION + +=head1 INSTANCE VARIABLES + +=over 4 + +=item version + +Table version number. + +=item langs + +Contains a hash where the key is the language id and the value is an array of +language records + +=back + +=head2 Language Records + +Each language record is itself an array of two values [fid, val]. fid is the +feature id and is held as a long. + +=cut + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +sub read +{ + my ($self) = @_; + my ($num, $i, $j); + + return $self if ($self->{' read'}); + $self->SUPER::read_dat or return $self; + + ($self->{'version'}, $num) = TTF_Unpack("vS", $self->{' dat'}); + + foreach $i (1 .. $num) # ignore bogus entry at end + { + my ($lid, $numf, $offset) = unpack("A4nn", substr($self->{' dat'}, $i * 8 + 4)); # 12 - 8 = 4 since i starts at 1. A4 strips nulls + my (@settings); + + foreach $j (1 .. $numf) + { + my ($fid, $val) = TTF_Unpack("Ls", substr($self->{' dat'}, $offset + $j * 8 - 8)); + push (@settings, [$fid, $val]); + } + $self->{'langs'}{$lid} = [@settings]; + } + delete $self->{' dat'}; + $self->{' read'} = 1; + $self; +} + +sub out +{ + my ($self, $fh) = @_; + my ($num, $range, $select, $shift) = TTF_bininfo(scalar keys %{$self->{'langs'}}, 1); + my ($offset) = $num * 8 + 20; #header = 12, dummy = 8 + my ($k, $s); + + return $self->SUPER::out($fh) unless ($self->{' read'}); + $fh->print(TTF_Pack("vSSSS", $self->{'version'}, $num, $range, $select, $shift)); + foreach $k ((sort keys %{$self->{'langs'}}), '+1') + { + my ($numf) = scalar @{$self->{'langs'}{$k}} unless ($k eq '+1'); + $fh->print(pack("a4nn", $k, $numf, $offset)); + $offset += $numf * 8; + } + + foreach $k (sort keys %{$self->{'langs'}}) + { + foreach $s (@{$self->{'langs'}{$k}}) + { $fh->print(TTF_Pack("LsS", @{$s}, 0)); } + } + $self; +} + +sub XML_element +{ + my ($self) = shift; + my ($context, $depth, $key, $dat) = @_; + my ($fh) = $context->{'fh'}; + my ($k, $s); + + return $self->SUPER::XML_element(@_) unless ($key eq 'langs'); + foreach $k (sort keys %{$self->{'langs'}}) + { + $fh->printf("%s\n", $depth, $k); + foreach $s (@{$self->{'langs'}{$k}}) + { + my ($fid) = $s->[0]; + if ($fid > 0x00FFFFFF) + { $fid = unpack("A4", pack ("N", $fid)); } + else + { $fid = sprintf("%d", $fid); } + $fh->printf("%s%s\n", + $depth, $context->{'indent'}, $fid, $s->[1]); + } + $fh->printf("%s\n", $depth); + } + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 6; +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Table.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Table.pm new file mode 100644 index 0000000000..5367c6e54f --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Table.pm @@ -0,0 +1,464 @@ +package Font::TTF::Table; + +=head1 NAME + +Font::TTF::Table - Superclass for tables and used for tables we don't have a class for + +=head1 DESCRIPTION + +Looks after the purely table aspects of a TTF table, such as whether the table +has been read before, locating the file pointer, etc. Also copies tables from +input to output. + +=head1 INSTANCE VARIABLES + +Instance variables start with a space + +=over 4 + +=item read + +Flag which indicates that the table has already been read from file. + +=item dat + +Allows the creation of unspecific tables. Data is simply output to any font +file being created. + +=item nocompress + +If set, overrides the font default for WOFF table compression. Is a scalar integer specifying a +table size threshold below which this table will not be compressed. Set to -1 to never +compress; 0 to always compress. + +=item INFILE + +The read file handle + +=item OFFSET + +Location of the file in the input file + +=item LENGTH + +Length in the input directory + +=item ZLENGTH + +Compressed length of the table if a WOFF font. 0 < ZLENGTH < LENGTH implies table is compressed. + +=item CSUM + +Checksum read from the input file's directory + +=item PARENT + +The L that table is part of + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw($VERSION); +use Font::TTF::Utils; +use IO::String; +$VERSION = 0.0001; + +my $havezlib = eval {require Compress::Zlib}; + +=head2 Font::TTF::Table->new(%parms) + +Creates a new table or subclass. Table instance variables are passed in +at this point as an associative array. + +=cut + +sub new +{ + my ($class, %parms) = @_; + my ($self) = {}; + my ($p); + + $class = ref($class) || $class; + foreach $p (keys %parms) + { $self->{" $p"} = $parms{$p}; } + bless $self, $class; +} + +=head2 $t->read + +Reads the table from the input file. Acts as a superclass to all true tables. +This method marks the table as read and then just sets the input file pointer +but does not read any data. If the table has already been read, then returns +C else returns C<$self> + +For WOFF-compressed tables, the table is first decompressed and a +replacement file handle is created for reading the decompressed data. In this +case ORIGINALOFFSET will preserve the original value of OFFSET for +applications that care. + +=cut + +sub read +{ + my ($self) = @_; + + return $self->read_dat if (ref($self) eq "Font::TTF::Table"); + return undef if $self->{' read'}; + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Uncompress it to memory and create new fh + die ("Cannot uncompress WOFF data: Compress::Zlib not present.\n") unless $havezlib; + $self->{' ORIGINALOFFSET'} = $self->{' OFFSET'}; # Preserve this for those who care + my $dat; + $self->{' INFILE'}->read($dat, $self->{' ZLENGTH'}); + $dat = Compress::Zlib::uncompress($dat); + warn "$self->{' NAME'} table decompressed to wrong length" if $self->{' LENGTH'} != bytes::length($dat); + $self->{' INFILE'} = IO::String->new($dat); + binmode $self->{' INFILE'}; + $self->{' OFFSET'} = 0; + } + $self->{' read'} = 1; + $self; +} + + +=head2 $t->read_dat + +Reads the table into the C instance variable for those tables which don't +know any better + +=cut + +sub read_dat +{ + my ($self) = @_; + +# can't just $self->read here otherwise those tables which start their read sub with +# $self->read_dat are going to permanently loop + return undef if ($self->{' read'}); +# $self->{' read'} = 1; # Let read do this, now out will call us for subclasses + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Uncompress it directly to ' dat' + die ("Cannot uncompress WOFF data: Compress::Zlib not present.\n") unless $havezlib; + my $dat; + $self->{' INFILE'}->read($dat, $self->{' ZLENGTH'}); + $dat = Compress::Zlib::uncompress($dat); + warn "$self->{' NAME'} table decompressed to wrong length" if $self->{' LENGTH'} != bytes::length($dat); + $self->{' dat'} = $dat; + } + else + { + $self->{' INFILE'}->read($self->{' dat'}, $self->{' LENGTH'}); + } + $self; +} + +=head2 $t->out($fh) + +Writes out the table to the font file. If there is anything in the +C instance variable then this is output, otherwise the data is copied +from the input file to the output + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($dat, $i, $len, $count); + + if (defined $self->{' dat'}) + { + $fh->print($self->{' dat'}); + return $self; + } + + return undef unless defined $self->{' INFILE'}; + + if (0 < $self->{' ZLENGTH'} && $self->{' ZLENGTH'} < $self->{' LENGTH'}) + { + # WOFF table is compressed. Have to uncompress first + $self->read_dat; + $fh->print($self->{' dat'}); + return $self; + } + + # We don't really have to keep the following code... we could have + # just always done a full read_dat() on the table. But the following + # is more memory-friendly so I've kept it for the more common case + # of non-compressed tables. + + $self->{' INFILE'}->seek($self->{' OFFSET'}, 0); + $len = $self->{' LENGTH'}; + while ($len > 0) + { + $count = ($len > 4096) ? 4096 : $len; + $self->{' INFILE'}->read($dat, $count); + $fh->print($dat); + $len -= $count; + } + $self; +} + + +=head2 $t->out_xml($context) + +Outputs this table in XML format. The table is first read (if not already read) and then if +there is no subclass, then the data is dumped as hex data + +=cut + +sub out_xml +{ + my ($self, $context, $depth) = @_; + my ($k); + + if (ref($self) eq __PACKAGE__) + { + $self->read_dat; + Font::TTF::Utils::XML_hexdump($context, $depth, $self->{' dat'}); + } + else + { + $self->read; + foreach $k (sort grep {$_ !~ m/^\s/o} keys %{$self}) + { + $self->XML_element($context, $depth, $k, $self->{$k}); + } + } + $self; +} + + +=head2 $t->XML_element + +Output a particular element based on its contents. + +=cut + +sub XML_element +{ + my ($self, $context, $depth, $k, $dat, $ind) = @_; + my ($fh) = $context->{'fh'}; + my ($ndepth, $d); + + return unless defined $dat; + + if (!ref($dat)) + { + $fh->printf("%s<%s>%s\n", $depth, $k, $dat, $k); + return $self; + } + + if ($ind) + { $fh->printf("%s<%s i='%d'>\n", $depth, $k, $ind); } + else + { $fh->printf("%s<%s>\n", $depth, $k); } + $ndepth = $depth . $context->{'indent'}; + + if (ref($dat) eq 'SCALAR') + { $self->XML_element($context, $ndepth, 'scalar', $$dat); } + elsif (ref($dat) eq 'ARRAY') + { + my ($c) = 1; + foreach $d (@{$dat}) + { $self->XML_element($context, $ndepth, 'elem', $d, $c++); } + } + elsif (ref($dat) eq 'HASH') + { + foreach $d (sort grep {$_ !~ m/^\s/o} keys %{$dat}) + { $self->XML_element($context, $ndepth, $d, $dat->{$d}); } + } + else + { + $context->{'name'} = ref($dat); + $context->{'name'} =~ s/^.*://o; + $dat->out_xml($context, $ndepth); + } + + $fh->printf("%s\n", $depth, $k); + $self; +} + + +=head2 $t->XML_end($context, $tag, %attrs) + +Handles the default type of for those tables which aren't subclassed + +=cut + +sub XML_end +{ + my ($self, $context, $tag, %attrs) = @_; + my ($dat, $addr); + + return undef unless ($tag eq 'data'); + $dat = $context->{'text'}; + $dat =~ s/([0-9a-f]{2})\s*/hex($1)/oig; + if (defined $attrs{'addr'}) + { $addr = hex($attrs{'addr'}); } + else + { $addr = length($self->{' dat'}); } + substr($self->{' dat'}, $addr, length($dat)) = $dat; + return $context; +} + + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 0; +} + +=head2 $t->dirty($val) + +This sets the dirty flag to the given value or 1 if no given value. It returns the +value of the flag + +=cut + +sub dirty +{ + my ($self, $val) = @_; + my ($res) = $self->{' isDirty'}; + + $self->{' isDirty'} = defined $val ? $val : 1; + $res; +} + +=head2 $t->update + +Each table knows how to update itself. This consists of doing whatever work +is required to ensure that the memory version of the table is consistent +and that other parameters in other tables have been updated accordingly. +I.e. by the end of sending C to all the tables, the memory version +of the font should be entirely consistent. + +Some tables which do no work indicate to themselves the need to update +themselves by setting isDirty above 1. This method resets that accordingly. + +=cut + +sub update +{ + my ($self) = @_; + + if ($self->{' isDirty'}) + { + $self->read; + $self->{' isDirty'} = 0; + return $self; + } + else + { return undef; } +} + + +=head2 $t->empty + +Clears a table of all data to the level of not having been read + +=cut + +sub empty +{ + my ($self) = @_; + my (%keep); + + foreach (qw(INFILE LENGTH OFFSET CSUM PARENT)) + { $keep{" $_"} = 1; } + + map {delete $self->{$_} unless $keep{$_}} keys %$self; + $self; +} + + +=head2 $t->release + +Releases ALL of the memory used by this table, and all of its component/child +objects. This method is called automatically by +'Font::TTF::Font-Erelease' (so you don't have to call it yourself). + +B, that it is important that this method get called at some point prior +to the actual destruction of the object. Internally, we track things in a +structure that can result in circular references, and without calling +'C' these will not properly get cleaned up by Perl. Once this +method has been called, though, don't expect to be able to do anything with the +C object; it'll have B internal state whatsoever. + +B As part of the brute-force cleanup done here, this method +will throw a warning message whenever unexpected key values are found within +the C object. This is done to help ensure that any +unexpected and unfreed values are brought to your attention so that you can bug +us to keep the module updated properly; otherwise the potential for memory +leaks due to dangling circular references will exist. + +=cut + +sub release +{ + my ($self) = @_; + +# delete stuff that we know we can, here + + my @tofree = map { delete $self->{$_} } keys %{$self}; + + while (my $item = shift @tofree) + { + my $ref = ref($item); + if (UNIVERSAL::can($item, 'release')) + { $item->release(); } + elsif ($ref eq 'ARRAY') + { push( @tofree, @{$item} ); } + elsif (UNIVERSAL::isa($ref, 'HASH')) + { release($item); } + } + +# check that everything has gone - it better had! + foreach my $key (keys %{$self}) + { warn ref($self) . " still has '$key' key left after release.\n"; } +} + + +sub __dumpvar__ +{ + my ($self, $key) = @_; + + return ($key eq ' PARENT' ? '...parent...' : $self->{$key}); +} + +1; + +=head1 BUGS + +No known bugs + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Ttc.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Ttc.pm new file mode 100644 index 0000000000..116221adb9 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Ttc.pm @@ -0,0 +1,176 @@ +package Font::TTF::Ttc; + +=head1 NAME + +Font::TTF::Ttc - Truetype Collection class + +=head1 DESCRIPTION + +A TrueType collection is a collection of TrueType fonts in one file in which +tables may be shared between different directories. In order to support this, +the TTC introduces the concept of a table being shared by different TrueType +fonts. This begs the question of what should happen to the ' PARENT' property +of a particular table. It is made to point to the first directory object which +refers to it. It is therefore up to the application to sort out any confusion. +Confusion only occurs if shared tables require access to non-shared tables. +This should not happen since the shared tables are dealing with glyph +information only and the private tables are dealing with encoding and glyph +identification. Thus the general direction is from identification to glyph and +not the other way around (at least not without knowledge of the particular +context). + +=head1 INSTANCE VARIABLES + +The following instance variables are preceded by a space + +=over 4 + +=item fname (P) + +Filename for this TrueType Collection + +=item INFILE (P) + +The filehandle of this collection + +=back + +The following instance variable does not start with a space + +=over 4 + +=item directs + +An array of directories (Font::TTF::Font objects) for each sub-font in the directory + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw($VERSION); + +use IO::File; + +$VERSION = 0.0001; + +=head2 Font::TTF::Ttc->open($fname) + +Opens and reads the given filename as a TrueType Collection. Reading a collection +involves reading each of the directories which go to make up the collection. + +=cut + +sub open +{ + my ($class, $fname) = @_; + my ($self) = {}; + my ($fh); + + unless (ref($fname)) + { + $fh = IO::File->new($fname) or return undef; + binmode $fh; + } else + { $fh = $fname; } + + bless $self, $class; + $self->{' INFILE'} = $fh; + $self->{' fname'} = $fname; + $fh->seek(0, 0); + $self->read; +} + + +=head2 $c->read + +Reads a Collection by reading all the directories in the collection + +=cut + +sub read +{ + my ($self) = @_; + my ($fh) = $self->{' INFILE'}; + my ($dat, $ttc, $ver, $num, $i, $loc); + + $fh->read($dat, 12); + ($ttc, $ver, $num) = unpack("A4N2", $dat); + + return undef unless $ttc eq "ttcf"; + $fh->read($dat, $num << 2); + for ($i = 0; $i < $num; $i++) + { + $loc = unpack("N", substr($dat, $i << 2, 4)); + $self->{'directs'}[$i] = Font::TTF::Font->new('INFILE' => $fh, + 'PARENT' => $self, + 'OFFSET' => $loc) || return undef; + } + for ($i = 0; $i < $num; $i++) + { $self->{'directs'}[$i]->read; } + $self; +} + + +=head2 $c->find($direct, $name, $check, $off, $len) + +Hunts around to see if a table with the given characteristics of name, checksum, +offset and length has been associated with a directory earlier in the list. +Actually on checks the offset since no two tables can share the same offset in +a TrueType font, collection or otherwise. + +=cut + +sub find +{ + my ($self, $direct, $name, $check, $off, $len) = @_; + my ($d); + + foreach $d (@{$self->{'directs'}}) + { + return undef if $d eq $direct; + next unless defined $d->{$name}; + return $d->{$name} if ($d->{$name}{' OFFSET'} == $off); + } + undef; # wierd that the font passed is not in the list! +} + + +=head2 $c->DESTROY + +Closees any opened files by us + +=cut + +sub DESTROY +{ + my ($self) = @_; + close ($self->{' INFILE'}) if $self->{' INFILE'}; + undef; +} + +1; + +=head1 BUGS + +No known bugs, but then not ever executed! + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Ttopen.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Ttopen.pm new file mode 100644 index 0000000000..15e0c1460b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Ttopen.pm @@ -0,0 +1,1345 @@ +package Font::TTF::Ttopen; + +=head1 NAME + +Font::TTF::Ttopen - Opentype superclass for standard Opentype lookup based tables +(GSUB and GPOS) + +=head1 DESCRIPTION + +Handles all the script, lang, feature, lookup stuff for a +L/L table leaving the class specifics to the +subclass + +=head1 INSTANCE VARIABLES + +The instance variables of an opentype table form a complex sub-module hierarchy. + +=over 4 + +=item Version + +This contains the version of the table as a floating point number + +=item SCRIPTS + +The scripts list is a hash of script tags. Each script tag (of the form +$t->{'SCRIPTS'}{$tag}) has information below it. + +=over 8 + +=item OFFSET + +This variable is preceded by a space and gives the offset from the start of the +table (not the table section) to the script table for this script + +=item REFTAG + +This variable is preceded by a space and gives a corresponding script tag to this +one such that the offsets in the file are the same. When writing, it is up to the +caller to ensure that the REFTAGs are set correctly, since these will be used to +assume that the scripts are identical. Note that REFTAG must refer to a script which +has no REFTAG of its own. + +=item DEFAULT + +This corresponds to the default language for this script, if there is one, and +contains the same information as an itemised language + +=item LANG_TAGS + +This contains an array of language tag strings (each 4 bytes) corresponding to +the languages listed by this script + +=item $lang + +Each language is a hash containing its information: + +=over 12 + +=item OFFSET + +This variable is preceded by a a space and gives the offset from the start of +the whole table to the language table for this language + +=item REFTAG + +This variable is preceded by a space and has the same function as for the script +REFTAG, only for the languages within a script. + +=item RE-ORDER + +This indicates re-ordering information, and has not been set. The value should +always be 0. + +=item DEFAULT + +This holds the index of the default feature, if there is one, or -1 otherwise. + +=item FEATURES + +This is an array of feature tags for all the features enabled for this language + +=back + +=back + +=item FEATURES + +The features section of instance variables corresponds to the feature table in +the opentype table. + +=over 8 + +=item FEAT_TAGS + +This array gives the ordered list of feature tags for this table. It is used during +reading and writing for converting between feature index and feature tag. + +=back + +The rest of the FEATURES variable is itself a hash based on the feature tag for +each feature. Each feature has the following structure: + +=over 8 + +=item OFFSET + +This attribute is preceded by a space and gives the offset relative to the start of the whole +table of this particular feature. + +=item PARMS + +If FeatureParams are defined for this feature, this contains a reference to the corresponding FeatureParams object. Otherwise set to null. + +=item LOOKUPS + +This is an array containing indices to lookups in the LOOKUP instance variable of the table + +=item INDEX + +This gives the feature index for this feature and is used during reading and writing for +converting between feature tag and feature index. + +=back + +=item LOOKUP + +This variable is an array of lookups in order and is indexed via the features of a language of a +script. Each lookup contains subtables and other information: + +=over 8 + +=item OFFSET + +This name is preceded by a space and contains the offset from the start of the table to this +particular lookup + +=item TYPE + +This is a subclass specific type for a lookup. It stipulates the type of lookup and hence subtables +within the lookup + +=item FLAG + +Holds the lookup flag bits + +=item FILTER + +Holds the MarkFilteringSet (that is, the index into GDEF->MARKSETS) for the lookup. + +=item SUB + +This holds an array of subtables which are subclass specific. Each subtable must have +an OFFSET. The other variables described here are an abstraction used in both the +GSUB and GPOS tables which are the target subclasses of this class. + +=over 12 + +=item OFFSET + +This is preceded by a space and gives the offset relative to the start of the table for this +subtable + +=item FORMAT + +Gives the sub-table sub format for this GSUB subtable. It is assumed that this +value is correct when it comes time to write the subtable. + +=item COVERAGE + +Most lookups consist of a coverage table corresponding to the first +glyph to match. The offset of this coverage table is stored here and the coverage +table looked up against the GSUB table proper. There are two lookups +without this initial coverage table which is used to index into the RULES array. +These lookups have one element in the RULES array which is used for the whole +match. + +=item RULES + +The rules are a complex array. In most cases, each element of the array +corresponds to an element in the coverage table (governed by the coverage index). +In a few caess, such as when there is +no coverage table, then there is considered to be only one element in the rules +array. Each element of the array is itself an array corresponding to the +possibly multiple string matches which may follow the initial glyph. Each +element of this array is a hash with fixed keys corresponding to information +needed to match a glyph string or act upon it. Thus the RULES element is an +array of arrays of hashes which contain the following keys: + +=over 16 + +=item MATCH + +This contains a sequence of elements held as an array. The elements may be +glyph ids (gid), class ids (cids), or offsets to coverage tables. Each element +corresponds to one glyph in the glyph string. See MATCH_TYPE for details of +how the different element types are marked. + +=item PRE + +This array holds the sequence of elements preceding the first match element +and has the same form as the MATCH array. + +=item POST + +This array holds the sequence of elements to be tested for following the match +string and is of the same form as the MATCH array. + +=item ACTION + +This array holds information regarding what should be done if a match is found. +The array may either hold glyph ids (which are used to replace or insert or +whatever glyphs in the glyph string) or 2 element arrays consisting of: + +=over 20 + +=item OFFSET + +Offset from the start of the matched string that the lookup should start at +when processing the substring. + +=item LOOKUP_INDEX + +The index to a lookup to be acted upon on the match string. + +=back + +=back + +=item CLASS + +For those lookups which use class categories rather than glyph ids for matching +this is the offset to the class definition used to categories glyphs in the +match string. + +=item PRE_CLASS + +This is the offset to the class definition for the before match glyphs + +=item POST_CLASS + +This is the offset to the class definition for the after match glyphs. + +=item ACTION_TYPE + +This string holds the type of information held in the ACTION variable of a RULE. +It is subclass specific. + +=item MATCH_TYPE + +This holds the type of information in the MATCH array of a RULE. This is subclass +specific. + +=item ADJUST + +This corresponds to a single action for all items in a coverage table. The meaning +is subclass specific. + +=item CACHE + +This key starts with a space + +A hash of other tables (such as coverage tables, classes, anchors, device tables) +based on the offset given in the subtable to that other information. +Note that the documentation is particularly +unhelpful here in that such tables are given as offsets relative to the +beginning of the subtable not the whole GSUB table. This includes those items which +are stored relative to another base within the subtable. + +=back + +=back + +=back + +=head1 METHODS + +=cut + +use Font::TTF::Table; +use Font::TTF::Utils; +use Font::TTF::Coverage; + +use strict; +use vars qw(@ISA %FeatParams); + +@ISA = qw(Font::TTF::Table); + +%FeatParams = ( + 'ss' => 'Font::TTF::Features::Sset', + 'cv' => 'Font::TTF::Features::Cvar', + 'si' => 'Font::TTF::Features::Size', + ); + +=head2 $t->read + +Reads the table passing control to the subclass to handle the subtable specifics + +=cut + +sub read +{ + my ($self) = @_; + $self->SUPER::read or return $self; + + my ($dat, $i, $l, $oScript, $oFeat, $oLook, $tag, $nScript, $off, $dLang, $nLang, $lTag); + my ($nFeat, $oParms, $FType, $nLook, $nSub, $j, $temp, $t); + my ($fh) = $self->{' INFILE'}; + my ($moff) = $self->{' OFFSET'}; + + $fh->read($dat, 10); + ($self->{'Version'}, $oScript, $oFeat, $oLook) = TTF_Unpack("vSSS", $dat); + +# read features first so that in the script/lang hierarchy we can use feature tags + + $fh->seek($moff + $oFeat, 0); + $fh->read($dat, 2); + $nFeat = unpack("n", $dat); + $self->{'FEATURES'} = {}; + $l = $self->{'FEATURES'}; + $fh->read($dat, 6 * $nFeat); + for ($i = 0; $i < $nFeat; $i++) + { + ($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6)); + while (defined $l->{$tag}) + { + if ($tag =~ m/(.*?)\s_(\d+)$/o) + { $tag = $1 . " _" . ($2 + 1); } + else + { $tag .= " _0"; } + } + $l->{$tag}{' OFFSET'} = $off + $oFeat; + $l->{$tag}{'INDEX'} = $i; + push (@{$l->{'FEAT_TAGS'}}, $tag); + } + + foreach $tag (grep {m/^.{4}(?:\s_\d+)?$/o} keys %$l) + { + $oFeat=$moff + $l->{$tag}{' OFFSET'}; + $fh->seek($oFeat, 0); + $fh->read($dat, 4); + ($oParms, $nLook) = unpack("n2", $dat); + $fh->read($dat, $nLook * 2); + $l->{$tag}{'LOOKUPS'} = [unpack("n*", $dat)]; + $l->{$tag}{'PARMS'}=""; + if ($oParms > 0) + { + $FType=$FeatParams{substr($tag,0,2)}; + if ($FType) + { + $t=$FType; + if ($^O eq "MacOS") + { $t =~ s/^|::/:/oig; } + else + { $t =~ s|::|/|oig; } + require "$t.pm"; + $l->{$tag}{'PARMS'} = $FType->new( INFILE => $fh, + OFFSET => $oFeat+$oParms); + $l->{$tag}{'PARMS'}->read; + } + } + + } + +# Now the script/lang hierarchy + + $fh->seek($moff + $oScript, 0); + $fh->read($dat, 2); + $nScript = unpack("n", $dat); + $self->{'SCRIPTS'} = {}; + $l = $self->{'SCRIPTS'}; + $fh->read($dat, 6 * $nScript); + for ($i = 0; $i < $nScript; $i++) + { + ($tag, $off) = unpack("a4n", substr($dat, $i * 6, 6)); + $off += $oScript; + foreach (keys %$l) + { $l->{$tag}{' REFTAG'} = $_ if ($l->{$_}{' OFFSET'} == $off + && !defined $l->{$_}{' REFTAG'}); } + $l->{$tag}{' OFFSET'} = $off; + } + + foreach $tag (keys %$l) + { + next if ($l->{$tag}{' REFTAG'}); + $fh->seek($moff + $l->{$tag}{' OFFSET'}, 0); + $fh->read($dat, 4); + ($dLang, $nLang) = unpack("n2", $dat); + $l->{$tag}{'DEFAULT'}{' OFFSET'} = + $dLang + $l->{$tag}{' OFFSET'} if $dLang; + $fh->read($dat, 6 * $nLang); + for ($i = 0; $i < $nLang; $i++) + { + ($lTag, $off) = unpack("a4n", substr($dat, $i * 6, 6)); + $off += $l->{$tag}{' OFFSET'}; + $l->{$tag}{$lTag}{' OFFSET'} = $off; + foreach (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT') + { $l->{$tag}{$lTag}{' REFTAG'} = $_ if ($l->{$tag}{$_}{' OFFSET'} == $off + && !$l->{$tag}{$_}{' REFTAG'}); } + push (@{$l->{$tag}{'LANG_TAGS'}}, $lTag); + } + foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT') + { + next unless defined $l->{$tag}{$lTag}; + next if ($l->{$tag}{$lTag}{' REFTAG'}); + $fh->seek($moff + $l->{$tag}{$lTag}{' OFFSET'}, 0); + $fh->read($dat, 6); + ($l->{$tag}{$lTag}{'RE-ORDER'}, $l->{$tag}{$lTag}{'DEFAULT'}, $nFeat) + = unpack("n3", $dat); + $fh->read($dat, $nFeat * 2); + $l->{$tag}{$lTag}{'FEATURES'} = [map {$self->{'FEATURES'}{'FEAT_TAGS'}[$_]} unpack("n*", $dat)]; + } + foreach $lTag (@{$l->{$tag}{'LANG_TAGS'}}, 'DEFAULT') + { + # Make copies of referenced languages for each reference. + next unless $l->{$tag}{$lTag}{' REFTAG'}; + $temp = $l->{$tag}{$lTag}{' REFTAG'}; + $l->{$tag}{$lTag} = ©($l->{$tag}{$temp}); + $l->{$tag}{$lTag}{' REFTAG'} = $temp; + } + } + foreach $tag (keys %$l) + { + next unless $l->{$tag}{' REFTAG'}; + $temp = $l->{$tag}{' REFTAG'}; + $l->{$tag} = ©($l->{$temp}); + $l->{$tag}{' REFTAG'} = $temp; + } + +# And finally the lookups + + $fh->seek($moff + $oLook, 0); + $fh->read($dat, 2); + $nLook = unpack("n", $dat); + $fh->read($dat, $nLook * 2); + $i = 0; + map { $self->{'LOOKUP'}[$i++]{' OFFSET'} = $_; } unpack("n*", $dat); + + for ($i = 0; $i < $nLook; $i++) + { + $l = $self->{'LOOKUP'}[$i]; + $fh->seek($l->{' OFFSET'} + $moff + $oLook, 0); + $fh->read($dat, 6); + ($l->{'TYPE'}, $l->{'FLAG'}, $nSub) = unpack("n3", $dat); + $fh->read($dat, $nSub * 2); + my @offsets = unpack("n*", $dat); + if ($l->{'FLAG'} & 0x0010) + { + $fh->read($dat, 2); + $l->{'FILTER'} = unpack("n", $dat); + } + my $isExtension = ($l->{'TYPE'} == $self->extension()); + for ($j = 0; $j < $nSub; $j++) + { + $l->{'SUB'}[$j]{' OFFSET'} = $offsets[$j]; + $fh->seek($moff + $oLook + $l->{' OFFSET'} + $l->{'SUB'}[$j]{' OFFSET'}, 0); + if ($isExtension) + { + $fh->read($dat, 8); + my $longOff; + (undef, $l->{'TYPE'}, $longOff) = unpack("nnN", $dat); + $l->{'SUB'}[$j]{' OFFSET'} += $longOff; + $fh->seek($moff + $oLook + $l->{' OFFSET'} + $l->{'SUB'}[$j]{' OFFSET'}, 0); + } + $self->read_sub($fh, $l, $j); + } + } + return $self; +} + +=head2 $t->read_sub($fh, $lookup, $index) + +This stub is to allow subclasses to read subtables of lookups in a table specific manner. A +reference to the lookup is passed in along with the subtable index. The file is located at the +start of the subtable to be read + +=cut + +sub read_sub +{ } + + +=head2 $t->extension() + +Returns the lookup number for the extension table that allows access to 32-bit offsets. + +=cut + +sub extension +{ } + + +=head2 $t->out($fh) + +Writes this Opentype table to the output calling $t->out_sub for each sub table +at the appropriate point in the output. The assumption is that on entry the +number of scripts, languages, features, lookups, etc. are all resolved and +the relationships fixed. This includes a LANG_TAGS list for a script, and that all +scripts and languages in their respective dictionaries either have a REFTAG or contain +real data. + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($i, $j, $base, $off, $tag, $t, $l, $lTag, $oScript, @script, @tags); + my ($end, $nTags, @offs, $oFeat, $oFtable, $oParms, $FType, $oLook, $nSub, $nSubs, $big, $out); + + return $self->SUPER::out($fh) unless $self->{' read'}; + +# First sort the features + $i = 0; + $self->{'FEATURES'}{'FEAT_TAGS'} = [sort grep {m/^.{4}(?:\s_\d+)?$/o} %{$self->{'FEATURES'}}] + if (!defined $self->{'FEATURES'}{'FEAT_TAGS'}); + foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}}) + { $self->{'FEATURES'}{$t}{'INDEX'} = $i++; } + + $base = $fh->tell(); + $fh->print(TTF_Pack("v", $self->{'Version'})); + $fh->print(pack("n3", 10, 0, 0)); + $oScript = $fh->tell() - $base; + @script = sort grep {length($_) == 4} keys %{$self->{'SCRIPTS'}}; + $fh->print(pack("n", $#script + 1)); + foreach $t (@script) + { $fh->print(pack("a4n", $t, 0)); } + + $end = $fh->tell(); + foreach $t (@script) + { + $fh->seek($end, 0); + $tag = $self->{'SCRIPTS'}{$t}; + next if ($tag->{' REFTAG'}); + $tag->{' OFFSET'} = tell($fh) - $base - $oScript; + $fh->print(pack("n2", 0, $#{$tag->{'LANG_TAGS'}} + 1)); + foreach $lTag (sort @{$tag->{'LANG_TAGS'}}) + { $fh->print(pack("a4n", $lTag, 0)); } + foreach $lTag (@{$tag->{'LANG_TAGS'}}, 'DEFAULT') + { + my ($def); + $l = $tag->{$lTag}; + next if (!defined $l || (defined $l->{' REFTAG'} && $l->{' REFTAG'} ne '')); + $l->{' OFFSET'} = $fh->tell() - $base - $oScript - $tag->{' OFFSET'}; + if (defined $l->{'DEFAULT'}) +# { $def = $self->{'FEATURES'}{$l->{'FEATURES'}[$l->{'DEFAULT'}]}{'INDEX'}; } + { $def = $l->{'DEFAULT'}; } + else + { $def = -1; } + $fh->print(pack("n*", $l->{'RE_ORDER'} || 0, $def, $#{$l->{'FEATURES'}} + 1, + map {$self->{'FEATURES'}{$_}{'INDEX'} || 0} @{$l->{'FEATURES'}})); + } + $end = $fh->tell(); + if ($tag->{'DEFAULT'}{' REFTAG'} || defined $tag->{'DEFAULT'}{'FEATURES'}) + { + $fh->seek($base + $oScript + $tag->{' OFFSET'}, 0); + if (defined $tag->{'DEFAULT'}{' REFTAG'}) + { + my ($ttag); + for ($ttag = $tag->{'DEFAULT'}{' REFTAG'}; defined $tag->{$ttag}{' REFTAG'}; $ttag = $tag->{$ttag}{' REFTAG'}) + { } + $off = $tag->{$ttag}{' OFFSET'}; + } + else + { $off = $tag->{'DEFAULT'}{' OFFSET'}; } + $fh->print(pack("n", $off)); + } + $fh->seek($base + $oScript + $tag->{' OFFSET'} + 4, 0); + foreach (sort @{$tag->{'LANG_TAGS'}}) + { + if (defined $tag->{$_}{' REFTAG'}) + { + my ($ttag); + for ($ttag = $tag->{$_}{' REFTAG'}; defined $tag->{$ttag}{' REFTAG'}; $ttag = $tag->{$ttag}{' REFTAG'}) + { } + $off = $tag->{$ttag}{' OFFSET'}; + } + else + { $off = $tag->{$_}{' OFFSET'}; } + $fh->print(pack("a4n", $_, $off)); + } + } + $fh->seek($base + $oScript + 2, 0); + foreach $t (@script) + { + $tag = $self->{'SCRIPTS'}{$t}; + $off = $tag->{' REFTAG'} ? $tag->{$tag->{' REFTAG'}}{' OFFSET'} : $tag->{' OFFSET'}; + $fh->print(pack("a4n", $t, $off)); + } + + $fh->seek($end, 0); + $oFeat = $end - $base; + $nTags = $#{$self->{'FEATURES'}{'FEAT_TAGS'}} + 1; + $fh->print(pack("n", $nTags)); + $fh->print(pack("a4n", " ", 0) x $nTags); + + foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}}) + { + $tag = $self->{'FEATURES'}{$t}; + $oFtable = tell($fh) - $base - $oFeat; + $tag->{' OFFSET'} = $oFtable; + $fh->print(pack("n*", 0, $#{$tag->{'LOOKUPS'}} + 1, @{$tag->{'LOOKUPS'}})); + if ($tag->{'PARMS'}) + { + $end = $fh->tell(); + $oParms = $end - $oFtable - $base - $oFeat; + $fh->seek($oFtable + $base + $oFeat,0); + $fh->print(pack("n",$oParms)); + $fh->seek($end,0); + $tag->{'PARMS'}->out($fh); + } + } + $end = $fh->tell(); + $fh->seek($oFeat + $base + 2, 0); + foreach $t (@{$self->{'FEATURES'}{'FEAT_TAGS'}}) + { $fh->print(pack("a4n", $t, $self->{'FEATURES'}{$t}{' OFFSET'})); } + + undef $big; + $fh->seek($end, 0); + $oLook = $end - $base; + + # LookupListTable (including room for offsets to LookupTables) + $nTags = $#{$self->{'LOOKUP'}} + 1; + $fh->print(pack("n", $nTags)); + $fh->print(pack("n", 0) x $nTags); + $end = $fh->tell(); # end of LookupListTable = start of Lookups + foreach $tag (@{$self->{'LOOKUP'}}) + { $nSubs += $self->num_sub($tag); } + for ($i = 0; $i < $nTags; $i++) + { + $fh->seek($end, 0); + $tag = $self->{'LOOKUP'}[$i]; + $off = $end - $base - $oLook; # BH 2004-03-04 + # Is there room, from the start of this i'th lookup, for this and the remaining + # lookups to be wrapped in extension lookups? + if (!defined $big && $off + ($nTags - $i) * 6 + $nSubs * 10 > 65535) # BH 2004-03-04 + { + # Not enough room -- need to start an extension! + my ($k, $ext); + $ext = $self->extension(); + # Must turn previous lookup into the first extension + $i--; + $tag = $self->{'LOOKUP'}[$i]; + $end = $tag->{' OFFSET'} + $base + $oLook; + $fh->seek($end, 0); + $big = $i; + # For this and the remaining lookups, build extensions lookups + for ($j = $i; $j < $nTags; $j++) + { + $tag = $self->{'LOOKUP'}[$j]; + $nSub = $self->num_sub($tag); + $tag->{' OFFSET'} = $fh->tell() - $base - $oLook; # offset to this extension lookup + # LookupTable (including actual offsets to subtables) + $fh->print(pack("nnn", $ext, $tag->{'FLAG'}, $nSub)); + $fh->print(pack("n*", map {6 + $nSub * 2 + $_ * 8 + ($tag->{'FLAG'} & 0x0010 ? 2 : 0) } (0 .. $nSub-1))); + $fh->print(pack("n", $tag->{'FILTER'})) if $tag->{'FLAG'} & 0x0010; + $tag->{' EXT_OFFSET'} = $fh->tell(); # = first extension lookup subtable + for ($k = 0; $k < $nSub; $k++) + { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, 0)); } + } + + $tag = $self->{'LOOKUP'}[$i]; + # Leave file positioned after all the extension lookups -- where the referenced lookups will start. + } + $tag->{' OFFSET'} = $off unless defined $big; # BH 2004-03-04 + $nSub = $self->num_sub($tag); + if (!defined $big) + { + # LookupTable (including room for subtable offsets) + $fh->print(pack("nnn", $tag->{'TYPE'}, $tag->{'FLAG'}, $nSub)); + $fh->print(pack("n", 0) x $nSub); + $fh->print(pack("n", $tag->{'FILTER'})) if $tag->{'FLAG'} & 0x0010; + } + else + { $end = $tag->{' EXT_OFFSET'}; } # Extension offsets computed relative to start of first Extension subtable -- corrected later + my (@offs, $out, @refs); + for ($j = 0; $j < $nSub; $j++) + { + my ($ctables) = {}; + my ($base) = length($out); + push(@offs, tell($fh) - $end + $base); + $out .= $self->out_sub($fh, $tag, $j, $ctables, $base); + push (@refs, [$ctables, $base]); + } + out_final($fh, $out, \@refs); + $end = $fh->tell(); + if (!defined $big) + { + $fh->seek($tag->{' OFFSET'} + $base + $oLook + 6, 0); + $fh->print(pack("n*", @offs)); + } + else + { + $fh->seek($tag->{' EXT_OFFSET'}, 0); + for ($j = 0; $j < $nSub; $j++) + { $fh->print(pack('nnN', 1, $tag->{'TYPE'}, $offs[$j] - $j * 8)); } + } + } + $fh->seek($oLook + $base + 2, 0); + $fh->print(pack("n*", map {$self->{'LOOKUP'}[$_]{' OFFSET'}} (0 .. $nTags - 1))); + $fh->seek($base + 6, 0); + $fh->print(pack('n2', $oFeat, $oLook)); + $fh->seek($end, 0); + $self; +} + + +=head2 $t->num_sub($lookup) + +Asks the subclass to count the number of subtables for a particular lookup and to +return that value. Used in out(). + +=cut + +sub num_sub +{ + my ($self, $lookup) = @_; + + return $#{$lookup->{'SUB'}} + 1; +} + + +=head2 $t->out_sub($fh, $lookup, $index) + +This stub is to allow subclasses to output subtables of lookups in a table specific manner. A +reference to the lookup is passed in along with the subtable index. The file is located at the +start of the subtable to be output + +=cut + +sub out_sub +{ } + +=head2 $t->dirty + +Setting GPOS or GSUB dirty means that OS/2 may need updating, so set it dirty. + +=cut + +sub dirty +{ + my ($self, $val) = @_; + my $res = $self->SUPER::dirty ($val); + $self->{' PARENT'}{'OS/2'}->read->dirty($val) if exists $self->{' PARENT'}{'OS/2'}; + $res; +} + +=head2 $t->maxContext + +Returns the length of the longest opentype rule in this table. + +=cut + +sub maxContext +{ + my ($self) = @_; + + # Make sure table is read + $self->read; + + # Calculate my contribution to OS/2 usMaxContext + + my ($maxcontext, $l, $s, $r, $m); + + for $l (@{$self->{'LOOKUP'}}) # Examine each lookup + { + for $s (@{$l->{'SUB'}}) # Multiple possible subtables for this lookup + { + for $r (@{$s->{'RULES'}}) # One ruleset for each covered glyph + { + for $m (@{$r}) # Multiple possible matches for this covered glyph + { + my $lgt; + $lgt++ if exists $s->{'COVERAGE'}; # Count 1 for the coverage table if it exists + for (qw(MATCH POST)) # only Input and Lookahead sequences count (Lookbehind doesn't) -- see OT spec. + { + $lgt += @{$m->{$_}} if exists $m->{$_}; + } + $maxcontext = $lgt if $lgt > $maxcontext; + } + } + + } + } + + $maxcontext; +} + + +=head2 $t->update + +Perform various housekeeping items: + +For all lookups, set/clear 0x0010 bit of flag words based on 'FILTER' value. + +Sort COVERAGE table and RULES for all lookups. + +Unless $t->{' PARENT'}{' noharmony'} is true, update will make sure that GPOS and GSUB include +the same scripts and languages. Any added scripts and languages will have empty feature sets. + +=cut + +# Assumes we are called on both GSUB and GPOS. So simply ADDS scripts and languages to $self that it finds +# in the other table. + +sub update +{ + my ($self) = @_; + + return undef unless ($self->SUPER::update); + + if (defined ($self->{'LOOKUP'})) + { + + # make flag word agree with mark filter setting: + for my $l (@{$self->{'LOOKUP'}}) + { + if (defined $l->{'FILTER'}) + { $l->{'FLAG'} |= 0x0010; } + else + { $l->{'FLAG'} &= ~0x0010; } + } + + unless ($Font::TTF::Coverage::dontsort) + { + # Sort coverage tables and rules of all lookups by glyphID + # The lookup types that need to be sorted are: + # GSUB: 1.2 2 3 4 5.1 6.1 8 (However GSUB type 8 lookups are not yet supported by Font::TTF) + # GPOS: 1.2 2.1 3 4 5 6 7.1 8.1 + + for my $l (@{$self->{'LOOKUP'}}) + { + next unless defined $l->{'SUB'}; + for my $sub (@{$l->{'SUB'}}) + { + if (defined $sub->{'COVERAGE'} and $sub->{'COVERAGE'}{'cover'} and !$sub->{'COVERAGE'}{'dontsort'}) + { + # OK! Found a lookup with coverage table: + my @map = $sub->{'COVERAGE'}->sort(); + if (defined $sub->{'RULES'} and ($sub->{'MATCH_TYPE'} =~ /g/ or $sub->{'ACTION_TYPE'} =~ /[gvea]/)) + { + # And also a RULES table which now needs to be re-sorted + my $newrules = []; + foreach (0 .. $#map) + { push @{$newrules}, $sub->{'RULES'}[$map[$_]]; } + $sub->{'RULES'} = $newrules; + } + } + + # Special case for Mark positioning -- need to also sort the MarkArray + if (exists($sub->{'MARKS'}) and ref($sub->{'MATCH'}[0]) =~ /Cover/ and $sub->{'MATCH'}[0]{'cover'} and !$sub->{'MATCH'}[0]{'dontsort'}) + { + my @map = $sub->{'MATCH'}[0]->sort(); + my $newmarks = []; + foreach (0 .. $#map) + { push @{$newmarks}, $sub->{'MARKS'}[$map[$_]]; } + $sub->{'MARKS'} = $newmarks; + } + } + } + } + } + + # Enforce script/lang congruence unless asked not to: + return $self if $self->{' PARENT'}{' noharmony'}; + + # Find my sibling (GSUB or GPOS, depending on which I am) + my $sibling = ref($self) eq 'Font::TTF::GSUB' ? 'GPOS' : ref($self) eq 'Font::TTF::GPOS' ? 'GSUB' : undef; + return $self unless $sibling && defined $self->{' PARENT'}{$sibling}; + $sibling = $self->{' PARENT'}{$sibling}; + + # Look through scripts defined in sibling: + for my $sTag (grep {length($_) == 4} keys %{$sibling->{'SCRIPTS'}}) + { + my $sibScript = $sibling->{'SCRIPTS'}{$sTag}; + $sibScript = $sibling->{$sibScript->{' REFTAG'}} if exists $sibScript->{' REFTAG'} && $sibScript->{' REFTAG'} ne ''; + + $self->{'SCRIPTS'}{$sTag} = {} unless defined $self->{'SCRIPTS'}{$sTag}; # Create script if not present in $self + + my $myScript = $self->{'SCRIPTS'}{$sTag}; + $myScript = $self->{$myScript->{' REFTAG'}} if exists $myScript->{' REFTAG'} && $myScript->{' REFTAG'} ne ''; + + foreach my $lTag (@{$sibScript->{'LANG_TAGS'}}) + { + # Ok, found a script/lang that is in our sibling. + next if exists $myScript->{$lTag}; # Already in $self + + # Need to create this lang: + push @{$myScript->{'LANG_TAGS'}}, $lTag; + $myScript->{$lTag} = { 'FEATURES' => [] }; + } + + if (defined $sibScript->{'DEFAULT'} && !defined $myScript->{'DEFAULT'}) + { + # Create default lang for this script. + $myScript->{'DEFAULT'} = { 'FEATURES' => [] }; + } + } + $self; +} + +=head1 Internal Functions & Methods + +Most of these methods are used by subclasses for handling such things as coverage +tables. + +=head2 copy($ref) + +Internal function to copy the top level of a dictionary to create a new dictionary. +Only the top level is copied. + +=cut + +sub copy +{ + my ($ref) = @_; + my ($res) = {}; + + foreach (keys %$ref) + { $res->{$_} = $ref->{$_}; } + $res; +} + + +=head2 $t->read_cover($cover_offset, $lookup_loc, $lookup, $fh, $is_cover) + +Reads a coverage table and stores the results in $lookup->{' CACHE'}, that is, if +it has not been read already. + +=cut + +sub read_cover +{ + my ($self, $offset, $base, $lookup, $fh, $is_cover) = @_; + my ($loc) = $fh->tell(); + my ($cover, $str); + + return undef unless $offset; + $str = sprintf("%X", $base + $offset); + return $lookup->{' CACHE'}{$str} if defined $lookup->{' CACHE'}{$str}; + $fh->seek($base + $offset, 0); + $cover = Font::TTF::Coverage->new($is_cover)->read($fh); + $fh->seek($loc, 0); + $lookup->{' CACHE'}{$str} = $cover; + return $cover; +} + + +=head2 ref_cache($obj, $cache, $offset [, $template]) + +Internal function to keep track of the local positioning of subobjects such as +coverage and class definition tables, and their offsets. +What happens is that the cache is a hash of +sub objects indexed by the reference (using a string mashing of the +reference name which is valid for the duration of the reference) and holds a +list of locations in the output string which should be filled in with the +offset to the sub object when the final string is output in out_final. + +Uses tricks for Tie::Refhash + +=cut + +sub ref_cache +{ + my ($obj, $cache, $offset, $template) = @_; + + return 0 unless defined $obj; + $template ||= 'n'; + unless (defined $cache->{"$obj"}) + { push (@{$cache->{''}}, $obj); } + push (@{$cache->{"$obj"}}, [$offset, $template]); + return 0; +} + + +=head2 out_final($fh, $out, $cache_list, $state) + +Internal function to actually output everything to the file handle given that +now we know the offset to the first sub object to be output and which sub objects +are to be output and what locations need to be updated, we can now +generate everything. $cache_list is an array of two element arrays. The first element +is a cache object, the second is an offset to be subtracted from each reference +to that object made in the cache. + +If $state is 1, then the output is not sent to the filehandle and the return value +is the string to be output. If $state is absent or 0 then output is not limited +by storing in a string first and the return value is ""; + +=cut + +sub out_final +{ + my ($fh, $out, $cache_list, $state) = @_; + my ($len) = length($out || ''); + my ($base_loc) = $state ? 0 : $fh->tell(); + my ($loc, $t, $r, $s, $master_cache, $offs, $str, %vecs); + + $fh->print($out || '') unless $state; # first output the current attempt + foreach $r (@$cache_list) + { + $offs = $r->[1]; + foreach $t (@{$r->[0]{''}}) + { + $str = "$t"; + if (!defined $master_cache->{$str}) + { + my ($vec) = $t->signature(); + if ($vecs{$vec}) + { $master_cache->{$str} = $master_cache->{$vecs{$vec}}; } + else + { + $vecs{$vec} = $str; + $master_cache->{$str} = ($state ? length($out) : $fh->tell()) + - $base_loc; + if ($state) + { $out .= $t->out($fh, 1); } + else + { $t->out($fh, 0); } + } + } + foreach (@{$r->[0]{$str}}) + { + $s = pack($_->[1], $master_cache->{$str} - $offs); + substr($out, $_->[0], length($s)) = $s; + } + } + } + if ($state) + { return $out; } + else + { + $loc = $fh->tell(); + $fh->seek($base_loc, 0); + $fh->print($out || ''); # the corrected version + $fh->seek($loc, 0); + } +} + + +=head2 $self->read_context($lookup, $fh, $type, $fmt, $cover, $count, $loc) + +Internal method to read context (simple and chaining context) lookup subtables for +the GSUB and GPOS table types. The assumed values for $type correspond to those +for GSUB, so GPOS should adjust the values upon calling. + +=cut + +sub read_context +{ + my ($self, $lookup, $fh, $type, $fmt, $cover, $count, $loc) = @_; + my ($dat, $i, $s, $t, @subst, @srec, $mcount, $scount); + + if ($type == 5 && $fmt < 3) + { + if ($fmt == 2) + { + $fh->read($dat, 2); + $lookup->{'CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0); + $count = TTF_Unpack('S', $dat); + } + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { + if ($s == 0) + { + push (@{$lookup->{'RULES'}}, []); + next; + } + @subst = (); + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + foreach $t (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s + $t, 0); + @srec = (); + $fh->read($dat, 4); + ($mcount, $scount) = TTF_Unpack('S2', $dat); + $mcount--; + $fh->read($dat, ($mcount << 1) + ($scount << 2)); + for ($i = 0; $i < $scount; $i++) + { push (@srec, [TTF_Unpack('S2', substr($dat, + ($mcount << 1) + ($i << 2), 4))]); } + push (@subst, {'ACTION' => [@srec], + 'MATCH' => [TTF_Unpack('S*', + substr($dat, 0, $mcount << 1))]}); + } + push (@{$lookup->{'RULES'}}, [@subst]); + } + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g'); + } elsif ($type == 5 && $fmt == 3) + { + $fh->read($dat, ($cover << 1) + ($count << 2)); + @subst = (); @srec = (); + for ($i = 0; $i < $cover; $i++) + { push (@subst, $self->read_cover(TTF_Unpack('S', substr($dat, $i << 1, 2)), + $loc, $lookup, $fh, 1)); } + for ($i = 0; $i < $count; $i++) + { push (@srec, [TTF_Unpack('S2', substr($dat, ($count << 1) + ($i << 2), 4))]); } + $lookup->{'RULES'} = [[{'ACTION' => [@srec], 'MATCH' => [@subst]}]]; + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = 'o'; + } elsif ($type == 6 && $fmt < 3) + { + if ($fmt == 2) + { + $fh->read($dat, 6); + $lookup->{'PRE_CLASS'} = $self->read_cover($count, $loc, $lookup, $fh, 0) if $count; + ($i, $mcount, $count) = TTF_Unpack('S3', $dat); # messy: 2 classes & count + $lookup->{'CLASS'} = $self->read_cover($i, $loc, $lookup, $fh, 0) if $i; + $lookup->{'POST_CLASS'} = $self->read_cover($mcount, $loc, $lookup, $fh, 0) if $mcount; + } + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { + if ($s == 0) + { + push (@{$lookup->{'RULES'}}, []); + next; + } + @subst = (); + $fh->seek($loc + $s, 0); + $fh->read($dat, 2); + $t = TTF_Unpack('S', $dat); + $fh->read($dat, $t << 1); + foreach $i (TTF_Unpack('S*', $dat)) + { + $fh->seek($loc + $s + $i, 0); + @srec = (); + $t = {}; + $fh->read($dat, 2); + $mcount = TTF_Unpack('S', $dat); + if ($mcount > 0) + { + $fh->read($dat, $mcount << 1); + $t->{'PRE'} = [TTF_Unpack('S*', $dat)]; + } + $fh->read($dat, 2); + $mcount = TTF_Unpack('S', $dat); + if ($mcount > 1) + { + $fh->read($dat, ($mcount - 1) << 1); + $t->{'MATCH'} = [TTF_Unpack('S*', $dat)]; + } + $fh->read($dat, 2); + $mcount = TTF_Unpack('S', $dat); + if ($mcount > 0) + { + $fh->read($dat, $mcount << 1); + $t->{'POST'} = [TTF_Unpack('S*', $dat)]; + } + $fh->read($dat, 2); + $scount = TTF_Unpack('S', $dat); + $fh->read($dat, $scount << 2); + for ($i = 0; $i < $scount; $i++) + { push (@srec, [TTF_Unpack('S2', substr($dat, $i << 2))]); } + $t->{'ACTION'} = [@srec]; + push (@subst, $t); + } + push (@{$lookup->{'RULES'}}, [@subst]); + } + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = ($fmt == 2 ? 'c' : 'g'); + } elsif ($type == 6 && $fmt == 3) + { + $t = {}; + unless ($cover == 0) + { + @subst = (); + $fh->read($dat, $cover << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'PRE'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'MATCH'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + unless ($count == 0) + { + @subst = (); + $fh->read($dat, $count << 1); + foreach $s (TTF_Unpack('S*', $dat)) + { push(@subst, $self->read_cover($s, $loc, $lookup, $fh, 1)); } + $t->{'POST'} = [@subst]; + } + $fh->read($dat, 2); + $count = TTF_Unpack('S', $dat); + @subst = (); + $fh->read($dat, $count << 2); + for ($i = 0; $i < $count; $i++) + { push (@subst, [TTF_Unpack('S2', substr($dat, $i << 2, 4))]); } + $t->{'ACTION'} = [@subst]; + $lookup->{'RULES'} = [[$t]]; + $lookup->{'ACTION_TYPE'} = 'l'; + $lookup->{'MATCH_TYPE'} = 'o'; + } + $lookup; +} + + +=head2 $self->out_context($lookup, $fh, $type, $fmt, $ctables, $out, $num) + +Provides shared behaviour between GSUB and GPOS tables during output for context +(chained and simple) rules. In addition, support is provided here for type 4 GSUB +tables, which are not used in GPOS. The value for $type corresponds to the type +in a GSUB table so calling from GPOS should adjust the value accordingly. + +=cut + +sub out_context +{ + my ($self, $lookup, $fh, $type, $fmt, $ctables, $out, $num, $base) = @_; + my ($offc, $offd, $i, $j, $r, $t, $numd); + + $out ||= ''; + if (($type == 4 || $type == 5 || $type == 6) && ($fmt == 1 || $fmt == 2)) + { + my ($base_off); + + if ($fmt == 1) + { + $out = pack("nnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + $num); + $base_off = 6; + } elsif ($type == 5) + { + $out = pack("nnnn", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 4 + $base), $num); + $base_off = 8; + } elsif ($type == 6) + { + $out = pack("n6", $fmt, Font::TTF::Ttopen::ref_cache($lookup->{'COVERAGE'}, $ctables, 2 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'PRE_CLASS'}, $ctables, 4 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'CLASS'}, $ctables, 6 + $base), + Font::TTF::Ttopen::ref_cache($lookup->{'POST_CLASS'}, $ctables, 8 + $base), + $num); + $base_off = 12; + } + + $out .= pack('n*', (0) x $num); + $offc = length($out); + for ($i = 0; $i < $num; $i++) + { + $r = $lookup->{'RULES'}[$i]; + next unless exists $r->[0]{'ACTION'}; + $numd = $#{$r} + 1; + substr($out, ($i << 1) + $base_off, 2) = pack('n', $offc); + $out .= pack('n*', $numd, (0) x $numd); + $offd = length($out) - $offc; + for ($j = 0; $j < $numd; $j++) + { + substr($out, $offc + 2 + ($j << 1), 2) = pack('n', $offd); + if ($type == 4) + { + $out .= pack('n*', $r->[$j]{'ACTION'}[0], $#{$r->[$j]{'MATCH'}} + 2, + @{$r->[$j]{'MATCH'}}); + } elsif ($type == 5) + { + $out .= pack('n*', $#{$r->[$j]{'MATCH'}} + 2, + $#{$r->[$j]{'ACTION'}} + 1, + @{$r->[$j]{'MATCH'}}); + foreach $t (@{$r->[$j]{'ACTION'}}) + { $out .= pack('n2', @$t); } + } elsif ($type == 6) + { + $out .= pack('n*', $#{$r->[$j]{'PRE'}} + 1, @{$r->[$j]{'PRE'}}, + $#{$r->[$j]{'MATCH'}} + 2, @{$r->[$j]{'MATCH'}}, + $#{$r->[$j]{'POST'}} + 1, @{$r->[$j]{'POST'}}, + $#{$r->[$j]{'ACTION'}} + 1); + foreach $t (@{$r->[$j]{'ACTION'}}) + { $out .= pack('n2', @$t); } + } + $offd = length($out) - $offc; + } + $offc = length($out); + } + } elsif ($type == 5 && $fmt == 3) + { + $out .= pack('n3', $fmt, $#{$lookup->{'RULES'}[0][0]{'MATCH'}} + 1, + $#{$lookup->{'RULES'}[0][0]{'ACTION'}} + 1); + foreach $t (@{$lookup->{'RULES'}[0][0]{'MATCH'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + foreach $t (@{$lookup->{'RULES'}[0][0]{'ACTION'}}) + { $out .= pack('n2', @$t); } + } elsif ($type == 6 && $fmt == 3) + { + $r = $lookup->{'RULES'}[0][0]; + no strict 'refs'; # temp fix - more code needed (probably "if" statements in the event 'PRE' or 'POST' are empty) + $out .= pack('n2', $fmt, defined $r->{'PRE'} ? scalar @{$r->{'PRE'}} : 0); + foreach $t (@{$r->{'PRE'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'MATCH'} ? scalar @{$r->{'MATCH'}} : 0); + foreach $t (@{$r->{'MATCH'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'POST'} ? scalar @{$r->{'POST'}} : 0); + foreach $t (@{$r->{'POST'}}) + { $out .= pack('n', Font::TTF::Ttopen::ref_cache($t, $ctables, length($out) + $base)); } + $out .= pack('n', defined $r->{'ACTION'} ? scalar @{$r->{'ACTION'}} : 0); + foreach $t (@{$r->{'ACTION'}}) + { $out .= pack('n2', @$t); } + } + $out; +} + +1; + + +=head1 BUGS + +=over 4 + +=item * + +No way to share cachable items (coverage tables, classes, anchors, device tables) +across different lookups. The items are always output after the lookup and +repeated if necessary. Within lookup sharing is possible. + +=back + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Useall.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Useall.pm new file mode 100644 index 0000000000..c140eb97bc --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Useall.pm @@ -0,0 +1,102 @@ +=head1 NAME + +Font::TTF::Useall - shortcut to 'use' all the Font::TTF modules + +=head1 SYNOPSIS + + use Font::TTF::Useall; + +=head1 DESCRIPTION + +Useful for debugging, this module simply does a 'use' on all the other +modules that are part of Font::TTF. + +=cut + +use Font::TTF::Ttc; +use Font::TTF::PSNames; +use Font::TTF::OTTags; +use Font::TTF::EBDT; +use Font::TTF::EBLC; +use Font::TTF::DSIG; +use Font::TTF::Sill; +use Font::TTF::Silf; +use Font::TTF::Cvt_; +use Font::TTF::Fpgm; +use Font::TTF::Glyf; +use Font::TTF::Hdmx; +use Font::TTF::Kern; +use Font::TTF::Loca; +use Font::TTF::LTSH; +use Font::TTF::Name; +use Font::TTF::OS_2; +use Font::TTF::PCLT; +use Font::TTF::Post; +use Font::TTF::Prep; +use Font::TTF::Vmtx; +use Font::TTF::AATKern; +use Font::TTF::AATutils; +use Font::TTF::Anchor; +use Font::TTF::Bsln; +use Font::TTF::Delta; +use Font::TTF::Fdsc; +use Font::TTF::Feat; +use Font::TTF::GrFeat; +use Font::TTF::Fmtx; +use Font::TTF::GPOS; +use Font::TTF::Mort; +use Font::TTF::Prop; +use Font::TTF::GDEF; +use Font::TTF::Coverage; +use Font::TTF::GSUB; +use Font::TTF::Hhea; +use Font::TTF::Table; +use Font::TTF::Ttopen; +use Font::TTF::Glyph; +use Font::TTF::Head; +use Font::TTF::Hmtx; +use Font::TTF::Vhea; +use Font::TTF::Cmap; +use Font::TTF::Utils; +use Font::TTF::Maxp; +use Font::TTF::Font; +use Font::TTF::Kern::ClassArray; +use Font::TTF::Kern::CompactClassArray; +use Font::TTF::Kern::OrderedList; +use Font::TTF::Kern::StateTable; +use Font::TTF::Kern::Subtable; +use Font::TTF::Mort::Chain; +use Font::TTF::Mort::Contextual; +use Font::TTF::Mort::Insertion; +use Font::TTF::Mort::Ligature; +use Font::TTF::Mort::Noncontextual; +use Font::TTF::Mort::Rearrangement; +use Font::TTF::Mort::Subtable; +use Font::TTF::Features::Cvar; +use Font::TTF::Features::Size; +use Font::TTF::Features::Sset; +use Font::TTF::Woff; +use Font::TTF::Woff::MetaData; +use Font::TTF::Woff::PrivateData; +use Font::TTF::Glat; +use Font::TTF::Gloc; +use Font::TTF::Dumper; + + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Utils.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Utils.pm new file mode 100644 index 0000000000..2beb1b3a9f --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Utils.pm @@ -0,0 +1,639 @@ +package Font::TTF::Utils; + +=head1 NAME + +Font::TTF::Utils - Utility functions to save fingers + +=head1 DESCRIPTION + +Lots of useful functions to save my fingers, especially for trivial tables + +=head1 FUNCTIONS + +The following functions are exported + +=cut + +use strict; +use vars qw(@ISA @EXPORT $VERSION @EXPORT_OK); +require Exporter; + +@ISA = qw(Exporter); +@EXPORT = qw(TTF_Init_Fields TTF_Read_Fields TTF_Out_Fields TTF_Pack + TTF_Unpack TTF_word_utf8 TTF_utf8_word TTF_bininfo); +@EXPORT_OK = (@EXPORT, qw(XML_hexdump)); +$VERSION = 0.0001; + +=head2 ($val, $pos) = TTF_Init_Fields ($str, $pos) + +Given a field description from the C section, creates an absolute entry +in the fields associative array for the class + +=cut + +sub TTF_Init_Fields +{ + my ($str, $pos, $inval) = @_; + my ($key, $val, $res, $len, $rel); + + $str =~ s/\r?\n$//o; + if ($inval) + { ($key, $val) = ($str, $inval); } + else + { ($key, $val) = split(',\s*', $str); } + return (undef, undef, 0) unless (defined $key && $key ne ""); + if ($val =~ m/^(\+?)(\d*)(\D+)(\d*)/oi) + { + $rel = $1; + if ($rel eq "+") + { $pos += $2; } + elsif ($2 ne "") + { $pos = $2; } + $val = $3; + $len = $4; + } + $len = "" unless defined $len; + $pos = 0 if !defined $pos || $pos eq ""; + $res = "$pos:$val:$len"; + if ($val eq "f" || $val eq 'v' || $val =~ m/^[l]/oi) + { $pos += 4 * ($len ne "" ? $len : 1); } + elsif ($val eq "F" || $val =~ m/^[s]/oi) + { $pos += 2 * ($len ne "" ? $len : 1); } + else + { $pos += 1 * ($len ne "" ? $len : 1); } + + ($key, $res, $pos); +} + + +=head2 TTF_Read_Fields($obj, $dat, $fields) + +Given a block of data large enough to account for all the fields in a table, +processes the data block to convert to the values in the objects instance +variables by name based on the list in the C block which has been run +through C + +=cut + +sub TTF_Read_Fields +{ + my ($self, $dat, $fields) = @_; + my ($pos, $type, $res, $f, $arrlen, $arr, $frac); + + foreach $f (keys %{$fields}) + { + ($pos, $type, $arrlen) = split(':', $fields->{$f}); + $pos = 0 if $pos eq ""; + if ($arrlen ne "") + { $self->{$f} = [TTF_Unpack("$type$arrlen", substr($dat, $pos))]; } + else + { $self->{$f} = TTF_Unpack("$type", substr($dat, $pos)); } + } + $self; +} + + +=head2 TTF_Unpack($fmt, $dat) + +A TrueType types equivalent of Perls C function. Thus $fmt consists of +type followed by an optional number of elements to read including *. The type +may be one of: + + c BYTE + C CHAR + f FIXED + F F2DOT14 + l LONG + L ULONG + s SHORT + S USHORT + v Version number (FIXED) + +Note that C, C and C are not data types but units. + +Returns array of scalar (first element) depending on context + +=cut + +sub TTF_Unpack +{ + my ($fmt, $dat) = @_; + my ($res, $frac, $i, $arrlen, $type, @res); + + while ($fmt =~ s/^([cflsv])(\d+|\*)?//oi) + { + $type = $1; + $arrlen = $2; + $arrlen = 1 if !defined $arrlen || $arrlen eq ""; + $arrlen = -1 if $arrlen eq "*"; + + for ($i = 0; ($arrlen == -1 && $dat ne "") || $i < $arrlen; $i++) + { + if ($type eq "f") + { + ($res, $frac) = unpack("nn", $dat); + substr($dat, 0, 4) = ""; + $res -= 65536 if $res > 32767; + $res += $frac / 65536.; + } + elsif ($type eq "v") + { + ($res, $frac) = unpack("nn", $dat); + substr($dat, 0, 4) = ""; + $res = sprintf("%d.%04X", $res, $frac); + } + elsif ($type eq "F") + { + $res = unpack("n", $dat); + substr($dat, 0, 2) = ""; +# $res -= 65536 if $res >= 32768; + $frac = $res & 0x3fff; + $res >>= 14; + $res -= 4 if $res > 1; +# $frac -= 16384 if $frac > 8191; + $res += $frac / 16384.; + } + elsif ($type =~ m/^[l]/oi) + { + $res = unpack("N", $dat); + substr($dat, 0, 4) = ""; + $res -= (1 << 32) if ($type eq "l" && $res >= 1 << 31); + } + elsif ($type =~ m/^[s]/oi) + { + $res = unpack("n", $dat); + substr($dat, 0, 2) = ""; + $res -= 65536 if ($type eq "s" && $res >= 32768); + } + elsif ($type eq "c") + { + $res = unpack("c", $dat); + substr($dat, 0, 1) = ""; + } + else + { + $res = unpack("C", $dat); + substr($dat, 0, 1) = ""; + } + push (@res, $res); + } + } + return wantarray ? @res : $res[0]; +} + + +=head2 $dat = TTF_Out_Fields($obj, $fields, $len) + +Given the fields table from C writes out the instance variables from +the object to the filehandle in TTF binary form. + +=cut + +sub TTF_Out_Fields +{ + my ($obj, $fields, $len) = @_; + my ($dat) = "\000" x $len; + my ($f, $pos, $type, $res, $arr, $arrlen, $frac); + + foreach $f (keys %{$fields}) + { + ($pos, $type, $arrlen) = split(':', $fields->{$f}); + if ($arrlen ne "") + { $res = TTF_Pack("$type$arrlen", @{$obj->{$f}}); } + else + { $res = TTF_Pack("$type", $obj->{$f}); } + substr($dat, $pos, length($res)) = $res; + } + $dat; +} + + +=head2 $dat = TTF_Pack($fmt, @data) + +The TrueType equivalent to Perl's C function. See details of C +for how to work the $fmt string. + +=cut + +sub TTF_Pack +{ + my ($fmt, @obj) = @_; + my ($type, $i, $arrlen, $dat, $res, $frac); + + $dat = ''; + while ($fmt =~ s/^([flscv])(\d+|\*)?//oi) + { + $type = $1; + $arrlen = $2 || ""; + $arrlen = $#obj + 1 if $arrlen eq "*"; + $arrlen = 1 if $arrlen eq ""; + + for ($i = 0; $i < $arrlen; $i++) + { + $res = shift(@obj) || 0; + if ($type eq "f") + { + $frac = int(($res - int($res)) * 65536); + $res = (int($res) << 16) + $frac; + $dat .= pack("N", $res); + } + elsif ($type eq "v") + { + if ($res =~ s/\.([0-9a-f]+)$//oi) + { + $frac = $1; + $frac .= "0" x (4 - length($frac)); + } + else + { $frac = 0; } + $dat .= pack('nn', $res, hex($frac)); + } + elsif ($type eq "F") + { + $frac = int(($res - int($res)) * 16384); + $res = (int($res) << 14) + $frac; + $dat .= pack("n", $res); + } + elsif ($type =~ m/^[l]/oi) + { + $res += 1 << 32 if ($type eq 'L' && $res < 0); + $dat .= pack("N", $res); + } + elsif ($type =~ m/^[s]/oi) + { + $res += 1 << 16 if ($type eq 'S' && $res < 0); + $dat .= pack("n", $res); + } + elsif ($type eq "c") + { $dat .= pack("c", $res); } + else + { $dat .= pack("C", $res); } + } + } + $dat; +} + + +=head2 ($num, $range, $select, $shift) = TTF_bininfo($num) + +Calculates binary search information from a number of elements + +=cut + +sub TTF_bininfo +{ + my ($num, $block) = @_; + my ($range, $select, $shift); + + $range = 1; + for ($select = 0; $range <= $num; $select++) + { $range *= 2; } + $select--; $range /= 2; + $range *= $block; + + $shift = $num * $block - $range; + ($num, $range, $select, $shift); +} + + +=head2 TTF_word_utf8($str) + +Returns the UTF8 form of the 16 bit string, assumed to be in big endian order, +including surrogate handling + +=cut + +sub TTF_word_utf8 +{ + my ($str) = @_; + my ($res, $i); + my (@dat) = unpack("n*", $str); + + return pack("U*", @dat) if ($] >= 5.006); + for ($i = 0; $i <= $#dat; $i++) + { + my ($dat) = $dat[$i]; + if ($dat < 0x80) # Thanks to Gisle Aas for some of his old code + { $res .= chr($dat); } + elsif ($dat < 0x800) + { $res .= chr(0xC0 | ($dat >> 6)) . chr(0x80 | ($dat & 0x3F)); } + elsif ($dat >= 0xD800 && $dat < 0xDC00) + { + my ($dat1) = $dat[++$i]; + my ($top) = (($dat & 0x3C0) >> 6) + 1; + $res .= chr(0xF0 | ($top >> 2)) + . chr(0x80 | (($top & 1) << 4) | (($dat & 0x3C) >> 2)) + . chr(0x80 | (($dat & 0x3) << 4) | (($dat1 & 0x3C0) >> 6)) + . chr(0x80 | ($dat1 & 0x3F)); + } else + { $res .= chr(0xE0 | ($dat >> 12)) . chr(0x80 | (($dat >> 6) & 0x3F)) + . chr(0x80 | ($dat & 0x3F)); } + } + $res; +} + + +=head2 TTF_utf8_word($str) + +Returns the 16-bit form in big endian order of the UTF 8 string, including +surrogate handling to Unicode. + +=cut + +sub TTF_utf8_word +{ + my ($str) = @_; + my ($res); + + return pack("n*", unpack("U*", $str)) if ($^V ge v5.6.0); + $str = "$str"; # copy $str + while (length($str)) # Thanks to Gisle Aas for some of his old code + { + $str =~ s/^[\x80-\xBF]+//o; + if ($str =~ s/^([\x00-\x7F]+)//o) + { $res .= pack("n*", unpack("C*", $1)); } + elsif ($str =~ s/^([\xC0-\xDF])([\x80-\xBF])//o) + { $res .= pack("n", ((ord($1) & 0x1F) << 6) | (ord($2) & 0x3F)); } + elsif ($str =~ s/^([\0xE0-\xEF])([\x80-\xBF])([\x80-\xBF])//o) + { $res .= pack("n", ((ord($1) & 0x0F) << 12) + | ((ord($2) & 0x3F) << 6) + | (ord($3) & 0x3F)); } + elsif ($str =~ s/^([\xF0-\xF7])([\x80-\xBF])([\x80-\xBF])([\x80-\xBF])//o) + { + my ($b1, $b2, $b3, $b4) = (ord($1), ord($2), ord($3), ord($4)); + $res .= pack("n", ((($b1 & 0x07) << 8) | (($b2 & 0x3F) << 2) + | (($b3 & 0x30) >> 4)) + 0xD600); # account for offset + $res .= pack("n", ((($b3 & 0x0F) << 6) | ($b4 & 0x3F)) + 0xDC00); + } + elsif ($str =~ s/^[\xF8-\xFF][\x80-\xBF]*//o) + { } + } + $res; +} + + +=head2 XML_hexdump($context, $dat) + +Dumps out the given data as a sequence of blocks each 16 bytes wide + +=cut + +sub XML_hexdump +{ + my ($context, $depth, $dat) = @_; + my ($fh) = $context->{'fh'}; + my ($i, $len, $out); + + $len = length($dat); + for ($i = 0; $i < $len; $i += 16) + { + $out = join(' ', map {sprintf("%02X", ord($_))} (split('', substr($dat, $i, 16)))); + $fh->printf("%s%s\n", $depth, $i, $out); + } +} + + +=head2 XML_outhints + +Converts a binary string of hinting code into a textual representation + +=cut + +{ + my (@hints) = ( + ['SVTCA[0]'], ['SVTCA[1]'], ['SPVTCA[0]'], ['SPVTCA[1]'], ['SFVTCA[0]'], ['SFVTCA[1]'], ['SPVTL[0]'], ['SPVTL[1]'], + ['SFVTL[0]'], ['SFVTL[1]'], ['SPVFS'], ['SFVFS'], ['GPV'], ['GFV'], ['SVFTPV'], ['ISECT'], +# 10 + ['SRP0'], ['SRP1'], ['SRP2'], ['SZP0'], ['SZP1'], ['SZP2'], ['SZPS'], ['SLOOP'], + ['RTG'], ['RTHG'], ['SMD'], ['ELSE'], ['JMPR'], ['SCVTCI'], ['SSWCI'], ['SSW'], +# 20 + ['DUP'], ['POP'], ['CLEAR'], ['SWAP'], ['DEPTH'], ['CINDEX'], ['MINDEX'], ['ALIGNPTS'], + [], ['UTP'], ['LOOPCALL'], ['CALL'], ['FDEF'], ['ENDF'], ['MDAP[0]'], ['MDAP[1]'], +# 30 + ['IUP[0]'], ['IUP[1]'], ['SHP[0]'], ['SHP[1]'], ['SHC[0]'], ['SHC[1]'], ['SHZ[0]'], ['SHZ[1]'], + ['SHPIX'], ['IP'], ['MSIRP[0]'], ['MSIRP[1]'], ['ALIGNRP'], ['RTDG'], ['MIAP[0]'], ['MIAP[1]'], +# 40 + ['NPUSHB', -1, 1], ['NPUSHW', -1, 2], ['WS', 0, 0], ['RS', 0, 0], ['WCVTP', 0, 0], ['RCVT', 0, 0], ['GC[0]'], ['GC[1]'], + ['SCFS'], ['MD[0]'], ['MD[1]'], ['MPPEM'], ['MPS'], ['FLIPON'], ['FLIPOFF'], ['DEBUG'], +# 50 + ['LT'], ['LTEQ'], ['GT'], ['GTEQ'], ['EQ'], ['NEQ'], ['ODD'], ['EVEN'], + ['IF'], ['EIF'], ['AND'], ['OR'], ['NOT'], ['DELTAP1'], ['SDB'], ['SDS'], +# 60 + ['ADD'], ['SUB'], ['DIV'], ['MULT'], ['ABS'], ['NEG'], ['FLOOR'], ['CEILING'], + ['ROUND[0]'], ['ROUND[1]'], ['ROUND[2]'], ['ROUND[3]'], ['NROUND[0]'], ['NROUND[1]'], ['NROUND[2]'], ['NROUND[3]'], +# 70 + ['WCVTF'], ['DELTAP2'], ['DELTAP3'], ['DELTAC1'], ['DELTAC2'], ['DELTAC3'], ['SROUND'], ['S45ROUND'], + ['JROT'], ['JROF'], ['ROFF'], [], ['RUTG'], ['RDTG'], ['SANGW'], [], +# 80 + ['FLIPPT'], ['FLIPRGON'], ['FLIPRGOFF'], [], [], ['SCANCTRL'], ['SDPVTL[0]'], ['SDPVTL[1]'], + ['GETINFO'], ['IDEF'], ['ROLL'], ['MAX'], ['MIN'], ['SCANTYPE'], ['INSTCTRL'], [], +# 90 + [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], +# A0 + [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], +# B0 + ['PUSHB1', 1, 1], ['PUSHB2', 2, 1], ['PUSHB3', 3, 1], ['PUSHB4', 4, 1], ['PUSHB5', 5, 1], ['PUSHB6', 6, 1], ['PUSHB7', 7, 1], ['PUSHB8', 8, 1], + ['PUSHW1', 1, 2], ['PUSHW2', 2, 2], ['PUSHW3', 3, 2], ['PUSHW4', 4, 2], ['PUSHW5', 5, 2], ['PUSHW6', 6, 2], ['PUSHW7', 7, 2], ['PUSHW8', 8, 2], +# C0 + ['MDRP[0]'], ['MDRP[1]'], ['MDRP[2]'], ['MDRP[3]'], ['MDRP[4]'], ['MDRP[5]'], ['MDRP[6]'], ['MDRP[7]'], + ['MDRP[8]'], ['MDRP[9]'], ['MDRP[A]'], ['MDRP[B]'], ['MDRP[C]'], ['MDRP[D]'], ['MDRP[E]'], ['MDRP[F]'], +# D0 + ['MDRP[10]'], ['MDRP[11]'], ['MDRP[12]'], ['MDRP[13]'], ['MDRP[14]'], ['MDRP[15]'], ['MDRP[16]'], ['MDRP[17]'], + ['MDRP[18]'], ['MDRP[19]'], ['MDRP[1A]'], ['MDRP[1B]'], ['MDRP[1C]'], ['MDRP[1D]'], ['MDRP[1E]'], ['MDRP[1F]'], +# E0 + ['MIRP[0]'], ['MIRP[1]'], ['MIRP[2]'], ['MIRP[3]'], ['MIRP[4]'], ['MIRP[5]'], ['MIRP[6]'], ['MIRP[7]'], + ['MIRP[8]'], ['MIRP[9]'], ['MIRP[A]'], ['MIRP[B]'], ['MIRP[C]'], ['MIRP[D]'], ['MIRP[E]'], ['MIRP[F]'], +# F0 + ['MIRP[10]'], ['MIRP[11]'], ['MIRP[12]'], ['MIRP[13]'], ['MIRP[14]'], ['MIRP[15]'], ['MIRP[16]'], ['MIRP[17]'], + ['MIRP[18]'], ['MIRP[19]'], ['MIRP[1A]'], ['MIRP[1B]'], ['MIRP[1C]'], ['MIRP[1D]'], ['MIRP[1E]'], ['MIRP[1F]']); + + my ($i); + my (%hints) = map { $_->[0] => $i++ if (defined $_->[0]); } @hints; + + sub XML_binhint + { + my ($dat) = @_; + my ($len) = length($dat); + my ($res, $i, $text, $size, $num); + + for ($i = 0; $i < $len; $i++) + { + ($text, $num, $size) = @{$hints[ord(substr($dat, $i, 1))]}; + $num = 0 unless (defined $num); + $text = sprintf("UNK[%02X]", ord(substr($dat, $i, 1))) unless defined $text; + $res .= $text; + if ($num != 0) + { + if ($num < 0) + { + $i++; + my ($nnum) = unpack($num == -1 ? 'C' : 'n', substr($dat, $i, -$num)); + $i += -$num - 1; + $num = $nnum; + } + $res .= "\t" . join(' ', unpack($size == 1 ? 'C*' : 'n*', substr($dat, $i + 1, $num * $size))); + $i += $num * $size; + } + $res .= "\n"; + } + $res; + } + + sub XML_hintbin + { + my ($dat) = @_; + my ($l, $res, @words, $num); + + foreach $l (split(/\s*\n\s*/, $dat)) + { + @words = split(/\s*/, $l); + next unless (defined $hints{$words[0]}); + $num = $hints{$words[0]}; + $res .= pack('C', $num); + if ($hints[$num][1] < 0) + { + $res .= pack($hints[$num][1] == -1 ? 'C' : 'n', $#words); + $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $#words]); + } + elsif ($hints[$num][1] > 0) + { + $res .= pack($hints[$num][2] == 1 ? 'C*' : 'n*', @words[1 .. $hints[$num][1]]); + } + } + $res; + } +} + + +=head2 make_circle($f, $cmap, [$dia, $sb, $opts]) + +Adds a dotted circle to a font. This function is very configurable. The +parameters passed in are: + +=over 4 + +=item $f + +Font to work with. This is required. + +=item $cmap + +A cmap table (not the 'val' sub-element of a cmap) to add the glyph too. Optional. + +=item $dia + +Optional diameter for the main circle. Defaults to 80% em + +=item $sb + +Side bearing. The left and right side-bearings are always the same. This value +defaults to 10% em. + +=back + +There are various options to control all sorts of interesting aspects of the circle + +=over 4 + +=item numDots + +Number of dots in the circle + +=item numPoints + +Number of curve points to use to create each dot + +=item uid + +Unicode reference to store this glyph under in the cmap. Defaults to 0x25CC + +=item pname + +Postscript name to give the glyph. Defaults to uni25CC. + +=item -dRadius + +Radius of each dot. + +=back + +=cut + +sub make_circle +{ + my ($font, $cmap, $dia, $sb, %opts) = @_; + my ($upem) = $font->{'head'}{'unitsPerEm'}; + my ($glyph) = Font::TTF::Glyph->new('PARENT' => $font, 'read' => 2, 'isDirty' => 1); + my ($PI) = 3.1415926535; + my ($R, $r, $xorg, $yorg); + my ($i, $j, $numg, $maxp); + my ($numc) = $opts{'-numDots'} || 16; + my ($nump) = ($opts{'-numPoints'} * 2) || 8; + my ($uid) = $opts{'-uid'} || 0x25CC; + my ($pname) = $opts{'-pname'} || 'uni25CC'; + + $dia ||= $upem * .8; # .95 to fit exactly + $sb ||= $upem * .1; + $R = $dia / 2; + $r = $opts{'-dRadius'} || ($R * .1); + ($xorg, $yorg) = ($R + $r, $R); + + $xorg += $sb; + $font->{'post'}->read; + $font->{'glyf'}->read; + for ($i = 0; $i < $numc; $i++) + { + my ($pxorg, $pyorg) = ($xorg + $R * cos(2 * $PI * $i / $numc), + $yorg + $R * sin(2 * $PI * $i / $numc)); + for ($j = 0; $j < $nump; $j++) + { + push (@{$glyph->{'x'}}, int ($pxorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * cos(2 * $PI * $j / $nump))); + push (@{$glyph->{'y'}}, int ($pyorg + ($j & 1 ? 1/cos(2*$PI/$nump) : 1) * $r * sin(2 * $PI * $j / $nump))); + push (@{$glyph->{'flags'}}, $j & 1 ? 0 : 1); + } + push (@{$glyph->{'endPoints'}}, $#{$glyph->{'x'}}); + } + $glyph->{'numberOfContours'} = $#{$glyph->{'endPoints'}} + 1; + $glyph->{'numPoints'} = $#{$glyph->{'x'}} + 1; + $glyph->update; + $numg = $font->{'maxp'}{'numGlyphs'}; + $font->{'maxp'}{'numGlyphs'}++; + + $font->{'hmtx'}{'advance'}[$numg] = int($xorg + $R + $r + $sb + .5); + $font->{'hmtx'}{'lsb'}[$numg] = int($xorg - $R - $r + .5); + $font->{'loca'}{'glyphs'}[$numg] = $glyph; + $cmap->{'val'}{$uid} = $numg if ($cmap); + $font->{'post'}{'VAL'}[$numg] = $pname; + delete $font->{'hdmx'}; + delete $font->{'VDMX'}; + delete $font->{'LTSH'}; + + $font->tables_do(sub {$_[0]->dirty;}); + $font->update; + return ($numg - 1); +} + + +1; + +=head1 BUGS + +No known bugs + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Vhea.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Vhea.pm new file mode 100644 index 0000000000..f4f630a04b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Vhea.pm @@ -0,0 +1,181 @@ +package Font::TTF::Vhea; + +=head1 NAME + +Font::TTF::Vhea - Vertical Header table + +=head1 DESCRIPTION + +This is a simple table with just standards specified instance variables + +=head1 INSTANCE VARIABLES + + version + Ascender + Descender + LineGap + advanceHeightMax + minTopSideBearing + minBottomSideBearing + yMaxExtent + caretSlopeRise + caretSlopeRun + metricDataFormat + numberOfVMetrics + + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; +use Font::TTF::Utils; + +@ISA = qw(Font::TTF::Table); +@field_info = ( + 'version' => 'v', + 'Ascender' => 's', + 'Descender' => 's', + 'LineGap' => 's', + 'advanceHeightMax' => 'S', + 'minTopSideBearing' => 's', + 'minBottomSideBearing' => 's', + 'yMaxExtent' => 's', + 'caretSlopeRise' => 's', + 'caretSlopeRun' => 's', + 'metricDataFormat' => '+10s', + 'numberOfVMetrics' => 's'); + +sub init +{ + my ($k, $v, $c, $i); + for ($i = 0; $i < $#field_info; $i += 2) + { + ($k, $v, $c) = TTF_Init_Fields($field_info[$i], $c, $field_info[$i + 1]); + next unless defined $k && $k ne ""; + $fields{$k} = $v; + } +} + + +=head2 $t->read + +Reads the table into memory as instance variables + +=cut + +sub read +{ + my ($self) = @_; + my ($dat); + + $self->SUPER::read or return $self; + init unless defined $fields{'Ascender'}; + $self->{' INFILE'}->read($dat, 36); + + TTF_Read_Fields($self, $dat, \%fields); + $self; +} + + +=head2 $t->out($fh) + +Writes the table to a file either from memory or by copying. + +=cut + +sub out +{ + my ($self, $fh) = @_; + + return $self->SUPER::out($fh) unless $self->{' read'}; + + $self->{'numberOfVMetrics'} = $self->{' PARENT'}{'vmtx'}->numMetrics || $self->{'numberOfVMetrics'}; + $fh->print(TTF_Out_Fields($self, \%fields, 36)); + $self; +} + +=head2 $t->minsize() + +Returns the minimum size this table can be. If it is smaller than this, then the table +must be bad and should be deleted or whatever. + +=cut + +sub minsize +{ + return 36; +} + + +=head2 $t->update + +Updates various parameters in the hhea table from the hmtx table, assuming +the C table is dirty. + +=cut + +sub update +{ + my ($self) = @_; + my ($vmtx) = $self->{' PARENT'}{'vmtx'}; + my ($glyphs); + my ($num); + my ($i, $maw, $mlsb, $mrsb, $mext, $aw, $lsb, $ext); + + return undef unless ($self->SUPER::update); + return undef unless (defined $vmtx && defined $self->{' PARENT'}{'loca'}); + $vmtx->read->update; + $self->{' PARENT'}{'loca'}->read->update; + $glyphs = $self->{' PARENT'}{'loca'}{'glyphs'}; + $num = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + + for ($i = 0; $i < $num; $i++) + { + $aw = $vmtx->{'advance'}[$i]; + $lsb = $vmtx->{'top'}[$i]; + if (defined $glyphs->[$i]) + { $ext = $lsb + $glyphs->[$i]->read->{'yMax'} - $glyphs->[$i]{'yMin'}; } + else + { $ext = $aw; } + $maw = $aw if ($aw > $maw); + $mlsb = $lsb if ($lsb < $mlsb or $i == 0); + $mrsb = $aw - $ext if ($aw - $ext < $mrsb or $i == 0); + $mext = $ext if ($ext > $mext); + } + $self->{'advanceHeightMax'} = $maw; + $self->{'minTopSideBearing'} = $mlsb; + $self->{'minBottomSideBearing'} = $mrsb; + $self->{'yMaxExtent'} = $mext; + $self->{'numberOfVMetrics'} = $vmtx->numMetrics; + $self; +} + + +1; + + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Vmtx.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Vmtx.pm new file mode 100644 index 0000000000..9d53290cbd --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Vmtx.pm @@ -0,0 +1,96 @@ +package Font::TTF::Vmtx; + +=head1 NAME + +Font::TTF::Vmtx - Vertical Metrics + +=head1 DESCRIPTION + +Contains the advance height and top side bearing for each glyph. Given the +compressability of the data onto disk, this table uses information from +other tables, and thus must do part of its output during the output of +other tables + +=head1 INSTANCE VARIABLES + +The vertical metrics are kept in two arrays by glyph id. The variable names +do not start with a space + +=over 4 + +=item advance + +An array containing the advance height for each glyph + +=item top + +An array containing the top side bearing for each glyph + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA); +require Font::TTF::Hmtx; + +@ISA = qw(Font::TTF::Hmtx); + + +=head2 $t->read + +Reads the vertical metrics from the TTF file into memory + +=cut + +sub read +{ + my ($self) = @_; + my ($numh, $numg); + + $numh = $self->{' PARENT'}{'vhea'}->read->{'numberOfVMetrics'}; + $numg = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + $self->_read($numg, $numh, "advance", "top"); +} + + +=head2 $t->out($fh) + +Writes the metrics to a TTF file. Assumes that the C has updated the +numVMetrics from here + +=cut + +sub out +{ + my ($self, $fh) = @_; + my ($numg) = $self->{' PARENT'}{'maxp'}{'numGlyphs'}; + my ($numh) = $self->{' PARENT'}{'vhea'}{'numberOfVMetrics'}; + $self->_out($fh, $numg, $numh, "advance", "top"); +} + +1; + +=head1 BUGS + +None known + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut + + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Win32.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Win32.pm new file mode 100644 index 0000000000..fcbf3ade49 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Win32.pm @@ -0,0 +1,49 @@ +package Font::TTF::Win32; + +# use strict; +# use vars qw($HKEY_LOCAL_MACHINE); + +use Win32::Registry; +use Win32; +use File::Spec; +use Font::TTF::Font; + + +sub findfonts +{ + my ($sub) = @_; + my ($font_key) = 'SOFTWARE\Microsoft\Windows' . (Win32::IsWinNT() ? ' NT' : '') . '\CurrentVersion\Fonts'; + my ($regFont, $list, $l, $font, $file); + +# get entry from registry for a font of this name + $::HKEY_LOCAL_MACHINE->Open($font_key, $regFont); + $regFont->GetValues($list); + + foreach $l (sort keys %{$list}) + { + my ($fname) = $list->{$l}[0]; + next unless ($fname =~ s/\(TrueType\)$//o); + $file = File::Spec->rel2abs($list->{$l}[2], "$ENV{'windir'}/fonts"); + $font = Font::TTF::Font->open($file) || next; + &{$sub}($font, $fname); + $font->release; + } +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff.pm new file mode 100644 index 0000000000..0e151c2621 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff.pm @@ -0,0 +1,61 @@ +package Font::TTF::Woff; + +=head1 NAME + +Font::TTF::WOFF - holds Web Open Font File (WOFF) data for the font + +=head1 DESCRIPTION + +This contains the WOFF packaging data. + +=head1 INSTANCE VARIABLES + +This object supports the following instance variables (which, because they +reflect the structure of the table, do not begin with a space): + +=over + +=item majorVersion + +=item minorVersion + +The two version integers come directly from the WOFF font header. + +=item metaData + +Contains a reference to Font::TTF::Woff::Meta structure, if the font has WOFF metadata. + +=item privateData + +Contains a reference to a Font::TTF::Woff::Private structure, if the font has a WOFF private data block + +=back + +=head1 METHODS + +=cut + +use strict; +use vars qw(@ISA %fields @field_info); + +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff/MetaData.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff/MetaData.pm new file mode 100644 index 0000000000..5202e07e44 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff/MetaData.pm @@ -0,0 +1,31 @@ +package Font::TTF::Woff::MetaData; + +=head1 NAME + +Font::TTF::Woff::MetaData - WOFF metadata + +=head1 DESCRIPTION + +Currently a stub, thus read() results in read_dat() + +=cut + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff/PrivateData.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff/PrivateData.pm new file mode 100644 index 0000000000..ccebdc6521 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/Woff/PrivateData.pm @@ -0,0 +1,32 @@ +package Font::TTF::Woff::PrivateData; + +=head1 NAME + +Font::TTF::Woff::PrivateData - WOFF Private data + +=head1 DESCRIPTION + +Currently a stub, thus read() results in read_dat() + +=cut + +use Font::TTF::Utils; +require Font::TTF::Table; + +@ISA = qw(Font::TTF::Table); + +1; + +=head1 AUTHOR + +Bob Hallissy. L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut + diff --git a/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/XMLparse.pm b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/XMLparse.pm new file mode 100644 index 0000000000..f3ff38e3a6 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/Font/TTF/XMLparse.pm @@ -0,0 +1,192 @@ +package Font::TTF::XMLparse; + +=head1 NAME + +Font::TTF::XMLparse - provides support for XML parsing. Requires Expat module XML::Parser::Expat + +=head1 SYNOPSIS + + use Font::TTF::Font; + use Font::TTF::XMLparse; + + $f = Font::TTF::Font->new; + read_xml($f, $ARGV[0]); + $f->out($ARGV[1]); + +=head1 DESCRIPTION + +This module contains the support routines for parsing XML and generating the +Truetype font structures as a result. The module has been separated from the rest +of the package in order to reduce the dependency that this would bring, of the +whole package on XML::Parser. This way, people without the XML::Parser can still +use the rest of the package. + +The package interacts with another package through the use of a context containing +and element 'receiver' which is an object which can possibly receive one of the +following messages: + +=over 4 + +=item XML_start + +This message is called when an open tag occurs. It is called with the context, +tag name and the attributes. The return value has no meaning. + +=item XML_end + +This messages is called when a close tag occurs. It is called with the context, +tag name and attributes (held over from when the tag was opened). There are 3 +possible return values from such a message: + +=over 8 + +=item undef + +This is the default return value indicating that default processing should +occur in which either the current element on the tree, or the text of this element +should be stored in the parent object. + +=item $context + +This magic value marks that the element should be deleted from the parent. +Nothing is stored in the parent. (This rather than '' is used to allow 0 returns.) + +=item anything + +Anything else is taken as the element content to be stored in the parent. + +=back + +In addition, the context hash passed to these messages contains the following +keys: + +=over 4 + +=item xml + +This is the expat xml object. The context is also available as +$context->{'xml'}{' mycontext'}. But that is a long winded way of not saying much! + +=item font + +This is the base object that was passed in for XML parsing. + +=item receiver + +This holds the current receiver of parsing events. It may be set in associated +application to adjust which objects should receive messages when. It is also stored +in the parsing stack to ensure that where an object changes it during XML_start, that +that same object that received XML_start will receive the corresponding XML_end + +=item stack + +This is the parsing stack, used internally to hold the current receiver and attributes +for each element open, as a complete hierarchy back to the root element. + +=item tree + +This element contains the storage tree corresponding to the parent of each element +in the stack. The default action is to push undef onto this stack during XML_start +and then to resolve this, either in the associated application (by changing +$context->{'tree'}[-1]) or during XML_end of a child element, by which time we know +whether we are dealing with an array or a hash or what. + +=item text + +Character processing is to insert all the characters into the text element of the +context for available use later. + +=back + +=back + +=head1 METHODS + +=cut + +use XML::Parser::Expat; +require Exporter; + +use strict; +use vars qw(@ISA @EXPORT); + +@ISA = qw(Exporter); +@EXPORT = qw(read_xml); + +sub read_xml +{ + my ($font, $fname) = @_; + + my ($xml) = XML::Parser::Expat->new; + my ($context) = {'xml' => $xml, 'font' => $font}; + + $xml->setHandlers('Start' => sub { + my ($x, $tag, %attrs) = @_; + my ($context) = $x->{' mycontext'}; + my ($fn) = $context->{'receiver'}->can('XML_start'); + + push(@{$context->{'tree'}}, undef); + push(@{$context->{'stack'}}, [$context->{'receiver'}, {%attrs}]); + &{$fn}($context->{'receiver'}, $context, $tag, %attrs) if defined $fn; + }, + 'End' => sub { + my ($x, $tag) = @_; + my ($context) = $x->{' mycontext'}; + my ($fn) = $context->{'receiver'}->can('XML_end'); + my ($stackinfo) = pop(@{$context->{'stack'}}); + my ($current, $res); + + $context->{'receiver'} = $stackinfo->[0]; + $context->{'text'} =~ s/^\s*(.*?)\s*$/$1/o; + $res = &{$fn}($context->{'receiver'}, $context, $tag, %{$stackinfo->[1]}) if defined $fn; + $current = pop(@{$context->{'tree'}}); + $current = $context->{'text'} unless (defined $current); + $context->{'text'} = ''; + + if (defined $res) + { + return if ($res eq $context); + $current = $res; + } + return unless $#{$context->{'tree'}} >= 0; + if ($tag eq 'elem') + { + $context->{'tree'}[-1] = [] unless defined $context->{'tree'}[-1]; + push (@{$context->{'tree'}[-1]}, $current); + } else + { + $context->{'tree'}[-1] = {} unless defined $context->{'tree'}[-1]; + $context->{'tree'}[-1]{$tag} = $current; + } + }, + 'Char' => sub { + my ($x, $str) = @_; + $x->{' mycontext'}{'text'} .= $str; + }); + + $xml->{' mycontext'} = $context; + + $context->{'receiver'} = $font; + if (ref $fname) + { return $xml->parse($fname); } + else + { return $xml->parsefile($fname); } +} + +1; + +=head1 AUTHOR + +Martin Hosken L. + + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This module is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + + + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/lib/ttfmod.pl b/.cpan/build/Font-TTF-1.06-0/lib/ttfmod.pl new file mode 100644 index 0000000000..c578a1a440 --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/lib/ttfmod.pl @@ -0,0 +1,187 @@ +# Title: TTFMOD.PL +# Author: M. Hosken +# Description: Read TTF file calling user functions for each table +# and output transformed tables to new TTF file. +# Useage: TTFMOD provides the complete control loop for processing +# the TTF files. All that the caller need supply is an +# associative array of functions to call keyed by the TTF +# table name and the two filenames. +# +# &ttfmod($infile, $outfile, *fns [, @must]); +# +# *fns is an associative array keyed by table name with +# values of the name of the subroutine in package main to +# be called to transfer the table from INFILE to OUTFILE. +# The subroutine is called with the following parameters and +# expected return values: +# +# ($len, $csum) = &sub(*INFILE, *OUTFILE, $len); +# +# INFILE and OUTFILE are the input and output streams, $len +# is the length of the table according to the directory. +# The return values are $len = new length of table to be +# given in the table directory. $csum = new value of table +# checksum. A way to test that this is correct is to +# checksum the whole file (e.g. using CSUM.BAT) and to +# ensure that the value is 0xB1B0AFBA according to a 32 bit +# checksum calculated bigendien. +# +# @must consists of a list of tables which must exist in the +# final output file, either by being there alread or by being +# inserted. +# +# Modifications: +# MJPH 1.00 22-SEP-1994 Original +# MJPH 1.1 18-MAR-1998 Added @must to ttfmod() +# MJPH 1.1.1 25-MAR-1998 Added $csum to copytab (to make reusable) + +package ttfmod; + +sub main'ttfmod { + local($infile, $outfile, *fns, @must) = @_; + + # open files as binary. Notice OUTFILE is opened for update not just write + open(INFILE, "$infile") || die "Unable top open \"$infile\" for reading"; + binmode INFILE; + open(OUTFILE, "+>$outfile") || die "Unable to open \"$outfile\" for writing"; + binmode OUTFILE; + + seek(INFILE, 0, 0); + read(INFILE, $dir_head, 12) || die "Reading table header"; + ($dir_num) = unpack("x4n", $dir_head); + print OUTFILE $dir_head; + # read and unpack table directory + for ($i = 0; $i < $dir_num; $i++) + { + read(INFILE, $dir_val, 16) || die "Reading table entry"; + $dir{unpack("a4", $dir_val)} = join(":", $i, unpack("x4NNN", $dir_val)); + print OUTFILE $dir_val; + printf STDERR "%s %08x\n", unpack("a4", $dir_val), unpack("x8N", $dir_val) + if (defined $main'opt_z); + } + foreach $n (@must) + { + next if defined $dir{$n}; + $dir{$n} = "$i:0:-1:0"; + $i++; $dir_num++; + print OUTFILE pack("a4NNN", $n, 0, -1, 0); + } + substr($dir_head, 4, 2) = pack("n", $dir_num); + $csum = unpack("%32N*", $dir_head); + $off = tell(OUTFILE); + seek(OUTFILE, 0, 0); + print OUTFILE $dir_head; + seek (OUTFILE, $off, 0); + # process tables in order they occur in the file + @dirlist = sort byoffset keys(%dir); + foreach $tab (@dirlist) + { + @tab_split = split(':', $dir{$tab}); + seek(INFILE, $tab_split[2], 0); # offset + $tab_split[2] = tell(OUTFILE); + if (defined $fns{$tab}) + { + $temp = "main'$fns{$tab}"; + ($dir_len, $sum) = &$temp(*INFILE, *OUTFILE, $tab_split[3]); + } + else + { + ($dir_len, $sum) = ©tab(*INFILE, *OUTFILE, $tab_split[3]); + } + $tab_split[3] = $dir_len; # len + $tab_split[1] = $sum; # checksum + $out_dir{$tab} = join(":", @tab_split); + } + # now output directory in same order as original directory + @dirlist = sort byindex keys(%out_dir); + foreach $tab (@dirlist) + { + @tab_split = split(':', $out_dir{$tab}); + seek (OUTFILE, 12 + $tab_split[0] * 16, 0); # directory index + print OUTFILE pack("A4N3", $tab, @tab_split[1..3]); + foreach $i (1..3, 1) # checksum directory values with csum twice + { + $csum += $tab_split[$i]; + # this line ensures $csum stays within 32 bit bounds, clipping as necessary + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + } + # checksum the tag + $csum += unpack("N", $tab); + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + } + # handle main checksum + @tab_split = split(':', $out_dir{"head"}); + seek(OUTFILE, $tab_split[2], 0); + read(OUTFILE, $head_head, 12); # read first bit of "head" table + @head_split = unpack("N3", $head_head); + $tab_split[1] -= $head_split[2]; # subtract old checksum + $csum -= $head_split[2] * 2; # twice because had double effect + # already + if ($csum < 0 ) { $csum += 0xffffffff; $csum++; } + $head_split[2] = 0xB1B0AFBA - $csum; # calculate new checksum + seek (OUTFILE, 12 + $tab_split[0] * 16, 0); + print OUTFILE pack("A4N3", "head", @tab_split[1..3]); + seek (OUTFILE, $tab_split[2], 0); # rewrite first bit of "head" table + print OUTFILE pack("N3", @head_split); + + # finish up + close(OUTFILE); + close(INFILE); + } + +# support function for sorting by table offset +sub byoffset { + @t1 = split(':', $dir{$a}); + @t2 = split(':', $dir{$b}); + return 1 if ($t1[2] == -1); # put inserted tables at the end + return -1 if ($t2[2] == -1); + return $t1[2] <=> $t2[2]; + } + +# support function for sorting by directory entry order +sub byindex { + $t1 = split(':', $dir{$a}, 1); + $t2 = split(':', $dir{$b}, 1); + return $t1 <=> $t2; + } + +# default table action: copies a table from input to output, recalculating +# the checksum (just to be absolutely sure). +sub copytab { + local(*INFILE, *OUTFILE, $len, $csum) = @_; + + while ($len > 0) + { + $count = ($len > 8192) ? 8192 : $len; # 8K buffering + read(INFILE, $buf, $count) == $count || die "Copying"; + $buf .= "\0" x (4 - ($count & 3)) if ($count & 3); # pad to long + print OUTFILE $buf; + $csum += unpack("%32N*", $buf); + if ($csum > 0xffffffff) { $csum -= 0xffffffff; $csum--; } + $len -= $count; + } + ($_[2], $csum); + } + +# test routine to copy file from input to output, no changes +package main; + +if ($test_package) + { + &ttfmod($ARGV[0], $ARGV[1], *dummy); + } +else + { 1; } + +=head1 AUTHOR + +Martin Hosken L. + +=head1 LICENSING + +Copyright (c) 1998-2016, SIL International (http://www.sil.org) + +This script is released under the terms of the Artistic License 2.0. +For details, see the full text of the license in the file LICENSE. + +=cut \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/pm_to_blib b/.cpan/build/Font-TTF-1.06-0/pm_to_blib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/Font-TTF-1.06-0/t/OFL.txt b/.cpan/build/Font-TTF-1.06-0/t/OFL.txt new file mode 100644 index 0000000000..e9d5b9031e --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/t/OFL.txt @@ -0,0 +1,94 @@ +Copyright (c) 2005-2008, SIL International (http://www.sil.org) +with Reserved Font Names "Gentium" and "SIL" + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/t/changes.t b/.cpan/build/Font-TTF-1.06-0/t/changes.t new file mode 100644 index 0000000000..0a767010fd --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/t/changes.t @@ -0,0 +1,7 @@ +#!/usr/bin/perl +use strict; +use Test::More; + +eval 'use Test::CPAN::Changes'; +plan skip_all => 'Test::CPAN::Changes required for this test' if $@; +changes_ok(); diff --git a/.cpan/build/Font-TTF-1.06-0/t/tags.t b/.cpan/build/Font-TTF-1.06-0/t/tags.t new file mode 100644 index 0000000000..217691096d --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/t/tags.t @@ -0,0 +1,17 @@ +#! /usr/bin/perl +use strict; + +use Test::Simple tests => 6; +use Font::TTF::OTTags qw( %tttags %ttnames %iso639 readtagsfile); + +ok($tttags{'SCRIPT'}{'Cypriot Syllabary'} eq 'cprt', 'tttags{SCRIPT}'); + +ok($ttnames{'LANGUAGE'}{'AFK '} eq 'Afrikaans', 'ttnames{LANGUAGE}'); + +ok($ttnames{'LANGUAGE'}{'DHV '} eq 'Divehi (Dhivehi, Maldivian) (deprecated)' && $ttnames{'LANGUAGE'}{'DIV '} eq 'Divehi (Dhivehi, Maldivian)', 'ttnames{LANGUAGE} Dhivehi'); + +ok($ttnames{'FEATURE'}{'cv01'} eq 'Character Variants 01', 'ttnames{FEATURE}'); + +ok($iso639{'atv'} eq 'ALT ', 'iso639{atv}'); + +ok($iso639{'ALT '}->[0] eq 'atv' && $iso639{'ALT '}->[1] eq 'alt', 'iso639{ALT}'); \ No newline at end of file diff --git a/.cpan/build/Font-TTF-1.06-0/t/testfont.ttf b/.cpan/build/Font-TTF-1.06-0/t/testfont.ttf new file mode 100644 index 0000000000..fbff8b44de Binary files /dev/null and b/.cpan/build/Font-TTF-1.06-0/t/testfont.ttf differ diff --git a/.cpan/build/Font-TTF-1.06-0/t/testfont.woff b/.cpan/build/Font-TTF-1.06-0/t/testfont.woff new file mode 100644 index 0000000000..bc97136bc6 Binary files /dev/null and b/.cpan/build/Font-TTF-1.06-0/t/testfont.woff differ diff --git a/.cpan/build/Font-TTF-1.06-0/t/ttfcopy.t b/.cpan/build/Font-TTF-1.06-0/t/ttfcopy.t new file mode 100644 index 0000000000..98d8eab79b --- /dev/null +++ b/.cpan/build/Font-TTF-1.06-0/t/ttfcopy.t @@ -0,0 +1,25 @@ +#!/usr/bin/perl + +use Test::Simple tests => 4; +use File::Compare; +use Font::TTF::Font; + +$f = Font::TTF::Font->open("t/testfont.ttf"); +ok($f); +$f->tables_do(sub { $_[0]->read; }); +$f->{'loca'}->glyphs_do(sub {$_[0]->read_dat; }); +$f->out("t/temp.ttf"); +$res = compare("t/temp.ttf", "t/testfont.ttf"); +ok(!$res); +unlink "t/temp.ttf" unless ($res); + +# same test with WOFF input: +$f = Font::TTF::Font->open("t/testfont.woff"); +ok($f); +$f->tables_do(sub { $_[0]->read; }); +$f->{'loca'}->glyphs_do(sub {$_[0]->read_dat; }); +$f->out("t/temp2.ttf"); +$res = compare("t/temp2.ttf", "t/testfont.ttf"); +ok(!$res); +unlink "t/temp2.ttf" unless ($res); + diff --git a/.cpan/build/IO-String-1.08-0/Changes b/.cpan/build/IO-String-1.08-0/Changes new file mode 100644 index 0000000000..38b5474923 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/Changes @@ -0,0 +1,121 @@ +2005-12-05 Gisle Aas + + Release 1.08 + + The untie code in close() just seemed wrong, so just + remove it. The object still seems to get cleaned up + on various versions perl. + + + +2005-10-24 Gisle Aas + + Release 1.07 + + Make sure read() will not return negative values. + + + + +2004-11-05 Gisle Aas + + Release 1.06 + + Make seek() return TRUE when it succeed. It used to + return the new position, but we want to be compatible with + the builtin seek(). + Patch contributed by Kurt M. Brown + + Make print() and printf() return TRUE even when printing + the empty string. The used to return the lenght of the string + printed, but now they always return 1 to be compatible with + the builtins. + + Make binmode() return TRUE unless layers are provided. + + + +2004-04-01 Gisle Aas + + Release 1.05 + + Fix handling of paragraph mode. + + + + +2004-01-08 Gisle Aas + + Release 1.04 + + Documentation fixes by Paul Croome . + + + +2003-10-06 Gisle Aas + + Release 1.03 + + Seek will not reset the input_line_number (aka $.) for the IO::String + object any more. + + Workaround for core dump in close() in perl-5.6.x. + + + +2002-12-27 Gisle Aas + + Release 1.02 + + Complemented the tiehandle interface with SEEK/TELL/EOF/BINMODE. + + Make close($io) untie the object. This make it possible + to avoid memory leaks in perl-5.8 which seems to have problems + with self-ties. Based on patch by Eric Kolve . + + + +2000-01-28 Gisle Aas + + Release 1.01 + + The eof() method had opposite logic. Bug spotted by + Daniel Gruhl + + + +1999-04-12 Gisle Aas + + Release 1.00 + + Perl version 5.005_03 or better is now needed, because that + perl has Chip's no-memory-leak-on-self-tie-patch. + + Documentation update + + + +1998-10-14 Gisle Aas + + Release 0.03 + + Loading of the SEEK_xxx constants from the IO::Handle module + is now optional. The previous way did not work with IO-1.20. + + + +1998-10-12 Gisle Aas + + Release 0.02 + + Added some documentation. + + Fixed $io->stat + + Fixed $io->pad to return the default if it is set to "" + + + +1998-10-07 Gisle Aas + + Release 0.01 diff --git a/.cpan/build/IO-String-1.08-0/MANIFEST b/.cpan/build/IO-String-1.08-0/MANIFEST new file mode 100644 index 0000000000..b7d1d27a4b --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/MANIFEST @@ -0,0 +1,12 @@ +Changes +MANIFEST +Makefile.PL +README +String.pm +t/close.t +t/para.t +t/read.t +t/seek.t +t/truncate.t +t/write.t +META.yml Module meta-data (added by MakeMaker) diff --git a/.cpan/build/IO-String-1.08-0/META.yml b/.cpan/build/IO-String-1.08-0/META.yml new file mode 100644 index 0000000000..bad4378f27 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/META.yml @@ -0,0 +1,10 @@ +# http://module-build.sourceforge.net/META-spec.html +#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# +name: IO-String +version: 1.08 +version_from: String.pm +installdirs: site +requires: + +distribution_type: module +generated_by: ExtUtils::MakeMaker version 6.17 diff --git a/.cpan/build/IO-String-1.08-0/MYMETA.json b/.cpan/build/IO-String-1.08-0/MYMETA.json new file mode 100644 index 0000000000..77f17379bf --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/MYMETA.json @@ -0,0 +1,37 @@ +{ + "abstract" : "unknown", + "author" : [ + "unknown" + ], + "dynamic_config" : 0, + "generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010", + "license" : [ + "unknown" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : 2 + }, + "name" : "IO-String", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + } + }, + "release_status" : "stable", + "version" : "1.08", + "x_serialization_backend" : "JSON::PP version 4.07" +} diff --git a/.cpan/build/IO-String-1.08-0/MYMETA.yml b/.cpan/build/IO-String-1.08-0/MYMETA.yml new file mode 100644 index 0000000000..c33d1a730c --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/MYMETA.yml @@ -0,0 +1,21 @@ +--- +abstract: unknown +author: + - unknown +build_requires: + ExtUtils::MakeMaker: '0' +configure_requires: + ExtUtils::MakeMaker: '0' +dynamic_config: 0 +generated_by: 'ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010' +license: unknown +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: IO-String +no_index: + directory: + - t + - inc +version: '1.08' +x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff --git a/.cpan/build/IO-String-1.08-0/Makefile.PL b/.cpan/build/IO-String-1.08-0/Makefile.PL new file mode 100644 index 0000000000..11fac07c47 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/Makefile.PL @@ -0,0 +1,9 @@ +require 5.005_03; # need self-tie patch + +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'IO::String', + VERSION_FROM => 'String.pm', + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, +); diff --git a/.cpan/build/IO-String-1.08-0/README b/.cpan/build/IO-String-1.08-0/README new file mode 100644 index 0000000000..56256e86c3 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/README @@ -0,0 +1,19 @@ +IO::String is an IO::File (and IO::Handle) compatible class that read +or write data from in-core strings. It is really just a +simplification of what I needed from Eryq's IO-stringy modules. As +such IO::String is a replacement for IO::Scalar. + +Installation as usual: + + perl Makefile.PL + make + make test + make install + +Documentation is embedded in the module. + + +Copyright 1998-2005 Gisle Aas. + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. diff --git a/.cpan/build/IO-String-1.08-0/String.pm b/.cpan/build/IO-String-1.08-0/String.pm new file mode 100644 index 0000000000..4bc8e71960 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/String.pm @@ -0,0 +1,551 @@ +package IO::String; + +# Copyright 1998-2005 Gisle Aas. +# +# This library is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. + +require 5.005_03; +use strict; +use vars qw($VERSION $DEBUG $IO_CONSTANTS); +$VERSION = "1.08"; # $Date: 2005/12/05 12:00:47 $ + +use Symbol (); + +sub new +{ + my $class = shift; + my $self = bless Symbol::gensym(), ref($class) || $class; + tie *$self, $self; + $self->open(@_); + return $self; +} + +sub open +{ + my $self = shift; + return $self->new(@_) unless ref($self); + + if (@_) { + my $bufref = ref($_[0]) ? $_[0] : \$_[0]; + $$bufref = "" unless defined $$bufref; + *$self->{buf} = $bufref; + } + else { + my $buf = ""; + *$self->{buf} = \$buf; + } + *$self->{pos} = 0; + *$self->{lno} = 0; + return $self; +} + +sub pad +{ + my $self = shift; + my $old = *$self->{pad}; + *$self->{pad} = substr($_[0], 0, 1) if @_; + return "\0" unless defined($old) && length($old); + return $old; +} + +sub dump +{ + require Data::Dumper; + my $self = shift; + print Data::Dumper->Dump([$self], ['*self']); + print Data::Dumper->Dump([*$self{HASH}], ['$self{HASH}']); + return; +} + +sub TIEHANDLE +{ + print "TIEHANDLE @_\n" if $DEBUG; + return $_[0] if ref($_[0]); + my $class = shift; + my $self = bless Symbol::gensym(), $class; + $self->open(@_); + return $self; +} + +sub DESTROY +{ + print "DESTROY @_\n" if $DEBUG; +} + +sub close +{ + my $self = shift; + delete *$self->{buf}; + delete *$self->{pos}; + delete *$self->{lno}; + undef *$self if $] eq "5.008"; # workaround for some bug + return 1; +} + +sub opened +{ + my $self = shift; + return defined *$self->{buf}; +} + +sub binmode +{ + my $self = shift; + return 1 unless @_; + # XXX don't know much about layers yet :-( + return 0; +} + +sub getc +{ + my $self = shift; + my $buf; + return $buf if $self->read($buf, 1); + return undef; +} + +sub ungetc +{ + my $self = shift; + $self->setpos($self->getpos() - 1); + return 1; +} + +sub eof +{ + my $self = shift; + return length(${*$self->{buf}}) <= *$self->{pos}; +} + +sub print +{ + my $self = shift; + if (defined $\) { + if (defined $,) { + $self->write(join($,, @_).$\); + } + else { + $self->write(join("",@_).$\); + } + } + else { + if (defined $,) { + $self->write(join($,, @_)); + } + else { + $self->write(join("",@_)); + } + } + return 1; +} +*printflush = \*print; + +sub printf +{ + my $self = shift; + print "PRINTF(@_)\n" if $DEBUG; + my $fmt = shift; + $self->write(sprintf($fmt, @_)); + return 1; +} + + +my($SEEK_SET, $SEEK_CUR, $SEEK_END); + +sub _init_seek_constants +{ + if ($IO_CONSTANTS) { + require IO::Handle; + $SEEK_SET = &IO::Handle::SEEK_SET; + $SEEK_CUR = &IO::Handle::SEEK_CUR; + $SEEK_END = &IO::Handle::SEEK_END; + } + else { + $SEEK_SET = 0; + $SEEK_CUR = 1; + $SEEK_END = 2; + } +} + + +sub seek +{ + my($self,$off,$whence) = @_; + my $buf = *$self->{buf} || return 0; + my $len = length($$buf); + my $pos = *$self->{pos}; + + _init_seek_constants() unless defined $SEEK_SET; + + if ($whence == $SEEK_SET) { $pos = $off } + elsif ($whence == $SEEK_CUR) { $pos += $off } + elsif ($whence == $SEEK_END) { $pos = $len + $off } + else { die "Bad whence ($whence)" } + print "SEEK(POS=$pos,OFF=$off,LEN=$len)\n" if $DEBUG; + + $pos = 0 if $pos < 0; + $self->truncate($pos) if $pos > $len; # extend file + *$self->{pos} = $pos; + return 1; +} + +sub pos +{ + my $self = shift; + my $old = *$self->{pos}; + if (@_) { + my $pos = shift || 0; + my $buf = *$self->{buf}; + my $len = $buf ? length($$buf) : 0; + $pos = $len if $pos > $len; + *$self->{pos} = $pos; + } + return $old; +} + +sub getpos { shift->pos; } + +*sysseek = \&seek; +*setpos = \&pos; +*tell = \&getpos; + + + +sub getline +{ + my $self = shift; + my $buf = *$self->{buf} || return; + my $len = length($$buf); + my $pos = *$self->{pos}; + return if $pos >= $len; + + unless (defined $/) { # slurp + *$self->{pos} = $len; + return substr($$buf, $pos); + } + + unless (length $/) { # paragraph mode + # XXX slow&lazy implementation using getc() + my $para = ""; + my $eol = 0; + my $c; + while (defined($c = $self->getc)) { + if ($c eq "\n") { + $eol++; + next if $eol > 2; + } + elsif ($eol > 1) { + $self->ungetc($c); + last; + } + else { + $eol = 0; + } + $para .= $c; + } + return $para; # XXX wantarray + } + + my $idx = index($$buf,$/,$pos); + if ($idx < 0) { + # return rest of it + *$self->{pos} = $len; + $. = ++ *$self->{lno}; + return substr($$buf, $pos); + } + $len = $idx - $pos + length($/); + *$self->{pos} += $len; + $. = ++ *$self->{lno}; + return substr($$buf, $pos, $len); +} + +sub getlines +{ + die "getlines() called in scalar context\n" unless wantarray; + my $self = shift; + my($line, @lines); + push(@lines, $line) while defined($line = $self->getline); + return @lines; +} + +sub READLINE +{ + goto &getlines if wantarray; + goto &getline; +} + +sub input_line_number +{ + my $self = shift; + my $old = *$self->{lno}; + *$self->{lno} = shift if @_; + return $old; +} + +sub truncate +{ + my $self = shift; + my $len = shift || 0; + my $buf = *$self->{buf}; + if (length($$buf) >= $len) { + substr($$buf, $len) = ''; + *$self->{pos} = $len if $len < *$self->{pos}; + } + else { + $$buf .= ($self->pad x ($len - length($$buf))); + } + return 1; +} + +sub read +{ + my $self = shift; + my $buf = *$self->{buf}; + return undef unless $buf; + + my $pos = *$self->{pos}; + my $rem = length($$buf) - $pos; + my $len = $_[1]; + $len = $rem if $len > $rem; + return undef if $len < 0; + if (@_ > 2) { # read offset + substr($_[0],$_[2]) = substr($$buf, $pos, $len); + } + else { + $_[0] = substr($$buf, $pos, $len); + } + *$self->{pos} += $len; + return $len; +} + +sub write +{ + my $self = shift; + my $buf = *$self->{buf}; + return unless $buf; + + my $pos = *$self->{pos}; + my $slen = length($_[0]); + my $len = $slen; + my $off = 0; + if (@_ > 1) { + $len = $_[1] if $_[1] < $len; + if (@_ > 2) { + $off = $_[2] || 0; + die "Offset outside string" if $off > $slen; + if ($off < 0) { + $off += $slen; + die "Offset outside string" if $off < 0; + } + my $rem = $slen - $off; + $len = $rem if $rem < $len; + } + } + substr($$buf, $pos, $len) = substr($_[0], $off, $len); + *$self->{pos} += $len; + return $len; +} + +*sysread = \&read; +*syswrite = \&write; + +sub stat +{ + my $self = shift; + return unless $self->opened; + return 1 unless wantarray; + my $len = length ${*$self->{buf}}; + + return ( + undef, undef, # dev, ino + 0666, # filemode + 1, # links + $>, # user id + $), # group id + undef, # device id + $len, # size + undef, # atime + undef, # mtime + undef, # ctime + 512, # blksize + int(($len+511)/512) # blocks + ); +} + +sub FILENO { + return undef; # XXX perlfunc says this means the file is closed +} + +sub blocking { + my $self = shift; + my $old = *$self->{blocking} || 0; + *$self->{blocking} = shift if @_; + return $old; +} + +my $notmuch = sub { return }; + +*fileno = $notmuch; +*error = $notmuch; +*clearerr = $notmuch; +*sync = $notmuch; +*flush = $notmuch; +*setbuf = $notmuch; +*setvbuf = $notmuch; + +*untaint = $notmuch; +*autoflush = $notmuch; +*fcntl = $notmuch; +*ioctl = $notmuch; + +*GETC = \&getc; +*PRINT = \&print; +*PRINTF = \&printf; +*READ = \&read; +*WRITE = \&write; +*SEEK = \&seek; +*TELL = \&getpos; +*EOF = \&eof; +*CLOSE = \&close; +*BINMODE = \&binmode; + + +sub string_ref +{ + my $self = shift; + return *$self->{buf}; +} +*sref = \&string_ref; + +1; + +__END__ + +=head1 NAME + +IO::String - Emulate file interface for in-core strings + +=head1 SYNOPSIS + + use IO::String; + $io = IO::String->new; + $io = IO::String->new($var); + tie *IO, 'IO::String'; + + # read data + <$io>; + $io->getline; + read($io, $buf, 100); + + # write data + print $io "string\n"; + $io->print(@data); + syswrite($io, $buf, 100); + + select $io; + printf "Some text %s\n", $str; + + # seek + $pos = $io->getpos; + $io->setpos(0); # rewind + $io->seek(-30, -1); + seek($io, 0, 0); + +=head1 DESCRIPTION + +The C module provides the C interface for in-core +strings. An C object can be attached to a string, and +makes it possible to use the normal file operations for reading or +writing data, as well as for seeking to various locations of the string. +This is useful when you want to use a library module that only +provides an interface to file handles on data that you have in a string +variable. + +Note that perl-5.8 and better has built-in support for "in memory" +files, which are set up by passing a reference instead of a filename +to the open() call. The reason for using this module is that it +makes the code backwards compatible with older versions of Perl. + +The C module provides an interface compatible with +C as distributed with F, but the following methods +are not available: new_from_fd, fdopen, format_write, +format_page_number, format_lines_per_page, format_lines_left, +format_name, format_top_name. + +The following methods are specific to the C class: + +=over 4 + +=item $io = IO::String->new + +=item $io = IO::String->new( $string ) + +The constructor returns a newly-created C object. It +takes an optional argument, which is the string to read from or write +into. If no $string argument is given, then an internal buffer +(initially empty) is allocated. + +The C object returned is tied to itself. This means +that you can use most Perl I/O built-ins on it too: readline, <>, getc, +print, printf, syswrite, sysread, close. + +=item $io->open + +=item $io->open( $string ) + +Attaches an existing IO::String object to some other $string, or +allocates a new internal buffer (if no argument is given). The +position is reset to 0. + +=item $io->string_ref + +Returns a reference to the string that is attached to +the C object. Most useful when you let the C +create an internal buffer to write into. + +=item $io->pad + +=item $io->pad( $char ) + +Specifies the padding to use if +the string is extended by either the seek() or truncate() methods. It +is a single character and defaults to "\0". + +=item $io->pos + +=item $io->pos( $newpos ) + +Yet another interface for reading and setting the current read/write +position within the string (the normal getpos/setpos/tell/seek +methods are also available). The pos() method always returns the +old position, and if you pass it an argument it sets the new +position. + +There is (deliberately) a difference between the setpos() and seek() +methods in that seek() extends the string (with the specified +padding) if you go to a location past the end, whereas setpos() +just snaps back to the end. If truncate() is used to extend the string, +then it works as seek(). + +=back + +=head1 BUGS + +In Perl versions < 5.6, the TIEHANDLE interface was incomplete. +If you use such a Perl, then seek(), tell(), eof(), fileno(), binmode() will +not do anything on an C handle. See L for +details. + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 1998-2005 Gisle Aas. + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=cut diff --git a/.cpan/build/IO-String-1.08-0/blib/arch/.exists b/.cpan/build/IO-String-1.08-0/blib/arch/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/blib/arch/auto/IO/String/.exists b/.cpan/build/IO-String-1.08-0/blib/arch/auto/IO/String/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/blib/bin/.exists b/.cpan/build/IO-String-1.08-0/blib/bin/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/blib/lib/IO/.exists b/.cpan/build/IO-String-1.08-0/blib/lib/IO/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/blib/lib/IO/String.pm b/.cpan/build/IO-String-1.08-0/blib/lib/IO/String.pm new file mode 100644 index 0000000000..4bc8e71960 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/blib/lib/IO/String.pm @@ -0,0 +1,551 @@ +package IO::String; + +# Copyright 1998-2005 Gisle Aas. +# +# This library is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. + +require 5.005_03; +use strict; +use vars qw($VERSION $DEBUG $IO_CONSTANTS); +$VERSION = "1.08"; # $Date: 2005/12/05 12:00:47 $ + +use Symbol (); + +sub new +{ + my $class = shift; + my $self = bless Symbol::gensym(), ref($class) || $class; + tie *$self, $self; + $self->open(@_); + return $self; +} + +sub open +{ + my $self = shift; + return $self->new(@_) unless ref($self); + + if (@_) { + my $bufref = ref($_[0]) ? $_[0] : \$_[0]; + $$bufref = "" unless defined $$bufref; + *$self->{buf} = $bufref; + } + else { + my $buf = ""; + *$self->{buf} = \$buf; + } + *$self->{pos} = 0; + *$self->{lno} = 0; + return $self; +} + +sub pad +{ + my $self = shift; + my $old = *$self->{pad}; + *$self->{pad} = substr($_[0], 0, 1) if @_; + return "\0" unless defined($old) && length($old); + return $old; +} + +sub dump +{ + require Data::Dumper; + my $self = shift; + print Data::Dumper->Dump([$self], ['*self']); + print Data::Dumper->Dump([*$self{HASH}], ['$self{HASH}']); + return; +} + +sub TIEHANDLE +{ + print "TIEHANDLE @_\n" if $DEBUG; + return $_[0] if ref($_[0]); + my $class = shift; + my $self = bless Symbol::gensym(), $class; + $self->open(@_); + return $self; +} + +sub DESTROY +{ + print "DESTROY @_\n" if $DEBUG; +} + +sub close +{ + my $self = shift; + delete *$self->{buf}; + delete *$self->{pos}; + delete *$self->{lno}; + undef *$self if $] eq "5.008"; # workaround for some bug + return 1; +} + +sub opened +{ + my $self = shift; + return defined *$self->{buf}; +} + +sub binmode +{ + my $self = shift; + return 1 unless @_; + # XXX don't know much about layers yet :-( + return 0; +} + +sub getc +{ + my $self = shift; + my $buf; + return $buf if $self->read($buf, 1); + return undef; +} + +sub ungetc +{ + my $self = shift; + $self->setpos($self->getpos() - 1); + return 1; +} + +sub eof +{ + my $self = shift; + return length(${*$self->{buf}}) <= *$self->{pos}; +} + +sub print +{ + my $self = shift; + if (defined $\) { + if (defined $,) { + $self->write(join($,, @_).$\); + } + else { + $self->write(join("",@_).$\); + } + } + else { + if (defined $,) { + $self->write(join($,, @_)); + } + else { + $self->write(join("",@_)); + } + } + return 1; +} +*printflush = \*print; + +sub printf +{ + my $self = shift; + print "PRINTF(@_)\n" if $DEBUG; + my $fmt = shift; + $self->write(sprintf($fmt, @_)); + return 1; +} + + +my($SEEK_SET, $SEEK_CUR, $SEEK_END); + +sub _init_seek_constants +{ + if ($IO_CONSTANTS) { + require IO::Handle; + $SEEK_SET = &IO::Handle::SEEK_SET; + $SEEK_CUR = &IO::Handle::SEEK_CUR; + $SEEK_END = &IO::Handle::SEEK_END; + } + else { + $SEEK_SET = 0; + $SEEK_CUR = 1; + $SEEK_END = 2; + } +} + + +sub seek +{ + my($self,$off,$whence) = @_; + my $buf = *$self->{buf} || return 0; + my $len = length($$buf); + my $pos = *$self->{pos}; + + _init_seek_constants() unless defined $SEEK_SET; + + if ($whence == $SEEK_SET) { $pos = $off } + elsif ($whence == $SEEK_CUR) { $pos += $off } + elsif ($whence == $SEEK_END) { $pos = $len + $off } + else { die "Bad whence ($whence)" } + print "SEEK(POS=$pos,OFF=$off,LEN=$len)\n" if $DEBUG; + + $pos = 0 if $pos < 0; + $self->truncate($pos) if $pos > $len; # extend file + *$self->{pos} = $pos; + return 1; +} + +sub pos +{ + my $self = shift; + my $old = *$self->{pos}; + if (@_) { + my $pos = shift || 0; + my $buf = *$self->{buf}; + my $len = $buf ? length($$buf) : 0; + $pos = $len if $pos > $len; + *$self->{pos} = $pos; + } + return $old; +} + +sub getpos { shift->pos; } + +*sysseek = \&seek; +*setpos = \&pos; +*tell = \&getpos; + + + +sub getline +{ + my $self = shift; + my $buf = *$self->{buf} || return; + my $len = length($$buf); + my $pos = *$self->{pos}; + return if $pos >= $len; + + unless (defined $/) { # slurp + *$self->{pos} = $len; + return substr($$buf, $pos); + } + + unless (length $/) { # paragraph mode + # XXX slow&lazy implementation using getc() + my $para = ""; + my $eol = 0; + my $c; + while (defined($c = $self->getc)) { + if ($c eq "\n") { + $eol++; + next if $eol > 2; + } + elsif ($eol > 1) { + $self->ungetc($c); + last; + } + else { + $eol = 0; + } + $para .= $c; + } + return $para; # XXX wantarray + } + + my $idx = index($$buf,$/,$pos); + if ($idx < 0) { + # return rest of it + *$self->{pos} = $len; + $. = ++ *$self->{lno}; + return substr($$buf, $pos); + } + $len = $idx - $pos + length($/); + *$self->{pos} += $len; + $. = ++ *$self->{lno}; + return substr($$buf, $pos, $len); +} + +sub getlines +{ + die "getlines() called in scalar context\n" unless wantarray; + my $self = shift; + my($line, @lines); + push(@lines, $line) while defined($line = $self->getline); + return @lines; +} + +sub READLINE +{ + goto &getlines if wantarray; + goto &getline; +} + +sub input_line_number +{ + my $self = shift; + my $old = *$self->{lno}; + *$self->{lno} = shift if @_; + return $old; +} + +sub truncate +{ + my $self = shift; + my $len = shift || 0; + my $buf = *$self->{buf}; + if (length($$buf) >= $len) { + substr($$buf, $len) = ''; + *$self->{pos} = $len if $len < *$self->{pos}; + } + else { + $$buf .= ($self->pad x ($len - length($$buf))); + } + return 1; +} + +sub read +{ + my $self = shift; + my $buf = *$self->{buf}; + return undef unless $buf; + + my $pos = *$self->{pos}; + my $rem = length($$buf) - $pos; + my $len = $_[1]; + $len = $rem if $len > $rem; + return undef if $len < 0; + if (@_ > 2) { # read offset + substr($_[0],$_[2]) = substr($$buf, $pos, $len); + } + else { + $_[0] = substr($$buf, $pos, $len); + } + *$self->{pos} += $len; + return $len; +} + +sub write +{ + my $self = shift; + my $buf = *$self->{buf}; + return unless $buf; + + my $pos = *$self->{pos}; + my $slen = length($_[0]); + my $len = $slen; + my $off = 0; + if (@_ > 1) { + $len = $_[1] if $_[1] < $len; + if (@_ > 2) { + $off = $_[2] || 0; + die "Offset outside string" if $off > $slen; + if ($off < 0) { + $off += $slen; + die "Offset outside string" if $off < 0; + } + my $rem = $slen - $off; + $len = $rem if $rem < $len; + } + } + substr($$buf, $pos, $len) = substr($_[0], $off, $len); + *$self->{pos} += $len; + return $len; +} + +*sysread = \&read; +*syswrite = \&write; + +sub stat +{ + my $self = shift; + return unless $self->opened; + return 1 unless wantarray; + my $len = length ${*$self->{buf}}; + + return ( + undef, undef, # dev, ino + 0666, # filemode + 1, # links + $>, # user id + $), # group id + undef, # device id + $len, # size + undef, # atime + undef, # mtime + undef, # ctime + 512, # blksize + int(($len+511)/512) # blocks + ); +} + +sub FILENO { + return undef; # XXX perlfunc says this means the file is closed +} + +sub blocking { + my $self = shift; + my $old = *$self->{blocking} || 0; + *$self->{blocking} = shift if @_; + return $old; +} + +my $notmuch = sub { return }; + +*fileno = $notmuch; +*error = $notmuch; +*clearerr = $notmuch; +*sync = $notmuch; +*flush = $notmuch; +*setbuf = $notmuch; +*setvbuf = $notmuch; + +*untaint = $notmuch; +*autoflush = $notmuch; +*fcntl = $notmuch; +*ioctl = $notmuch; + +*GETC = \&getc; +*PRINT = \&print; +*PRINTF = \&printf; +*READ = \&read; +*WRITE = \&write; +*SEEK = \&seek; +*TELL = \&getpos; +*EOF = \&eof; +*CLOSE = \&close; +*BINMODE = \&binmode; + + +sub string_ref +{ + my $self = shift; + return *$self->{buf}; +} +*sref = \&string_ref; + +1; + +__END__ + +=head1 NAME + +IO::String - Emulate file interface for in-core strings + +=head1 SYNOPSIS + + use IO::String; + $io = IO::String->new; + $io = IO::String->new($var); + tie *IO, 'IO::String'; + + # read data + <$io>; + $io->getline; + read($io, $buf, 100); + + # write data + print $io "string\n"; + $io->print(@data); + syswrite($io, $buf, 100); + + select $io; + printf "Some text %s\n", $str; + + # seek + $pos = $io->getpos; + $io->setpos(0); # rewind + $io->seek(-30, -1); + seek($io, 0, 0); + +=head1 DESCRIPTION + +The C module provides the C interface for in-core +strings. An C object can be attached to a string, and +makes it possible to use the normal file operations for reading or +writing data, as well as for seeking to various locations of the string. +This is useful when you want to use a library module that only +provides an interface to file handles on data that you have in a string +variable. + +Note that perl-5.8 and better has built-in support for "in memory" +files, which are set up by passing a reference instead of a filename +to the open() call. The reason for using this module is that it +makes the code backwards compatible with older versions of Perl. + +The C module provides an interface compatible with +C as distributed with F, but the following methods +are not available: new_from_fd, fdopen, format_write, +format_page_number, format_lines_per_page, format_lines_left, +format_name, format_top_name. + +The following methods are specific to the C class: + +=over 4 + +=item $io = IO::String->new + +=item $io = IO::String->new( $string ) + +The constructor returns a newly-created C object. It +takes an optional argument, which is the string to read from or write +into. If no $string argument is given, then an internal buffer +(initially empty) is allocated. + +The C object returned is tied to itself. This means +that you can use most Perl I/O built-ins on it too: readline, <>, getc, +print, printf, syswrite, sysread, close. + +=item $io->open + +=item $io->open( $string ) + +Attaches an existing IO::String object to some other $string, or +allocates a new internal buffer (if no argument is given). The +position is reset to 0. + +=item $io->string_ref + +Returns a reference to the string that is attached to +the C object. Most useful when you let the C +create an internal buffer to write into. + +=item $io->pad + +=item $io->pad( $char ) + +Specifies the padding to use if +the string is extended by either the seek() or truncate() methods. It +is a single character and defaults to "\0". + +=item $io->pos + +=item $io->pos( $newpos ) + +Yet another interface for reading and setting the current read/write +position within the string (the normal getpos/setpos/tell/seek +methods are also available). The pos() method always returns the +old position, and if you pass it an argument it sets the new +position. + +There is (deliberately) a difference between the setpos() and seek() +methods in that seek() extends the string (with the specified +padding) if you go to a location past the end, whereas setpos() +just snaps back to the end. If truncate() is used to extend the string, +then it works as seek(). + +=back + +=head1 BUGS + +In Perl versions < 5.6, the TIEHANDLE interface was incomplete. +If you use such a Perl, then seek(), tell(), eof(), fileno(), binmode() will +not do anything on an C handle. See L for +details. + +=head1 SEE ALSO + +L, L, L + +=head1 COPYRIGHT + +Copyright 1998-2005 Gisle Aas. + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=cut diff --git a/.cpan/build/IO-String-1.08-0/blib/lib/auto/IO/String/.exists b/.cpan/build/IO-String-1.08-0/blib/lib/auto/IO/String/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/blib/man1/.exists b/.cpan/build/IO-String-1.08-0/blib/man1/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/blib/man3/.exists b/.cpan/build/IO-String-1.08-0/blib/man3/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git "a/.cpan/build/IO-String-1.08-0/blib/man3/IO\357\200\242\357\200\242String.3pm" "b/.cpan/build/IO-String-1.08-0/blib/man3/IO\357\200\242\357\200\242String.3pm" new file mode 100644 index 0000000000..b6cc6debe1 --- /dev/null +++ "b/.cpan/build/IO-String-1.08-0/blib/man3/IO\357\200\242\357\200\242String.3pm" @@ -0,0 +1,207 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "String 3pm" +.TH String 3pm "2005-12-05" "perl v5.36.0" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +IO::String \- Emulate file interface for in\-core strings +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 4 +\& use IO::String; +\& $io = IO::String\->new; +\& $io = IO::String\->new($var); +\& tie *IO, \*(AqIO::String\*(Aq; +\& +\& # read data +\& <$io>; +\& $io\->getline; +\& read($io, $buf, 100); +\& +\& # write data +\& print $io "string\en"; +\& $io\->print(@data); +\& syswrite($io, $buf, 100); +\& +\& select $io; +\& printf "Some text %s\en", $str; +\& +\& # seek +\& $pos = $io\->getpos; +\& $io\->setpos(0); # rewind +\& $io\->seek(\-30, \-1); +\& seek($io, 0, 0); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \f(CW\*(C`IO::String\*(C'\fR module provides the \f(CW\*(C`IO::File\*(C'\fR interface for in-core +strings. An \f(CW\*(C`IO::String\*(C'\fR object can be attached to a string, and +makes it possible to use the normal file operations for reading or +writing data, as well as for seeking to various locations of the string. +This is useful when you want to use a library module that only +provides an interface to file handles on data that you have in a string +variable. +.PP +Note that perl\-5.8 and better has built-in support for \*(L"in memory\*(R" +files, which are set up by passing a reference instead of a filename +to the \fBopen()\fR call. The reason for using this module is that it +makes the code backwards compatible with older versions of Perl. +.PP +The \f(CW\*(C`IO::String\*(C'\fR module provides an interface compatible with +\&\f(CW\*(C`IO::File\*(C'\fR as distributed with \fI\s-1IO\-1.20\s0\fR, but the following methods +are not available: new_from_fd, fdopen, format_write, +format_page_number, format_lines_per_page, format_lines_left, +format_name, format_top_name. +.PP +The following methods are specific to the \f(CW\*(C`IO::String\*(C'\fR class: +.ie n .IP "$io = IO::String\->new" 4 +.el .IP "\f(CW$io\fR = IO::String\->new" 4 +.IX Item "$io = IO::String->new" +.PD 0 +.ie n .IP "$io = IO::String\->new( $string )" 4 +.el .IP "\f(CW$io\fR = IO::String\->new( \f(CW$string\fR )" 4 +.IX Item "$io = IO::String->new( $string )" +.PD +The constructor returns a newly-created \f(CW\*(C`IO::String\*(C'\fR object. It +takes an optional argument, which is the string to read from or write +into. If no \f(CW$string\fR argument is given, then an internal buffer +(initially empty) is allocated. +.Sp +The \f(CW\*(C`IO::String\*(C'\fR object returned is tied to itself. This means +that you can use most Perl I/O built-ins on it too: readline, <>, getc, +print, printf, syswrite, sysread, close. +.ie n .IP "$io\->open" 4 +.el .IP "\f(CW$io\fR\->open" 4 +.IX Item "$io->open" +.PD 0 +.ie n .IP "$io\->open( $string )" 4 +.el .IP "\f(CW$io\fR\->open( \f(CW$string\fR )" 4 +.IX Item "$io->open( $string )" +.PD +Attaches an existing IO::String object to some other \f(CW$string\fR, or +allocates a new internal buffer (if no argument is given). The +position is reset to 0. +.ie n .IP "$io\->string_ref" 4 +.el .IP "\f(CW$io\fR\->string_ref" 4 +.IX Item "$io->string_ref" +Returns a reference to the string that is attached to +the \f(CW\*(C`IO::String\*(C'\fR object. Most useful when you let the \f(CW\*(C`IO::String\*(C'\fR +create an internal buffer to write into. +.ie n .IP "$io\->pad" 4 +.el .IP "\f(CW$io\fR\->pad" 4 +.IX Item "$io->pad" +.PD 0 +.ie n .IP "$io\->pad( $char )" 4 +.el .IP "\f(CW$io\fR\->pad( \f(CW$char\fR )" 4 +.IX Item "$io->pad( $char )" +.PD +Specifies the padding to use if +the string is extended by either the \fBseek()\fR or \fBtruncate()\fR methods. It +is a single character and defaults to \*(L"\e0\*(R". +.ie n .IP "$io\->pos" 4 +.el .IP "\f(CW$io\fR\->pos" 4 +.IX Item "$io->pos" +.PD 0 +.ie n .IP "$io\->pos( $newpos )" 4 +.el .IP "\f(CW$io\fR\->pos( \f(CW$newpos\fR )" 4 +.IX Item "$io->pos( $newpos )" +.PD +Yet another interface for reading and setting the current read/write +position within the string (the normal getpos/setpos/tell/seek +methods are also available). The \fBpos()\fR method always returns the +old position, and if you pass it an argument it sets the new +position. +.Sp +There is (deliberately) a difference between the \fBsetpos()\fR and \fBseek()\fR +methods in that \fBseek()\fR extends the string (with the specified +padding) if you go to a location past the end, whereas \fBsetpos()\fR +just snaps back to the end. If \fBtruncate()\fR is used to extend the string, +then it works as \fBseek()\fR. +.SH "BUGS" +.IX Header "BUGS" +In Perl versions < 5.6, the \s-1TIEHANDLE\s0 interface was incomplete. +If you use such a Perl, then \fBseek()\fR, \fBtell()\fR, \fBeof()\fR, \fBfileno()\fR, \fBbinmode()\fR will +not do anything on an \f(CW\*(C`IO::String\*(C'\fR handle. See perltie for +details. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +IO::File, IO::Stringy, \*(L"open\*(R" in perlfunc +.SH "COPYRIGHT" +.IX Header "COPYRIGHT" +Copyright 1998\-2005 Gisle Aas. +.PP +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. diff --git a/.cpan/build/IO-String-1.08-0/blib/script/.exists b/.cpan/build/IO-String-1.08-0/blib/script/.exists new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/pm_to_blib b/.cpan/build/IO-String-1.08-0/pm_to_blib new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.cpan/build/IO-String-1.08-0/t/close.t b/.cpan/build/IO-String-1.08-0/t/close.t new file mode 100644 index 0000000000..e6b2e5bb24 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/t/close.t @@ -0,0 +1,36 @@ +#!perl -w + +print "1..1\n"; + +use strict; +use IO::String; + +my $str = "abcd"; + +my $destroyed = 0; + +{ + package MyStr; + @MyStr::ISA = qw(IO::String); + + sub DESTROY { + $destroyed++; + print "DESTROY @_\n"; + } +} + + +my $rounds = 5; + +for (1..$rounds) { + my $io = MyStr->new($str); + die unless $io->getline eq "abcd"; + $io->close; + undef($io); + print "-\n"; +} + +print "XXX $destroyed\n"; + +print "not " unless $destroyed == $rounds; +print "ok 1\n"; diff --git a/.cpan/build/IO-String-1.08-0/t/para.t b/.cpan/build/IO-String-1.08-0/t/para.t new file mode 100644 index 0000000000..d613d01f5a --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/t/para.t @@ -0,0 +1,49 @@ +#!perl -w + +use strict; +use Test qw(plan ok); + +plan tests => 8; + +use IO::String; + +my $fh = IO::String->new(<, "a\n\n"); +ok(<$fh>, "a\nb\n\n"); +ok(<$fh>, "a\nb\nc\n\n"); +ok(<$fh>, "a\nb\nc\nd\n"); +ok(<$fh>, undef); + +$fh = IO::String->new(<, "a\nb\n\n"); +ok(<$fh>, undef); +ok(<$fh>, undef); diff --git a/.cpan/build/IO-String-1.08-0/t/read.t b/.cpan/build/IO-String-1.08-0/t/read.t new file mode 100644 index 0000000000..3c876689d4 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/t/read.t @@ -0,0 +1,109 @@ +print "1..17\n"; + +$str = <new($str); + +@lines = <$io>; +print "not " unless @lines == 5 && $lines[1] eq "of a paragraph\n" && $. == 5; +print "ok 1\n"; + +use vars qw(@tmp); + +print "not " if defined($io->getline) || + (@tmp = $io->getlines) || + defined(<$io>) || + defined($io->getc) || + read($io, $buf, 100) != 0 || + $io->getpos != length($str); +print "ok 2\n"; + + +{ + local $/; # slurp mode + $io->setpos(0); + @lines = $io->getlines; + print "not " unless @lines == 1 && $lines[0] eq $str; + print "ok 3\n"; + + $io->setpos(index($str, "and")); + $line = <$io>; + print "not " unless $line eq "and a single line.\n\n"; + print "ok 4\n"; +} + +{ + local $/ = ""; # paragraph mode + $io->setpos(0); + @lines = <$io>; + print "not " unless @lines == 2 && $lines[1] eq "and a single line.\n\n"; + print "ok 5\n"; +} + +{ + local $/ = "is"; + $io->setpos(0); + @lines = (); + my $no = $io->input_line_number; + my $err; + while (<$io>) { + push(@lines, $_); + $err++ if $. != ++$no; + } + + print "not " if $err; + print "ok 6\n"; + + print "not " unless @lines == 3 && join("-", @lines) eq + "This- is- an example\n" . + "of a paragraph\n\n" . + "and a single line.\n\n"; + print "ok 7\n"; +} + + +# Test read + +$io->setpos(0); + +print "not " unless read($io, $buf, 3) == 3 && $buf eq "Thi"; +print "ok 8\n"; + +print "not " unless sysread($io, $buf, 3, 2) == 3 && $buf eq "Ths i"; +print "ok 9\n"; + +$io->seek(-4, 2); + +print "not " if $io->eof; +print "ok 10\n"; + +print "not " unless read($io, $buf, 20) == 4 && $buf eq "e.\n\n"; +print "ok 11\n"; + +print "not " unless read($io, $buf, 20) == 0 && $buf eq ""; +print "ok 12\n"; + +print "not " unless $io->eof; +print "ok 13\n"; + + +$io->setpos(0); +print "not " if defined(read($io, $buf, -1)); +print "ok 14\n"; + +print "not " unless read($io, $buf, 0) == 0; +print "ok 15\n"; + +print "not " unless read($io, $buf, 4) == 4 && $buf eq "This"; +print "ok 16\n"; + +$str = ""; +print "not " if defined(read($io, $buf, 4)); +print "ok 17\n"; diff --git a/.cpan/build/IO-String-1.08-0/t/seek.t b/.cpan/build/IO-String-1.08-0/t/seek.t new file mode 100644 index 0000000000..42c6cc0a72 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/t/seek.t @@ -0,0 +1,63 @@ +print "1..10\n"; + +$str = "abcd"; + +#$IO::String::DEBUG++; + +use IO::String; +$io = IO::String->new($str); + +sub all_pos +{ + my($io, $expect) = @_; + $io->getpos == $expect && + $io->pos == $expect && + $io->tell == $expect && + $io->seek(0, 1) == $expect && + $io->sysseek(0, 1) == $expect && + $] >= 5.006 ? ( tell($io) == $expect && + seek($io, 0, 1) == $expect && + sysseek($io, 0, 1) == $expect + ) + : 1; +} + +print "not " unless all_pos($io, 0); +print "ok 1\n"; + +$io->setpos(2); +print "not " unless all_pos($io, 2); +print "ok 2\n"; + +$io->setpos(10); # XXX should it be defined in terms of seek?? +print "not " unless all_pos($io, 4); +print "ok 3\n"; + +$io->seek(10, 0); +print "not " unless all_pos($io, 10); +print "ok 4\n"; + +$io->print("ćřĺ"); +print "not " unless all_pos($io, 13); +print "ok 5\n"; + +$io->seek(-4, 2); +print "not " unless all_pos($io, 9); +print "ok 6\n"; + +print "not " unless $io->read($buf, 20) == 4 && $buf eq "\0ćřĺ"; +print "ok 7\n"; + +print "not " unless $io->seek(-10,1) && all_pos($io, 3); +print "ok 8\n"; + +$io->seek(0,0); +print "not " unless all_pos($io, 0); +print "ok 9\n"; + +if ($] >= 5.006) { + seek($io, 1, 0); + print "not " unless all_pos($io, 1); +} +print "ok 10\n"; + diff --git a/.cpan/build/IO-String-1.08-0/t/truncate.t b/.cpan/build/IO-String-1.08-0/t/truncate.t new file mode 100644 index 0000000000..50a33977d2 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/t/truncate.t @@ -0,0 +1,38 @@ +print "1..6\n"; + +use IO::String; + +$io = IO::String->new($str); + +$io->truncate(10); +print "not " unless length($str) == 10; +print "ok 1\n"; + +print "not " unless $io->getpos == 0; +print "ok 2\n"; + +$io->setpos(8); +$io->truncate(2); +print "not " unless length($str) == 2 && $io->getpos == 2; +print "ok 3\n"; + +undef($io); +$str = ""; + +$io = IO::String->new($str); +$io->pad("+"); + +$io->truncate(5); + +$n = read($io, $buf, 20); +print "not " unless $n == 5 && $buf eq "+++++" && $buf eq $str; +print "ok 4\n"; + +print "not " unless read($io, $buf, 20) == 0; +print "ok 5\n"; + +$io->truncate(0); +print "not " unless $str eq ""; +print "ok 6\n"; + + diff --git a/.cpan/build/IO-String-1.08-0/t/write.t b/.cpan/build/IO-String-1.08-0/t/write.t new file mode 100644 index 0000000000..c813e8e110 --- /dev/null +++ b/.cpan/build/IO-String-1.08-0/t/write.t @@ -0,0 +1,46 @@ +print "1..1\n"; + +#$IO::String::DEBUG++; + +use IO::String; +$io = IO::String->new; + +print $io "Heisan\n"; +$io->print("a", "b", "c"); + +{ + local($\) = "\n"; + print $io "d", "e"; + local($,) = ","; + print $io "f", "g", "h"; +} + +$foo = "1234567890"; + +syswrite($io, $foo, length($foo)); +$io->syswrite($foo); +$io->syswrite($foo, length($foo)); +$io->write($foo, length($foo), 5); +$io->write("xxx\n", 100, -1); + +for (1..3) { + printf $io "i(%d)", $_; + $io->printf("[%d]\n", $_); +} +select $io; +print "\n"; + +$io->setpos(0); +print "h"; + + +local *str = $io->string_ref; + +select STDOUT; +print $str; + +print "not " unless $str eq "heisan\nabcde\nf,g,h\n" . + ("1234567890" x 3) . "67890\n" . + "i(1)[1]\ni(2)[2]\ni(3)[3]\n\n"; +print "ok 1\n"; + diff --git a/.cpan/sources/authors/01mailrc.txt.gz b/.cpan/sources/authors/01mailrc.txt.gz new file mode 100644 index 0000000000..ec2708b8c9 Binary files /dev/null and b/.cpan/sources/authors/01mailrc.txt.gz differ diff --git a/.cpan/sources/authors/id/B/BH/BHALLISSY/CHECKSUMS b/.cpan/sources/authors/id/B/BH/BHALLISSY/CHECKSUMS new file mode 100644 index 0000000000..af921af2ee --- /dev/null +++ b/.cpan/sources/authors/id/B/BH/BHALLISSY/CHECKSUMS @@ -0,0 +1,99 @@ +0&&<<''; # this PGP-signed message is also valid perl +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +# CHECKSUMS file written on Sun Nov 21 23:33:46 2021 GMT by CPAN::Checksums (v2.13) +$cksum = { + 'Font-TTF-1.06.meta' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => '8c5234672077febf716e5f38425f22ac', + 'mtime' => '2016-08-18', + 'sha256' => 'e690b04e37b51166f7b533cd76d1701beba4da1cead5b95e07d7ad83b0983f55', + 'size' => 733 + }, + 'Font-TTF-1.06.tar.gz' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => '241b59310ad4450e6e050d5e790f1b21', + 'md5-ungz' => 'e8cc78be6294e5c3c909f65e281bde5c', + 'mtime' => '2016-08-25', + 'sha256' => '4b697d444259759ea02d2c442c9bffe5ffe14c9214084a01f743693a944cc293', + 'sha256-ungz' => '0db601c4d0a3a1b9f952ed5d19a61f8636b62444551615110601a637e7cb6373', + 'size' => 256048 + }, + 'Font-TTF-Scripts-1.06.meta' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => '2322b98c747070f8d6b2d6390865bd18', + 'mtime' => '2016-08-25', + 'sha256' => '0e6d148060c1f7eb8477208f022c1f51d08b3b52fff27edfd0dce72bc15c3e27', + 'size' => 765 + }, + 'Font-TTF-Scripts-1.06.tar.gz' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => 'e206f32a46172caee156690d4e31f8b6', + 'md5-ungz' => 'bf31f3e0cd3653258c0658c1a206feb5', + 'mtime' => '2016-08-25', + 'sha256' => 'dc6d6392fd742f58179b2317c1aeb2afea9e0728f1318fdbc752b4a0cfbcc353', + 'sha256-ungz' => '4a3a00a226e712c6b64a4fafe00cf0ee3e5f8bb7adba33198a2f5ba829a59537', + 'size' => 1637967 + }, + 'Text-PDF-0.30.meta' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => 'bdaf2b8099039db5593f7e09113a20e4', + 'mtime' => '2016-08-18', + 'sha256' => 'e314337cf0d09cf03e78fd149a86aa32a83fe95554e528909e02bc464577fcee', + 'size' => 736 + }, + 'Text-PDF-0.30.tar.gz' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => 'cd3ca14a3caef9bde747c72124b47ca7', + 'md5-ungz' => 'a1e2fdc90660c55fe5bbb748c45da8ed', + 'mtime' => '2016-08-18', + 'sha256' => 'c40cd3a279a9b54ee756c6ef12436cf46fa220afaacf7effdb39b5ea45c1d9e0', + 'sha256-ungz' => '0450c7eaff6e2354a863b1c551d01b89f7eafe4c6d66d8cb7a71cccf3cf6c009', + 'size' => 56169 + }, + 'Text-PDF-0.31.meta' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => '9f02b634c5e689dab10d70b7fd2c627c', + 'mtime' => '2016-08-24', + 'sha256' => '997e2de193041fc0087fdaba7fe8896dcc9fa86b826759a4b551b0692dba4b86', + 'size' => 736 + }, + 'Text-PDF-0.31.tar.gz' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => 'bf63812e65f2e2012e10e422a637760a', + 'md5-ungz' => '0eac76675533f98a836e660e68b45446', + 'mtime' => '2016-08-25', + 'sha256' => 'df9f515ee159804b0d5a75d5adb93c4584c7ec401d8c59c27e9f73925d8dac68', + 'sha256-ungz' => '93d61f0e68c187aad686cf0aa1552e124e390827c363699c8d6a47322e4ee32c', + 'size' => 56267 + }, + 'Text-Unicode-Equivalents-0.05.meta' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => 'd72f2719165cf1b9b2855ec7dddb2546', + 'mtime' => '2011-06-27', + 'sha256' => 'fac0c2d4920b4f3a23ef23decde12c5a98f71bd9d89f3e06f9bf46fdb77beded', + 'size' => 546 + }, + 'Text-Unicode-Equivalents-0.05.tar.gz' => { + 'cpan_path' => 'B/BH/BHALLISSY', + 'md5' => '78f48a7e6283f2c0f8586a86f33700d6', + 'md5-ungz' => '4b57e0a7a8888cd2eb056ad71d8284f2', + 'mtime' => '2011-06-27', + 'sha256' => 'a53862f7f935c1f894ff23d4fd2834573f6c537f05efd876612a3abcc7a0a3d6', + 'sha256-ungz' => '5e04ae137ad4a383648383a3c1defa4242c43e3a585e7fcec9dcabd032bd9aec', + 'size' => 6165 + } +}; +__END__ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.14 (GNU/Linux) + +iQEcBAEBAgAGBQJhmtdaAAoJELahc5BjdgzKG9EH/2Q8g5/AZg+q8muoqoL6Th03 +RltA3ANdVRe5i5SgkEuE1gFlqYy9jkPVwK4dQjyVMd7W+aSsyMtKJ+zVx1MfCBsz +S2dhJpEsoq81G3S8sdK6OJpVJq2kbg3meMm++5UbKrkhOmVnnUd/B8zlSE4+UasE +DT6WTmwQs5Qtlqw6648WNe9pp0niiUNYmdBjTHG0TUfJG6yoVEJ8jF13sBIAM8TT +avblBLXHu6ge2LdwJpWS9Rupbhc4RSxh/CT1pb3xQnkJhuAfWbKM7ymm5bK9YOIW +hd+VtKQFK0QogtdI9vJuuHKRFPgfi6GogOX2HE9VZ0/Hg6JMqeYoBRwrqpwS8mA= +=JAv8 +-----END PGP SIGNATURE----- diff --git a/.cpan/sources/authors/id/B/BH/BHALLISSY/Font-TTF-1.06.tar.gz b/.cpan/sources/authors/id/B/BH/BHALLISSY/Font-TTF-1.06.tar.gz new file mode 100644 index 0000000000..877f9d69fc Binary files /dev/null and b/.cpan/sources/authors/id/B/BH/BHALLISSY/Font-TTF-1.06.tar.gz differ diff --git a/.cpan/sources/authors/id/G/GA/GAAS/CHECKSUMS b/.cpan/sources/authors/id/G/GA/GAAS/CHECKSUMS new file mode 100644 index 0000000000..7a83d2960d --- /dev/null +++ b/.cpan/sources/authors/id/G/GA/GAAS/CHECKSUMS @@ -0,0 +1,994 @@ +0&&<<''; # this PGP-signed message is also valid perl +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +# CHECKSUMS file written on Mon Nov 22 00:49:13 2021 GMT by CPAN::Checksums (v2.13) +$cksum = { + 'Array-RefElem-1.00.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '43ff2dd2049258634cb00697198572d1', + 'md5-ungz' => '480546e09fad66336860bc8f253fe6a1', + 'mtime' => '2003-12-18', + 'sha256' => '53b880a3aec043e4e370ce12682b4756de45dd742dab57294fe21a15453cefe3', + 'sha256-ungz' => '3ae1b9c79da1b84b9a89642cf27e674256577e07ce1c5f5892664fd095de1a5e', + 'size' => 2030 + }, + 'Convert-Recode-1.04.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'fac0f792e6ff23b8837750d35485c095', + 'md5-ungz' => 'e5a3866101b3a57ce6c260542eab561c', + 'mtime' => '2003-12-18', + 'sha256' => '62f6e2ff524d98b39a9c6881198e1addd1e84254308dc45d9d254294d7d744f2', + 'sha256-ungz' => '9135d7dd0e0cd7864e8a42794e556ff5524f09e716684dd2ee618a20bcad22ed', + 'size' => 2548 + }, + 'Crypt-SSLeay-0.07.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'e5b557654736e42456c5868d4c9a294f', + 'md5-ungz' => '5e91a6a3fe5a1829b301ce91ce1701a5', + 'mtime' => '1998-10-13', + 'sha256' => '0409879abb6a3e75587a5612c3c0e8fc1c2f7548e7d016c4df5e5fcac985c1d9', + 'sha256-ungz' => '052d5204b4487ba39b3dabd9695ba1f091ec2686c1ec7136172334b3429577fa', + 'size' => 6965 + }, + 'Data-Dump-1.22.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'e56aa46aea44c5aa5db0149f14fe169e', + 'mtime' => '2013-05-10', + 'sha256' => '1386e89d6244a8cff68ce3b413f32caf44dcccc1db7457353179bb8e1a80b463', + 'size' => 1071 + }, + 'Data-Dump-1.22.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'db211fe64a5cab15b1e86e5b0dc379a4', + 'md5-ungz' => 'a92c013dc7363ff20c4df30d68596b38', + 'mtime' => '2013-05-10', + 'sha256' => '533caad79f2f5ff453ed30137c96c1cb2a7e83972bf9dc48d265e0e035a738b2', + 'sha256-ungz' => '37e16210de43ac8cb899e92569a8a0766306546a656defe49a1a9b17341b56be', + 'size' => 20621 + }, + 'Data-Dump-1.23.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '84bc29d0eb30e53bbe5e2b07b3157f7a', + 'mtime' => '2015-06-09', + 'sha256' => 'a444889be9d9fd34457ad9c8a6cadfbad6b8dcadfa98ddc7b54d07ccf02104ad', + 'size' => 1073 + }, + 'Data-Dump-1.23.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '762c111e525c82ff23d62c90821b26e9', + 'md5-ungz' => '7e76f9fb8ce9801836e78e36bce441f6', + 'mtime' => '2015-06-09', + 'sha256' => 'af53b05ef1387b4cab4427e6789179283e4f0da8cf036e8db516ddb344512b65', + 'sha256-ungz' => '49a59896975487fccf689e3977224e7894b98c25a7ff6b14f976b6bcbf93e921', + 'size' => 20771 + }, + 'Data-DumpXML-1.02.dtd' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'eb553a6b821756e8d9da892bae398dde', + 'mtime' => '2001-12-11', + 'sha256' => 'e825243445b724259e4ac64357995bb6f800f6e91c0ff6d5d6a4b0480a2dcef0', + 'size' => 887 + }, + 'Data-DumpXML-1.02.xsd' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'd80cb5956d84a64c28780b5a7614158f', + 'mtime' => '2001-12-11', + 'sha256' => '072bd4a61166b3953a0dacf19686123fc81fca9df16bfab1f62a1261ab02f3d4', + 'size' => 2485 + }, + 'Data-DumpXML-1.03.xsd' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'a1c18769924b0accc6d7367985b6b5e4', + 'mtime' => '2001-12-30', + 'sha256' => 'd97bce15a5359612fe90c9dcb74c06f3d5cf85d751992f273f26ca4642415d69', + 'size' => 2544 + }, + 'Data-DumpXML-1.04.dtd' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'ffbce6cfe8fac09577a3e40adebe6f23', + 'mtime' => '2002-12-28', + 'sha256' => 'b4eb318f6aef82313fdbe573fb1b8b6b35312b9e5f634a1c1e2c2bd87e5dfc80', + 'size' => 857 + }, + 'Data-DumpXML-1.04.xsd' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'a1c18769924b0accc6d7367985b6b5e4', + 'mtime' => '2002-12-28', + 'sha256' => 'd97bce15a5359612fe90c9dcb74c06f3d5cf85d751992f273f26ca4642415d69', + 'size' => 2544 + }, + 'Data-DumpXML-1.05.xsd' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '11a06e5c9d6a00ba38b9354da0f22830', + 'mtime' => '2003-01-06', + 'sha256' => '09ab8def8a5a84280b4c1fad47149d1149c920a62e4ccfce454620b94cfcc3a3', + 'size' => 2532 + }, + 'Data-DumpXML-1.06.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0ff69d238847d62f24a217d67b2ae9d8', + 'md5-ungz' => '27206616e10406ea6cd692708e19ef90', + 'mtime' => '2003-12-18', + 'sha256' => 'c62c7e90b98ad4965367b873bbad42bba35728194fcea0469868b4335e20db68', + 'sha256-ungz' => 'f7d030e083ef1efadf31c968bb4dfd3d7e99e9463ba7519342c3e6123dde5d8e', + 'size' => 7935 + }, + 'Digest-1.17.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '4ac78a8ac25d7e9ada76059a090bdf2e', + 'mtime' => '2011-10-02', + 'sha256' => '2b63e95d2ec9d0cc6e9ae75cabaf832d8cc6f5dd89a2792effd24e66bfa63715', + 'size' => 662 + }, + 'Digest-1.17.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '2f8a38f7f6c1bd2df36feb16d8208d6d', + 'md5-ungz' => '583f818e70aa6ce3b413fac6fbe11367', + 'mtime' => '2011-10-02', + 'sha256' => '2f6a54459fc7f37c0669d548bb224b695eb8d2ddc089aa5547645ce1f5fd86f7', + 'sha256-ungz' => 'aca538ec6c0645b913e4f121ae0af93bf611358ea7d9a37a117cd4df0754b260', + 'size' => 9034 + }, + 'Digest-Adler32-0.03.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '63fc73aa3f3ea5e0eaa76f14ce9ecafa', + 'md5-ungz' => '3ea462bbd63e9c413c30255f713edd3f', + 'mtime' => '2003-11-30', + 'sha256' => '43ca2e412f0acfaf826f565f62042e8ab79654db9209953aca770e6ab99328f8', + 'sha256-ungz' => '58ea15ef404542616c45384e5ae00ea121611735d83cf58821ad5efe51834b76', + 'size' => 2105 + }, + 'Digest-HMAC-1.03.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '412ab96e610caf1ed2d8e0068a9f13f3', + 'mtime' => '2011-07-25', + 'sha256' => 'a1e5ba4aab16e932a96f0dce5f97229010bf7571ca0546349957ede7972d4ca4', + 'size' => 604 + }, + 'Digest-HMAC-1.03.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'e6a5d6f552da16eacb5157ea4369ff9d', + 'md5-ungz' => '2d37bcddbd0fd91d296b7d26a6a6a385', + 'mtime' => '2011-07-25', + 'sha256' => '3bc72c6d3ff144d73aefb90e9a78d33612d58cf1cd1631ecfb8985ba96da4a59', + 'sha256-ungz' => '3ca0f6e17a08225bc7d501aec9a87d36e9ae5d7fad7011ebd0b86c7a6c9f01fd', + 'size' => 7251 + }, + 'Digest-MD2-2.04.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '4fa406da1888e41a6798971be83ac41b', + 'mtime' => '2014-04-28', + 'sha256' => '35e5ef228ef696d23e36f391759ac527320a2261a4fc38540b4e508c72178a84', + 'size' => 788 + }, + 'Digest-MD2-2.04.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'cdb34485ef5c345f40d8aae016a00ff6', + 'md5-ungz' => 'ed6a64102b9e3fb98bd7680e68370f43', + 'mtime' => '2014-04-28', + 'sha256' => 'd0aabf4834c20ac411bea427c4a308b59a5fcaa327679ef5294c1d68ab71eed3', + 'sha256-ungz' => '673a2b1e1069dc95c49d9c251044717fce54fa583405c779a7dd3c681e1893b6', + 'size' => 17379 + }, + 'Digest-MD5-2.53.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '7763e4d586cc2d398143e0a6764ea957', + 'mtime' => '2013-07-02', + 'sha256' => '636209e5c60d8fec272c7e4e174129002ecf098b6ed0225a1183ef6a14871ef1', + 'size' => 1058 + }, + 'Digest-MD5-2.53.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'affc629d05c4c7b3efe4b3b874bce528', + 'md5-ungz' => 'cfe427ff1be67fa2ce7572ac81ab78c5', + 'mtime' => '2013-07-02', + 'sha256' => 'cde667c0c0c8a4d819d332ba9a4cad7e9f75fc7cabd490aae405ce7bc54d5152', + 'sha256-ungz' => 'f9403d06c32fb09befdf67ed4713ffd2ff83a43c990b6fd12debc05e375a9a16', + 'size' => 47476 + }, + 'Digest-MD5-2.54.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '5568475146ddb3aff0e124d7916edfc7', + 'mtime' => '2015-01-12', + 'sha256' => 'a40d85dcaad55aceb868d50885dba0280eb204864ca668253066cb029da1c080', + 'size' => 1059 + }, + 'Digest-MD5-2.54.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'bb2c9e79a8fd181abcb3071e94d7c099', + 'md5-ungz' => 'ab7e087d96ddece7741f15f8b635bc85', + 'mtime' => '2015-01-12', + 'sha256' => '90de11e3743ef1c753a5c2032b434e09472046fbcf346996cbe5d135b217f390', + 'sha256-ungz' => 'a0b57fb884ba793cfc0ffffb9bc8fbba6443ca9a65593595d565b0fd0f5452d2', + 'size' => 48699 + }, + 'Digest-MD5-2.55.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '1890c2e03d5b242954e95bac5175d293', + 'mtime' => '2016-03-09', + 'sha256' => 'ff5d966c55b544b2592e93a79468548aa9141287d4c1ab0610340443513fc38f', + 'size' => 1061 + }, + 'Digest-MD5-2.55.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '601519b826ca14c233f13a4578b967ef', + 'md5-ungz' => '15077438eed99a152d246962cd69f500', + 'mtime' => '2016-03-09', + 'sha256' => '03b198a2d14425d951e5e50a885d3818c3162c8fe4c21e18d7798a9a179d0e3c', + 'sha256-ungz' => '33ff58498ff61313a16f54869de1d3c91e8639b552acb52f6db1390eb77788c8', + 'size' => 48823 + }, + 'Digest-SHA1-2.13.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'e473102e21c043d2801fd0eae9326dcb', + 'mtime' => '2010-07-03', + 'sha256' => '55af6887e8c53b10e37e7cd66d8d52109ea1215f0d5f12326e9595abd807259f', + 'size' => 639 + }, + 'Digest-SHA1-2.13.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'bd22388f268434f2b24f64e28bf1aa35', + 'md5-ungz' => 'fe4fcaaf3323d72922a60af8ef93ac44', + 'mtime' => '2010-07-03', + 'sha256' => '68c1dac2187421f0eb7abf71452a06f190181b8fc4b28ededf5b90296fb943cc', + 'sha256-ungz' => 'f4ca255c39cf061944db11e34cebb18e80cb78caf452df60650b7e318d06f9e4', + 'size' => 39078 + }, + 'Encode-Locale-1.03.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '8901d5163fc92b3fedd7f6ceaf84fc5c', + 'mtime' => '2012-02-11', + 'sha256' => '748cead42a5dfd7314e91af4aaa373a53700374fb02b310e29b78802dd48304e', + 'size' => 710 + }, + 'Encode-Locale-1.03.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'de8422d068634e7c1068dab4e18b452f', + 'md5-ungz' => '60161cd42de4634b899a96f610694931', + 'mtime' => '2012-02-11', + 'sha256' => 'f76337e0933225914111fcc3319ff4db359b1abfd1aa56dff2df5378db0e2d55', + 'sha256-ungz' => 'a90951bb9f0977e17ae9790e107c005dd6285ae79a27b34d46ff7371be068811', + 'size' => 6846 + }, + 'Encode-Locale-1.04.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '6800a8a7c3310fbdf296fe6e5e39c9bf', + 'mtime' => '2015-01-12', + 'sha256' => 'cf6ae67d15f39ae246e8f81dc3b9e3c77ae4bd4bd4e0ec8d554d81e3c42dbff7', + 'size' => 1194 + }, + 'Encode-Locale-1.04.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0565984b048732e4fd1315212f21d462', + 'md5-ungz' => '3a1fdbe38b9e4424eac17154ce943cfb', + 'mtime' => '2015-01-12', + 'sha256' => '33aca4aa35829bd5c8c5e64ebfde86d0a2e8cd59dac2c4de707ffe9dc10bfbd4', + 'sha256-ungz' => 'f531fec787c6abb84713141d805c1fed14f5f22aa9eff2fc591fe81677dc2726', + 'size' => 8298 + }, + 'Encode-Locale-1.05.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '44aa6267e3749d22463e2b97b7127b20', + 'mtime' => '2015-06-09', + 'sha256' => '25ed23ac214121c607fcd629cde7b50b9e8790c88a8bac0ce41493404fdc2c8d', + 'size' => 1160 + }, + 'Encode-Locale-1.05.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'fcfdb8e4ee34bcf62aed429b4a23db27', + 'md5-ungz' => 'f12f1a94014b5ef5e0a2e732396978d4', + 'mtime' => '2015-06-09', + 'sha256' => '176fa02771f542a4efb1dbc2a4c928e8f4391bf4078473bd6040d8f11adb0ec1', + 'sha256-ungz' => '12f2d573e0b538d299937abecdec65418ff1b9042c92ff69a6185f190386d4b3', + 'size' => 8355 + }, + 'File-CounterFile-1.04.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'df77e2dbc80aa3ec9647a570bb5e0cf8', + 'md5-ungz' => 'f913f93ba5feef8a6a5c9f5a959ac32a', + 'mtime' => '2004-01-23', + 'sha256' => '3fd6d66ffa92b884fc9feb4f200daf47250570520c6955fdca7e717fd4a6ac1f', + 'sha256-ungz' => '8619b26570e66a64fd668133bdd933fa64744d961b4f545f0aa873bdc9328569', + 'size' => 4811 + }, + 'File-Listing-6.04.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '306f57adc5255d274daf987c8d67ea50', + 'mtime' => '2012-02-15', + 'sha256' => '7c1f21a86e84ba65270111054cf5ba2eda8974d85e0d75397b1c26ab56b16bfc', + 'size' => 700 + }, + 'File-Listing-6.04.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '83f636b477741f3a014585bb9cc079a6', + 'md5-ungz' => 'f77ec68440083033095b04b115359941', + 'mtime' => '2012-02-15', + 'sha256' => '1e0050fcd6789a2179ec0db282bf1e90fb92be35d1171588bd9c47d52d959cf5', + 'sha256-ungz' => '68d8bfbbbed2300e64df5a9ae227f8ca9064a1c52f87c95817e7a772cd6e9015', + 'size' => 51536 + }, + 'Font-AFM-1.20.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '9fb7323ef0dab1615a1a498cf3acd67d', + 'mtime' => '2008-06-04', + 'sha256' => '76b5bb063b668d57bd4e82ce8cc1584c5d705cff83b0cbc597fe1118e79c960e', + 'size' => 336 + }, + 'Font-AFM-1.20.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'b14ecf4dc4edbd63940aa354eb13c499', + 'md5-ungz' => '1e2f3af8dd51f5727a641453b3307402', + 'mtime' => '2008-06-04', + 'sha256' => '32671166da32596a0f6baacd0c1233825a60acaf25805d79c81a3f18d6088bc1', + 'sha256-ungz' => '44973476ab79b98c2a54a249fd6d9662f43837f0350c72411e3c187a7c0dbb83', + 'size' => 10421 + }, + 'GAAS' => { + 'cpan_path' => 'G/GA/GAAS', + 'isdir' => 1 + }, + 'HTML-Form-6.03.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'b0161cc47f2d6b81810ec5802f50edff', + 'mtime' => '2012-03-30', + 'sha256' => '801e586b6a3912117898f2a6f183cac3c25761035eb036657a77172f395a8ba9', + 'size' => 827 + }, + 'HTML-Form-6.03.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'fa6c2680207ed4fef5ea2ef09c210614', + 'md5-ungz' => 'a5c129d7d28c360b311cddef24290be8', + 'mtime' => '2012-03-30', + 'sha256' => '68c01d94f005d5ca9c4d55ad2a1bf3a8d034a5fc6db187d91a4c42f3fdc9fc36', + 'sha256-ungz' => '436b08740cf8150924d8faf488bd1c32332879fa6bbd0276321195029d97af8a', + 'size' => 23522 + }, + 'HTML-Format-1.23.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '78f94c359a399ad8c0ead462a69243b4', + 'md5-ungz' => '2148502fffb91aa64ae5ff88e08c5935', + 'mtime' => '2000-06-09', + 'sha256' => 'e04e55b8a4176ae5ad6b873475b43e8e16746d671be60dce360474530edf57e2', + 'sha256-ungz' => '0a6379029446a2282e49a8bf81f79cf26f71ee9d33f0b854387a8519d2c67559', + 'size' => 11244 + }, + 'HTML-Parser-2.25.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '26b0b0b6fabedd85e04c795eb6bc79cc', + 'md5-ungz' => 'ae5944d7c6d526b505dcce7574b7b8d1', + 'mtime' => '1999-11-05', + 'sha256' => 'fcf569b58a633ce604af8033d585eb7fe6b4862af8fee64d51cb234e87e0420b', + 'sha256-ungz' => 'a68b7822370c45410ab805054f7185c457b603d463eeb9791ed6ab4875a53823', + 'size' => 23619 + }, + 'HTML-Parser-3.71.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '664780483a9c2880680289b56ce464fd', + 'mtime' => '2013-05-08', + 'sha256' => '864d9e8e44f0631dbc7649e5acee4efcf1d6f99df6d467e73c31e831a62524cc', + 'size' => 1192 + }, + 'HTML-Parser-3.71.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '9128a45893097dfa3bf03301b19c5efe', + 'md5-ungz' => 'c2613ec3334ef7ddc53fe714bafe514a', + 'mtime' => '2013-05-08', + 'sha256' => 'be918b3749d3ff93627f72ee4b825683332ecb4c81c67a3a8d72b0435ffbd802', + 'sha256-ungz' => 'c07541b675786740ba2eee9995b91a7f92f42923866c807ebe7688696002fbf1', + 'size' => 90368 + }, + 'HTML-Parser-3.72.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '190acab71ff3b73a3e62d891cb508915', + 'mtime' => '2016-01-19', + 'sha256' => '59899de798c6ba8dce8b225687caf95c308df8b791f835c59b43eea7a2b76522', + 'size' => 1192 + }, + 'HTML-Parser-3.72.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'eb7505e5f626913350df9dd4a03d54a8', + 'md5-ungz' => '2a348b568add4638458b21e68f883a77', + 'mtime' => '2016-01-19', + 'sha256' => 'ec28c7e1d9e67c45eca197077f7cdc41ead1bb4c538c7f02a3296a4bb92f608b', + 'sha256-ungz' => 'cec2b0b45bf9f47319d3466a94a973c6e9eb589f04cddd0a9a67c421c1be44a7', + 'size' => 90680 + }, + 'HTML-Tree-0.53.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '116845119c0c7f7349bd83ce73e8007f', + 'md5-ungz' => '95249e4482bee6cc8efa7555b16539ae', + 'mtime' => '1999-12-15', + 'sha256' => '148250579b940b8775e0518a9309dcaf8f3392eca4ed1e845f05d6bcea62c6d8', + 'sha256-ungz' => '817035efd4c3f88a8a08c82f6fe04d0012259016b0fc6bd27c4e0a4c307e5ecb', + 'size' => 24261 + }, + 'HTTP-Cookies-6.01.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'a6004f936aba6d0f830e24bfccef2836', + 'mtime' => '2012-02-15', + 'sha256' => '5e8b1cf7585df8de83edc7acdcc9335a8c6e1d740e39da97ad85766434541546', + 'size' => 743 + }, + 'HTTP-Cookies-6.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'ecfd0eeb88512033352c2f13c9580f03', + 'md5-ungz' => '2fd8140e7c60511d3fa2b64b5d6026f0', + 'mtime' => '2012-02-15', + 'sha256' => 'f5d3ade383ce6389d80cb0d0356b643af80435bb036afd8edce335215ec5eb20', + 'sha256-ungz' => '7f2b07627722409f73e64c5b2b0dfe11a4908aeebac2216b95811fa33c0059b1', + 'size' => 18751 + }, + 'HTTP-Daemon-6.01.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '5cd0a1ca34c98ee00bbc8f2aa90aba9d', + 'mtime' => '2012-02-18', + 'sha256' => '22ca00698e9af256f41fab6224a07b9d58bb92608a858aca4ee5963c21d9a874', + 'size' => 831 + }, + 'HTTP-Daemon-6.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'ed0ae02d25d7f1e89456d4d69732adc2', + 'md5-ungz' => '92f3d018365d7cb6f1b559b57500f9db', + 'mtime' => '2012-02-18', + 'sha256' => '43fd867742701a3f9fcc7bd59838ab72c6490c0ebaf66901068ec6997514adc2', + 'sha256-ungz' => 'ab5dae0d83b359c22c2d3ee99911f4b0e9a421c1c0d56c1b16501622bf4f0a82', + 'size' => 18628 + }, + 'HTTP-Date-6.02.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '9b1fa6fa1ea18ae8ad93021d20dafb5f', + 'mtime' => '2012-03-30', + 'sha256' => '89b96b80b45da77e3fae39b10aff18b199fecceb2f8e56e6a2015f253b86de38', + 'size' => 704 + }, + 'HTTP-Date-6.02.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '52b7a0d5982d61be1edb217751d7daba', + 'md5-ungz' => '4e25a92eac7fb92467ce540af22f9450', + 'mtime' => '2012-03-30', + 'sha256' => 'e8b9941da0f9f0c9c01068401a5e81341f0e3707d1c754f8e11f42a7e629e333', + 'sha256-ungz' => '23a1d26f597eff352064289d9221cf84bccc0a11de4deea30369b6ff4bbe544b', + 'size' => 7319 + }, + 'HTTP-Message-6.06.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'a2c7ef15292751c00d3da07e895a2f7f', + 'mtime' => '2012-10-20', + 'sha256' => '58dfbf3b6515aaa3aff4d9378dc6de7cd000b67aee3438ba5be976908676997b', + 'size' => 1152 + }, + 'HTTP-Message-6.06.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'e563ac516e28d33f65bc0f295f625f85', + 'md5-ungz' => '5267cafa62740e34033e33d558af6500', + 'mtime' => '2012-10-20', + 'sha256' => '087e97009c5239dca4631cf433d836771b3fc5ba5685eef1965f9d3415cbad63', + 'sha256-ungz' => '9e4bd4703571b5fa20e55f7400629fcebf2dfc1321fc769c3c93166dfb2c2fc2', + 'size' => 50806 + }, + 'HTTP-Negotiate-6.01.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '9ee080c99592ac31fba750c85e525e79', + 'mtime' => '2012-02-18', + 'sha256' => 'a592c2a50872a61c8b33013eff2d3505b43e0a51e1aeb10835bd223615bf1b55', + 'size' => 688 + }, + 'HTTP-Negotiate-6.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '1236195250e264d7436e7bb02031671b', + 'md5-ungz' => '9c166780ff274d923ce87e64a8baf54c', + 'mtime' => '2012-02-18', + 'sha256' => '1c729c1ea63100e878405cda7d66f9adfd3ed4f1d6cacaca0ee9152df728e016', + 'sha256-ungz' => '2a2a5391b04e6421994e821e69b428e43f6bf8f78252931822482a85830618c1', + 'size' => 8596 + }, + 'IO-String-1.08.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '848b8115264345402db1bdb48fd95c52', + 'mtime' => '2005-12-06', + 'sha256' => '3b22c577fb00ed453efa28765b26a333af2f4228fb37ed002e9ad9a98a0b2f92', + 'size' => 295 + }, + 'IO-String-1.08.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '250e5424f290299fc3d6b5d1e9da3835', + 'md5-ungz' => 'd578c049d117f1205aec552e788a89f5', + 'mtime' => '2005-12-06', + 'sha256' => '2a3f4ad8442d9070780e58ef43722d19d1ee21a803bf7c8206877a10482de5a0', + 'sha256-ungz' => '598a56b771051253b5637e34bb6ff40caa530564d8a29b44e3fc61f3d43c252e', + 'size' => 7480 + }, + 'Image-Info-1.16.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '502b6299ef2d41f67bca4e1f7d9335ab', + 'md5-ungz' => 'e3a31c9295dc8068109766107fc36916', + 'mtime' => '2004-01-07', + 'sha256' => '8708c6bd0b6927de330f906c842a34cdd5a715063985e7b580e3e69c706df998', + 'sha256-ungz' => '5f1e3942f275f689d1c237b7a4d8308a9bfefc6439677f729059514277fbde57', + 'size' => 312250 + }, + 'LWP-MediaTypes-6.02.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'b82b10281e11e276c86232912081b42b', + 'mtime' => '2012-02-16', + 'sha256' => 'a5b54f98e3dde2f0110b95425f8592154015976ec372d533ecefe49a0143c339', + 'size' => 668 + }, + 'LWP-MediaTypes-6.02.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '8c5f25fb64b974d22aff424476ba13c9', + 'md5-ungz' => '501aec80510c1eea8cd8fb203c3c2ec2', + 'mtime' => '2012-02-16', + 'sha256' => '18790b0cc5f0a51468495c3847b16738f785a2d460403595001e0b932e5db676', + 'sha256-ungz' => '9485bcdc729204f7009ea67339f5b704f462cfc6cedec0b24a8736d76d21d6f0', + 'size' => 18722 + }, + 'LWP-Protocol-http10-6.03.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '8de2584affdcca4add3e2d15bf36f21d', + 'mtime' => '2012-02-18', + 'sha256' => '392a0837bb386b5741dd447aef7d2ffd9e5355026470f86fac3197561ffd4478', + 'size' => 798 + }, + 'LWP-Protocol-http10-6.03.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'c3d2f6efc2ce06066cf95a24fed6fff1', + 'md5-ungz' => 'a7cf45a730d49668c1c8e5c2b6ed8911', + 'mtime' => '2012-02-18', + 'sha256' => 'f3ffa911f9d59181f1717910ea26620905c298b74dc30f7d4e5139ee3020b8d3', + 'sha256-ungz' => 'ce5d4328d15c32419e76d8fd7c3f64d120931a21f4cd75f703bc48ad0539a0af', + 'size' => 4792 + }, + 'LWP-Protocol-https-6.04.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'b2514b09cf67157012f64cf8db39c202', + 'mtime' => '2013-04-29', + 'sha256' => '8fdecdebfbead995d75bef87a62c1098c26699f96a44c068fc98d819814e0fc6', + 'size' => 1223 + }, + 'LWP-Protocol-https-6.04.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '1b422a7d3b5fed1eb4d748fdc9fd79a4', + 'md5-ungz' => '751b456ad0841eacee40feb9957bf949', + 'mtime' => '2013-04-29', + 'sha256' => '1ef67750ee363525cf729b59afde805ac4dc80eaf8d36ca01082a4d78a7af629', + 'sha256-ungz' => 'c1b7237935e5001a5bded4780642f4f20bcfde860b739acf2efe861338a2df81', + 'size' => 4035 + }, + 'LWP-attic-1.00.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '2ccf6a0c44621e2be5983ed5ba3a12cd', + 'md5-ungz' => '3633a38b92cb5b842f796b002e961c7f', + 'mtime' => '1998-01-26', + 'sha256' => '4328943d5ab3cfa53301554c54ca19bf50cd3aabed1feab4f7485c2b413345c0', + 'sha256-ungz' => 'eca5676d18521a0db85251377b0a3adfce8c7873157a6d8eace1bbce7cf739c9', + 'size' => 6058 + }, + 'LWP5emu-0.01_01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '240e73f47fc21e306cb0f6fb8440ef5d', + 'md5-ungz' => 'f9a086f040a54eca3401ce2a35a0ac4b', + 'mtime' => '1998-04-24', + 'sha256' => 'e7ae8117e267a3317a41de4bb6efdf337c6eef60e0084110cf16adfbb4e8dd21', + 'sha256-ungz' => 'f37bc4cc430672ed99be71affc6829942d16a928e68cb25989c4e06e5b3fa67f', + 'size' => 11012 + }, + 'MD5-2.03.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0957f02fc30bc2106b3286ba854917bc', + 'md5-ungz' => 'af26f05235cd51dacb372c1cd8627128', + 'mtime' => '2003-11-27', + 'sha256' => '764d34efb50ecf12d83561f66ef6724f89c3dde6f5aa26ea18cf5f84c87bf7e1', + 'sha256-ungz' => 'b038fde064eb33ff6ee7403078917f3bfaec60ebf4c0e57d18b413df2093cc2c', + 'size' => 2810 + }, + 'MIME-Base64-3.14.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '07192d239f9d219a567998a30e776f46', + 'mtime' => '2013-07-02', + 'sha256' => 'ac4b41fa6ed8d0d5684255518adc0492d0e75c1a7d2f5eaabcda11dcf4739b23', + 'size' => 1008 + }, + 'MIME-Base64-3.14.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '66185dd11586d724245ba957db561e75', + 'md5-ungz' => 'cdfb8ab3657499462ed21899575239b3', + 'mtime' => '2013-07-02', + 'sha256' => '125a9427625477f90c8214d2ec80714c443c2d15ac390b7111fb1e19fb8d6ce1', + 'sha256-ungz' => '0189ea18a135a2c1f7149f07d8abc675226c9ab184953fe0fe6fd4834639e762', + 'size' => 18193 + }, + 'MIME-Base64-3.15.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0fb99f43c833a2bcb4319c43d0c80359', + 'mtime' => '2015-01-12', + 'sha256' => '6c519625c8f615e884cf5b59851d1d186fb0efebf0e66c09592086be02d886c9', + 'size' => 1039 + }, + 'MIME-Base64-3.15.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'ef958dc2bf96be5f759391c6ac1debd4', + 'md5-ungz' => '63b5811121f8010e4087c7cf5ddfe46a', + 'mtime' => '2015-01-12', + 'sha256' => '7f863566a6a9cb93eda93beadb77d9aa04b9304d769cea3bb921b9a91b3a1eb9', + 'sha256-ungz' => '34164346282adf4de0dd1a0feeecc0241e18cb1d4595920fbd5189d9bf886cd3', + 'size' => 18438 + }, + 'MIME-Base64-Perl-1.00.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'd81b4f6f5544a665f4de764c204f2220', + 'md5-ungz' => '6d079fd9248941afa30d8faec3b23550', + 'mtime' => '2004-01-14', + 'sha256' => 'f78c7ab62043518c31f733344a617ee22b04218c3ebadf796e73338acbb2f2ab', + 'sha256-ungz' => '21f74452144181e1e71aac6a38278278dba1836a8a6815e5386329d9da32847a', + 'size' => 10337 + }, + 'MIME-Base64-Scripts-1.00.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '7e861d070b3063b0bf14ef3b3653b029', + 'md5-ungz' => 'd3dee7d6c0a8d16125377e4cc4f55e9b', + 'mtime' => '2005-02-19', + 'sha256' => '0c8b0b50235d28ef921168b08be96f859a5685ea49e2443298c6d15ffa16f15c', + 'sha256-ungz' => 'd58611e88f2f576998b7711f4717d0e4177a0ca00abfcc9adf6cef4ff3af7f6f', + 'size' => 1227 + }, + 'Mozilla-CA-20110209.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '414857d1217a4f760a696e036a29efc2', + 'mtime' => '2011-02-11', + 'sha256' => '03fd832696cd20a6768053d4f99262d5894f2c64994ddbb5cde4811712000ff4', + 'size' => 625 + }, + 'Mozilla-CA-20110209.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '9ede08e57dbb404445d367e6479b3806', + 'md5-ungz' => '1f9cebea6417856e82145929b1f8be75', + 'mtime' => '2011-02-11', + 'sha256' => '9fb71687ee315655dce99bf7bf09f72a5162f50943b328b686f413eaf863da96', + 'sha256-ungz' => '47aaa6b4228d1ccd9aaf11a3bad08a0af1d5273272e2727d127163a56861c48b', + 'size' => 129926 + }, + 'Net-HTTP-6.06.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '647d1aa1ba1d8497ef1aa6ceff9bb425', + 'mtime' => '2013-03-10', + 'sha256' => '03a497f6167dae8bbffcaf1ff18fc9552511ebdd3a5e4d2936a886ae4b4c781b', + 'size' => 820 + }, + 'Net-HTTP-6.06.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '6e74d76205f168775de68347266793a7', + 'md5-ungz' => '6a55de41a29f5966b956ceab00fd5eeb', + 'mtime' => '2013-03-10', + 'sha256' => '1d4e3ced899efad12431564d93abe73dd2a1224aa208af5f4ab829e7a2dd39d4', + 'sha256-ungz' => 'e2056005f5e3438a54b7009ee2f18e959f4b764d25fada8edc764bcc2f1f8edd', + 'size' => 15609 + }, + 'Norge-1.08.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '99a06f56b89b7a07c9eb2bebf59d9dfe', + 'md5-ungz' => '5a5d0d35e93b327245e5df87239b83a1', + 'mtime' => '2004-05-21', + 'sha256' => '2564ff9c159170d3b8c45cc42584c7b5903f2907f487fcbef7f3bf95f36cbece', + 'sha256-ungz' => '7e9b465966863d0ab5a98333908a5840b8deaf5654cc0d0ad44f8c4a9e09a433', + 'size' => 13690 + }, + 'Perl-API-0.01.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '03b79421779f1981095c9e468a6dfba4', + 'mtime' => '2003-10-09', + 'sha256' => '076a5fc3c4d5c7bd4a35bb756d06edf4ea714de3f7865327e22845740eccb470', + 'size' => 291 + }, + 'Perl-API-0.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'eff6fc7dcb02f7a32438b254e8746a45', + 'md5-ungz' => '294f8a8767e4e5c52ee469b601524eed', + 'mtime' => '2003-10-09', + 'sha256' => 'cd72f9f348f9c7d8d5cd7041257528a1ec054378cf522a96a1b0df472e6aae3e', + 'sha256-ungz' => '5acb2f84dd9eb08f0e3acb41c5ce66c8ccdcf1f23df2035448acad14015c5ae3', + 'size' => 2003 + }, + 'PostScript-EPSF-0.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '66a9c8e1173c5b1ad649545ae90e73b2', + 'md5-ungz' => '6542fcfe0ec1bcf7dbd6771a07a764f0', + 'mtime' => '1999-04-05', + 'sha256' => '9cbefe3781d6db6dffce15f5895be9d384751d022e57012e79fd555a89ecdb43', + 'sha256-ungz' => '5c16fe8e17a641a941ca7cd2c75d4ad6e555b856f178401d69cc96b876a40f31', + 'size' => 4489 + }, + 'SHA-2.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '56573202d94ace4da5641a6f4f25cfe0', + 'md5-ungz' => '0ab401c8c1fee4bc75277fc6b009d89d', + 'mtime' => '2001-03-14', + 'sha256' => '8571331eac2cf9f9e3f4dee586017884c6dbb02ec64960f3e5f526b6514ef4ea', + 'sha256-ungz' => '61717e834b2a5e0255b8a0a78f113d1488b5b2a6826054bca14bd5c057fc39e7', + 'size' => 2282 + }, + 'Tkx-1.09.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '06d60d2e0e125dbf1314c03aaabcd15f', + 'mtime' => '2010-11-24', + 'sha256' => 'dbd2b39d742f2d25992a3cc8fcbf54f243332bb3320bde3771d38dad92eb463c', + 'size' => 641 + }, + 'Tkx-1.09.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '8dfe38d1b7c6a92101e840949c584d7d', + 'md5-ungz' => '29180abf13dee8b64e69aa423ad6ca20', + 'mtime' => '2010-11-24', + 'sha256' => '78f1f4e3fbaff10cf96358454c27bf01e3c31fde092a23bddce4afeffc52601f', + 'sha256-ungz' => 'eb26167283983410e480d4c852775e603637e9a94c36d6543a7f40aaef465cb3', + 'size' => 28390 + }, + 'UDDI-0.03.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '772d64406092a073feeebd00f0f80eff', + 'md5-ungz' => 'b211ca4cde4c54dd2906643b11dd0044', + 'mtime' => '2000-11-07', + 'sha256' => 'aab05b43668972ea93695f8a9510b9ba958976b127904865c20d71ca7fc109c8', + 'sha256-ungz' => '50d0ca6330518612dbaf170a9d9b56335892cf483155394e7f6d478bd1a44599', + 'size' => 12345 + }, + 'URI-1.40.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '3e4f3479353748fdf4fc17c59518d4b4', + 'mtime' => '2009-08-14', + 'sha256' => '017c7403f891964815c8060127d55b170b86a946969b72a54e6a64efc76bf400', + 'size' => 689 + }, + 'URI-1.40.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '626cc85f1939a89981f82aae43497b53', + 'md5-ungz' => '55d55f662ad8701426f9e3afe1b47825', + 'mtime' => '2009-08-14', + 'sha256' => '7104e9c602083066967c6fbfd06c2648f839fedb866e9bc77ae6c263d3f42fbf', + 'sha256-ungz' => 'e1c46e47dc3fd99dfaced140da939caca42d55adf969e78af78e38a137c0eea3', + 'size' => 97180 + }, + 'URI-1.60.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'ec752cde299de33fbf47b9b6fddac1dd', + 'mtime' => '2012-03-25', + 'sha256' => '5c9a1be06b1f14bc7d7c80a54d2e682564329ce22fe8dc34bf54d7d99539cfd8', + 'size' => 789 + }, + 'URI-1.60.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '70f739be8ce28b8baba7c5920ffee4dc', + 'md5-ungz' => 'd41388943211a38bfe16d56a30fadaad', + 'mtime' => '2012-03-25', + 'sha256' => '1f92d3dc64acb8845e9917c945e22b9a5275aeb9ff924eb7873c3b7a5c0d2377', + 'sha256-ungz' => 'db5351ff1f6f5640deced116e61017b1e6b413e61f421e51689e16d3a59513d6', + 'size' => 81196 + }, + 'URI-GoogleChart-1.02.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0297c54f5bf0850efeb3a9e540f7b1f5', + 'mtime' => '2009-08-15', + 'sha256' => '9885e7ed130176e30deebffa50e211618b586d26ec4f7429cf8d540cf885d825', + 'size' => 642 + }, + 'URI-GoogleChart-1.02.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '592d845ef7e55c5d5e23372cde5e09bd', + 'md5-ungz' => 'c64d6ad77994fc64513b05c123fcc4cc', + 'mtime' => '2009-08-15', + 'sha256' => '5a82c22ec6017a35d0fc826fef13412226872fc4a23c0e2c014a9fa92f2b1802', + 'sha256-ungz' => '2b040fb4747aca840a3dfdcf8d3fd3b7e23ee380f22daae3c21e1310ff45f98f', + 'size' => 13517 + }, + 'Unicode-Map8-0.12.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'b76a10615258894b1699b140f93940d0', + 'md5-ungz' => '7b4adc1d5667717c751192111a3b0b09', + 'mtime' => '2002-12-28', + 'sha256' => '8b9e51baa3c3c315be60f1e6274b2ba852c5010253297fdd989492da5817613b', + 'sha256-ungz' => '0791a7b2478b7ed1eb1c275ae09bcc28016a99b95ed70e997e6e98e6d136bb8c', + 'size' => 102882 + }, + 'Unicode-Map8-0.13.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '32182d06b440f0dcbed8260a3c18e595', + 'mtime' => '2010-01-18', + 'sha256' => 'a09daf69b2cb7155303588ed1ad2959fc13ecf27b11bd56c20ff5e13d031ad1f', + 'size' => 493 + }, + 'Unicode-Map8-0.13.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'fc93a37cabcae488bd95ca07bf5c919e', + 'md5-ungz' => 'fc62de808e22dab279d5008384334520', + 'mtime' => '2010-01-18', + 'sha256' => 'af1e85b8ebad93a9c520bf0851948dd3ba6cf11336764891ce2b62b6b6a92b6e', + 'sha256-ungz' => '35b1eb4a3ac6a0fb878c621442acadd34e563d141bba6aab7915b44fe526aa60', + 'size' => 99250 + }, + 'Unicode-String-2.09.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'c922508ae822f0b351b1c9bca5d2102e', + 'mtime' => '2005-10-26', + 'sha256' => '21e9550ee718626ae20b8893e8551c3f8a9f112711676d6e63950c6ae3e53029', + 'size' => 337 + }, + 'Unicode-String-2.09.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '553e68e603723bf7c631f8701ab0d678', + 'md5-ungz' => '5d0b28164acbc556215ad80544679303', + 'mtime' => '2005-10-26', + 'sha256' => 'c817bedb954ea2d488bade56059028b99e0198f6826482e2f68fd6d78653faad', + 'sha256-ungz' => '493ac436d019a19d9e3bbee4637d700508048f4a3497f639162a3cb1bf65b2c4', + 'size' => 122705 + }, + 'WWW-RobotRules-6.00.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'ea67689c14c8ff44495160ce18681927', + 'mtime' => '2011-02-25', + 'sha256' => 'f8e41c0e47278f9d1e25d82d2006f571310cffd7f5b385c7a7934225c5b1ff5e', + 'size' => 738 + }, + 'WWW-RobotRules-6.00.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '4b5f4838bf1de44057b0bd6240b05dd7', + 'md5-ungz' => '48fbbfccdc31df1427d01bb1e3f1b5dd', + 'mtime' => '2011-02-25', + 'sha256' => 'd815bb98bac35fd2f52f5dd027f564c05bc6431f0b18ab2dd40e6582a236aabb', + 'sha256-ungz' => '12b717195a6ea19bdd64e79237f814e3c6f94cb6dd60d46ec1e45538a85df7c0', + 'size' => 8841 + }, + 'WWW-RobotRules-6.01.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0edaa2730c2974655a5bcf2d9e4210b6', + 'mtime' => '2011-03-13', + 'sha256' => '886d170ac791b9a3de8e016572e4f312024a4eb5c4d23bc35f7cc2aabf7b14c3', + 'size' => 765 + }, + 'WWW-RobotRules-6.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'b1252da49727320a1b5e20b3521d2499', + 'md5-ungz' => '7a0ceebddf08ac6d9c3add5f933f0e25', + 'mtime' => '2011-03-13', + 'sha256' => 'f817e3e982c9d869c7796bcb5737c3422c2272355424acd162d0f3b132bec9d3', + 'sha256-ungz' => '78fd207a04191231f406db92db5b2733a3d8761fc6afafc98bc0cc745a5657e8', + 'size' => 9047 + }, + 'WWW-RobotRules-6.02.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '97fa9a9632995a0e0d5a85af8742095e', + 'mtime' => '2012-02-18', + 'sha256' => 'da7d2d8ded94a975e82e9c28a0db966efd7465007c590e53b41f92c0425b2f4c', + 'size' => 744 + }, + 'WWW-RobotRules-6.02.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'b7186e8b8b3701e70c22abf430742403', + 'md5-ungz' => 'ea618e6acb1d7ce93723f6c723212acf', + 'mtime' => '2012-02-18', + 'sha256' => '46b502e7a288d559429891eeb5d979461dd3ecc6a5c491ead85d165b6e03a51e', + 'sha256-ungz' => 'b715540d7bbae8480958cf99d95fb8bd0bcd6dd0071360d5806f732a53ced013', + 'size' => 9059 + }, + 'illguts-0.09.pdf' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '699883d9ab5580b84f793eede32e9389', + 'mtime' => '2007-08-21', + 'sha256' => '89fb6a5d1cdc04e9083487d30f19040dcc25fff08325b5b3cd2207e23708af1e', + 'size' => 161682 + }, + 'illguts-0.09.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'c8030f7a62c69a40abae5e346a47ca54', + 'md5-ungz' => '0f1de4238de8aaafb8fd72bd38ec20ff', + 'mtime' => '1999-11-05', + 'sha256' => '5f3f1286fd997d4e70437c8ac758c2b25498727e128f71fe162ebcf699f0cdd0', + 'sha256-ungz' => '87e18495fdafe80384095147f348f4c5b858b300824b09573c4e3db9fd94f99d', + 'size' => 193534 + }, + 'libwww-perl-5.837.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0c0c9ab65f6b8ccfc7996a5d9e85ef74', + 'mtime' => '2010-09-20', + 'sha256' => 'dac73f775e08183789db358868f4322723f268a3798dd532911012d06df92b14', + 'size' => 1068 + }, + 'libwww-perl-5.837.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '9bbf1bce482b0bac98bb4f04253c03d0', + 'md5-ungz' => '5fed809bbb7511edde7d23eab9e8fc14', + 'mtime' => '2010-09-20', + 'sha256' => '4f651e9241df8fccd2eeb125eb6a3bfddcfc65f49adb5469313fe4a95aaded45', + 'sha256-ungz' => 'be293598d4e8ecf1c8a385d9e9bd2c2840f1e9670f7932bc402cbff6ae79e6f6', + 'size' => 270223 + }, + 'libwww-perl-6.05.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'c64eafbe66c2f2c6b865774cb424ace4', + 'mtime' => '2013-03-11', + 'sha256' => '49697f419c166b3850dc787e30809f569b071622bcde981899a175222adebfa7', + 'size' => 1446 + }, + 'libwww-perl-6.05.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '637d5f1eb61336ca2caa6e026b382f87', + 'md5-ungz' => '3fb9af39f07c266e4aa96fbada96d8c6', + 'mtime' => '2013-03-11', + 'sha256' => '7b25799ff7eec18e8e4e97dc0cad7b2a5b433b50b13feb59d9179173bee78f23', + 'sha256-ungz' => '9bd39a3ada16981d001ae9d152715a731e57b5422994c13be978bfdc52e8bac2', + 'size' => 132505 + }, + 'mylib-1.02.meta' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => 'f796d5039143f394e921ada74005d49d', + 'mtime' => '2008-06-04', + 'sha256' => '8eaf480f8206db91813bd839aec61ae61ac71164cf1639b3d4e0740bc65ecdc5', + 'size' => 370 + }, + 'mylib-1.02.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '88056c5ec87d77fd7ad7ed15432fd660', + 'md5-ungz' => '3e2d16507dd34cec0c8c3e1d18c2a053', + 'mtime' => '2008-06-04', + 'sha256' => 'f5f3e9c1b2064156ab5450ce0b953d3acb1917a07cd605eefe1481b7fff7623b', + 'sha256-ungz' => 'c61506eeae91d84df7c5cae6cef07db7984011269016ed31310a6b95d03f9fe1', + 'size' => 2107 + }, + 'perl-lisp-0.06.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '9527dbc83c9b028df49e02a32fe1e368', + 'md5-ungz' => '96fee2f5466b73c1c987547d6036311e', + 'mtime' => '2004-11-19', + 'sha256' => '9670ab8bf6562d3a945a869d3c802f9d2bb1e078bca3a70f90c95d18e816ab23', + 'sha256-ungz' => '8f5738da4c6e86bf168a69d7077765cb6b8fcb01f39653c254bb763be37eef0c', + 'size' => 14661 + }, + 'perlbench-0.93.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '0cacffd5e03f590202c553f3bc26928d', + 'md5-ungz' => '5da2afcf5b23e597ee7eb18a2edbd4a4', + 'mtime' => '2005-12-30', + 'sha256' => 'cb7c20ecd15d841f5e3ad68d91e898c87a51f9f752f8e3b00a2c09f58a443892', + 'sha256-ungz' => '3b9e8c780ea4b8f56c9e3cd812c94ec50cea773d794d0074b8eafb26f40fbcf5', + 'size' => 152796 + }, + 'pyperl-1.0.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '6e48c2c889bf55c2656e6ed4589854bf', + 'md5-ungz' => '520a8b11e5857656478eaf4399db8958', + 'mtime' => '2001-03-02', + 'sha256' => '6b786ad2e89032d9b0b5e6f75e717f79aed9ae70fa5894c27219c48df6e11ba4', + 'sha256-ungz' => '9ad03ed506e4049b34a02208906e4e962163e870a725c77310b4ac7bf4318f7b', + 'size' => 62089 + }, + 'rlib-0.01.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '97adb786a2329ce21c892f4e52d29740', + 'md5-ungz' => '300f0bf739233ae137e116aad0d6d542', + 'mtime' => '1998-01-13', + 'sha256' => '4a03558c2b413576d3a87b2d784286813abc8d7b63aa130b19f24c0424ae84b1', + 'sha256-ungz' => '7e48e616eb32a1530a2cdc4837a78ee398ec524dfb90ba23d9681c971134356d', + 'size' => 1107 + }, + 'webchat-0.05.tar.gz' => { + 'cpan_path' => 'G/GA/GAAS', + 'md5' => '2200537841e2d93cbfd9c926c0259df2', + 'md5-ungz' => '9bbc8973e2a9bdbe1c9c32a5d217f3ef', + 'mtime' => '1999-11-16', + 'sha256' => '8d1eebe6220381fb694a6a210e4e050bc474e8c91f1c28a4434b2329fe3e1f65', + 'sha256-ungz' => 'df56f0ffbbb6d010ad3c8e66a958de6626bea6009a001f7b1517e1897d34a316', + 'size' => 5279 + } +}; +__END__ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.14 (GNU/Linux) + +iQEcBAEBAgAGBQJhmukJAAoJELahc5BjdgzKHlYH/0s4tHZmrN7OXKtQhALiu0Rm +kDdTBD+7pCag62vfrRM1aSiGpCjV19cfY3yXbYfOrBzVIl7SAbqSIQzSs43dn1VI +McKEJoLQqOfaKy8JJLpIUCg7O67KO8iSg0BDiFzm4Lb578Fs3hmHZ/uLtjI4go4f +jvRn42HOSX68uMJt8aF6sCb2K6ofmhYtevTaNRb155VwaTMhB35V5Lq8Qpju5YxX +RMFpKk/RUKxwGIX3DPluclDoOR0VWiJHl05DqkiyJ1Di8pCYvorpo6ExkzOJBG7H +X3Jwqx6IPK6+Tdjvld1aN9YUftfQTlt3Z1W5yPnorQGfGnday7uLH3mWUQBdTHM= +=aSa8 +-----END PGP SIGNATURE----- diff --git a/.cpan/sources/authors/id/G/GA/GAAS/IO-String-1.08.tar.gz b/.cpan/sources/authors/id/G/GA/GAAS/IO-String-1.08.tar.gz new file mode 100644 index 0000000000..9f911afec7 Binary files /dev/null and b/.cpan/sources/authors/id/G/GA/GAAS/IO-String-1.08.tar.gz differ diff --git a/.cpan/sources/modules/02packages.details.txt.gz b/.cpan/sources/modules/02packages.details.txt.gz new file mode 100644 index 0000000000..c404dc5274 Binary files /dev/null and b/.cpan/sources/modules/02packages.details.txt.gz differ diff --git a/.cpan/sources/modules/03modlist.data.gz b/.cpan/sources/modules/03modlist.data.gz new file mode 100644 index 0000000000..d31f7584c4 Binary files /dev/null and b/.cpan/sources/modules/03modlist.data.gz differ diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..8ef3c954e3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Force all text files to have LF line endings on checkout and commit. +* text eol=lf diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..dd84ea7824 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..bbcbbe7d61 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..9b227fae44 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,84 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '33 8 * * 5' + +jobs: + analyze: + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + # required for all workflows + security-events: write + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + language: [ 'c-cpp' ] + # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] + # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # ℹ️ Command-line programs to run using the OS shell. + # đź“š See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..87b94b1025 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Layout folder +binutils-2.41 +busybox-w32 +cppcheck-2.10 +ctags-6.0.0 +expat-2.5.0 +gcc-13.2.0 +gdb-13.1 +gmp-6.3.0 +libiconv-1.17 +make-4.4.1 +mingw-w64-v11.0.1 +mpc-1.3.1 +mpfr-4.2.1 +nasm-2.15.05 +PDCurses-3.9 +vim90 + +# Build folder +.gnu-windows/bootstrap +.gnu-windows/make +.gnu-windows/ad-installer +*Makefile +*.exe +*.dll \ No newline at end of file diff --git a/.gnu-windows/.gitkeep b/.gnu-windows/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.gnu-windows/ad-installer/GNU Windows.aip b/.gnu-windows/ad-installer/GNU Windows.aip new file mode 100644 index 0000000000..7157d1413e --- /dev/null +++ b/.gnu-windows/ad-installer/GNU Windows.aip @@ -0,0 +1,7837 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gnu-windows/bootstrap/.gitkeep b/.gnu-windows/bootstrap/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.gnu-windows/build.sh b/.gnu-windows/build.sh new file mode 100644 index 0000000000..925026dbda --- /dev/null +++ b/.gnu-windows/build.sh @@ -0,0 +1,482 @@ +#/bin/sh + +ARCH=x86_64-w64-mingw32 + +WORKDIR="$(cd "$(dirname "$0")" && pwd)" +BOOTSTRAP="$WORKDIR/bootstrap" +MAKE_FOLDER="$WORKDIR/make" +SOURCE_CODE="$WORKDIR/src" +GNU_FOLDER="$WORKDIR/.." +PATH="$BOOTSTRAP/bin:${PATH}" + +BINUTILS_VERSION=2.41 +BUSYBOX_VERSION=FRP-5236-g7dff7f376 +CPPCHECK_VERSION=2.10 +CTAGS_VERSION=6.0.0 +EXPAT_VERSION=2.5.0 +GCC_VERSION=13.2.0 +GDB_VERSION=13.1 +GMP_VERSION=6.3.0 +LIBICONV_VERSION=1.17 +MAKE_VERSION=4.4.1 +MINGW_VERSION=11.0.1 +MPC_VERSION=1.3.1 +MPFR_VERSION=4.2.1 +NASM_VERSION=2.15.05 +PDCURSES_VERSION=3.9 +VERSION=1.21.0 +VIM_VERSION=9.0 + +cd $WORKDIR + +# Cross-build system + +#cd $GNU_FOLDER/binutils-$BINUTILS_VERSION +#sed -ri 's/(static bool insert_timestamp = )/\1!/' ld/emultempl/pe*.em + +mkdir $MAKE_FOLDER/x-binutils && cd "$_" +chmod +x $GNU_FOLDER/binutils-$BINUTILS_VERSION/configure +$GNU_FOLDER/binutils-$BINUTILS_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --with-sysroot=$BOOTSTRAP/$ARCH \ + --target=$ARCH \ + --disable-nls \ + --with-static-standard-libraries \ + --disable-multilib \ + && make MAKEINFO=true \ + && make MAKEINFO=true install + +cd $WORKDIR + +#sed -i /OpenThreadToken/d $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-crt/lib32/kernel32.def + +mkdir $MAKE_FOLDER/x-mingw-headers && cd "$_" +chmod +x $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-headers/configure +$GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-headers/configure \ + --prefix=$BOOTSTRAP/$ARCH \ + --host=$ARCH \ + --with-default-msvcrt=msvcrt-os \ + && make \ + && make install + +cd $BOOTSTRAP +ln -s $ARCH mingw + +mkdir $MAKE_FOLDER/x-gcc && cd "$_" +mkdir $BOOTSTRAP/src && cp $SOURCE_CODE/gcc-*.patch $BOOTSTRAP/src/ +#cat $BOOTSTRAP/src/gcc-*.patch | patch -d $GNU_FOLDER/gcc-$GCC_VERSION -p1 +chmod +x $GNU_FOLDER/gcc-$GCC_VERSION/configure +$GNU_FOLDER/gcc-$GCC_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --with-sysroot=$BOOTSTRAP \ + --target=$ARCH \ + --enable-static \ + --disable-shared \ + --with-pic \ + --with-gnu-ld \ + --enable-languages=c,c++ \ + --enable-libgomp \ + --enable-threads=posix \ + --enable-version-specific-runtime-libs \ + --disable-dependency-tracking \ + --disable-nls \ + --disable-lto \ + --disable-multilib \ + CFLAGS_FOR_TARGET="-Os" \ + CXXFLAGS_FOR_TARGET="-Os" \ + LDFLAGS_FOR_TARGET="-s" \ + CFLAGS="-Os" \ + CXXFLAGS="-Os" \ + LDFLAGS="-s" \ + && make all-gcc \ + && make install-gcc + +mkdir -p $BOOTSTRAP/$ARCH/lib \ + && chmod +x $BOOTSTRAP/bin/$ARCH-gcc \ + && CC=$BOOTSTRAP/bin/$ARCH-gcc DESTDIR=$BOOTSTRAP/$ARCH/lib/ sh $SOURCE_CODE/libmemory.c \ + && CC=$BOOTSTRAP/bin/$ARCH-gcc DESTDIR=$BOOTSTRAP/$ARCH/lib/ sh $SOURCE_CODE/libchkstk.S + +mkdir $MAKE_FOLDER/x-mingw-crt && cd "$_" +chmod +x $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-crt/configure +$GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-crt/configure \ + --prefix=$BOOTSTRAP/$ARCH \ + --with-sysroot=$BOOTSTRAP/$ARCH \ + --host=$ARCH \ + --with-default-msvcrt=msvcrt-os \ + --disable-dependency-tracking \ + --disable-lib32 \ + --enable-lib64 \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +mkdir $MAKE_FOLDER/x-winpthreads && cd "$_" +chmod +x $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-libraries/winpthreads/configure +$GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-libraries/winpthreads/configure \ + --prefix=$BOOTSTRAP/$ARCH \ + --with-sysroot=$BOOTSTRAP/$ARCH \ + --host=$ARCH \ + --enable-static \ + --disable-shared \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +cd $MAKE_FOLDER/x-gcc +make +make install + +# Cross-compile GCC + +mkdir $MAKE_FOLDER/binutils && cd "$_" +$GNU_FOLDER/binutils-$BINUTILS_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --with-sysroot=$BOOTSTRAP/$ARCH \ + --host=$ARCH \ + --target=$ARCH \ + --disable-nls \ + --with-static-standard-libraries \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make MAKEINFO=true \ + && make MAKEINFO=true install + +mkdir $MAKE_FOLDER/gmp && cd "$_" +chmod +x $GNU_FOLDER/gmp-$GMP_VERSION/configure +$GNU_FOLDER/gmp-$GMP_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --host=$ARCH \ + --enable-static \ + --disable-shared \ + CFLAGS="-Os" \ + CXXFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +mkdir $MAKE_FOLDER/mpfr && cd "$_" +chmod +x $GNU_FOLDER/mpfr-$MPFR_VERSION/configure +$GNU_FOLDER/mpfr-$MPFR_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --host=$ARCH \ + --with-gmp-include=$BOOTSTRAP/include \ + --with-gmp-lib=$BOOTSTRAP/lib \ + --enable-static \ + --disable-shared \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +mkdir $MAKE_FOLDER/mpc && cd "$_" +chmod +x $GNU_FOLDER/mpc-$MPC_VERSION/configure +$GNU_FOLDER/mpc-$MPC_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --host=$ARCH \ + --with-gmp-include=$BOOTSTRAP/include \ + --with-gmp-lib=$BOOTSTRAP/lib \ + --with-mpfr-include=$BOOTSTRAP/include \ + --with-mpfr-lib=$BOOTSTRAP/lib \ + --enable-static \ + --disable-shared \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +mkdir $MAKE_FOLDER/mingw-headers && cd "$_" +chmod +x $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-headers/configure +$GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-headers/configure \ + --prefix=$BOOTSTRAP/$ARCH \ + --host=$ARCH \ + --with-default-msvcrt=msvcrt-os \ + && make \ + && make install + +mkdir $MAKE_FOLDER/mingw-crt && cd "$_" +chmod +x $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-crt/configure +$GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-crt/configure \ + --prefix=$BOOTSTRAP/$ARCH \ + --with-sysroot=$BOOTSTRAP/$ARCH \ + --host=$ARCH \ + --with-default-msvcrt=msvcrt-os \ + --disable-dependency-tracking \ + --disable-lib32 \ + --enable-lib64 \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +mkdir $MAKE_FOLDER/winpthreads && cd "$_" +chmod +x $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-libraries/winpthreads/configure +$GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-libraries/winpthreads/configure \ + --prefix=$BOOTSTRAP/$ARCH \ + --with-sysroot=$BOOTSTRAP/$ARCH \ + --host=$ARCH \ + --enable-static \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +mkdir $MAKE_FOLDER/gcc && cd "$_" +chmod +x $GNU_FOLDER/gcc-$GCC_VERSION/configure +$GNU_FOLDER/gcc-$GCC_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --with-sysroot=$BOOTSTRAP/$ARCH \ + --with-native-system-header-dir=/include \ + --target=$ARCH \ + --host=$ARCH \ + --enable-static \ + --disable-shared \ + --with-pic \ + --with-gnu-ld \ + --with-gmp-include=$BOOTSTRAP/include \ + --with-gmp-lib=$BOOTSTRAP/lib \ + --with-mpc-include=$BOOTSTRAP/include \ + --with-mpc-lib=$BOOTSTRAP/lib \ + --with-mpfr-include=$BOOTSTRAP/include \ + --with-mpfr-lib=$BOOTSTRAP/lib \ + --enable-languages=c,c++ \ + --enable-libgomp \ + --enable-lto \ + --enable-threads=posix \ + --enable-version-specific-runtime-libs \ + --disable-dependency-tracking \ + --disable-lto \ + --disable-multilib \ + --disable-nls \ + --disable-win32-registry \ + --enable-mingw-wildcard \ + CFLAGS_FOR_TARGET="-Os" \ + CXXFLAGS_FOR_TARGET="-Os" \ + LDFLAGS_FOR_TARGET="-s" \ + CFLAGS="-Os" \ + CXXFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install \ + && $BOOTSTRAP/bin/$ARCH-gcc -DEXE=g++.exe -DCMD=c++ \ + -Os -fno-asynchronous-unwind-tables \ + -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/c++.exe \ + $WORKDIR/src/alias.c -lkernel32 + +$BOOTSTRAP/bin/$ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ + -Os -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/cc.exe $SOURCE_CODE/alias.c -lkernel32 \ + && $BOOTSTRAP/bin/$ARCH-gcc -DEXE=gcc.exe -DCMD="cc -std=c99" \ + -Os -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/c99.exe $SOURCE_CODE/alias.c -lkernel32 \ + && $BOOTSTRAP/bin/$ARCH-gcc -DEXE=gcc.exe -DCMD="cc -ansi" \ + -Os -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/c89.exe $SOURCE_CODE/alias.c -lkernel32 \ + && printf '%s\n' addr2line ar as c++filt cpp dlltool dllwrap elfedit g++ \ + gcc gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool ld nm objcopy \ + objdump ranlib readelf size strings strip windmc windres \ + | xargs -I{} -P$(nproc) \ + $BOOTSTRAP/bin/$ARCH-gcc -DEXE={}.exe -DCMD=$ARCH-{} \ + -Os -fno-asynchronous-unwind-tables \ + -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/$ARCH-{}.exe $SOURCE_CODE/alias.c -lkernel32 + +mkdir $SOURCE_CODE/mingw-tools-gendef && cd "$_" +cp $SOURCE_CODE/gendef-silent.patch $BOOTSTRAP/src/ +#patch -d $GNU_FOLDER/mingw-w64-v$MINGW_VERSION -p1 <$BOOTSTRAP/src/gendef-silent.patch \ +chmod +x $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-tools/gendef/configure +$GNU_FOLDER/mingw-w64-v$MINGW_VERSION/mingw-w64-tools/gendef/configure \ + --host=$ARCH \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && cp gendef.exe $BOOTSTRAP/bin/ + +mkdir $MAKE_FOLDER/expat && cd "$_" +chmod +x $GNU_FOLDER/expat-$EXPAT_VERSION/configure +$GNU_FOLDER/expat-$EXPAT_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --host=$ARCH \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +cd $GNU_FOLDER/PDCurses-$PDCURSES_VERSION +make -C wincon \ + CC=$BOOTSTRAP/bin/$ARCH-gcc AR=$ARCH-ar CFLAGS="-I.. -Os -DPDC_WIDE" pdcurses.a \ + && cp wincon/pdcurses.a $BOOTSTRAP/lib/libcurses.a \ + && cp curses.h $BOOTSTRAP/include + +mkdir $MAKE_FOLDER/libiconv && cd "$_" +chmod +x $GNU_FOLDER/libiconv-$LIBICONV_VERSION/configure +$GNU_FOLDER/libiconv-$LIBICONV_VERSION/configure \ + --prefix=$BOOTSTRAP \ + --host=$ARCH \ + --disable-nls \ + --disable-shared \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && make install + +mkdir $MAKE_FOLDER/gdb && cd "$_" +cp $SOURCE_CODE/gdb-*.patch $BOOTSTRAP/src/ +#cat $SOURCE_CODE/gdb-*.patch | patch -d $GNU_FOLDER/gdb-$GDB_VERSION -p1 \ +# && sed -i 's/quiet = 0/quiet = 1/' $GNU_FOLDER/gdb-$GDB_VERSION/gdb/main.c \ +chmod +x $GNU_FOLDER/gdb-$GDB_VERSION/configure +$GNU_FOLDER/gdb-$GDB_VERSION/configure \ + --host=$ARCH \ + --enable-tui \ + CFLAGS="-Os -DPDC_WIDE -I$BOOTSTRAP/include" \ + CXXFLAGS="-Os -DPDC_WIDE -I$BOOTSTRAP/include" \ + LDFLAGS="-s -L$BOOTSTRAP/lib" \ + && make MAKEINFO=true \ + && cp gdb/.libs/gdb.exe gdbserver/gdbserver.exe $BOOTSTRAP/bin/ + +mkdir $MAKE_FOLDER/make && cd "$_" +chmod +x $GNU_FOLDER/make-$MAKE_VERSION/configure +$GNU_FOLDER/make-$MAKE_VERSION/configure \ + --host=$ARCH \ + --disable-nls \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && make \ + && cp make.exe $BOOTSTRAP/bin/ \ + && $BOOTSTRAP/bin/$ARCH-gcc -DEXE=make.exe -DCMD=make \ + -Os -fno-asynchronous-unwind-tables \ + -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/mingw32-make.exe $SOURCE_CODE/alias.c -lkernel32 + +cd $GNU_FOLDER/busybox-w32 +#cp $SOURCE_CODE/busybox-* $BOOTSTRAP/src/ +cat $SOURCE_CODE/busybox-*.patch | patch -p1 +make mingw64_defconfig \ + && sed -ri 's/^(CONFIG_AR)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_ASCII)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_DPKG\w*)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_FTP\w*)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_LINK)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_MAN)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_MAKE)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_PDPMAKE)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_RPM\w*)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_STRINGS)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_TEST2)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_TSORT)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_UNLINK)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_VI)=y/\1=n/' .config \ + && sed -ri 's/^(CONFIG_XXD)=y/\1=n/' .config \ + && make CROSS_COMPILE=$ARCH- \ + CONFIG_EXTRA_CFLAGS="-D_WIN32_WINNT=0x502" \ + && cp busybox.exe $BOOTSTRAP/bin/ + +cd $BOOTSTRAP/bin + +$BOOTSTRAP/bin/$ARCH-gcc -Os -fno-asynchronous-unwind-tables -Wl,--gc-sections -s \ + -nostdlib -o alias.exe $SOURCE_CODE/busybox-alias.c -lkernel32 \ + && printf '%s\n' arch ash awk base32 base64 basename bash bc bunzip2 bzcat \ + bzip2 cal cat chattr chmod cksum clear cmp comm cp cpio crc32 cut date \ + dc dd df diff dirname dos2unix du echo ed egrep env expand expr factor \ + false fgrep find fold free fsync getopt grep groups gunzip gzip hd \ + head hexdump httpd iconv id inotifyd install ipcalc jn kill killall \ + lash less ln logname ls lsattr lzcat lzma lzop lzopcat md5sum mkdir \ + mktemp mv nc nl nproc od paste patch pgrep pidof pipe_progress pkill \ + printenv printf ps pwd readlink realpath reset rev rm rmdir sed seq sh \ + sha1sum sha256sum sha3sum sha512sum shred shuf sleep sort split \ + ssl_client stat su sum sync tac tail tar tee test time timeout touch \ + tr true truncate ts ttysize uname uncompress unexpand uniq unix2dos \ + unlzma unlzop unxz unzip uptime usleep uudecode uuencode watch \ + wc wget which whoami whois xargs xz xzcat yes zcat \ + | xargs -I{} cp alias.exe $BOOTSTRAP/bin/{}.exe + +cd $GNU_FOLDER/vim90/src +ARCH= make -f Make_ming.mak \ + OPTIMIZE=SIZE STATIC_STDCPLUS=yes HAS_GCC_EH=no \ + UNDER_CYGWIN=yes CROSS=yes CROSS_COMPILE=$ARCH- \ + FEATURES=HUGE VIMDLL=yes NETBEANS=no WINVER=0x0501 \ + && $ARCH-strip vimrun.exe \ + && rm -rf ../runtime/tutor/tutor.* \ + && cp -r ../runtime $BOOTSTRAP/share/vim \ + && cp vimrun.exe gvim.exe vim.exe *.dll $BOOTSTRAP/share/vim/ \ + && cp xxd/xxd.exe $BOOTSTRAP/bin \ + && printf '@set SHELL=\r\n@start "" "%%~dp0/../share/vim/gvim.exe" %%*\r\n' \ + >$BOOTSTRAP/bin/gvim.bat \ + && printf '@set SHELL=\r\n@"%%~dp0/../share/vim/vim.exe" %%*\r\n' \ + >$BOOTSTRAP/bin/vim.bat \ + && printf '@set SHELL=\r\n@"%%~dp0/../share/vim/vim.exe" %%*\r\n' \ + >$BOOTSTRAP/bin/vi.bat \ + && printf '@vim -N -u NONE "+read %s" "+write" "%s"\r\n' \ + '$VIMRUNTIME/tutor/tutor' '%TMP%/tutor%RANDOM%' \ + >$BOOTSTRAP/bin/vimtutor.bat + +# NOTE: nasm's configure script is broken, so no out-of-source build +chmod +x $GNU_FOLDER/nasm-$NASM_VERSION/configure && chmod +x $GNU_FOLDER/nasm-$NASM_VERSION/autogen.sh +cd $GNU_FOLDER/nasm-$NASM_VERSION/ +$GNU_FOLDER/nasm-$NASM_VERSION/autogen.sh +mkdir $MAKE_FOLDER/nasm-$NASM_VERSION && cd "$_" +$GNU_FOLDER/nasm-$NASM_VERSION/configure \ + --host=$ARCH \ + CFLAGS="-Os" \ + LDFLAGS="-s" \ + && mkdir include \ + && make \ + && cp nasm.exe ndisasm.exe $BOOTSTRAP/bin + +cd $GNU_FOLDER/ctags-$CTAGS_VERSION +sed -i RT_MANIFEST/d win32/ctags.rc \ + && make -f mk_mingw.mak CC=gcc packcc.exe \ + && make -f mk_mingw.mak \ + CC=$BOOTSTRAP/bin/$ARCH-gcc WINDRES=$ARCH-windres \ + OPT= CFLAGS=-Os LDFLAGS=-s \ + && cp ctags.exe $BOOTSTRAP/bin/ + +cd $GNU_FOLDER/cppcheck-$CPPCHECK_VERSION +cp $SOURCE_CODE/cppcheck* $BOOTSTRAP/src/ +cat $BOOTSTRAP/src/cppcheck-*.patch | patch -p1 \ + && make -f $BOOTSTRAP/src/cppcheck.mak CXX=$ARCH-g++ \ + && mkdir $BOOTSTRAP/share/cppcheck/ \ + && cp -r cppcheck.exe cfg/ $BOOTSTRAP/share/cppcheck \ + && $BOOTSTRAP/bin/$ARCH-gcc -DEXE=../share/cppcheck/cppcheck.exe -DCMD=cppcheck \ + -Os -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/cppcheck.exe $SOURCE_CODE/alias.c -lkernel32 + + +#pack-up + +cd $WORKDIR + +cp -r $SOURCE_CODE/* $BOOTSTRAP/src #?? +printf "id ICON \"$BOOTSTRAP/src/gnu-windows.ico\"" >gnu-windows.rc \ + && $BOOTSTRAP/bin/$ARCH-windres -o gnu-windows.o gnu-windows.rc \ + && $BOOTSTRAP/bin/$ARCH-gcc \ + -Os -fno-asynchronous-unwind-tables \ + -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/debugbreak.exe $BOOTSTRAP/src/debugbreak.c \ + -lkernel32 \ + && $BOOTSTRAP/bin/$ARCH-gcc \ + -Os -fwhole-program -fno-asynchronous-unwind-tables \ + -Wl,--gc-sections -s -nostdlib -DPKG_CONFIG_PREFIX="\"/$ARCH\"" \ + -o $BOOTSTRAP/bin/pkg-config.exe $BOOTSTRAP/src/pkg-config.c \ + -lkernel32 \ + && $BOOTSTRAP/bin/$ARCH-gcc \ + -Os -fno-asynchronous-unwind-tables -fno-builtin -Wl,--gc-sections \ + -s -nostdlib -o $BOOTSTRAP/bin/vc++filt.exe $BOOTSTRAP/src/vc++filt.c \ + -lkernel32 -lshell32 -ldbghelp \ + && $BOOTSTRAP/bin/$ARCH-gcc -DEXE=pkg-config.exe -DCMD=pkg-config \ + -Os -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib \ + -o $BOOTSTRAP/bin/$ARCH-pkg-config.exe $BOOTSTRAP/src/alias.c -lkernel32 \ + && mkdir -p $BOOTSTRAP/$ARCH/lib/pkgconfig \ + && cp $GNU_FOLDER/mingw-w64-v$MINGW_VERSION/COPYING.MinGW-w64-runtime/COPYING.MinGW-w64-runtime.txt \ + $BOOTSTRAP/ \ + && printf "\n===========\nwinpthreads\n===========\n\n" \ + >>$BOOTSTRAP/COPYING.MinGW-w64-runtime.txt . \ + && echo $VERSION >$BOOTSTRAP/VERSION.txt + +cd $WORKDIR + +cp $BOOTSTRAP/$ARCH/bin/libwinpthread-1.dll $BOOTSTRAP/bin/libwinpthread-1.dll + +echo -e -n "Build sucessfully. Your GNU Windows is under path: $BOOTSTRAP" diff --git a/.gnu-windows/make/.gitkeep b/.gnu-windows/make/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.gnu-windows/src/.dirstamp b/.gnu-windows/src/.dirstamp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.gnu-windows/src/SHA256SUMS b/.gnu-windows/src/SHA256SUMS new file mode 100644 index 0000000000..3503e1690d --- /dev/null +++ b/.gnu-windows/src/SHA256SUMS @@ -0,0 +1,16 @@ +ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450 binutils-2.41.tar.xz +e9376e8848200ca085bd74804861f2904e12916e836a23d53bb41d166d38ac0d busybox-w32-FRP-5236-g7dff7f376.tgz +785dcbf711048dfe43ae920b6eff2eeebb4a096e88188a40e173ca4c030f57c3 cppcheck-2.10.tar.gz +71229a73f25529c9e3dabb2cb7310c55405d31caee8e8a9ab5c71b2406d4005a ctags-6.0.0.tar.gz +ef2420f0232c087801abf705e89ae65f6257df6b7931d37846a193ef2e8cdcbe expat-2.5.0.tar.xz +e275e76442a6067341a27f04c5c6b83d8613144004c0413528863dc6b5c743da gcc-13.2.0.tar.xz +115ad5c18d69a6be2ab15882d365dda2a2211c14f480b3502c6eba576e2e95a0 gdb-13.1.tar.xz +a3c2b80201b89e68616f4ad30bc66aee4927c3ce50e33929ca819d5c43538898 gmp-6.3.0.tar.xz +8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313 libiconv-1.17.tar.gz +dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3 make-4.4.1.tar.gz +3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10 mingw-w64-v11.0.1.tar.bz2 +ab642492f5cf882b74aa0cb730cd410a81edcdbec895183ce930e706c1c759b8 mpc-1.3.1.tar.gz +277807353a6726978996945af13e52829e3abd7a9a5b7fb2793894e18f1fcbb2 mpfr-4.2.1.tar.xz +3caf6729c1073bf96629b57cee31eeb54f4f8129b01902c73428836550b30a3f nasm-2.15.05.tar.xz +590dbe0f5835f66992df096d3602d0271103f90cf8557a5d124f693c2b40d7ec PDCurses-3.9.tar.gz +a6456bc154999d83d0c20d968ac7ba6e7df0d02f3cb6427fb248660bacfb336e vim-9.0.tar.bz2 diff --git a/.gnu-windows/src/alias.c b/.gnu-windows/src/alias.c new file mode 100644 index 0000000000..91fc7b8028 --- /dev/null +++ b/.gnu-windows/src/alias.c @@ -0,0 +1,225 @@ +// Well-behaved command line aliases for gnu-windows +// +// Unlike batch script aliases, this program will not produce an annoying +// and useless "Terminate batch job (Y/N)" prompt. When compiling, define +// EXE as the target executable (relative or absolute path), and define CMD +// as the argv[0] replacement, including additional arguments. +// +// $ gcc -DEXE="target.exe" -DCMD="argv0 argv1" +// -nostartfiles -fno-builtin -o alias.exe alias.c +// +// This is free and unencumbered software released into the public domain. + +#define sizeof(x) (i32)sizeof(x) +#define alignof(x) (i32)_Alignof(x) +#define countof(a) (sizeof(a) / sizeof(*(a))) +#define lengthof(s) (countof(s) - 1) + +#define LSTR(s) XSTR(s) +#define XSTR(s) u ## # s +#define LEXE LSTR(EXE) +#define LCMD LSTR(CMD) + +typedef __UINT8_TYPE__ u8; +typedef signed short i16; +typedef signed int b32; +typedef signed int i32; +typedef unsigned int u32; +typedef unsigned char byte; +typedef __UINTPTR_TYPE__ uptr; +typedef __SIZE_TYPE__ usize; +typedef unsigned short char16_t; // for GDB +typedef char16_t c16; + +// Win32 + +#define MAX_PATH 260 +#define MAX_CMDLINE (1<<15) + +typedef struct {} *handle; + +typedef struct { + u32 cb; + uptr a, b, c; + i32 d, e, f, g, h, i, j, k; + i16 l, m; + uptr n, o, p, q; +} si; + +typedef struct { + handle process; + handle thread; + u32 pid; + u32 tid; +} pi; + +#define W32 __attribute((dllimport, stdcall)) +W32 b32 CreateProcessW(c16*,c16*,void*,void*,b32,u32,c16*,c16*,si*,pi*); +W32 void ExitProcess(u32) __attribute((noreturn)); +W32 c16 *GetCommandLineW(void); +W32 i32 GetExitCodeProcess(handle, u32 *); +W32 u32 GetFullPathNameW(c16 *, u32, c16 *, c16 *); +W32 u32 GetModuleFileNameW(handle, c16 *, u32); +W32 handle GetStdHandle(u32); +W32 byte *VirtualAlloc(byte *, usize, u32, u32); +W32 b32 VirtualFree(byte *, usize, u32); +W32 u32 WaitForSingleObject(handle, u32); +W32 b32 WriteFile(handle, u8 *, u32, u32 *, void *); + +// Application + +#define ERR(s) "gnu-windows (alias): " s "\n" + +#define new(h, t, n) (t *)alloc(h, sizeof(t), alignof(t), n) +__attribute((malloc)) +__attribute((alloc_align(3))) +__attribute((alloc_size(2, 4))) +static byte *alloc(byte **heap, i32 size, i32 align, i32 count) +{ + *heap += -(uptr)*heap & (align - 1); + byte *p = *heap; + *heap += size * count; + return p; +} + +typedef struct { + c16 *buf; + i32 len; + i32 cap; + b32 err; +} c16buf; + +static void append(c16buf *b, c16 *s, i32 len) +{ + i32 avail = b->cap - b->len; + i32 count = availbuf[b->len+i] = s[i]; + } + b->len += count; + b->err |= avail < len; +} + +// Find the end of argv[0]. +static c16 *findargs(c16 *s) +{ + if (s[0] == '"') { + for (s++;; s++) { // quoted argv[0] + switch (*s) { + case 0: return s; + case '"': return s + 1; + } + } + } else { + for (;; s++) { // unquoted argv[0] + switch (*s) { + case 0: + case '\t': + case ' ': return s; + } + } + } +} + +static i32 c16len(c16 *s) +{ + i32 len = 0; + for (; s[len]; len++) {} + return len; +} + +static u32 fatal(u8 *msg, i32 len) +{ + handle stderr = GetStdHandle(-12); + u32 dummy; + WriteFile(stderr, msg, len, &dummy, 0); + return 0x17e; +} + +static void getmoduledir(c16buf *b) +{ + c16 path[MAX_PATH]; + u32 len = GetModuleFileNameW(0, path, countof(path)); + for (; len; len--) { + switch (path[len-1]) { + case '/': case '\\': + append(b, path, len); + return; + } + } +} + +static si *newstartupinfo(byte **heap) +{ + si *s = new(heap, si, 1); + s->cb = sizeof(si); + return s; +} + +static i32 aliasmain(void) +{ + byte *heap_start = VirtualAlloc(0, 1<<18, 0x3000, 4); + byte *heap = heap_start; + if (!heap) { + static const u8 msg[] = ERR("out of memory"); + return fatal((u8 *)msg, lengthof(msg)); + } + + // Construct a path to the .exe + c16buf *exe = new(&heap, c16buf, 1); + exe->cap = 2*MAX_PATH; // concatenating two paths + exe->buf = new(&heap, c16, exe->cap); + if (LEXE[1] != ':') { // relative path? + getmoduledir(exe); + } + append(exe, LEXE, countof(LEXE)); + if (exe->err) { + static const u8 msg[] = ERR(".exe path too long"); + return fatal((u8 *)msg, lengthof(msg)); + } + + // Try to collapse relative components + if (LEXE[0] == '.') { // relative components? + c16buf *tmp = new(&heap, c16buf, 1); + tmp->buf = new(&heap, c16, MAX_PATH); + tmp->cap = MAX_PATH; + tmp->len = GetFullPathNameW(exe->buf, tmp->cap, tmp->buf, 0); + if (tmp->len>0 && tmp->lencap) { + tmp->len++; // include null terminator + *exe = *tmp; + } + } + + // Construct a new command line string + c16buf *cmd = new(&heap, c16buf, 1); + cmd->cap = MAX_CMDLINE; + cmd->buf = new(&heap, c16, cmd->cap); + append(cmd, LCMD, lengthof(LCMD)); + c16 *args = findargs(GetCommandLineW()); + append(cmd, args, c16len(args)+1); + if (cmd->err) { + static const u8 msg[] = ERR("command line too long"); + return fatal((u8 *)msg, lengthof(msg)); + } + + si *si = newstartupinfo(&heap); + pi pi; + if (!CreateProcessW(exe->buf, cmd->buf, 0, 0, 1, 0, 0, 0, si, &pi)) { + static const u8 msg[] = ERR("could not start process\n"); + return fatal((u8 *)msg, lengthof(msg)); + } + + // Wait for child to exit + VirtualFree(heap_start, 0, 0x8000); + u32 ret; + WaitForSingleObject(pi.process, -1); + GetExitCodeProcess(pi.process, &ret); + return ret; +} + +__attribute((force_align_arg_pointer)) +void mainCRTStartup(void) +{ + u32 r = aliasmain(); + ExitProcess(r); +} diff --git a/.gnu-windows/src/busybox-000-disable-beep.patch b/.gnu-windows/src/busybox-000-disable-beep.patch new file mode 100644 index 0000000000..9c6a17bae6 --- /dev/null +++ b/.gnu-windows/src/busybox-000-disable-beep.patch @@ -0,0 +1,10 @@ +--- a/libbb/lineedit.c ++++ b/libbb/lineedit.c +@@ -488,7 +488,6 @@ + + static void beep(void) + { +- bb_putchar('\007'); + } + + /* Full or last/sole prompt line, reset edit cursor, calculate terminal cursor. diff --git a/.gnu-windows/src/busybox-001-disable-empty-complete.patch b/.gnu-windows/src/busybox-001-disable-empty-complete.patch new file mode 100644 index 0000000000..e392bd0b53 --- /dev/null +++ b/.gnu-windows/src/busybox-001-disable-empty-complete.patch @@ -0,0 +1,17 @@ +--- a/libbb/lineedit.c ++++ b/libbb/lineedit.c +@@ -860,6 +860,14 @@ + const char *basecmd; + char *dirbuf = NULL; + ++ /* Discovering all commands in PATH is painfully expensive (typically ++ * several seconds) on Windows where file access is slow, so don't do ++ * it. Worse, due to an alt-tab handling bug in the Windows console ++ * it's very easy to activate this completion by accident. ++ */ ++ if (type == FIND_EXE_ONLY && !command[0]) ++ return 0; ++ + npaths = 1; + path1[0] = (char*)"."; + diff --git a/.gnu-windows/src/busybox-alias.c b/.gnu-windows/src/busybox-alias.c new file mode 100644 index 0000000000..60ed0ad024 --- /dev/null +++ b/.gnu-windows/src/busybox-alias.c @@ -0,0 +1,122 @@ +// busybox-w32 command alias +// Starts the adjacent busybox.exe with an unmodified command line. +// $ cc -nostartfiles -fno-builtin -o COMMAND busybox-alias.c +// This is free and unencumbered software released into the public domain. + +#define sizeof(x) (i32)sizeof(x) +#define countof(a) (sizeof(a) / sizeof(*(a))) +#define lengthof(s) (countof(s) - 1) + +typedef __UINT8_TYPE__ u8; +typedef signed short i16; +typedef signed int b32; +typedef signed int i32; +typedef unsigned int u32; +typedef unsigned short char16_t; // for GDB +typedef char16_t c16; + +#define MAX_PATH 260 + +typedef struct {} *handle; + +typedef struct { + u32 cb; + void *a, *b, *c; + i32 d, e, f, g, h, i, j, k; + i16 l, m; + void *n, *o, *p, *q; +} si; + +typedef struct { + handle process; + handle thread; + u32 pid; + u32 tid; +} pi; + +#define W32 __attribute((dllimport, stdcall)) +W32 b32 CreateProcessW(c16*,c16*,void*,void*,b32,u32,c16*,c16*,si*,pi*); +W32 void ExitProcess(u32) __attribute((noreturn)); +W32 c16 *GetCommandLineW(void); +W32 i32 GetExitCodeProcess(handle, u32 *); +W32 u32 GetModuleFileNameW(handle, c16 *, u32); +W32 handle GetStdHandle(u32); +W32 u32 WaitForSingleObject(handle, u32); +W32 b32 WriteFile(handle, u8 *, u32, u32 *, void *); + +typedef struct { + c16 *buf; + i32 len; + i32 cap; + b32 err; +} c16buf; + +static void append(c16buf *b, c16 *buf, i32 len) +{ + i32 avail = b->cap - b->len; + i32 count = availbuf + b->len; + for (i32 i = 0; i < count; i++) { + dst[i] = buf[i]; + } + b->len += count; + b->err |= count < len; +} + +static void getmoduledir(c16buf *b) +{ + c16 path[MAX_PATH]; + u32 len = GetModuleFileNameW(0, path, countof(path)); + for (; len; len--) { + switch (path[len-1]) { + case '/': case '\\': + append(b, path, len-1); + return; + } + } +} + +static u32 fatal(u8 *msg, i32 len) +{ + handle stderr = GetStdHandle(-12); + u32 dummy; + WriteFile(stderr, msg, len, &dummy, 0); + return 0x17e; +} + +static u32 run(void) +{ + c16 buf[MAX_PATH]; + c16buf exe = {}; + exe.buf = buf; + exe.cap = countof(buf); + + getmoduledir(&exe); + c16 busybox[] = u"\\busybox.exe"; + append(&exe, busybox, countof(busybox)); + if (exe.err) { + static u8 msg[] = "gnu-windows: busybox.exe path too long\n"; + return fatal(msg, lengthof(msg)); + } + + si si = {}; + si.cb = sizeof(si); + pi pi; + c16 *cmdline = GetCommandLineW(); + if (!CreateProcessW(exe.buf, cmdline, 0, 0, 1, 0, 0, 0, &si, &pi)) { + static u8 msg[] = "gnu-windows: could not start busybox.exe\n"; + return fatal(msg, lengthof(msg)); + } + + u32 ret; + WaitForSingleObject(pi.process, -1); + GetExitCodeProcess(pi.process, &ret); + return ret; +} + +__attribute((force_align_arg_pointer)) +void mainCRTStartup(void) +{ + u32 r = run(); + ExitProcess(r); +} diff --git a/.gnu-windows/src/cppcheck-gcc13.patch b/.gnu-windows/src/cppcheck-gcc13.patch new file mode 100644 index 0000000000..4e4953a9bb --- /dev/null +++ b/.gnu-windows/src/cppcheck-gcc13.patch @@ -0,0 +1,18 @@ +GCC 13 has stricter allocator checks: +https://gcc.gnu.org/gcc-13/porting_to.html + +Also, libstdc++ no longer leaks stdint.h definitions. +--- a/lib/mathlib.cpp ++++ b/lib/mathlib.cpp +@@ -25,2 +25,3 @@ + #include ++#include + #include +--- a/lib/smallvector.h ++++ b/lib/smallvector.h +@@ -43,2 +43,5 @@ + {} ++ ++ template TaggedAllocator(const TaggedAllocator); ++ template struct rebind { using other = TaggedAllocator; }; + }; diff --git a/.gnu-windows/src/cppcheck-quiet.patch b/.gnu-windows/src/cppcheck-quiet.patch new file mode 100644 index 0000000000..b471899116 --- /dev/null +++ b/.gnu-windows/src/cppcheck-quiet.patch @@ -0,0 +1,7 @@ +--- a/cli/cmdlineparser.cpp ++++ b/cli/cmdlineparser.cpp +@@ -131,3 +131,3 @@ + #if defined(_WIN64) || defined(_WIN32) +-bool CmdLineParser::SHOW_DEF_PLATFORM_MSG = true; ++bool CmdLineParser::SHOW_DEF_PLATFORM_MSG = false; + #endif diff --git a/.gnu-windows/src/cppcheck.mak b/.gnu-windows/src/cppcheck.mak new file mode 100644 index 0000000000..e7ae46b470 --- /dev/null +++ b/.gnu-windows/src/cppcheck.mak @@ -0,0 +1,8 @@ +ext := $(shell find externals -mindepth 1 -type d) +src := $(shell find cli lib externals -name '*.cpp') +obj := $(src:.cpp=.o) +CXXFLAGS := -w -Os -Ilib $(addprefix -I,$(ext)) +cppcheck.exe: $(obj) + $(CXX) -s -o $@ $(obj) -lshlwapi +cppcheck: $(obj) + $(CXX) -pthread -s -o $@ $(obj) diff --git a/.gnu-windows/src/debugbreak.c b/.gnu-windows/src/debugbreak.c new file mode 100644 index 0000000000..0583548dea --- /dev/null +++ b/.gnu-windows/src/debugbreak.c @@ -0,0 +1,78 @@ +// debugbreak - raise a breakpoint exception in all Win32 debuggees +// +// Graphical programs with windows can rely on the F12 hotkey to break in +// the attached debugger, but console programs have no such hotkey. This +// program fills that gap, breaking your console program mid-execution, +// such as when it's stuck in an infinite loop. +// +// Mingw-w64: +// gcc -Os -fno-asynchronous-unwind-tables -Wl,--gc-sections -s -nostdlib +// -o debugbreak.exe debugbreak.c -lkernel32 +// +// MSVC: +// cl /GS- /Os debugbreak.c +// +// This is free and unencumbered software released into the public domain. +#define WIN32_LEAN_AND_MEAN +#include +#include +#if defined(_MSC_VER) +# pragma comment(lib, "kernel32") +# pragma comment(linker, "/subsystem:console") +#endif + +// Try to put data in .text to pack the binary even smaller. +#if __GNUC__ +# define STATIC __attribute__((section(".text.data"))) static const +#else +# define STATIC static const +#endif + +STATIC char usage[] = +"Usage: debugbreak\n" +" raise a breakpoint exception in all Win32 debuggees\n"; + +int +mainCRTStartup(void) +{ + // Skip argv[0] and space separator. This avoids linking shell32.dll + // for CommandLineToArgvW just to count the arguments. + wchar_t *cmd = GetCommandLineW(); + switch (*cmd) { + default : for (; *cmd && *cmd != '\t' && *cmd != ' '; cmd++); + break; + case '"': for (cmd++; *cmd && *cmd != '"'; cmd++); + cmd += !!*cmd; + } + for (; *cmd == '\t' || *cmd == ' '; cmd++); + + // Print usage and fail if argc > 1. The program's purpose will be + // more discoverable, including responding to -h/--help. + if (*cmd) { + DWORD n; + HANDLE h = GetStdHandle(STD_ERROR_HANDLE); + WriteFile(h, usage, sizeof(usage)-1, &n, 0); + return 1; + } + + // Cannot fail with this configuration + HANDLE s = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + PROCESSENTRY32W p = {sizeof(p)}; + for (BOOL r = Process32FirstW(s, &p); r; r = Process32NextW(s, &p)) { + // 64-bit only requires PROCESS_CREATE_THREAD. 32-bit additionally + // requires PROCESS_VM_OPERATION and PROCESS_VM_WRITE. Since it's + // not clearly documented, just ask for PROCESS_ALL_ACCESS in case + // it changes in the future. + HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, p.th32ProcessID); + if (h) { + // If the process has no debugger attached, nothing happens. + // Otherwise this would require CheckRemoteDebuggerPresent to + // avoid terminating normal processes. + DebugBreakProcess(h); + CloseHandle(h); + } + } + int status = GetLastError() != ERROR_NO_MORE_FILES; + ExitProcess(status); +} diff --git a/.gnu-windows/src/gcc-typeinfo-inline.patch b/.gnu-windows/src/gcc-typeinfo-inline.patch new file mode 100644 index 0000000000..7defb908e3 --- /dev/null +++ b/.gnu-windows/src/gcc-typeinfo-inline.patch @@ -0,0 +1,9 @@ +"std::type_info::operator==(std::info const&) const" must be inlined when +static linking with libstdc++: https://gcc.gnu.org/PR110572 +--- a/gcc/config/i386/cygming.h ++++ b/gcc/config/i386/cygming.h +@@ -148,3 +148,3 @@ along with GCC; see the file COPYING3. If not see + builtin_define ("__GXX_MERGED_TYPEINFO_NAMES=0"); \ +- builtin_define ("__GXX_TYPEINFO_EQUALITY_INLINE=0"); \ ++ builtin_define ("__GXX_TYPEINFO_EQUALITY_INLINE=1"); \ + EXTRA_OS_CPP_BUILTINS (); \ diff --git a/.gnu-windows/src/gdb-000-alternate-main.patch b/.gnu-windows/src/gdb-000-alternate-main.patch new file mode 100644 index 0000000000..c7b1c5da6b --- /dev/null +++ b/.gnu-windows/src/gdb-000-alternate-main.patch @@ -0,0 +1,26 @@ +--- a/gdb/symtab.c ++++ b/gdb/symtab.c +@@ -6300,6 +6300,23 @@ + if (symbol_found_p) + return; + ++ if (gdbarch_osabi (target_gdbarch ()) == GDB_OSABI_WINDOWS) ++ { ++ static const char *const mains[] = { ++ "WinMain", "wWinMain", "main", "wmain", "WinMainCRTStartup", "mainCRTStartup" ++ }; ++ for (const char *main : mains) ++ { ++ struct bound_minimal_symbol msym; ++ msym = lookup_minimal_symbol (main, NULL, NULL); ++ if (msym.minsym != NULL) ++ { ++ set_main_name (main, language_unknown); ++ return; ++ } ++ } ++ } ++ + set_main_name ("main", language_unknown); + } + diff --git a/.gnu-windows/src/gdb-001-confirm-off.patch b/.gnu-windows/src/gdb-001-confirm-off.patch new file mode 100644 index 0000000000..48328481ed --- /dev/null +++ b/.gnu-windows/src/gdb-001-confirm-off.patch @@ -0,0 +1,10 @@ +GDB's definition of "potentially dangerous" is far too broad. This option +creates substantial friction and should be off by default. + +--- a/gdb/top.c ++++ b/gdb/top.c +@@ -132,3 +132,3 @@ + +-bool confirm = true; ++bool confirm = false; + diff --git a/.gnu-windows/src/gendef-silent.patch b/.gnu-windows/src/gendef-silent.patch new file mode 100644 index 0000000000..2668e8c4a2 --- /dev/null +++ b/.gnu-windows/src/gendef-silent.patch @@ -0,0 +1,25 @@ +--- a/mingw-w64-tools/gendef/src/gendef.c ++++ b/mingw-w64-tools/gendef/src/gendef.c +@@ -310,13 +310,11 @@ + && gPEDta->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + gPEPDta = NULL; +- fprintf (stderr, " * [%s] Found PE image\n", fninput); + } + else if (gPEPDta->FileHeader.SizeOfOptionalHeader == IMAGE_SIZEOF_NT_OPTIONAL64_HEADER + && gPEPDta->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + gPEDta = NULL; +- fprintf (stderr, " * [%s] Found PE+ image\n", fninput); + } + else + { +@@ -642,8 +640,6 @@ + fprintf(stderr," * failed to create %s ...\n",fnoutput); + return; + } +- fprintf (fp,";\n; Definition file of %s\n; Automatic generated by gendef\n; written by Kai Tietz 2008\n;\n", +- fndllname); + fprintf (fp,"LIBRARY \"%s\"\nEXPORTS\n",fndllname); + while ((exp = gExp) != NULL) + { diff --git a/.gnu-windows/src/gnu-windows.c b/.gnu-windows/src/gnu-windows.c new file mode 100644 index 0000000000..97ce0d525b --- /dev/null +++ b/.gnu-windows/src/gnu-windows.c @@ -0,0 +1,552 @@ +// Tiny, standalone launcher for gnu_windows +// * Sets $gnu_windows to the release version (-DVERSION) +// * Sets $gnu_windows_HOME to the install location +// * Maybe sets $HOME according to gnu_windows.ini +// * Starts a login shell with "sh -l" +// +// $ gcc -DVERSION="$VERSION" -nostartfiles -fno-builtin +// -o gnu_windows.exe gnu_windows.c +// +// This is free and unencumbered software released into the public domain. + +#define sizeof(a) (size)(sizeof(a)) +#define alignof(a) (size)(_Alignof(a)) +#define countof(a) (sizeof(a) / sizeof(*(a))) +#define lengthof(s) (countof(s) - 1) + +#define new(...) newx(__VA_ARGS__, new4, new3, new2)(__VA_ARGS__) +#define newx(a,b,c,d,e,...) e +#define new2(a, t) (t *)alloc(a, sizeof(t), alignof(t), 1, 0) +#define new3(a, t, n) (t *)alloc(a, sizeof(t), alignof(t), n, 0) +#define new4(a, t, n, f) (t *)alloc(a, sizeof(t), alignof(t), n, f) + +typedef unsigned char byte; +typedef __UINT8_TYPE__ u8; +typedef unsigned short u16; +typedef signed int i32; +typedef signed int b32; +typedef unsigned int u32; +typedef __UINTPTR_TYPE__ uptr; +typedef __PTRDIFF_TYPE__ size; +typedef __SIZE_TYPE__ usize; +typedef unsigned short char16_t; // for GDB +typedef char16_t c16; + +typedef struct {} *handle; + +typedef struct { + u32 cb; + uptr a, b, c; + i32 d, e, f, g, h, i, j, k; + u16 l, m; + uptr n, o, p, q; +} si; + +typedef struct { + handle process; + handle thread; + u32 pid; + u32 tid; +} pi; + +#define MAX_PATH 260 +#define MAX_ENVVAR 32767 +#define MAX_CMDLINE 32767 +#define MAX_INI (1<<18) +#define CP_UTF8 65001 +#define PAGE_READWRITE 0x04 +#define MEM_COMMIT 0x1000 +#define MEM_RESERVE 0x2000 +#define MEM_RELEASE 0x8000 +#define GENERIC_READ 0x80000000 +#define OPEN_EXISTING 3 +#define FILE_SHARE_ALL 7 + +#define W32 __attribute((dllimport,stdcall)) +W32 b32 CloseHandle(handle); +W32 handle CreateFileW(c16 *, u32, u32, void *, u32, u32, handle); +W32 b32 CreateProcessW(c16*,c16*,void*,void*,i32,u32,c16*,c16*,si*,pi*); +W32 void ExitProcess(u32) __attribute((noreturn)); +W32 u32 ExpandEnvironmentStringsW(c16 *, c16 *, u32); +W32 u32 GetEnvironmentVariableW(c16 *, c16 *, u32); +W32 i32 GetExitCodeProcess(handle, u32 *); +W32 u32 GetFullPathNameW(c16 *, u32, c16 *, c16 *); +W32 u32 GetModuleFileNameW(handle, c16 *, u32); +W32 i32 MessageBoxW(handle, c16 *, c16 *, u32); +W32 i32 MultiByteToWideChar(u32, u32, u8 *, i32, c16 *, i32); +W32 b32 ReadFile(handle, u8 *, u32, u32 *, void *); +W32 b32 SetConsoleTitleW(c16 *); +W32 b32 SetCurrentDirectoryW(c16 *); +W32 b32 SetEnvironmentVariableW(c16 *, c16 *); +W32 byte *VirtualAlloc(byte *, usize, u32, u32); +W32 b32 VirtualFree(byte *, usize, u32); +W32 u32 WaitForSingleObject(handle, u32); + +#define S(s) (s8){(u8 *)s, lengthof(s)} +typedef struct { + u8 *s; + size len; +} s8; + +#define U(s) (s16){s, lengthof(s)} +typedef struct { + c16 *s; + size len; +} s16; + +static s8 s8span(u8 *beg, u8 *end) +{ + s8 s = {}; + s.s = beg; + s.len = end - beg; + return s; +} + +static b32 s8equals(s8 a, s8 b) +{ + if (a.len != b.len) { + return 0; + } + for (size i = 0; i < a.len; i++) { + if (a.s[i] != b.s[i]) { + return 0; + } + } + return 1; +} + +static void fatal(c16 *msg) +{ + MessageBoxW(0, msg, u"gnu_windows launcher", 0x10); + ExitProcess(2); +} + +typedef struct { + byte *mem; + size cap; + size off; +} arena; + +static arena *newarena(size cap) +{ + arena *a = 0; + byte *mem = VirtualAlloc(0, cap, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if (mem) { + a = (arena *)mem; + a->mem = mem; + a->cap = cap; + a->off = sizeof(arena); + } + return a; +} + +static void freearena(arena *a) +{ + VirtualFree(a->mem, 0, MEM_RELEASE); +} + +#define NOZERO (1<<0) +#define SOFTFAIL (1<<1) +__attribute((malloc)) +__attribute((alloc_align(3))) +__attribute((alloc_size(2, 4))) +static byte *alloc(arena *a, size objsize, size align, size count, i32 flags) +{ + size avail = a->cap - a->off; + size pad = -a->off & (align - 1); + if (count > (avail - pad)/objsize) { + if (flags & SOFTFAIL) { + return 0; + } + fatal(u"Out of memory"); + } + size total = count*objsize; + byte *p = a->mem + a->off + pad; + if (!(flags & NOZERO)) { + for (size i = 0; i < total; i++) { + p[i] = 0; + } + } + a->off += pad + total; + return p; +} + +static arena splitarena(arena *a, i32 div) +{ + size avail = a->cap - a->off; + size cap = avail / div; + arena sub = {}; + sub.mem = alloc(a, 1, 32, cap, NOZERO); + sub.cap = cap; + return sub; +} + +typedef enum { + INI_eof, + INI_section, + INI_key, + INI_value +} initype; + +typedef struct { + s8 name; + initype type; +} initoken; + +typedef struct { + u8 *beg; + u8 *end; + b32 invalue; +} iniparser; + +static b32 inidone(iniparser *p) +{ + return p->beg == p->end; +} + +static u8 ininext(iniparser *p) +{ + return *p->beg++; +} + +static b32 iniblank(u8 c) +{ + return c==' ' || c=='\t' || c=='\r'; +} + +static void iniskip(iniparser *p) +{ + for (; !inidone(p) && iniblank(*p->beg); p->beg++) {} +} + +static u8 *initok(iniparser *p, u8 term) +{ + u8 *end = p->beg; + while (!inidone(p)) { + u8 c = ininext(p); + if (c == term) { + return end; + } else if (c == '\n') { + break; + } else if (!iniblank(c)) { + end = p->beg; + } + } + return term=='\n' ? end : 0; +} + +static b32 iniquoted(s8 s) +{ + return s.len>1 && s.s[0]=='"' && s.s[s.len-1]=='"'; +} + +// Parses like GetPrivateProfileString except sections cannot contain +// newlines. Invalid input lines are ignored. Comment lines begin with +// ';' following any whitespace. No trailing comments. Trims leading and +// trailing whitespace from sections, keys, and values. To preserve +// whitespace, values may be double-quoted. No quote escapes. Content on +// a line following a closing section ']' is ignored. Token encoding +// matches input encoding. An INI_value always follows an INI_key key. +static initoken iniparse(iniparser *p) +{ + initoken r = {}; + + if (p->invalue) { + p->invalue = 0; + iniskip(p); + u8 *beg = p->beg; + u8 *end = initok(p, '\n'); + r.name = s8span(beg, end); + r.type = INI_value; + if (iniquoted(r.name)) { + r.name.s++; + r.name.len -= 2; + } + return r; + } + + for (;;) { + iniskip(p); + if (inidone(p)) { + return r; + } + + u8 *end; + u8 *beg = p->beg; + switch (ininext(p)) { + case ';': + while (!inidone(p) && ininext(p)!='\n') {} + break; + + case '[': + iniskip(p); + beg = p->beg; + end = initok(p, ']'); + if (end) { + // skip over anything else on the line + while (!inidone(p) && ininext(p)!='\n') {} + r.name = s8span(beg, end); + r.type = INI_section; + return r; + } + break; + + case '\n': + break; + + default: + end = initok(p, '='); + if (end) { + p->invalue = 1; + r.name = s8span(beg, end); + r.type = INI_key; + return r; + } + } + } +} + +typedef enum { + sym_null = 0, + sym_gnu_windows, + sym_home, +} symbol; + +static symbol intern(s8 s) +{ + static struct { + s8 name; + symbol symbol; + } symbols[] = { + {S("gnu_windows"), sym_gnu_windows}, + {S("home"), sym_home}, + }; + for (size i = 0; i < countof(symbols); i++) { + if (s8equals(symbols[i].name, s)) { + return symbols[i].symbol; + } + } + return sym_null; +} + +static u8 *makecstr(arena *a, s8 s) +{ + u8 *r = new(a, u8, s.len+1); + for (size i = 0; i < s.len; i++) { + r[i] = s.s[i]; + } + return r; +} + +// Read and process "gnu_windows.home" from "gnu_windows.ini". Environment +// variables are expanded, and if relative, the result is converted into +// an absolute path. Returns null on error. +// +// Before calling, the current working directory must be changed to the +// location of gnu_windows.exe. +static c16 *homeconfig(arena *perm, arena scratch) +{ + handle h = CreateFileW( + u"gnu_windows.ini", + GENERIC_READ, + FILE_SHARE_ALL, + 0, + OPEN_EXISTING, + 0, + 0 + ); + if (h == (handle)-1) { + return 0; + } + + iniparser *p = new(&scratch, iniparser); + p->beg = new(&scratch, u8, MAX_INI, NOZERO); + u32 inilen; + b32 r = ReadFile(h, p->beg, MAX_INI, &inilen, 0); + CloseHandle(h); + if (!r || inilen == MAX_INI) { + return 0; + } + p->end = p->beg + inilen; + + u8 *home = 0; + u32 len = 0; + for (symbol section = 0, key = 0;;) { + initoken t = iniparse(p); + switch (t.type) { + case INI_eof: + break; + case INI_section: + section = intern(t.name); + continue; + case INI_key: + key = intern(t.name); + continue; + case INI_value: + if (!home && section==sym_gnu_windows && key==sym_home) { + home = makecstr(&scratch, t.name); + len = (u32)(t.name.len + 1); // include terminator + } + continue; + } + break; + } + + c16 *whome = new(&scratch, c16, len); + if (!MultiByteToWideChar(CP_UTF8, 0, home, len, whome, len)) { + return 0; + } + + // Process INI string into a final HOME path. Allocate a bit more + // than MAX_PATH, because GetFullPathNameW could technically reduce + // it to within MAX_PATH if there are lots of relative components. + u32 cap = MAX_PATH*4; + c16 *expanded = new(&scratch, c16, cap); + len = ExpandEnvironmentStringsW(whome, expanded, cap); + if (!len || len>cap) { + return 0; + } + + // The final result must fit within MAX_PATH in order to be useful. + c16 *path = new(perm, c16, MAX_PATH); + len = GetFullPathNameW(expanded, MAX_PATH, path, 0); + if (!len || len>=MAX_PATH) { + return 0; + } + return path; +} + +typedef struct { + c16 *buf; + size cap; + size len; + b32 err; +} buf16; + +static buf16 newbuf16(arena *a, size cap) +{ + buf16 buf = {}; + buf.buf = new(a, c16, cap, NOZERO); + buf.cap = cap; + return buf; +} + +static void buf16cat(buf16 *buf, s16 s) +{ + size avail = buf->cap - buf->len; + size count = s.lenbuf + buf->len; + for (size i = 0; i < count; i++) { + dst[i] = s.s[i]; + } + buf->len += count; + buf->err |= count < s.len; +} + +static void buf16c16(buf16 *buf, c16 c) +{ + s16 s = {&c, 1}; + buf16cat(buf, s); +} + +static void buf16moduledir(buf16 *buf, arena scratch) +{ + c16 *path = new(&scratch, c16, MAX_PATH); + size len = GetModuleFileNameW(0, path, MAX_PATH); + for (; len; len--) { + switch (path[len-1]) { + case '/': + case '\\': buf16cat(buf, (s16){path, len-1}); + return; + } + } +} + +static void buf16getenv(buf16 *buf, c16 *key, arena scratch) +{ + s16 var = {}; + var.s = new(&scratch, c16, MAX_ENVVAR, NOZERO); + u32 len = GetEnvironmentVariableW(key, var.s, MAX_ENVVAR); + var.len = len>=MAX_ENVVAR ? 0 : len; + buf16cat(buf, var); +} + +static void toslashes(c16 *path) +{ + for (size i = 0; i < path[i]; i++) { + path[i] = path[i]=='\\' ? '/' : path[i]; + } +} + +static u32 gnu_windows(void) +{ + arena *perm = newarena(1<<22); + if (!perm) { + fatal(u"Out of memory on startup"); + } + arena scratch = splitarena(perm, 2); + + // First load the module directory into the fresh buffer, and use it + // for a few different operations. + buf16 path = newbuf16(perm, MAX_ENVVAR); + buf16moduledir(&path, scratch); + buf16 moduledir = path; // to truncate back to the module dir + + buf16c16(&path, 0); // null terminator + SetEnvironmentVariableW(u"gnu_windows_HOME", path.buf); // ignore errors + + // Maybe set HOME from gnu_windows.ini + if (SetCurrentDirectoryW(path.buf)) { + c16 *home = homeconfig(perm, scratch); + if (home) { + toslashes(home); + SetEnvironmentVariableW(u"HOME", home); // ignore errors + } + } + + // Continue building PATH + path = moduledir; + buf16cat(&path, U(u"\\bin;")); + buf16getenv(&path, u"PATH", scratch); + buf16c16(&path, 0); // null terminator + if (path.err || !SetEnvironmentVariableW(u"PATH", path.buf)) { + fatal(u"Failed to configure $PATH"); + } + + #ifdef VERSION + #define LSTR(s) XSTR(s) + #define XSTR(s) u ## # s + SetEnvironmentVariableW(u"gnu_windows", LSTR(VERSION)); // ignore errors + #endif + + // Set the console title as late as possible, but not after starting + // the shell because .profile might change it. + SetConsoleTitleW(u"gnu_windows"); // ignore errors + + path = moduledir; + buf16cat(&path, U(u"\\bin\\busybox.exe")); + buf16c16(&path, 0); // null terminator + + // Start a BusyBox login shell + si si = {}; + si.cb = sizeof(si); + pi pi; + c16 cmdline[] = u"sh -l"; // NOTE: must be mutable! + if (!CreateProcessW(path.buf, cmdline, 0, 0, 1, 0, 0, 0, &si, &pi)) { + fatal(u"Failed to launch a login shell"); + } + + // Wait for shell to exit + freearena(perm); + u32 ret; + WaitForSingleObject(pi.process, -1); + GetExitCodeProcess(pi.process, &ret); + return ret; +} + +__attribute((force_align_arg_pointer)) +void mainCRTStartup(void) +{ + u32 r = gnu_windows(); + ExitProcess(r); +} diff --git a/.gnu-windows/src/gnu-windows.ico b/.gnu-windows/src/gnu-windows.ico new file mode 100644 index 0000000000..6de3a36f51 Binary files /dev/null and b/.gnu-windows/src/gnu-windows.ico differ diff --git a/.gnu-windows/src/gnu-windows.ini b/.gnu-windows/src/gnu-windows.ini new file mode 100644 index 0000000000..bec644d0d4 --- /dev/null +++ b/.gnu-windows/src/gnu-windows.ini @@ -0,0 +1,18 @@ +; Win-GDevKit.ini -- configuration for Win-GDevKit.exe +; This file must be encoded as UTF-8. + +[Win-GDevKit] +; home: Sets the HOME environment variable for the shell. Place a +; .profile in this directory to do further environment configuration +; using the shell itself. +; +; This path may be relative and reference environment variables using +; percent symbols, like a batch script. Variables will be expanded, a +; la ExpandEnvironmentStrings, and a relative path will be converted to +; an absolute path relative to this .ini file. +; +; Known bugs: busybox-w32 uses the narrow API and does not support wide +; paths, so be mindful when using non-ASCII paths for this value. +; +;home = ..\home +;home = %HOMEDRIVE%%HOMEPATH% diff --git a/.gnu-windows/src/libchkstk.S b/.gnu-windows/src/libchkstk.S new file mode 100644 index 0000000000..55be31f188 --- /dev/null +++ b/.gnu-windows/src/libchkstk.S @@ -0,0 +1,82 @@ +#if 0 +# Implementations of ___chkstk_ms (GCC) and __chkstk (MSVC). Unlike +# libgcc, no work happens if the stack is already committed. Execute +# this source with a shell to build libchkstk.a. +# This is free and unencumbered software released into the public domain. +set -ex +${CC:-cc} -c -DCHKSTK_MS -Wa,--no-pad-sections -o chkstk_ms.o $0 +${CC:-cc} -c -DCHKSTK -Wa,--no-pad-sections -o chkstk.o $0 +rm -f "${DESTDIR}libchkstk.a" +ar r "${DESTDIR}libchkstk.a" chkstk_ms.o chkstk.o +rm chkstk_ms.o chkstk.o +exit 0 +#endif + +#if __amd64 +// On x64, ___chkstk_ms and __chkstk have identical semantics. Unlike +// x86 __chkstk, neither adjusts the stack pointer. This implementation +// preserves all registers. +// +// The frame size is passed in rax, and this function ensures that +// enough of the stack is committed for the frame. It commits stack +// pages by writing to the guard page, one page at a time. +# if CHKSTK_MS + .globl ___chkstk_ms +___chkstk_ms: +# elif CHKSTK + .globl __chkstk +__chkstk: +# endif + push %rax + push %rcx + neg %rax // rax = frame low address + add %rsp, %rax // " + mov %gs:(0x10), %rcx // rcx = stack low address + jmp 1f +0: sub $0x1000, %rcx // extend stack into guard page + test %eax, (%rcx) // commit page (two instruction bytes) +1: cmp %rax, %rcx + ja 0b + pop %rcx + pop %rax + ret +#endif // __amd64 + +#if __i386 +# if CHKSTK_MS +// Behaves exactly like x64 ___chkstk_ms. + .globl ___chkstk_ms +___chkstk_ms: + push %eax + push %ecx + neg %eax // eax = frame low address + add %esp, %eax // " + mov %fs:(0x08), %ecx // ecx = stack low address + jmp 1f +0: sub $0x1000, %ecx // extend stack into guard page + test %eax, (%ecx) // commit page (two instruction bytes) +1: cmp %eax, %ecx + ja 0b + sub %esp, %eax + pop %ecx + pop %eax + ret +# elif CHKSTK +// On x86, __chkstk allocates the new stack frame. This implementation +// clobbers eax. MSVC only seems to care about ebp and ecx (this). + .globl __chkstk +__chkstk: + push %ecx // preserve ecx + neg %eax // eax = frame low address + lea 8(%esp,%eax), %eax // " + mov %fs:(0x08), %ecx // ecx = stack low address + jmp 1f +0: sub $0x1000, %ecx // extend stack into guard page + test %eax, (%ecx) // commit page (two instruction bytes) +1: cmp %eax, %ecx + ja 0b + pop %ecx // restore ecx + xchg %eax, %esp // allocate frame + jmp *(%eax) // return +# endif +#endif // __i386 diff --git a/.gnu-windows/src/libmemory.c b/.gnu-windows/src/libmemory.c new file mode 100644 index 0000000000..5dae39cb61 --- /dev/null +++ b/.gnu-windows/src/libmemory.c @@ -0,0 +1,179 @@ +#if 0 +# memset, memcpy, memmove, and memcmp via x86 string instructions +# Execute this source with a shell to build libmemory.a. +# This is free and unencumbered software released into the public domain. +set -e +CFLAGS="-Os -fno-builtin -fno-asynchronous-unwind-tables -fno-ident" +objects="" +for func in memset memcpy memmove memcmp strlen; do + FUNC="$(echo $func | tr '[:lower:]' '[:upper:]')" + objects="$objects $func.o" + (set -x; ${CC:-cc} -c -D$FUNC -Wa,--no-pad-sections $CFLAGS -o $func.o $0) +done +rm -f "${DESTDIR}libmemory.a" +ar r "${DESTDIR}libmemory.a" $objects +rm $objects +exit 0 +#endif + +typedef __SIZE_TYPE__ size_t; +typedef __UINTPTR_TYPE__ uintptr_t; + +#ifdef MEMSET +void *memset(void *dst, int c, size_t len) +{ + void *r = dst; + asm volatile ( + "rep stosb" + : "+D"(dst), "+c"(len) + : "a"(c) + : "memory" + ); + return r; +} +#endif + +#ifdef MEMCPY +void *memcpy(void *restrict dst, void *restrict src, size_t len) +{ + void *r = dst; + asm volatile ( + "rep movsb" + : "+D"(dst), "+S"(src), "+c"(len) + : + : "memory" + ); + return r; +} +#endif + +#ifdef MEMMOVE +void *memmove(void *dst, void *src, size_t len) +{ + // Use uintptr_t to bypass pointer semantics: + // (1) comparing unrelated pointers + // (2) pointer arithmetic on null (i.e. gracefully handle null dst/src) + // (3) pointer overflow ("one-before-the-beginning" in reversed copy) + uintptr_t d = (uintptr_t)dst; + uintptr_t s = (uintptr_t)src; + if (d > s) { + d += len - 1; + s += len - 1; + asm ("std"); + } + asm volatile ( + "rep movsb; cld" + : "+D"(d), "+S"(s), "+c"(len) + : + : "memory" + ); + return dst; +} +#endif + +#ifdef MEMCMP +int memcmp(void *s1, void *s2, size_t len) +{ + // CCa "after" == CF=0 && ZF=0 + // CCb "before" == CF=1 + int a, b; + asm volatile ( + "xor %%eax, %%eax\n" // CF=0, ZF=1 (i.e. CCa = CCb = 0) + "repz cmpsb\n" + : "+D"(s1), "+S"(s2), "+c"(len), "=@cca"(a), "=@ccb"(b) + : + : "ax", "memory" + ); + return b - a; +} +#endif + +#ifdef STRLEN +size_t strlen(char *s) +{ + size_t n = -1; + asm volatile ( + "repne scasb" + : "+D"(s), "+c"(n) + : "a"(0) + : "memory" + ); + return -n - 2; +} +#endif + +#ifdef TEST +// $ sh libmemory.c +// $ cc -nostdlib -fno-builtin -DTEST -g3 -O -o test libmemory.c libmemory.a +// $ gdb -ex r -ex q ./test + +#define assert(c) while (!(c)) __builtin_trap() +void *memset(void *, int, size_t); +int memcmp(void *, void *, size_t); +void *memcpy(void *restrict, void *restrict, size_t); +void *memmove(void *, void *, size_t); +size_t strlen(char *); + +#if defined(__linux) && defined(__amd64) +asm (" .global _start\n" + "_start: call mainCRTStartup\n" + " mov %eax, %edi\n" + " mov $60, %eax\n" + " syscall\n"); +#elif defined(__linux) && defined(__i386) +asm (" .global _start\n" + "_start: call mainCRTStartup\n" + " mov %eax, %ebx\n" + " mov $1, %eax\n" + " int $0x80\n"); +#endif + +int mainCRTStartup(void) +{ + { + char buf[12] = "............"; + memset(buf+4, 'x', 4); + assert(!memcmp(buf, "....xxxx....", 12)); + memset(buf, 0, 12); + assert(!memcmp(buf, (char[12]){0}, 12)); + memset(buf+8, 1, 0); + assert(!memcmp(buf, (char[12]){0}, 12)); + } + + { + char buf[7] = "abcdefg"; + memcpy(buf+0, buf+3, 3); + assert(!memcmp(buf, "defdefg", 7)); + memcpy(buf+5, buf+1, 2); + assert(!memcmp(buf, "defdeef", 7)); + memcpy(buf+1, buf+4, 0); + assert(!memcmp(buf, "defdeef", 7)); + } + + { + char buf[] = "abcdefgh"; + memmove(buf+0, buf+1, 7); + assert(!memcmp(buf, "bcdefghh", 8)); + buf[7] = 0; + memmove(buf+1, buf+0, 7); + assert(!memcmp(buf, "bbcdefgh", 8)); + memmove(buf+2, buf+1, 0); + assert(!memcmp(buf, "bbcdefgh", 8)); + } + + assert(memcmp("\xff", "1", 1) > 0); + assert(memcmp("", "", 0) == 0); // test empty after > result + assert(memcmp("1", "\xff", 1) < 0); + assert(memcmp("", "", 0) == 0); // test empty after < result + assert(memcmp("ab", "aa", 2) > 0); + assert(memcmp("aa", "ab", 2) < 0); + assert(memcmp("x", "y", 0) == 0); + + assert(0 == strlen("")); + assert(1 == strlen(" ")); + assert(1 == strlen("\xff")); + assert(5 == strlen("hello")); + + return 0; +} +#endif diff --git a/.gnu-windows/src/pkg-config.c b/.gnu-windows/src/pkg-config.c new file mode 100644 index 0000000000..e3036af428 --- /dev/null +++ b/.gnu-windows/src/pkg-config.c @@ -0,0 +1,2559 @@ +// u-config: a small, simple, portable pkg-config clone +// https://github.com/skeeto/u-config +// $ cc -nostartfiles -o pkg-config.exe pkg-config.c +// $ cl pkg-config.c +// This is free and unencumbered software released into the public domain. + +// Fundamental definitions + +#define VERSION "0.31.1" + +typedef int Size; +#define Size_MASK ((unsigned)-1) +#define Size_MAX ((Size)(Size_MASK >> 1)) + +#define SIZEOF(x) (Size)(sizeof(x)) +#define COUNTOF(a) (SIZEOF(a)/SIZEOF(a[0])) + +typedef int Bool; +typedef unsigned char Byte; + +#if __GNUC__ + #define TRAP __builtin_trap() + #define NORETURN __attribute__((noreturn)) +#elif _MSC_VER + #define TRAP __debugbreak() + #define NORETURN __declspec(noreturn) +#else + #define TRAP *(volatile int *)0 = 0 + #define NORETURN +#endif + +#ifdef DEBUG + #define ASSERT(c) if (!(c)) TRAP +#else + #define ASSERT(c) +#endif + +typedef struct { + Byte *s; + Size len; +} Str; + +#ifdef __cplusplus + #define S(s) makestr((Byte *)s, SIZEOF(s)-1) + static inline Str makestr(Byte *s, Size len) + { + Str r = {s, len}; + return r; + } +#else + #define S(s) (Str){(Byte *)s, SIZEOF(s)-1} +#endif + +typedef struct { + Str mem; + Size off; +} Arena; + +typedef struct { + Arena arena; + Str *args; + Size nargs; + Str envpath; // $PKG_CONFIG_PATH or empty + Str fixedpath; // $PKG_CONFIG_LIBDIR or default + Str top_builddir; // $PKG_CONFIG_TOP_BUILD_DIR or default + Str sys_incpath; // $PKG_CONFIG_SYSTEM_INCLUDE_PATH or default + Str sys_libpath; // $PKG_CONFIG_SYSTEM_LIBRARY_PATH or default + Bool define_prefix; + Byte delim; +} Config; + + +// Platform API + +// Application entry point. Returning from this function indicates the +// application itself completed successfully. However, an os_write error +// may result in a non-zero exit. +static void appmain(Config); + +typedef enum {MapFile_OK, MapFile_NOTFOUND, MapFile_READERR} MapFileStatus; + +typedef struct { + Str contents; + MapFileStatus status; +} MapFileResult; + +// Load a file into memory, maybe using the arena. The path must include +// a null terminator since it may be passed directly to the OS interface. +static MapFileResult os_mapfile(Arena *, Str path); + +// Write buffer to stdout (1) or stderr (2). The platform must detect +// write errors and arrange for an eventual non-zero exit status. +static void os_write(int fd, Str); + +// Immediately exit the program with a non-zero status. +NORETURN static void os_fail(void); + + +// Application + +NORETURN static void oom(void) +{ + os_write(2, S("pkg-config: out of memory\n")); + os_fail(); +} + +static Bool digit(Byte c) +{ + return c>='0' && c<='9'; +} + +static Bool whitespace(Byte c) +{ + switch (c) { + case '\t': case '\n': case '\b': case '\f': case '\r': case ' ': + return 1; + } + return 0; +} + +static Bool pathsep(Byte c) +{ + return c=='/' || c=='\\'; +} + +static Str fillstr(Str s, Byte b) +{ + for (Size i = 0; i < s.len; i++) { + s.s[i] = b; + } + return s; +} + +static void *alloc(Arena *a, Size size) +{ + ASSERT(size >= 0); + Size align = -size & (SIZEOF(void *) - 1); + Size avail = a->mem.len - a->off; + if (avail-align < size) { + oom(); + } + Byte *p = a->mem.s + a->off; + a->off += size + align; + return p; +} + +static void *allocarray(Arena *a, Size size, Size count) +{ + ASSERT(size > 0); + ASSERT(count >= 0); + if (count > Size_MAX/size) { + oom(); + } + return alloc(a, size*count); +} + +static Str newstr(Arena *a, Size len) +{ + Str r = {(Byte *)alloc(a, len), len}; + return r; +} + +static void *zalloc(Arena *a, Size size) +{ + Str r = newstr(a, size); + return fillstr(r, 0).s; +} + +static Str maxstr(Arena *a) +{ + Size len = a->mem.len - a->off; + return newstr(a, len); +} + +// Fill free space with garbage when debugging. +static void shredfree(Arena *a) +{ + (void)a; + #ifdef DEBUG + Arena temp = *a; + fillstr(maxstr(&temp), 0xa5); + #endif +} + +static Str fromptrs(Byte *beg, Byte *end) +{ + ASSERT(beg); + ASSERT(end); + ASSERT(end >= beg); + Str s = {beg, (Size)(end - beg)}; + return s; +} + +// Copy src into dst returning the remaining portion of dst. +static Str copy(Str dst, Str src) +{ + ASSERT(dst.len >= src.len); + for (Size i = 0; i < src.len; i++) { + dst.s[i] = src.s[i]; + } + Str r = {dst.s+src.len, dst.len-src.len}; + return r; +} + +// Compare strings, returning -1, 0, or +1. +static int orderstr(Str a, Str b) +{ + // NOTE: "null" strings are still valid strings + Size len = a.len= 0); + ASSERT(off <= s.len); + s.s += off; + s.len -= off; + return s; +} + +static Str takehead(Str s, Size len) +{ + ASSERT(len >= 0); + ASSERT(len <= s.len); + s.len = len; + return s; +} + +static Str cuttail(Str s, Size len) +{ + ASSERT(len >= 0); + ASSERT(len <= s.len); + Str r = {s.s, s.len-len}; + return r; +} + +static Str taketail(Str s, Size len) +{ + return cuthead(s, s.len-len); +} + +static Bool startswith(Str s, Str prefix) +{ + return s.len>=prefix.len && equals(takehead(s, prefix.len), prefix); +} + +static Size hash(Str s) +{ + unsigned long long h = 257; + for (Size i = 0; i < s.len; i++) { + h ^= s.s[i]; + h *= 1111111111111111111; + } + h ^= h >> 33; + return (Size)(h & Size_MASK); +} + +typedef struct { + Str head; + Str tail; +} StrPair; + +static StrPair digits(Str s) +{ + Size i = 0; + for (; ikey)) { + case -1: target = parent->child + 0; break; + case 0: return parent; + case +1: target = parent->child + 1; break; + } + } + + // None found, insert a new leaf + if (!a) { + return 0; // "only browsing, thanks" + } + Treap *node = (Treap *)zalloc(a, size); + node->key = key; + node->parent = parent; + *target = node; + + // Randomly rotate the tree according to the hash + Size keyhash = hash(key); + while (node->parent && hash(node->parent->key)parent; + + // Swap places with parent, also updating grandparent + node->parent = parent->parent; + parent->parent = node; + if (node->parent) { + int i = node->parent->child[0] == parent; + node->parent->child[!i] = node; + } else { + *t = node; + } + + // Move the opposing child to the ex-parent + int i = parent->child[0] == node; + parent->child[!i] = node->child[i]; + if (node->child[i]) { + node->child[i]->parent = parent; + } + node->child[i] = parent; + } + return node; +} + +typedef struct { + Str buf; + Str avail; + Arena *a; + int fd; +} Out; + +// Buffered output for os_write(). +static Out newoutput(Arena *a, int fd, Size len) +{ + Str buf = newstr(a, len); + Out out = {buf, buf, 0, fd}; + return out; +} + +static Out newnullout(void) +{ + Out out = {0}; + out.fd = -1; + return out; +} + +// Output to a dynamically-grown arena buffer. The arena cannot be used +// again until this buffer is finalized. +static Out newmembuf(Arena *a) +{ + Str max = maxstr(a); + Out out = {max, max, a, 0}; + return out; +} + +// Close the stream and release the arena, returning the result buffer. +static Str finalize(Out *out) +{ + ASSERT(!out->fd); + Size len = out->buf.len - out->avail.len; + out->a->off -= out->buf.len; + return newstr(out->a, len); +} + +static void flush(Out *out) +{ + ASSERT(out->fd); + if (out->buf.len != out->avail.len) { + Str fill = {out->buf.s, out->buf.len-out->avail.len}; + os_write(out->fd, fill); + out->avail = out->buf; + } +} + +static void outstr(Out *out, Str s) +{ + if (out->fd == -1) { + return; // /dev/null + } + + if (out->fd == 0) { + // Output to a memory buffer, not a stream + if (out->avail.len < s.len) { + oom(); + } + out->avail = copy(out->avail, s); + return; + } + + // Copy into the stream buffer + while (s.len) { + if (out->avail.len >= s.len) { + out->avail = copy(out->avail, s); + s.len = 0; + } else if (out->buf.len==out->avail.len && s.len>=out->buf.len) { + os_write(out->fd, s); + s.len = 0; + } else { + Size len = out->avail.len; + Str head = takehead(s, len); + s = cuthead(s, len); + out->avail = copy(out->avail, head); + flush(out); + } + } +} + +static void outbyte(Out *out, Byte b) +{ + Str s = {&b, 1}; + outstr(out, s); +} + +typedef struct Var { + Treap node; + Str value; +} Var; + +typedef struct { + Treap *vars; +} Env; + +// Return a pointer to the binding so that the caller can choose to fill +// it. The arena is optional. If given, the binding will be created and +// set to a null string. An unallocated, zero-initialized environment is +// a valid empty environment. +static Str *insert(Arena *a, Env *e, Str name) +{ + Var *var = (Var *)treapinsert(a, &e->vars, name, SIZEOF(*var)); + return var ? &var->value : 0; +} + +// Try to find the binding in the global environment, then failing that, +// the second environment. Returns a null string if no entry was found. +// An unallocated, zero-initialized environment is valid for lookups. +static Str lookup(Env *global, Env *env, Str name) +{ + Str *s = insert(0, global, name); + if (s) { + return *s; + } + s = insert(0, env, name); + if (s) { + return *s; + } + Str r = {0}; + return r; +} + +static Str dirname(Str path) +{ + Size len = path.len; + while (len>0 && !pathsep(path.s[--len])) {} + return takehead(path, len); +} + +static Str basename(Str path) +{ + Size len = path.len; + for (; len>0 && !pathsep(path.s[len-1]); len--) {} + return taketail(path, path.len-len); +} + +static Str buildpath(Arena *a, Str dir, Str pc) +{ + Str sep = S("/"); + Str suffix = S(".pc\0"); + Size pathlen = dir.len + sep.len + pc.len + suffix.len; + Str path = newstr(a, pathlen); + Str p = path; + p = copy(p, dir); + p = copy(p, sep); + p = copy(p, pc); + copy(p, suffix); + return path; +} + +typedef enum {Pkg_DIRECT=1<<0, Pkg_PUBLIC=1<<1} PkgFlags; + +typedef struct Pkg { + Treap node; + struct Pkg *list; // total load order list + Str path; + Str realname; + Str contents; + Env env; + int flags; + + #define PKG_NFIELDS 10 + Str name; + Str description; + Str url; + Str version; + Str requires; + Str requiresprivate; + Str conflicts; + Str libs; + Str libsprivate; + Str cflags; +} Pkg; + +static Str *fieldbyid(Pkg *p, int id) +{ + ASSERT(id >= 0); + ASSERT(id < PKG_NFIELDS); + return &p->name + id; +} + +static Str *fieldbyname(Pkg *p, Str name) +{ + static const unsigned char offs[] = {0,4,15,18,25,25,41,50,50,62}; + static const unsigned char lens[] = {4,11,3,7,8,16,9,4,12,6}; + static const Byte fields[] = + "Name" "Description" "URL" "Version" "Requires.private" + "Conflicts" "Libs.private" "Cflags"; + for (int i = 0; i < COUNTOF(offs); i++) { + Str field = {(Byte *)fields+offs[i], lens[i]}; + if (equals(field, name)) { + return fieldbyid(p, i); + } + } + return 0; +} + +typedef struct { + Treap *pkgs; + Pkg *head, *tail; + Size count; +} Pkgs; + +// Locate a previously-loaded package, or allocate zero-initialized +// space in the set for a new package. +static Pkg *locate(Arena *a, Pkgs *t, Str realname) +{ + Pkg *p = (Pkg *)treapinsert(a, &t->pkgs, realname, SIZEOF(*p)); + if (!p->realname.s) { + t->count++; + p->realname = realname; + if (!t->head) { + t->head = t->tail = p; + } else { + t->tail->list = p; + t->tail = p; + } + } + return p; +} + +typedef enum { + Parse_OK, + Parse_DUPFIELD, + Parse_DUPVARABLE +} ParseStatus; + +typedef struct { + Pkg pkg; + Str dupname; + ParseStatus status; +} ParseResult; + +// Return the number of escape bytes at the beginning of the input. +static Size escaped(Str s) +{ + if (startswith(s, S("\\\n"))) { + return 2; + } + if (startswith(s, S("\\\r\n"))) { + return 3; + } + return 0; +} + +// Return a copy of the input with the escapes squashed out. +static Str stripescapes(Arena *a, Str s) +{ + Size len = 0; + Str c = newstr(a, s.len); + for (Size i = 0; i < s.len; i++) { + Byte b = s.s[i]; + if (b == '\\') { + Size r = escaped(cuthead(s, i)); + if (r) { + i += r - 1; + } else if (is) { + ParseResult dup = {0}; + dup.dupname = name; + dup.status = Parse_DUPFIELD; + return dup; + } + break; + } + + // Skip leading space; newlines may be escaped with a backslash + while (p < e) { + if (*p == '\\') { + Size r = escaped(fromptrs(p, e)); + if (r) { + p += r; + } else { + break; + } + } else if (*p=='\n' || !whitespace(*p)) { + break; + } else { + p++; + } + } + + Bool cleanup = 0; + end = beg = p; + for (; pindex == p->nargs) { + OptionResult r = {0}; + return r; + } + + for (;;) { + Str arg = p->args[p->index++]; + + if (p->dashdash || arg.len<2 || arg.s[0]!='-') { + OptionResult r = {0}; + r.arg = arg; + r.ok = 1; + return r; + } + + if (!p->dashdash && equals(arg, S("--"))) { + p->dashdash = 1; + continue; + } + + OptionResult r = {0}; + r.isoption = 1; + r.ok = 1; + arg = cuthead(arg, 1); + Cut c = cut(arg, '='); + if (c.ok) { + r.arg = c.head; + r.value = c.tail; + } else { + r.arg = arg; + } + return r; + } +} + +static Str getargopt(Out *err, OptionParser *p, Str option) +{ + if (p->index == p->nargs) { + missing(err, option); + } + return p->args[p->index++]; +} + +static void usage(Out *out) +{ + static const char usage[] = + "u-config " VERSION " https://github.com/skeeto/u-config\n" + "free and unencumbered software released into the public domain\n" + "usage: pkg-config [OPTIONS...] [PACKAGES...]\n" + " --cflags, --cflags-only-I, --cflags-only-other\n" + " --define-prefix, --dont-define-prefix\n" + " --define-variable=NAME=VALUE, --variable=NAME\n" + " --exists, --validate, --{atleast,exact,max}-version=VERSION\n" + " --errors-to-stdout\n" + " --keep-system-cflags, --keep-system-libs\n" + " --libs, --libs-only-L, --libs-only-l, --libs-only-other\n" + " --maximum-traverse-depth=N\n" + " --modversion\n" + " --msvc-syntax\n" + " --newlines\n" + " --silence-errors\n" + " --static\n" + " --with-path=PATH\n" + " -h, --help, --version\n" + "environment:\n" + " PKG_CONFIG_PATH\n" + " PKG_CONFIG_LIBDIR\n" + " PKG_CONFIG_TOP_BUILD_DIR\n" + " PKG_CONFIG_SYSTEM_INCLUDE_PATH\n" + " PKG_CONFIG_SYSTEM_LIBRARY_PATH\n"; + outstr(out, S(usage)); +} + +typedef struct StrListNode { + struct StrListNode *next; + Str entry; +} StrListNode; + +typedef struct { + StrListNode *head; + StrListNode *tail; +} StrList; + +static void append(Arena *a, StrList *list, Str str) +{ + StrListNode *node = (StrListNode *)alloc(a, SIZEOF(*node)); + node->next = 0; + node->entry = str; + if (list->tail) { + ASSERT(list->head); + list->tail->next = node; + } else { + ASSERT(!list->tail); + list->head = node; + } + list->tail = node; +} + +typedef struct { + StrList list; + Byte delim; +} Search; + +static Search newsearch(Byte delim) +{ + Search r = {0}; + r.delim = delim; + return r; +} + +static void appendpath(Arena *a, Search *dirs, Str path) +{ + while (path.len) { + Cut c = cut(path, dirs->delim); + Str dir = c.head; + if (dir.len) { + append(a, &dirs->list, dir); + } + path = c.tail; + } +} + +static void prependpath(Arena *a, Search *dirs, Str path) +{ + if (!dirs->list.head) { + // Empty, so appending is the same a prepending + appendpath(a, dirs, path); + } else { + // Append to an empty Search, then transplant in front + Search temp = newsearch(dirs->delim); + appendpath(a, &temp, path); + temp.list.tail->next = dirs->list.head; + dirs->list.head = temp.list.head; + } +} + +static Bool realnameispath(Str realname) +{ + return realname.len>3 && equals(taketail(realname, 3), S(".pc")); +} + +static Str pathtorealname(Str path) +{ + if (!realnameispath(path)) { + return path; + } + + Size baselen = 0; + for (Size i = 0; i < path.len; i++) { + if (pathsep(path.s[i])) { + baselen = i + 1; + } + } + Str name = cuthead(path, baselen); + return cuttail(name, 3); +} + +static Str readpackage(Arena *a, Out *err, Str path, Str realname) +{ + if (equals(realname, S("pkg-config"))) { + return S( + "Name: u-config\n" + "Version: " VERSION "\n" + "Description:\n" + ); + } + + Str null = {0}; + MapFileResult m = os_mapfile(a, path); + switch (m.status) { + case MapFile_NOTFOUND: + return null; + + case MapFile_READERR: + outstr(err, S("pkg-config: ")); + outstr(err, S("could not read package '")); + outstr(err, realname); + outstr(err, S("' from '")); + outstr(err, path); + outstr(err, S("'\n")); + flush(err); + os_fail(); + + case MapFile_OK: + return m.contents; + } + ASSERT(0); + return null; +} + +static void expand(Out *out, Out *err, Env *global, Pkg *p, Str str) +{ + int top = 0; + Str stack[128]; + + stack[top] = str; + while (top >= 0) { + Str s = stack[top--]; + for (Size i = 0; i < s.len-1; i++) { + if (s.s[i]=='$' && s.s[i+1]=='{') { + if (top >= COUNTOF(stack)-2) { + outstr(err, S("pkg-config: ")); + outstr(err, S("exceeded max recursion depth in '")); + outstr(err, p->path); + outstr(err, S("'\n")); + flush(err); + os_fail(); + } + + Str head = {s.s, i}; + outstr(out, head); + + Size beg = i + 2; + Size end = beg; + for (; endenv, name); + if (!value.s) { + outstr(err, S("pkg-config: ")); + outstr(err, S("undefined variable '")); + outstr(err, name); + outstr(err, S("' in '")); + outstr(err, p->path); + outstr(err, S("'\n")); + flush(err); + os_fail(); + } + stack[++top] = value; + s.len = 0; + break; + + } else if (s.s[i]=='$' && s.s[i+1]=='$') { + Str head = {s.s, i+1}; + outstr(out, head); + Str tail = {s.s+i+2, s.len-i-2}; + stack[++top] = tail; + s.len = 0; + break; + } + } + outstr(out, s); + } +} + +// Merge and expand data from "update" into "base". +static void expandmerge(Arena *a, Out *err, Env *g, Pkg *base, Pkg *update) +{ + base->path = update->path; + base->contents = update->contents; + base->env = update->env; + base->flags = update->flags; + for (int i = 0; i < PKG_NFIELDS; i++) { + Out mem = newmembuf(a); + Str src = *fieldbyid(update, i); + expand(&mem, err, g, update, src); + *fieldbyid(base, i) = finalize(&mem); + } +} + +static Pkg findpackage(Arena *a, Search *dirs, Out *err, Str realname) +{ + Str path = {0, 0}; + Str contents = {0, 0}; + + if (realnameispath(realname)) { + path = newstr(a, realname.len+1); + copy(path, realname).s[0] = 0; + contents = readpackage(a, err, path, realname); + path = cuttail(path, 1); // remove null terminator + if (contents.s) { + realname = pathtorealname(path); + } + } + + for (StrListNode *n = dirs->list.head; n && !contents.s; n = n->next) { + path = buildpath(a, n->entry, realname); + contents = readpackage(a, err, path, realname); + path = cuttail(path, 1); // remove null terminator + } + + if (!contents.s) { + outstr(err, S("pkg-config: ")); + outstr(err, S("could not find package '")); + outstr(err, realname); + outstr(err, S("'\n")); + flush(err); + os_fail(); + } + + ParseResult r = parsepackage(a, contents); + switch (r.status) { + case Parse_DUPVARABLE: + outstr(err, S("pkg-config: ")); + outstr(err, S("duplicate variable '")); + outstr(err, r.dupname); + outstr(err, S("' in '")); + outstr(err, path); + outstr(err, S("'\n")); + flush(err); + os_fail(); + + case Parse_DUPFIELD: + outstr(err, S("pkg-config: ")); + outstr(err, S("duplicate field '")); + outstr(err, r.dupname); + outstr(err, S("' in '")); + outstr(err, path); + outstr(err, S("'\n")); + flush(err); + os_fail(); + + case Parse_OK: + break; + } + r.pkg.path = path; + r.pkg.realname = realname; + *insert(a, &r.pkg.env, S("pcfiledir")) = dirname(path); + + Str missing = {0, 0}; + if (!r.pkg.name.s) { + missing = S("Name"); + } else if (!r.pkg.version.s) { + missing = S("Version"); + } else if (!r.pkg.description.s) { + missing = S("Description"); + } + if (missing.s) { + outstr(err, S("pkg-config: ")); + outstr(err, S("missing field '")); + outstr(err, missing); + outstr(err, S("' in '")); + outstr(err, r.pkg.path); + outstr(err, S("'\n")); + flush(err); + #ifndef DEBUG + // Do not enforce during fuzzing + os_fail(); + #endif + } + + return r.pkg; +} + +typedef struct { + Str arg; + Str tail; + Bool ok; +} DequoteResult; + +static Bool shellmeta(Byte c) +{ + // NOTE: matches pkg-config's listing, which excludes "$()" + Str meta = S("\"!#%&'*<>?[\\]`{|}"); + for (Size i = 0; i < meta.len; i++) { + if (meta.s[i] == c) { + return 1; + } + } + return 0; +} + +// Process the next token. Return it and the unprocessed remainder. +static DequoteResult dequote(Arena *a, Str s) +{ + Size i; + Byte quote = 0; + Bool escaped = 0; + Arena save = *a; + Out mem = newmembuf(a); + + for (; s.len && whitespace(*s.s); s = cuthead(s, 1)) {} + + for (i = 0; i < s.len; i++) { + Byte c = s.s[i]; + if (whitespace(c)) { + c = ' '; + } + + if (quote == '\'') { + if (c == '\'') { + quote = 0; + } else if (c==' ' || shellmeta(c)) { + outbyte(&mem, '\\'); + outbyte(&mem, c); + } else { + outbyte(&mem, c); + } + + } else if (quote == '"') { + if (escaped) { + escaped = 0; + if (c!='\\' && c!='"') { + outbyte(&mem, '\\'); + if (c==' ' || shellmeta(c)) { + outbyte(&mem, '\\'); + } + } + outbyte(&mem, c); + } else if (c == '\"') { + quote = 0; + } else if (c==' ' || shellmeta(c)) { + outbyte(&mem, '\\'); + outbyte(&mem, c); + } else { + escaped = c == '\\'; + outbyte(&mem, c); + } + + } else if (c=='\'' || c=='"') { + quote = c; + + } else if (shellmeta(c)) { + outbyte(&mem, '\\'); + outbyte(&mem, c); + + } else if (c==' ') { + break; + + } else { + outbyte(&mem, c); + } + } + + if (quote) { + *a = save; + shredfree(a); + DequoteResult r = {0}; + return r; + } + + DequoteResult r = {finalize(&mem), cuthead(s, i), 1}; + return r; +} + +// Compare version strings, returning [-1, 0, +1]. Follows the RPM +// version comparison specification like the original pkg-config. +static int compareversions(Str va, Str vb) +{ + Size i = 0; + while (i b) { + return +1; + } + i++; + } else { + StrPair pa = digits(cuthead(va, i)); + StrPair pb = digits(cuthead(vb, i)); + if (pa.head.len < pb.head.len) { + return -1; + } else if (pa.head.len > pb.head.len) { + return +1; + } + for (i = 0; i < pa.head.len; i++) { + a = pa.head.s[i]; + b = pb.head.s[i]; + if (a < b) { + return -1; + } else if (a > b) { + return +1; + } + } + va = pa.tail; + vb = pb.tail; + i = 0; + } + } + if (va.len < vb.len) { + return -1; + } else if (va.len > vb.len) { + return +1; + } + return 0; +} + +typedef enum { + VersionOp_ERR=0, + VersionOp_LT, + VersionOp_LTE, + VersionOp_EQ, + VersionOp_GTE, + VersionOp_GT +} VersionOp; + +static VersionOp parseop(Str s) +{ + if (equals(S("<"), s)) { + return VersionOp_LT; + } else if (equals(S("<="), s)) { + return VersionOp_LTE; + } else if (equals(S("="), s)) { + return VersionOp_EQ; + } else if (equals(S(">="), s)) { + return VersionOp_GTE; + } else if (equals(S(">"), s)) { + return VersionOp_GT; + } + return VersionOp_ERR; +} + +static Str opname(VersionOp op) +{ + switch (op) { + case VersionOp_ERR: break; + case VersionOp_LT: return S("<"); + case VersionOp_LTE: return S("<="); + case VersionOp_EQ: return S("="); + case VersionOp_GTE: return S(">="); + case VersionOp_GT: return S(">"); + } + ASSERT(0); + Str null = {0}; + return null; +} + +static Bool validcompare(VersionOp op, int result) +{ + switch (op) { + case VersionOp_ERR: break; + case VersionOp_LT: return result < 0; + case VersionOp_LTE: return result <= 0; + case VersionOp_EQ: return result == 0; + case VersionOp_GTE: return result >= 0; + case VersionOp_GT: return result > 0; + } + ASSERT(0); + return 0; +} + +typedef struct { + Out *err; + Search search; + Env *global; + Pkgs *pkgs; + Pkg *last; + int maxdepth; + VersionOp op; + Bool define_prefix; + Bool recursive; + Bool ignore_versions; +} Processor; + +static Processor newprocessor(Config *c, Out *err, Env *g, Pkgs *pkgs) +{ + Arena *a = &c->arena; + Processor proc = {0}; + proc.err = err; + proc.search = newsearch(c->delim); + appendpath(a, &proc.search, c->envpath); + appendpath(a, &proc.search, c->fixedpath); + proc.global = g; + proc.pkgs = pkgs; + proc.maxdepth = (unsigned)-1 >> 1; + proc.define_prefix = 1; + proc.recursive = 1; + return proc; +} + +static void procfail(Out *err, VersionOp op, Pkg *p) +{ + outstr(err, S("pkg-config: ")); + outstr(err, S("expected version following operator ")); + outstr(err, opname(op)); + if (p) { + outstr(err, S(" in package '")); + outstr(err, p->realname); + outstr(err, S("'")); + } + outstr(err, S("\n")); + flush(err); + os_fail(); +} + +// Wrap the string in quotes if it contains whitespace. +static Str maybequote(Arena *a, Str s) +{ + for (Size i = 0; i < s.len; i++) { + if (whitespace(s.s[i])) { + Str r = newstr(a, s.len + 2); + Str t = copy(r, S("\"")); + t = copy(t, s); + copy(t, S("\"")); + return r; + } + } + return s; +} + +static void setprefix(Arena *a, Pkg *p) +{ + Str parent = dirname(p->path); + if (equals(S("pkgconfig"), basename(parent))) { + Str prefix = dirname(dirname(parent)); + prefix = maybequote(a, prefix); + *insert(a, &p->env, S("prefix")) = prefix; + } +} + +typedef struct { + Str arg; + Pkg *last; + short depth; + short flags; + VersionOp op; +} ProcState; + +static void failmaxrecurse(Out *err, Str tok) +{ + outstr(err, S("pkg-config: ")); + outstr(err, S("exceeded max recursion depth on '")); + outstr(err, tok); + outstr(err, S("'\n")); + flush(err); + os_fail(); +} + +static void failversion(Out *err, Pkg *pkg, VersionOp op, Str want) +{ + outstr(err, S("pkg-config: ")); + outstr(err, S("requested '")); + outstr(err, pkg->realname); + outstr(err, S("' ")); + outstr(err, opname(op)); + outstr(err, S(" '")); + outstr(err, want); + outstr(err, S("' but got '")); + outstr(err, pkg->version); + outstr(err, S("'\n")); + flush(err); + os_fail(); +} + +static void process(Arena *a, Processor *proc, Str arg) +{ + Out *err = proc->err; + Pkgs *pkgs = proc->pkgs; + Env *global = proc->global; + Search *search = &proc->search; + + // NOTE: At >=128, GCC generates a __chkstk_ms on x86-64 because the + // stack frame exceeds 4kB. A -mno-stack-arg-probe solves this, but + // limiting the recursion depth to 64, which is still plenty, avoids + // the issue entirely. + ProcState stack[64]; + int top = 0; + stack[0].arg = arg; + stack[0].last = proc->last; + stack[0].depth = 0; + stack[0].flags = Pkg_DIRECT | Pkg_PUBLIC; + stack[0].op = proc->op; + + while (top >= 0) { + ProcState *s = stack + top; + StrPair pair = nexttoken(s->arg); + Str tok = pair.head; + if (!tok.len) { + if (top>0 && s->op) { + procfail(err, s->op, s->last); + } + top--; + continue; + } + stack[top].arg = pair.tail; + + if (s->op) { + if (!proc->ignore_versions) { + int cmp = compareversions(s->last->version, tok); + if (!validcompare(s->op, cmp)) { + failversion(err, s->last, s->op, tok); + } + } + s->last = 0; + s->op = VersionOp_ERR; + continue; + } + + s->op = parseop(tok); + if (s->op) { + if (!s->last) { + outstr(err, S("pkg-config: ")); + outstr(err, S("unexpected operator '")); + outstr(err, tok); + outstr(err, S("'\n")); + flush(err); + os_fail(); + } + continue; + } + + short depth = s->depth + 1; + short flags = s->flags; + Pkg *pkg = s->last = locate(a, pkgs, pathtorealname(tok)); + if (pkg->contents.s) { + if (flags&Pkg_PUBLIC && !(pkg->flags & Pkg_PUBLIC)) { + // We're on a public branch, but this package was + // previously loaded as private. Recursively traverse + // its public requires and mark all as public. + pkg->flags |= Pkg_PUBLIC; + if (proc->recursive && depthmaxdepth) { + if (top >= COUNTOF(stack)-1) { + failmaxrecurse(err, tok); + } + top++; + stack[top].arg = pkg->requires; + stack[top].last = 0; + stack[top].depth = depth; + stack[top].flags = flags & ~Pkg_DIRECT; + stack[top].op = VersionOp_ERR; + } + } + } else { + // Package hasn't been loaded yet, so find and load it. + Pkg newpkg = findpackage(a, search, err, tok); + if (proc->define_prefix) { + setprefix(a, &newpkg); + } + expandmerge(a, err, global, pkg, &newpkg); + if (proc->recursive && depthmaxdepth) { + if (top >= COUNTOF(stack)-2) { + failmaxrecurse(err, tok); + } + top++; + stack[top].arg = pkg->requiresprivate; + stack[top].last = 0; + stack[top].depth = depth; + stack[top].flags = 0; + stack[top].op = VersionOp_ERR; + top++; + stack[top].arg = pkg->requires; + stack[top].last = 0; + stack[top].depth = depth; + stack[top].flags = flags & ~Pkg_DIRECT; + stack[top].op = VersionOp_ERR; + } + } + pkg->flags |= flags; + } + + proc->last = stack[0].last; + proc->op = stack[0].op; +} + +static void endprocessor(Processor *proc, Out *err) +{ + if (proc->op) { + procfail(err, proc->op, 0); + } +} + +typedef enum { + Filter_ANY, + Filter_I, + Filter_L, + Filter_l, + Filter_OTHERC, + Filter_OTHERL +} Filter; + +static Bool filterok(Filter f, Str arg) +{ + switch (f) { + case Filter_ANY: + return 1; + case Filter_I: + return startswith(arg, S("-I")); + case Filter_L: + return startswith(arg, S("-L")); + case Filter_l: + return startswith(arg, S("-l")); + case Filter_OTHERC: + return !startswith(arg, S("-I")); + case Filter_OTHERL: + return !startswith(arg, S("-L")) && !startswith(arg, S("-l")); + } + ASSERT(0); + return 0; +} + +static void msvcize(Out *out, Str arg) +{ + if (startswith(arg, S("-L"))) { + outstr(out, S("/libpath:")); + outstr(out, cuthead(arg, 2)); + } else if (startswith(arg, S("-I"))) { + outstr(out, S("/I")); + outstr(out, cuthead(arg, 2)); + } else if (startswith(arg, S("-l"))) { + outstr(out, cuthead(arg, 2)); + outstr(out, S(".lib")); + } else if (startswith(arg, S("-D"))) { + outstr(out, S("/D")); + outstr(out, cuthead(arg, 2)); + } else if (equals(arg, S("-mwindows"))) { + outstr(out, S("/subsystem:windows")); + } else if (equals(arg, S("-mconsole"))) { + outstr(out, S("/subsystem:console")); + } else { + outstr(out, arg); + } +} + +typedef struct { + Treap node; + Size position; +} ArgsNode; + +typedef struct { + StrList list; + Treap *map; + Size count; +} Args; + +static Bool dedupable(Str arg) +{ + // Do not count "-I" or "-L" with detached argument + if (arg.len<3 || arg.s[0]!='-') { + return 0; + } else if (equals(arg, S("-pthread"))) { + return 1; + } + Str flags = S("DILflm"); + for (Size i = 0; i < flags.len; i++) { + if (arg.s[1] == flags.s[i]) { + return 1; + } + } + return 0; +} + +static void appendarg(Arena *a, Args *args, Str arg) +{ + Size position = args->count++; + append(a, &args->list, arg); + if (dedupable(arg)) { + ArgsNode *n = (ArgsNode *)treapinsert(a, &args->map, arg, SIZEOF(*n)); + if (!n->position || startswith(arg, S("-l"))) { + // Zero position reserved for null, so bias it by 1 + n->position = 1 + position; + } + } +} + +static void excludearg(Arena *a, Args *args, Str arg) +{ + ArgsNode *n = (ArgsNode *)treapinsert(a, &args->map, arg, SIZEOF(*n)); + n->position = -1; // i.e. position before first argument +} + +// Is this the correct position for the given argument? +static Bool inposition(Args *args, Str arg, Size position) +{ + ArgsNode *n = (ArgsNode *)treapinsert(0, &args->map, arg, SIZEOF(*n)); + return !n || n->position==position+1; +} + +typedef struct { + Arena *arena; + Size *argcount; + Args args; + Filter filter; + Bool msvc; + Byte delim; +} FieldWriter; + +static FieldWriter newfieldwriter(Arena *a, Filter filter, Size *argcount) +{ + FieldWriter w = {0}; + w.arena = a; + w.filter = filter; + w.argcount = argcount; + return w; +} + +static void insertsyspath(FieldWriter *w, Str path, Byte delim, Byte flag) +{ + Arena *a = w->arena; + Byte flagbuf[] = {'-', flag}; + Str prefix = {flagbuf, SIZEOF(flagbuf)}; + + while (path.len) { + Cut c = cut(path, delim); + Str dir = c.head; + path = c.tail; + if (!dir.len) { + continue; + } + + // Prepend option flag + Str syspath = newstr(a, prefix.len+dir.len); + copy(copy(syspath, prefix), dir); + + // Process as an argument, as though being printed + syspath = maybequote(a, syspath); + DequoteResult dr = dequote(a, syspath); + syspath = dr.arg; + + // NOTE(NRK): Technically, the path doesn't need to follow the flag + // immediately e.g `-I /usr/include` (notice the space between -I and + // the include dir!). + // + // But I have not seen a single pc file that does this and so we're not + // handling this edge-case. As a proof that this should be fine in + // practice, `pkgconf` which is used by many distros, also doesn't + // handle it. + if (dr.ok && !dr.tail.len) { + excludearg(a, &w->args, syspath); + } + } +} + +static void appendfield(Out *err, FieldWriter *w, Pkg *p, Str field) +{ + Arena *a = w->arena; + Filter f = w->filter; + while (field.len) { + DequoteResult r = dequote(a, field); + if (!r.ok) { + outstr(err, S("pkg-config: ")); + outstr(err, S("unmatched quote in '")); + outstr(err, p->realname); + outstr(err, S("'\n")); + flush(err); + os_fail(); + } + if (filterok(f, r.arg)) { + appendarg(a, &w->args, r.arg); + } + field = r.tail; + } +} + +static void writeargs(Out *out, FieldWriter *w) +{ + Size position = 0; + Byte delim = w->delim ? w->delim : ' '; + for (StrListNode *n = w->args.list.head; n; n = n->next) { + Str arg = n->entry; + if (inposition(&w->args, arg, position++)) { + if ((*w->argcount)++) { + outbyte(out, delim); + } + if (w->msvc) { + msvcize(out, arg); + } else { + outstr(out, arg); + } + } + } +} + +static int parseuint(Str s, int hi) +{ + int v = 0; + for (Size i = 0; i < s.len; i++) { + Byte c = s.s[i]; + if (digit(c)) { + v = v*10 + c - '0'; + if (v >= hi) { + return hi; + } + } + } + return v; +} + +static void appmain(Config conf) +{ + Arena *a = &conf.arena; + shredfree(a); + + Env global = {0}; + Filter filterc = Filter_ANY; + Filter filterl = Filter_ANY; + Pkgs pkgs = {0}; + Out out = newoutput(a, 1, 1<<12); + Out err = newoutput(a, 2, 1<<7); + Processor proc = newprocessor(&conf, &err, &global, &pkgs); + Size argcount = 0; + + Bool msvc = 0; + Bool libs = 0; + Bool cflags = 0; + Bool err_to_stdout = 0; + Bool silent = 0; + Bool static_ = 0; + Byte argdelim = ' '; + Bool modversion = 0; + VersionOp override_op = VersionOp_ERR; + Str override_version = {0, 0}; + Bool print_sysinc = 0; + Bool print_syslib = 0; + Str variable = {0, 0}; + + proc.define_prefix = conf.define_prefix; + if (!conf.top_builddir.s) { + conf.top_builddir = S("$(top_builddir)"); + } + + *insert(a, &global, S("pc_path")) = conf.fixedpath; + *insert(a, &global, S("pc_system_includedirs")) = conf.sys_incpath; + *insert(a, &global, S("pc_system_libdirs")) = conf.sys_libpath; + *insert(a, &global, S("pc_sysrootdir")) = S("/"); + *insert(a, &global, S("pc_top_builddir")) = conf.top_builddir; + + Str *args = (Str *)allocarray(a, SIZEOF(Str), conf.nargs); + Size nargs = 0; + + for (OptionParser opts = newoptionparser(conf.args, conf.nargs);;) { + OptionResult r = nextoption(&opts); + if (!r.ok) { + break; + } + + if (!r.isoption) { + args[nargs++] = r.arg; + + } else if (equals(r.arg, S("h")) || equals(r.arg, S("-help"))) { + usage(&out); + flush(&out); + return; + + } else if (equals(r.arg, S("-version"))) { + outstr(&out, S(VERSION)); + outbyte(&out, '\n'); + flush(&out); + return; + + } else if (equals(r.arg, S("-modversion"))) { + modversion = 1; + + } else if (equals(r.arg, S("-define-prefix"))) { + proc.define_prefix = 1; + + } else if (equals(r.arg, S("-dont-define-prefix"))) { + proc.define_prefix = 0; + + } else if (equals(r.arg, S("-cflags"))) { + cflags = 1; + filterc = Filter_ANY; + + } else if (equals(r.arg, S("-libs"))) { + libs = 1; + filterl = Filter_ANY; + + } else if (equals(r.arg, S("-variable"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + variable = r.value; + + } else if (equals(r.arg, S("-static"))) { + static_ = 1; + + } else if (equals(r.arg, S("-libs-only-L"))) { + libs = 1; + filterl = Filter_L; + + } else if (equals(r.arg, S("-libs-only-l"))) { + libs = 1; + filterl = Filter_l; + + } else if (equals(r.arg, S("-libs-only-other"))) { + libs = 1; + filterl = Filter_OTHERL; + + } else if (equals(r.arg, S("-cflags-only-I"))) { + cflags = 1; + filterc = Filter_I; + + } else if (equals(r.arg, S("-cflags-only-other"))) { + cflags = 1; + filterc = Filter_OTHERC; + + } else if (equals(r.arg, S("-with-path"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + prependpath(a, &proc.search, r.value); + + } else if (equals(r.arg, S("-maximum-traverse-depth"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + proc.maxdepth = parseuint(r.value, 1000); + + } else if (equals(r.arg, S("-msvc-syntax"))) { + msvc = 1; + + } else if (equals(r.arg, S("-define-variable"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + Cut c = cut(r.value, '='); + if (!c.ok) { + outstr(&err, S("pkg-config: ")); + outstr(&err, S("value missing in --define-variable for '")); + outstr(&err, r.value); + outstr(&err, S("'\n")); + flush(&err); + os_fail(); + } + *insert(a, &global, c.head) = c.tail; + + } else if (equals(r.arg, S("-newlines"))) { + argdelim = '\n'; + + } else if (equals(r.arg, S("-exists"))) { + // The check already happens, just disable the messages + silent = 1; + + } else if (equals(r.arg, S("-atleast-pkgconfig-version"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + return; // always succeeds + + } else if (equals(r.arg, S("-atleast-version"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + override_op = VersionOp_GTE; + override_version = r.value; + silent = 1; + proc.recursive = 0; + proc.ignore_versions = 1; + + } else if (equals(r.arg, S("-exact-version"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + override_op = VersionOp_EQ; + override_version = r.value; + silent = 1; + proc.recursive = 0; + proc.ignore_versions = 1; + + } else if (equals(r.arg, S("-max-version"))) { + if (!r.value.s) { + r.value = getargopt(&err, &opts, r.arg); + } + override_op = VersionOp_LTE; + override_version = r.value; + silent = 1; + proc.recursive = 0; + proc.ignore_versions = 1; + + } else if (equals(r.arg, S("-silence-errors"))) { + silent = 1; + + } else if (equals(r.arg, S("-errors-to-stdout"))) { + err_to_stdout = 1; + + } else if (equals(r.arg, S("-print-errors"))) { + // Ignore + + } else if (equals(r.arg, S("-short-errors"))) { + // Ignore + + } else if (equals(r.arg, S("-uninstalled"))) { + // Ignore + + } else if (equals(r.arg, S("-keep-system-cflags"))) { + print_sysinc = 1; + + } else if (equals(r.arg, S("-keep-system-libs"))) { + print_syslib = 1; + + } else if (equals(r.arg, S("-validate"))) { + silent = 1; + proc.recursive = 0; + + } else { + outstr(&err, S("pkg-config: ")); + outstr(&err, S("unknown option -")); + outstr(&err, r.arg); + outstr(&err, S("\n")); + flush(&err); + os_fail(); + } + } + + if (err_to_stdout) { + err = out; + } + + if (silent) { + err = newnullout(); + } + + for (Size i = 0; i < nargs; i++) { + process(a, &proc, args[i]); + } + endprocessor(&proc, &err); + + if (!pkgs.count) { + outstr(&err, S("pkg-config: ")); + outstr(&err, S("requires at least one package name\n")); + flush(&err); + os_fail(); + } + + // --{atleast,exact,max}-version + if (override_op) { + for (Pkg *p = pkgs.head; p; p = p->list) { + int cmp = compareversions(p->version, override_version); + if (!validcompare(override_op, cmp)) { + failversion(&err, p, override_op, override_version); + } + } + } + + if (modversion) { + for (Pkg *p = pkgs.head; p; p = p->list) { + if (p->flags & Pkg_DIRECT) { + outstr(&out, p->version); + outstr(&out, S("\n")); + } + } + } + + if (variable.s) { + for (Pkg *p = pkgs.head; p; p = p->list) { + if (p->flags & Pkg_DIRECT) { + Str value = lookup(&global, &p->env, variable); + if (value.s) { + expand(&out, &err, &global, p, value); + outstr(&out, S("\n")); + } + } + } + } + + if (cflags) { + Arena temp = *a; // auto-free when done + FieldWriter fw = newfieldwriter(&temp, filterc, &argcount); + fw.delim = argdelim; + fw.msvc = msvc; + if (!print_sysinc) { + insertsyspath(&fw, conf.sys_incpath, conf.delim, 'I'); + } + for (Pkg *p = pkgs.head; p; p = p->list) { + appendfield(&err, &fw, p, p->cflags); + } + writeargs(&out, &fw); + } + + if (libs) { + Arena temp = *a; // auto-free when done + FieldWriter fw = newfieldwriter(&temp, filterl, &argcount); + fw.delim = argdelim; + fw.msvc = msvc; + if (!print_syslib) { + insertsyspath(&fw, conf.sys_libpath, conf.delim, 'L'); + } + for (Pkg *p = pkgs.head; p; p = p->list) { + if (static_) { + appendfield(&err, &fw, p, p->libs); + appendfield(&err, &fw, p, p->libsprivate); + } else if (p->flags & Pkg_PUBLIC) { + appendfield(&err, &fw, p, p->libs); + } + } + writeargs(&out, &fw); + } + + if (cflags || libs) { + outstr(&out, S("\n")); + } + + flush(&out); +} + +#define CMDLINE_CMD_MAX 32767 // max command line length on Windows +#define CMDLINE_ARGV_MAX (16384+(98298+(int)sizeof(char*))/(int)sizeof(char*)) + +// Convert an ill-formed-UTF-16 command line to a WTF-8 argv following +// field splitting semantics identical to CommandLineToArgvW, including +// undocumented behavior. Populates argv with pointers into itself and +// returns argc, which is always positive. +// +// Expects that cmd has no more than 32,767 (CMDLINE_CMD_MAX) elements +// including the null terminator, and argv has at least CMDLINE_ARGV_MAX +// elements. This covers the worst possible cases for a Windows command +// string, so no further allocation is ever necessary. +// +// Unlike CommandLineToArgvW, when the command line string is zero +// length this function does not invent an artificial argv[0] based on +// the calling module file name. To implement this behavior yourself, +// test if cmd[0] is zero and then act accordingly. +// +// If the input is UTF-16, then the output is UTF-8. +static int cmdline_to_argv8(unsigned short *cmd, char **argv) +{ + int argc = 1; // worst case: argv[0] is an empty string + int state = 6; // special argv[0] state + int slash = 0; + // Use second half as byte buffer + unsigned char *buf = (unsigned char *)(argv + 16384); + + argv[0] = (char *)buf; + while (*cmd) { + int c = *cmd++; + if (c>>10 == 0x36 && *cmd>>10 == 0x37) { // surrogates? + c = 0x10000 + ((c - 0xd800)<<10) + (*cmd++ - 0xdc00); + } + + switch (state) { + case 0: switch (c) { // outside token + case 0x09: + case 0x20: continue; + case 0x22: argv[argc++] = (char *)buf; + state = 2; + continue; + case 0x5c: argv[argc++] = (char *)buf; + slash = 1; + state = 3; + break; + default : argv[argc++] = (char *)buf; + state = 1; + } break; + case 1: switch (c) { // inside unquoted token + case 0x09: + case 0x20: *buf++ = 0; + state = 0; + continue; + case 0x22: state = 2; + continue; + case 0x5c: slash = 1; + state = 3; + break; + } break; + case 2: switch (c) { // inside quoted token + case 0x22: state = 5; + continue; + case 0x5c: slash = 1; + state = 4; + break; + } break; + case 3: + case 4: switch (c) { // backslash sequence + case 0x22: buf -= (1 + slash) >> 1; + if (slash & 1) { + state -= 2; + break; + } // fallthrough + default : cmd -= 1 + (c >= 0x10000); + state -= 2; + continue; + case 0x5c: slash++; + } break; + case 5: switch (c) { // quoted token exit + default : cmd -= 1 + (c >= 0x10000); + state = 1; + continue; + case 0x22: state = 1; + } break; + case 6: switch (c) { // begin argv[0] + case 0x09: + case 0x20: *buf++ = 0; + state = 0; + continue; + case 0x22: state = 8; + continue; + default : state = 7; + } break; + case 7: switch (c) { // unquoted argv[0] + case 0x09: + case 0x20: *buf++ = 0; + state = 0; + continue; + } break; + case 8: switch (c) { // quoted argv[0] + case 0x22: *buf++ = 0; + state = 0; + continue; + } break; + } + + // WTF-8/UTF-8 encoding + switch ((c >= 0x80) + (c >= 0x800) + (c >= 0x10000)) { + case 0: *buf++ = 0x00 | ((char)(c >> 0) ); break; + case 1: *buf++ = 0xc0 | ((char)(c >> 6) ); + *buf++ = 0x80 | ((char)(c >> 0) & 63); break; + case 2: *buf++ = 0xe0 | ((char)(c >> 12) ); + *buf++ = 0x80 | ((char)(c >> 6) & 63); + *buf++ = 0x80 | ((char)(c >> 0) & 63); break; + case 3: *buf++ = 0xf0 | ((char)(c >> 18) ); + *buf++ = 0x80 | ((char)(c >> 12) & 63); + *buf++ = 0x80 | ((char)(c >> 6) & 63); + *buf++ = 0x80 | ((char)(c >> 0) & 63); break; + } + } + + *buf = 0; + argv[argc] = 0; + return argc; +} + +// Win32 API: windows.h replacement, halves build times + +typedef int BOOL; +typedef void *HANDLE; +typedef unsigned DWORD; +#if __GNUC__ // in MSVC size_t is a built-in type + typedef __SIZE_TYPE__ size_t; +#endif +#if !__cplusplus || (_MSC_VER && !_NATIVE_WCHAR_T_DEFINED) + // NOTE: wchar_t is a built-in type in C++, except older versions of + // Visual Studio are not so C++-compliant without /Zc:wchar_t. + typedef unsigned short wchar_t; +#endif + +#define CP_UTF8 65001 + +#define FILE_ATTRIBUTE_NORMAL 0x80 + +#define FILE_MAP_READ 4 + +#define FILE_SHARE_DELETE 4 +#define FILE_SHARE_READ 1 +#define FILE_SHARE_WRITE 2 + +#define GENERIC_READ 0x80000000 + +#define INVALID_HANDLE_VALUE ((HANDLE)-1) + +#define MAX_PATH 260 + +#define MEM_COMMIT 0x1000 +#define MEM_RESERVE 0x2000 + +#define OPEN_EXISTING 3 + +#define PAGE_READONLY 2 +#define PAGE_READWRITE 4 + +#define STD_ERROR_HANDLE -12 +#define STD_OUTPUT_HANDLE -11 + +#ifdef __cplusplus +extern "C" { +#endif +__declspec(dllimport) HANDLE __stdcall CreateFileW( + wchar_t *, DWORD, DWORD, void *, DWORD, DWORD, HANDLE); +__declspec(dllimport) BOOL __stdcall CloseHandle(HANDLE); +__declspec(dllimport) HANDLE __stdcall CreateFileMappingA( + HANDLE, void *, DWORD, DWORD, DWORD, char *); +__declspec(dllimport) int __stdcall MultiByteToWideChar( + unsigned, DWORD, char *, int, wchar_t *, int); +__declspec(dllimport) wchar_t *__stdcall GetCommandLineW(void); +__declspec(dllimport) BOOL __stdcall GetConsoleMode(HANDLE, DWORD *); +__declspec(dllimport) DWORD __stdcall GetEnvironmentVariableW( + const wchar_t *, wchar_t *, DWORD); +__declspec(dllimport) DWORD __stdcall GetFileSize(HANDLE, DWORD *); +__declspec(dllimport) DWORD __stdcall GetModuleFileNameW( + HANDLE, wchar_t *, DWORD); +__declspec(dllimport) HANDLE __stdcall GetStdHandle(DWORD); +__declspec(dllimport) void *__stdcall MapViewOfFile( + HANDLE, DWORD, DWORD, DWORD, size_t); +__declspec(dllimport) void *__stdcall VirtualAlloc( + void *, size_t, DWORD, DWORD); +__declspec(dllimport) int __stdcall WideCharToMultiByte( + unsigned, DWORD, wchar_t *, int, char *, int, char *, BOOL *); +__declspec(dllimport) BOOL __stdcall WriteConsoleW( + HANDLE, wchar_t *, DWORD, DWORD *, void *); +__declspec(dllimport) BOOL __stdcall WriteFile( + HANDLE, void *, DWORD, DWORD *, void *); +__declspec(dllimport) __declspec(noreturn) void __stdcall ExitProcess(DWORD); +#ifdef __cplusplus +} +#endif + +// Win32 platform layer for u-config +// This is free and unencumbered software released into the public domain. + +#ifndef PKG_CONFIG_PREFIX +# define PKG_CONFIG_PREFIX +#endif + +#ifdef _MSC_VER + #ifdef __cplusplus + #define EXTERN extern "C" + #else + #define EXTERN + #endif + #define ENTRYPOINT EXTERN + #pragma comment(lib, "kernel32.lib") + #pragma comment(linker, "/subsystem:console") + EXTERN void *memset(void *, int, size_t); + #pragma function(memset) + EXTERN void *memset(void *d, int c, size_t n) + { + char *dst = (char *)d; + for (; n; n--) *dst++ = (char)c; + return d; + } + EXTERN void *memcpy(void *, const void *, size_t); + #pragma function(memcpy) + EXTERN void *memcpy(void *d, const void *s, size_t n) + { + char *dst = (char *)d; + char *src = (char *)s; + for (; n; n--) *dst++ = *src++; + return d; + } +#elif __GNUC__ + #ifdef __cplusplus + #define EXTERN extern "C" __attribute__((externally_visible)) + #else + #define EXTERN __attribute__((externally_visible)) + #endif + #if __i686__ + #define ENTRYPOINT EXTERN __attribute__((force_align_arg_pointer)) + #else + #define ENTRYPOINT EXTERN + #endif + // NOTE: These functions are required at higher GCC optimization + // levels. Placing them in their own section allows them to be + // ommitted via -Wl,--gc-sections when unused. + EXTERN + __attribute__((section(".text.memcpy"))) + void *memcpy(void *d, const void *s, size_t n) + { + // NOTE: polyglot x86 and x64 inline assembly + void *r = d; + __asm volatile ( + "rep movsb" + : "=D"(d), "=S"(s), "=c"(n) + : "0"(d), "1"(s), "2"(n) + : "memory" + ); + return r; + } + EXTERN + __attribute__((section(".text.strlen"))) + size_t strlen(const char *s) + { + const char *b = s; + __asm("repne scasb" : "=D"(s) : "0"(s), "a"(0), "c"((size_t)-1)); + return s - b - 1; + } +#endif + +static Bool error_is_console = 0; + +static Arena newarena_(void) +{ + Arena arena = {0}; + Size cap = 1<<28; + #if DEBUG + cap = 1<<21; + #endif + DWORD type = MEM_COMMIT | MEM_RESERVE; + arena.mem.s = (Byte *)VirtualAlloc(0, cap, type, PAGE_READWRITE); + arena.mem.len = arena.mem.s ? cap : 0; + shredfree(&arena); + return arena; +} + +static Str fromwide_(Arena *a, wchar_t *w, Size wlen) +{ + // NOTE: consider replacing the Win32 UTF-8 encoder/decoder with an + // embedded WTF-8 encoder/decoder + int len = WideCharToMultiByte(CP_UTF8, 0, w, wlen, 0, 0, 0, 0); + Str s = newstr(a, len); + WideCharToMultiByte(CP_UTF8, 0, w, wlen, (char *)s.s, s.len, 0, 0); + return s; +} + +static Str fromenv_(Arena *a, const wchar_t *name) +{ + // NOTE: maximum environment variable size is 2**15-1, so this + // cannot fail if the variable actually exists + static wchar_t w[1<<15]; + DWORD wlen = GetEnvironmentVariableW(name, w, sizeof(w)); + if (!wlen) { + Str r = {0}; + return r; + } + return fromwide_(a, w, wlen); +} + +static Str installdir_(Arena *a) +{ + wchar_t exe[MAX_PATH]; + Size len = GetModuleFileNameW(0, exe, MAX_PATH); + for (Size i = 0; i < len; i++) { + if (exe[i] == '\\') { + exe[i] = '/'; + } + } + Str path = fromwide_(a, exe, len); + return dirname(dirname(path)); +} + +static Str append2_(Arena *a, Str pre, Str suf) +{ + Str s = newstr(a, pre.len+suf.len); + copy(copy(s, pre), suf); + return s; +} + +static Str makepath_(Arena *a, Str base, Str lib, Str share) +{ + Str delim = S(";"); + Size len = base.len + lib.len + delim.len + base.len + share.len; + Str s = newstr(a, len); + Str r = copy(s, base); + r = copy(r, lib); + r = copy(r, delim); + r = copy(r, base); + copy(r, share); + return s; +} + +static Str fromcstr_(char *z) +{ + Str s = {(Byte *)z, 0}; + if (s.s) { + for (; s.s[s.len]; s.len++) {} + } + return s; +} + +ENTRYPOINT +int mainCRTStartup(void) +{ + Config conf = {0}; + conf.delim = ';'; + conf.define_prefix = 1; + conf.arena = newarena_(); + Arena *a = &conf.arena; + + DWORD dummy; + HANDLE err = GetStdHandle(STD_ERROR_HANDLE); + error_is_console = GetConsoleMode(err, &dummy); + + char **argv = (char **)allocarray(a, SIZEOF(*argv), CMDLINE_ARGV_MAX); + unsigned short *cmdline = (unsigned short *)GetCommandLineW(); + conf.nargs = cmdline_to_argv8(cmdline, argv) - 1; + conf.args = (Str *)allocarray(a, SIZEOF(Str), conf.nargs); + for (Size i = 0; i < conf.nargs; i++) { + conf.args[i] = fromcstr_(argv[i+1]); + } + + Str base = installdir_(a); + conf.envpath = fromenv_(a, L"PKG_CONFIG_PATH"); + conf.fixedpath = fromenv_(a, L"PKG_CONFIG_LIBDIR"); + if (!conf.fixedpath.s) { + Str lib = S(PKG_CONFIG_PREFIX "/lib/pkgconfig"); + Str share = S(PKG_CONFIG_PREFIX "/share/pkgconfig"); + conf.fixedpath = makepath_(a, base, lib, share); + } + conf.top_builddir = fromenv_(a, L"PKG_CONFIG_TOP_BUILD_DIR"); + conf.sys_incpath = append2_(a, base, S(PKG_CONFIG_PREFIX "/include")); + conf.sys_libpath = append2_(a, base, S(PKG_CONFIG_PREFIX "/lib")); + + appmain(conf); + ExitProcess(0); +} + +static MapFileResult os_mapfile(Arena *a, Str path) +{ + (void)a; + ASSERT(path.len > 0); + ASSERT(!path.s[path.len-1]); + + wchar_t wpath[MAX_PATH]; + int wlen = MultiByteToWideChar( + CP_UTF8, 0, (char *)path.s, path.len, wpath, MAX_PATH + ); + if (!wlen) { + MapFileResult r = {{0, 0}, MapFile_NOTFOUND}; + return r; + } + + HANDLE h = CreateFileW( + wpath, + GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0 + ); + if (h == INVALID_HANDLE_VALUE) { + MapFileResult r = {{0, 0}, MapFile_NOTFOUND}; + return r; + } + + DWORD hi, lo = GetFileSize(h, &hi); + if (hi || lo>Size_MAX) { + CloseHandle(h); + MapFileResult r = {{0, 0}, MapFile_READERR}; + return r; + } else if (!lo) { + CloseHandle(h); + // Cannot map an empty file, so use the arena for a zero-size + // allocation, distinguishing it from a null string. + MapFileResult r = {newstr(a, 0), MapFile_OK}; + return r; + } + + HANDLE map = CreateFileMappingA(h, 0, PAGE_READONLY, 0, lo, 0); + CloseHandle(h); + if (!map) { + MapFileResult r = {{0, 0}, MapFile_READERR}; + return r; + } + + void *p = MapViewOfFile(map, FILE_MAP_READ, 0, 0, lo); + CloseHandle(map); + if (!p) { + MapFileResult r = {{0, 0}, MapFile_READERR}; + return r; + } + + MapFileResult r = {{(Byte *)p, (Size)lo}, MapFile_OK}; + return r; +} + +static void os_fail(void) +{ + ExitProcess(1); +} + +static void os_write(int fd, Str s) +{ + ASSERT(fd==1 || fd==2); + DWORD id = fd==1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE; + HANDLE h = GetStdHandle(id); + DWORD n; + + if (fd==2 && error_is_console) { + static wchar_t tmp[1<<12]; + int len = MultiByteToWideChar( + CP_UTF8, 0, (char *)s.s, s.len, tmp, sizeof(tmp) + ); + if (len) { + WriteConsoleW(h, tmp, len, &n, 0); + return; + } + // Too large, fallback to WriteFile + } + + BOOL r = WriteFile(h, s.s, s.len, &n, 0); + if (!r || (Size)n!=s.len) { + os_fail(); + } +} diff --git a/.gnu-windows/src/variant-fortran.patch b/.gnu-windows/src/variant-fortran.patch new file mode 100644 index 0000000000..55f4dfa53b --- /dev/null +++ b/.gnu-windows/src/variant-fortran.patch @@ -0,0 +1,17 @@ +--- a/Dockerfile ++++ b/Dockerfile +@@ -102,3 +102,3 @@ RUN cat $PREFIX/src/gcc-*.patch | patch -d/gcc-$GCC_VERSION -p1 \ + --with-pic \ +- --enable-languages=c,c++ \ ++ --enable-languages=c,c++,fortran \ + --enable-libgomp \ +@@ -254,3 +254,3 @@ RUN sed -i 's#=/mingw/include#=/include#' /gcc-$GCC_VERSION/gcc/config.gcc \ + --with-mpfr-lib=/deps/lib \ +- --enable-languages=c,c++ \ ++ --enable-languages=c,c++,fortran \ + --enable-libgomp \ +@@ -288,3 +288,3 @@ RUN $ARCH-gcc -DEXE=gcc.exe -DCMD=cc \ + gcc gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool ld nm objcopy \ +- objdump ranlib readelf size strings strip windmc windres \ ++ objdump ranlib readelf size strings strip windmc windres gfortran \ + | xargs -I{} -P$(nproc) \ diff --git a/.gnu-windows/src/variant-i686.patch b/.gnu-windows/src/variant-i686.patch new file mode 100644 index 0000000000..530758e294 --- /dev/null +++ b/.gnu-windows/src/variant-i686.patch @@ -0,0 +1,43 @@ +--- a/Dockerfile ++++ b/Dockerfile +@@ -65,3 +65,3 @@ COPY gnu-windows.c ../gnu-windows.ico \ + +-ARG ARCH=x86_64-w64-mingw32 ++ARG ARCH=i686-w64-mingw32 + +@@ -93,2 +93,3 @@ RUN /mingw-w64-v$MINGW_VERSION/mingw-w64-headers/configure \ + --with-default-msvcrt=msvcrt-os \ ++ --with-default-win32-winnt=0x0501 \ + && make -j$(nproc) \ +@@ -99,2 +100,5 @@ RUN ln -s $ARCH mingw + ++# Disable UTF-8 manifest for Windows XP (#58) ++RUN echo >/gcc-$GCC_VERSION/gcc/config/i386/winnt-utf8.manifest ++ + WORKDIR /x-gcc +@@ -103,2 +107,3 @@ RUN /gcc-$GCC_VERSION/configure \ + --with-sysroot=/bootstrap \ ++ --with-arch=pentium4 \ + --target=$ARCH \ +@@ -132,4 +137,4 @@ RUN /mingw-w64-v$MINGW_VERSION/mingw-w64-crt/configure \ + --disable-dependency-tracking \ +- --disable-lib32 \ +- --enable-lib64 \ ++ --enable-lib32 \ ++ --disable-lib64 \ + CFLAGS="-Os" \ +@@ -217,2 +222,3 @@ RUN /mingw-w64-v$MINGW_VERSION/mingw-w64-headers/configure \ + --with-default-msvcrt=msvcrt-os \ ++ --with-default-win32-winnt=0x0501 \ + && make -j$(nproc) \ +@@ -227,4 +233,4 @@ RUN /mingw-w64-v$MINGW_VERSION/mingw-w64-crt/configure \ + --disable-dependency-tracking \ +- --disable-lib32 \ +- --enable-lib64 \ ++ --enable-lib32 \ ++ --disable-lib64 \ + CFLAGS="-Os" \ +@@ -251,2 +257,3 @@ RUN /gcc-$GCC_VERSION/configure \ + --with-native-system-header-dir=/include \ ++ --with-arch=pentium4 \ + --target=$ARCH \ diff --git a/.gnu-windows/src/vc++filt.c b/.gnu-windows/src/vc++filt.c new file mode 100644 index 0000000000..6edf851759 --- /dev/null +++ b/.gnu-windows/src/vc++filt.c @@ -0,0 +1,523 @@ +// vc++filt: c++filt for Microsoft Visual C++, like undname +// $ cc -nostartfiles -O -o vc++filt.exe vc++filt.c -ldbghelp +// $ cl /O1 vc++filt.c /link /subsystem:console +// kernel32.lib shell32.lib dbghelp.lib libvcruntime.lib +// * Full Unicode support, including UTF-8 and wide console output +// * Tiny, slim, fast binary, low resource use, CRT-free +// This is free and unencumbered software released into the public domain. +#include + +enum { + BUFFER_CAP = 1<<14, + CONVERT_CAP = 1<<10, + SYMBOL_MAX = 1<<16, + MEMORY_CAP = 1<<24, +}; + +#define countof(a) (size)(sizeof(a) / sizeof(*(a))) +#define new(h, t, n) (t *)alloc(h, sizeof(t)*n) + +typedef unsigned char u8; +typedef unsigned short u16; +typedef signed int b32; +typedef signed int i32; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef char byte; +typedef size_t uptr; +typedef ptrdiff_t size; + +#define W32(r) __declspec(dllimport) r __stdcall +W32(u16 **) CommandLineToArgvW(u16 *, i32 *); +W32(void) ExitProcess(i32); +W32(u16 *) GetCommandLineW(void); +W32(b32) GetConsoleMode(uptr, i32 *); +W32(i32) GetStdHandle(i32); +W32(b32) ReadFile(uptr, u8 *, i32, i32 *, uptr); +W32(i32) UnDecorateSymbolName(u8 *, u8 *, i32, i32); // dbghelp.dll +W32(byte *) VirtualAlloc(byte *, size, i32, i32); +W32(i32) WideCharToMultiByte(i32, i32, u16 *, i32, u8 *, i32, uptr, uptr); +W32(b32) WriteConsoleW(uptr, u16 *, i32, i32 *, uptr); +W32(b32) WriteFile(uptr, u8 *, i32, i32 *, uptr); + +typedef struct { + byte *beg; + byte *end; +} arena; + +// Allocate pointer-aligned, zero-initialized memory, or null on failure. +static void *alloc(arena *a, size len) +{ + size available = a->end - a->beg; + size alignment = -len & (sizeof(void *) - 1); + if (len > available-alignment) { + return 0; // out of memory + } + return a->end -= len + alignment; // NOTE: assume arena is zeroed +} + +typedef struct { + u8 *data; + size len; +} s8; + +static u64 s8hash(s8 s) +{ + // NOTE: hash is fast enough; faster has no throughput impact + u64 h = 0x100; + for (size i = 0; i < s.len; i++) { + h ^= s.data[i]; + h *= 1111111111111111111u; + } + return h; +} + +static b32 s8equals(s8 a, s8 b) +{ + if (a.len != b.len) { + return 0; + } + for (size i = 0; i < a.len; i++) { + if (a.data[i] != b.data[i]) { + return 0; + } + } + return 1; +} + +static s8 s8push(s8 s, u8 c) +{ + s.data[s.len++] = c; + return s; +} + +static s8 s8dup(s8 s, arena *perm) +{ + s8 r = {0}; + r.data = new(perm, u8, s.len); + if (!r.data) { + return r; // out of memory + } + for (size i = 0; i < s.len; i++) { + r.data[i] = s.data[i]; + } + r.len = s.len; + return r; +} + +static s8 s8cuthead(s8 s, size len) +{ + s.data += len; + s.len -= len; + return s; +} + +typedef struct { + s8 remain; + i32 rune; +} utf8result; + +static utf8result utf8decode(s8 s) +{ + utf8result r = {0}; + switch (s.data[0]&0xf0) { + default : r.rune = s.data[0]; + if (r.rune > 0x7f) break; + r.remain = s8cuthead(s, 1); + return r; + case 0xc0: + case 0xd0: if (s.len < 2) break; + if ((s.data[1]&0xc0) != 0x80) break; + r.rune = (i32)(s.data[0]&0x1f) << 6 | + (i32)(s.data[1]&0x3f) << 0; + if (r.rune < 0x80) break; + r.remain = s8cuthead(s, 2); + return r; + case 0xe0: if (s.len < 3) break; + if ((s.data[1]&0xc0) != 0x80) break; + if ((s.data[2]&0xc0) != 0x80) break; + r.rune = (i32)(s.data[0]&0x0f) << 12 | + (i32)(s.data[1]&0x3f) << 6 | + (i32)(s.data[2]&0x3f) << 0; + if (r.rune < 0x800) break; + if (r.rune>=0xd800 && r.rune<=0xdfff) break; + r.remain = s8cuthead(s, 3); + return r; + case 0xf0: if (s.len < 4) break; + if ((s.data[1]&0xc0) != 0x80) break; + if ((s.data[2]&0xc0) != 0x80) break; + if ((s.data[3]&0xc0) != 0x80) break; + r.rune = (i32)(s.data[0]&0x0f) << 18 | + (i32)(s.data[1]&0x3f) << 12 | + (i32)(s.data[2]&0x3f) << 6 | + (i32)(s.data[3]&0x3f) << 0; + if (r.rune < 0x10000) break; + if (r.rune > 0x10ffff) break; + r.remain = s8cuthead(s, 4); + return r; + } + r.rune = 0xfffd; // Replacement Character + r.remain = s8cuthead(s, 1); + return r; +} + +// Encode code point returning the output length (1-2). +static i32 utf16encode(u16 *dst, i32 rune) +{ + if (rune >= 0x10000) { + rune -= 0x10000; + dst[0] = (u16)((rune >> 10) + 0xd800); + dst[1] = (u16)((rune&0x3ff) + 0xdc00); + return 2; + } + dst[0] = (u16)rune; + return 1; +} + +typedef struct { + u8 buf[BUFFER_CAP]; + i32 len; + i32 off; + i32 fd; + b32 eof; +} bufin; + +static bufin *newbufin(arena *perm) +{ + bufin *b = new(perm, bufin, 1); + b->fd = GetStdHandle(-10); + return b; +} + +static u8 readu8(bufin *b) +{ + if (b->eof) { + return 0; + } else if (b->off == b->len) { + ReadFile(b->fd, b->buf, BUFFER_CAP, &b->len, 0); + if (!b->len) { + b->eof = 1; + return 0; + } + b->off = 0; + } + return b->buf[b->off++]; +} + +typedef struct { + u8 buf[BUFFER_CAP]; + i32 len; + i32 fd; + b32 err; + u16 *convert; // scratch space for WriteConsoleW +} bufout; + +static bufout *newbufout(arena *perm) +{ + bufout *b = new(perm, bufout, 1); + b->fd = GetStdHandle(-11); + i32 dummy; + if (GetConsoleMode(b->fd, &dummy)) { + b->convert = new(perm, u16, CONVERT_CAP); + } + return b; +} + +static void flushconsole(bufout *b) +{ + u16 *convert = b->convert; + utf8result r = {0}; + r.remain.data = b->buf; + r.remain.len = b->len; + for (i32 len = 0; !b->err && r.remain.len;) { + r = utf8decode(r.remain); + len += utf16encode(convert+len, r.rune); + if (len>=CONVERT_CAP-1 || !r.remain.len) { + i32 dummy; + b->err = !WriteConsoleW(b->fd, convert, len, &dummy, 0); + len = 0; + } + } + b->len = 0; +} + +static void flush(bufout *b) +{ + if (!b->err && b->len) { + if (b->convert) { + flushconsole(b); + } else { + i32 dummy; + b->err = !WriteFile(b->fd, b->buf, b->len, &dummy, 0); + b->len = 0; + } + } +} + +static void writes8(bufout *b, s8 s) +{ + for (size off = 0; !b->err && offlen; + i32 count = s.len-offbuf + b->len; + for (i32 i = 0; i < count; i++) { + dst[i] = s.data[off+i]; + } + off += count; + b->len += count; + if (b->len == BUFFER_CAP) { + flush(b); + } + } +} + +static void writeu8(bufout *b, u8 c) +{ + s8 s = {0}; + s.data = &c; + s.len = 1; + writes8(b, s); +} + +static b32 ident(u8 c) +{ + // matches $0-9?@A-Z_a-z and 0x80-0xff + static const u32 t[] = { + 0x00000000, 0x83ff0010, 0x87ffffff, 0x07fffffe, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + }; + return t[c>>5] & (u32)1<<(c&31); +} + +typedef struct map map; +struct map { + map *child[4]; + s8 input; + s8 output; +}; + +static map *upsert(map **m, s8 input, arena *perm) +{ + for (u64 h = s8hash(input); *m; h <<= 2) { + if (s8equals(input, (*m)->input)) { + return *m; + } + m = &(*m)->child[h>>62]; + } + input = s8dup(input, perm); + *m = input.data ? new(perm, map, 1) : 0; + if (*m) { + (*m)->input = input; + } + return *m; +} + +// Caches UnDecorateSymbolName calls. Typically ~90% of the symbols are +// repeats. A hash map lookup is significantly faster than undecorating +// through this API, so this measurably improves performance. The cache +// operates correctly when out of memory, just with less caching. +typedef struct { + map *seen; + arena *perm; + u8 *temp; + i32 flags; + i32 hits; // for debugging / tuning + i32 misses; // " +} callcache; + +static callcache *newcache(i32 flags, arena *perm) +{ + callcache *c = new(perm, callcache, 1); + c->perm = perm; + c->temp = new(perm, u8, SYMBOL_MAX); + c->flags = flags; + return c; +} + +static s8 undecorate(callcache *c, s8 sym) +{ + map *m = upsert(&c->seen, sym, c->perm); + if (m && m->output.data) { + c->hits++; + return m->output; + } + + c->misses++; + s8 r = {0}; + r.data = c->temp; + r.len = UnDecorateSymbolName(sym.data, c->temp, SYMBOL_MAX, c->flags); + if (m) { + m->output = s8dup(r, c->perm); + } + return r; +} + +static b32 usage(i32 fd) +{ + static const u8 usage[] = + "usage: vc++filt [-_ahnp] [symbols...] args.index) { + // Do not process standard input + flush(stdout); + return stdout->err; + } + + bufin *stdin = newbufin(&scratch); + for (u8 c = readu8(stdin); !stdin->eof; c = readu8(stdin)) { + if (sym_start && c=='?') { + // Start of a new identifier? + sym = s8push(sym, c); + + } else if (sym.len) { + if (ident(c)) { + // Continue the current identifier + sym = s8push(sym, c); + sym_at |= c=='@'; + if (sym.len == SYMBOL_MAX) { + // Too long, give up on this one + writes8(stdout, sym); + sym.len = sym_at = 0; + } + + } else if (sym_at) { + // Contains at least one @? Try to decode it. + sym = s8push(sym, 0); + s8 out = undecorate(cache, sym); + writes8(stdout, out); + writeu8(stdout, c); + sym.len = sym_at = 0; + + } else { + // Don't try to decode it, just pass it through + writes8(stdout, sym); + writeu8(stdout, c); + sym.len = sym_at = 0; + } + + } else { + // Pass it through + writeu8(stdout, c); + } + + sym_start = !ident(c); + } + + if (sym_at) { + sym = s8push(sym, 0); + s8 out = undecorate(cache, sym); + writes8(stdout, out); + } else { + writes8(stdout, sym); + } + + flush(stdout); + return stdout->err; +} + +void mainCRTStartup(void) +{ + arena scratch = {0}; + scratch.beg = VirtualAlloc(0, MEMORY_CAP, 0x3000, 4); + scratch.end = scratch.beg + MEMORY_CAP; + i32 r = run(scratch); + ExitProcess(r); +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..780144f435 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,55 @@ +# Community Guidelines + +At TheFlightSims, we recognize and celebrate the creativity and collaboration of open +source contributors and the diversity of skills, experiences, cultures, and +opinions they bring to the projects and communities they participate in. + +Everyone of the communities are inclusive environments, based on treating +all individuals respectfully, regardless of +gender identity and expression, sexual orientation, disabilities, +neurodiversity, physical appearance, body size, ethnicity, nationality, race, +age, religion, or similar personal characteristic. + +We value diverse opinions, but we value respectful behavior more. + +Respectful behavior includes: + +* Being considerate, kind, constructive, and helpful. +* Not engaging in demeaning, discriminatory, harassing, hateful, sexualized, or + physically threatening behavior, speech, and imagery. +* Not engaging in unwanted physical contact. + +Some TheFlightSims open source projects may adopt an explicit project code of +conduct, which may have additional detailed expectations for participants. Most +of those projects will use our modified Contributor Covenant. + +## Resolve peacefully + +We do not believe that all conflict is necessarily bad; healthy debate and +disagreement often yields positive results. However, it is never okay to be +disrespectful. + +If you see someone behaving disrespectfully, you are encouraged to address the +behavior directly with those involved. Many issues can be resolved quickly and +easily, and this gives people more control over the outcome of their dispute. +If you are unable to resolve the matter for any reason, or if the behavior is +threatening or harassing, report it. We are dedicated to providing an +environment where participants feel welcome and safe. + +## Reporting problems + +Some TheFlightSims open source projects may adopt a project-specific code of conduct. +In those cases, a TheFlightSims employee will be identified as the Project Steward, +who will receive and handle reports of code of conduct violations. In the event +that a project hasn’t identified a Project Steward, you can report problems by +emailing to welcome.tfs@outlook.com. + +We will investigate every complaint, but you may not receive a direct response. +We will use our discretion in determining when and how to follow up on reported +incidents, which may range from not taking action to permanent expulsion from +the project and project-sponsored spaces. We will notify the accused of the +report and provide them an opportunity to discuss it before any action is +taken. The identity of the reporter will be omitted from the details of the +report supplied to the accused. In potentially harmful situations, such as +ongoing harassment or threats to anyone's safety, we may take action without +notice. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..2ecc6ad2e2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,61 @@ +# CONTRIBUTING + +## Unchangable folders + +Except for the following folders, these unlisted folders should not be changed, under any circumstances, because these are created by GNU, and should be stored in there as the rest-overs. + +* `.admin` - Admin folder, for further changing in the repo +* `.github` - Containing GitHub-related files and actions. +* `.gnu-windows` - Including sources and build instructions. May can change to compatible with the installation +* `.gitattributes`, `.gitignore`, `*.md`, `dockerfile`, and `LICENSE` are all generated by GitHub Actions workflows or manually written. + +## Changes in repo layout and updating versions and tools + +For in-repo layout and updating versions and tools, please run `.admin/run_admin.sh` with changes variables. + +Once it's done, make sure you move all extracted folders into the main repo, remove all compressed files, and also update versioning, paths, and build instructions in `.gnu-windows/build.sh` + +## Building the repo + +> :warning: Warning +> +> Because an unknown error was detected in the Windows Subsystem for Linux, we recommend you build the repo in Linux or use Docker Desktop within Hyper-V. + +### Building within Docker + +You need to run the pre-defined Docker image, mount your cloned GitHub repo, and build from that. + +Replace `` with your real path to the local repo. Double-quote is needed if there are spaces in your path. + +```shell +docker run -it -v :/root shiroinekotfs/gnu-windows:latest bash +``` + +Once you're in the `bash`, try this command: + +```shell +/root/.gnu-windows/build.sh +``` + +Once it's done, you'll see your GNU application is building in folder `.gnu-windows\bootstrap` + +### Building within Linux + +Make sure you've installed all of these packages before building GNU Windows + +```bash +autotools-dev binutils binutils-x86-64-linux-gnu cmake-data cpp cpp-12 fakeroot +fontconfig-config fonts-dejavu-core g++-12 gcc-12 libalgorithm-diff-perl libalgorithm-diff-xs-perl +libalgorithm-merge-perl libaom3 libarchive13 libasan8 libatomic1 libbinutils libbrotli1 libc-dev-bin +libc-devtools libc6-dev libcc1-0 libcrypt-dev libctf-nobfd0 libctf0 libcurl4 libde265-0 libdeflate0 +libdpkg-perl libexpat1 libfakeroot libfile-fcntllock-perl libfl2 libfontconfig1 libfreetype6 +libgcc-12-dev libgd3 libgmpxx4ldbl libgomp1 libheif1 libitm1 libjbig0 libjsoncpp25 liblsan0 +libnghttp2-14 libnsl-dev libnsl2 libnuma1 libpng16-16 libpsl5 libquadmath0 librhash0 librtmp1 +libssh2-1 libstdc++-12-dev libtirpc-dev libtsan2 libubsan1 libuv1 libwebp7 libx11-6 libx11-data +libx265-199 libxau6 libxcb1 libxdmcp6 libxml2 libxpm4 libyuv0 linux-libc-dev manpages-dev patch +publicsuffix rpcsvc-proto unzip autoconf automake bison build-essential cmake curl dpkg-dev flex +g++ gcc libfl-dev libgmp-dev libmpc-dev libmpfr-dev m4 make wget zip texinfo pkg-config python3 +python3-pip python3-venv file mingw-w64-x86-64-dev mingw-w64-i686-dev mingw-w64-tools +``` + +Just run the `/.gnu-windows/build.sh` directly, without changing the current console directory. Don't forget to use `chmod` command. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..f288702d2f --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..69c84e8305 --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +```text +This directory contains various GNU tools for Windows, including +binutils, busybox, cppcheck, ctags, expat, gcc/g++, gdb, libiconv, +make, mingw-64, mpc, mpfr, nasm, PDCurses, vim. + +Each directory (except the one started with dot(.) - these folders +are the main and admin folders) contains tools, with their COPYRIGHT, +assigned to various developers. Except in maintenance, this folder +must be reserved for building the binaries. + +See https://github.com/tfslabs/gnu-windows/issues for reporting +issues. Note please describe your issue in as much detail as possible. + +Copyright years on source files may be listed using range notation, +e.g., 1987-2012, indicating that every year in the range, inclusive, +is a copyrightable year that could otherwise be listed individually. +``` + +# GNU Windows + +GNU Windows is a suite of development kits for Windows, including the tools mentioned above. It is used to build [@TheFlightSims](https://github.com/TheFlightSims) application binaries from sources. + +All exclusive documents, you can try to search for yourself over the Internet. + +> :warning: Warning +> +> GNU Windows only supports the 64-bit Windows operating system. Run best on Windows 10 1903 and later. + +## Getting started + +### Building GNU Windows + +#### Building within Docker + +You must run the pre-defined Docker image, mount your cloned GitHub repo, and build from that. + +Replace `` with your real path to the local repo. Double-quote is needed if there are spaces in your path. + +```shell +docker run -it -v :/root theflightsims/gnu-windows-build:latest bash +``` + +Once you're in the `bash`, try this command: + +```shell +/root/.gnu-windows/build.sh +``` + +Once it's done, you'll see your GNU application is building in folder `.gnu-windows\bootstrap` + +#### Building within Linux + +Make sure you've installed all of these packages before building GNU Windows + +```bash +autotools-dev binutils binutils-x86-64-linux-gnu cmake-data cpp cpp-12 fakeroot fontconfig-config fonts-dejavu-core g++-12 gcc-12 libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libaom3 libarchive13 libasan8 libatomic1 libbinutils libbrotli1 libc-dev-bin libc-devtools libc6-dev libcc1-0 libcrypt-dev libctf-nobfd0 libctf0 libcurl4 libde265-0 libdeflate0 libdpkg-perl libexpat1 libfakeroot libfile-fcntllock-perl libfl2 libfontconfig1 libfreetype6 libgcc-12-dev libgd3 libgmpxx4ldbl libgomp1 libheif1 libitm1 libjbig0 libjsoncpp25 liblsan0 libnghttp2-14 libnsl-dev libnsl2 libnuma1 libpng16-16 libpsl5 libquadmath0 librhash0 librtmp1 libssh2-1 libstdc++-12-dev libtirpc-dev libtsan2 libubsan1 libuv1 libwebp7 libx11-6 libx11-data libx265-199 libxau6 libxcb1 libxdmcp6 libxml2 libxpm4 libyuv0 linux-libc-dev manpages-dev patch publicsuffix rpcsvc-proto unzip autoconf automake bison build-essential cmake curl dpkg-dev flex g++ gcc libfl-dev libgmp-dev libmpc-dev libmpfr-dev m4 make wget zip texinfo pkg-config python3 python3-pip python3-venv file +``` + +Run the `/.gnu-windows/build.sh` directly, without changing the current console directory. Don't forget to use `chmod` command. + +### Extension + +For installing additional GNU Windows extensions, you can go [search at TheFlightSims Internal Labs repos](https://github.com/orgs/tfslabs/repositories?q=gnu-windows) + +### Contributing + +Read the instructions [here](https://github.com/tfslabs/gnu-windows/blob/master/CONTRIBUTING.md) + +## License + +This project is linked with GNU GPL 3.0 License. With no restriction on distribution and reuse. + +GNU Windows is made by the team of TheFlightSims - Department of Research. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..b4ff1fcab8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,28 @@ +# Security + +TheFlightSims takes the security responsibilities of our software products and services seriously, including all open-source software and closed-source software + +## Reporting Security Issues + +**Note:** You shouldn't report the security vulnerabilities on the Issue or the public place. Any attackers can use these vulnerabilities to exploit non-public data - which causes security vulnerability. + +You can report security issues on these platforms: + +* The repository security page (Preferred) +* [Email](mailto:welcome.tfs@outlook.com) + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +* Type of issue (e.g., buffer overflow, SQL injection, cross-site scripting) +* Full paths of the source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the case, including how an attacker might control the issue + +This information will help us triage your report more quickly. + +## Preferred Languages + +You can use all human-valid languages. However, you may consider using English (US) to prevent misunderstanding. diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000000..e0299dface --- /dev/null +++ b/dockerfile @@ -0,0 +1,18 @@ +# Use an official Ubuntu image as base +FROM debian:latest + +# Install git and any other dependencies needed for your build script +RUN apt update && \ + apt upgrade -y && \ + apt install -y autotools-dev binutils binutils-x86-64-linux-gnu cmake-data cpp cpp-12 fakeroot \ + fontconfig-config fonts-dejavu-core g++-12 gcc-12 libalgorithm-diff-perl libalgorithm-diff-xs-perl \ + libalgorithm-merge-perl libaom3 libarchive13 libasan8 libatomic1 libbinutils libbrotli1 libc-dev-bin \ + libc-devtools libc6-dev libcc1-0 libcrypt-dev libctf-nobfd0 libctf0 libcurl4 libde265-0 libdeflate0 \ + libdpkg-perl libexpat1 libfakeroot libfile-fcntllock-perl libfl2 libfontconfig1 libfreetype6 \ + libgcc-12-dev libgd3 libgmpxx4ldbl libgomp1 libheif1 libitm1 libjbig0 libjsoncpp25 liblsan0 \ + libnghttp2-14 libnsl-dev libnsl2 libnuma1 libpng16-16 libpsl5 libquadmath0 librhash0 librtmp1 \ + libssh2-1 libstdc++-12-dev libtirpc-dev libtsan2 libubsan1 libuv1 libwebp7 libx11-6 libx11-data \ + libx265-199 libxau6 libxcb1 libxdmcp6 libxml2 libxpm4 libyuv0 linux-libc-dev manpages-dev patch \ + publicsuffix rpcsvc-proto unzip autoconf automake bison build-essential cmake curl dpkg-dev flex \ + g++ gcc libfl-dev libgmp-dev libmpc-dev libmpfr-dev m4 make wget zip texinfo pkg-config python3 \ + python3-pip python3-venv file