--- /dev/null
+## Process this file with automake to produce Makefile.in\r
+CC=gcc\r
+INCLUDE=-I ./include -I /usr/include/freetype2/ -I /usr/include/freetype2/freetype/ -I /usr/include/freetype2/freetype/config/\r
+\r
+OPTIONS=-g -FPIC \r
+\r
+MAINSOURCES = \\r
+ src/harfbuzz-dump.c \\r
+ src/harfbuzz-shaper-all.c \\r
+ src/harfbuzz-external.c \\r
+ src/harfbuzz.c\r
+ \r
+ OBJECTS = \\r
+ harfbuzz-dump.o \\r
+ harfbuzz-shaper-all.o \\r
+ harfbuzz-external.o \\r
+ harfbuzz.o\r
+\r
+\r
+TARGET=libharfbuzz.so\r
+library :\r
+ cc -Wall $(INCLUDE) $(OPTIONS) -c $(MAINSOURCES) \r
+\r
+all: library\r
+ cc -shared -Wl,-soname,$(TARGET) -o $(TARGET) $(OBJECTS)\r
+install:\r
+ mkdir -p debian/tmp/usr/lib\r
+ mv $(TARGET) debian/tmp/usr/lib\r
+\r
+clean:\r
+ rm -rf *.o *.so\r
--- /dev/null
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-04-22'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit 0 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ amd64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit 0 ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms && exit 0 ;;
+ I*) echo ia64-dec-vms && exit 0 ;;
+ V*) echo vax-dec-vms && exit 0 ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-04-22'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit 0 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ amd64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit 0 ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms && exit 0 ;;
+ I*) echo ia64-dec-vms && exit 0 ;;
+ V*) echo vax-dec-vms && exit 0 ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-04-22'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+libharfbuzz (0.1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- prameet <prameet.k@partner.samsung.coms> Fri, 05 Mar 2010 10:49:10 +0530
--- /dev/null
+Source: libharfbuzz
+Section: libs
+Priority: optional
+Maintainer: prameet <prameet.k@partner.samsung.coms>
+Build-Depends: debhelper (>= 5),libfreetype6-dev,autotools-dev, libelm-dev, libslp-utilx-dev, libslp-applog-dev, libui-indicator-dev, libslp-appfwk-dev, libisf-dev,libslp-setting-dev,libslp-util-dev
+Standards-Version: 3.7.2
+
+Package: libharfbuzz
+Architecture: any
+Depends:
+Description: Hindi reshaping library
+
+Package: libharfbuzz-dbg
+Section: debug
+Architecture: any
+Depends:
+Description: Hindi reshaping library (unstripped)
+
--- /dev/null
+This is harfbuzz library ,maintained by prameet <prameet.k@partner.samsung.coms>
+on Fri, 05 Mar 2010 10:49:10 +0530.
+
+The original source can always be found at:
+ ftp://ftp.debian.org/dists/unstable/main/source/
+
+Copyright Holder: unknown
+
+License:
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
--- /dev/null
+usr/bin
+usr/sbin
--- /dev/null
+libharfbuzz_0.1_armel.deb libs optional
+libharfbuzz-dbg_0.1_armel.deb debug optional
--- /dev/null
+Package: libharfbuzz-dbg
+Source: libharfbuzz
+Version: 0.1
+Architecture: armel
+Maintainer: prameet <prameet.k@partner.samsung.coms>
+Installed-Size: 52
+Section: debug
+Priority: optional
+Description: Hindi reshaping library (unstripped)
--- /dev/null
+88c5a21ba88009f719bf8bc1a8f45b83 usr/share/doc/libharfbuzz-dbg/copyright
+2e52c13d24bea17bfeb558305c5680d9 usr/share/doc/libharfbuzz-dbg/changelog.gz
+a493443ed45e75d80aeb2cc40938de79 usr/lib/debug/usr/lib/libharfbuzz.so
--- /dev/null
+usr/lib/libharfbuzz.so
--- /dev/null
+Package: libharfbuzz
+Version: 0.1
+Architecture: armel
+Maintainer: prameet <prameet.k@partner.samsung.coms>
+Installed-Size: 304
+Section: libs
+Priority: optional
+Description: Hindi reshaping library
--- /dev/null
+88c5a21ba88009f719bf8bc1a8f45b83 usr/share/doc/libharfbuzz/copyright
+2e52c13d24bea17bfeb558305c5680d9 usr/share/doc/libharfbuzz/changelog.gz
+9221bd50ac8b7266e64caa16cd11e100 usr/lib/libharfbuzz.so
--- /dev/null
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+CFLAGS ?= -Wall -g
+CXXFLAGS ?= -Wall -g
+LDFLAGS ?=
+PREFIX ?= /usr
+DATADIR ?= /opt
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+ CXXFLAGS += -O0
+else
+ CFLAGS += -O2
+ CXXFLAGS += -O2
+endif
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ # Add here commands to configure the package.
+ PREFIX=$(PREFIX) make -f Makefile all
+
+build: build-stamp
+
+build-stamp: configure-stamp
+ dh_testdir
+
+ # Add here commands to compile the package.
+ $(MAKE)
+ #docbook-to-man debian/harfbuzz.sgml > harfbuzz.1
+ for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+ cat $$f > $${f%.in}; \
+ sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
+ sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
+ done
+
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ -$(MAKE) clean
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+ cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+ cp -f /usr/share/misc/config.guess config.guess
+endif
+
+ for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+ rm -f $${f%.in}; \
+ done
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/harfbuzz.
+ $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installdocs
+ dh_installexamples
+ dh_install --sourcedir=debian/tmp
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_python
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+ dh_installman
+ dh_link
+ dh_strip
+ dh_strip --dbg-package=libharfbuzz-dbg
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2004,2007 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Owen Taylor, Behdad Esfahbod\r
+ */\r
+\r
+#ifndef HARFBUZZ_BUFFER_PRIVATE_H\r
+#define HARFBUZZ_BUFFER_PRIVATE_H\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-buffer.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+#define HB_GLYPH_PROPERTIES_UNKNOWN 0xFFFF\r
+\r
+HB_INTERNAL void\r
+_hb_buffer_swap( HB_Buffer buffer );\r
+\r
+HB_INTERNAL void\r
+_hb_buffer_clear_output( HB_Buffer buffer );\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_clear_positions( HB_Buffer buffer );\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_add_output_glyphs( HB_Buffer buffer,\r
+ HB_UShort num_in,\r
+ HB_UShort num_out,\r
+ HB_UShort *glyph_data,\r
+ HB_UShort component,\r
+ HB_UShort ligID );\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_add_output_glyph ( HB_Buffer buffer,\r
+ HB_UInt glyph_index,\r
+ HB_UShort component,\r
+ HB_UShort ligID );\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_copy_output_glyph ( HB_Buffer buffer );\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_replace_output_glyph ( HB_Buffer buffer,\r
+ HB_UInt glyph_index,\r
+ HB_Bool inplace );\r
+\r
+HB_INTERNAL HB_UShort\r
+_hb_buffer_allocate_ligid( HB_Buffer buffer );\r
+\r
+\r
+/* convenience macros */\r
+\r
+#define IN_GLYPH( pos ) (buffer->in_string[(pos)].gindex)\r
+#define IN_ITEM( pos ) (&buffer->in_string[(pos)])\r
+#define IN_CURGLYPH() (buffer->in_string[buffer->in_pos].gindex)\r
+#define IN_CURITEM() (&buffer->in_string[buffer->in_pos])\r
+#define IN_PROPERTIES( pos ) (buffer->in_string[(pos)].properties)\r
+#define IN_LIGID( pos ) (buffer->in_string[(pos)].ligID)\r
+#define IN_COMPONENT( pos ) (buffer->in_string[(pos)].component)\r
+#define POSITION( pos ) (&buffer->positions[(pos)])\r
+#define OUT_GLYPH( pos ) (buffer->out_string[(pos)].gindex)\r
+#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])\r
+\r
+#define CHECK_Property( gdef, index, flags, property ) \\r
+ ( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags), \\r
+ (property) ) ) != HB_Err_Ok )\r
+\r
+#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \\r
+ ( ( error = _hb_buffer_add_output_glyphs( (buffer), \\r
+ (num_in), (num_out), \\r
+ (glyph_data), (component), (ligID) \\r
+ ) ) != HB_Err_Ok )\r
+#define ADD_Glyph( buffer, glyph_index, component, ligID ) \\r
+ ( ( error = _hb_buffer_add_output_glyph( (buffer), \\r
+ (glyph_index), (component), (ligID) \\r
+ ) ) != HB_Err_Ok )\r
+#define REPLACE_Glyph( buffer, glyph_index, nesting_level ) \\r
+ ( ( error = _hb_buffer_replace_output_glyph( (buffer), (glyph_index), \\r
+ (nesting_level) == 1 ) ) != HB_Err_Ok )\r
+#define COPY_Glyph( buffer ) \\r
+ ( (error = _hb_buffer_copy_output_glyph ( buffer ) ) != HB_Err_Ok )\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_BUFFER_PRIVATE_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2004,2007 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Owen Taylor, Behdad Esfahbod\r
+ */\r
+\r
+#ifndef HARFBUZZ_BUFFER_H\r
+#define HARFBUZZ_BUFFER_H\r
+\r
+#include "harfbuzz-global.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+typedef struct HB_GlyphItemRec_ {\r
+ HB_UInt gindex;\r
+ HB_UInt properties;\r
+ HB_UInt cluster;\r
+ HB_UShort component;\r
+ HB_UShort ligID;\r
+ HB_UShort gproperties;\r
+} HB_GlyphItemRec, *HB_GlyphItem;\r
+\r
+typedef struct HB_PositionRec_ {\r
+ HB_Fixed x_pos;\r
+ HB_Fixed y_pos;\r
+ HB_Fixed x_advance;\r
+ HB_Fixed y_advance;\r
+ HB_UShort back; /* number of glyphs to go back\r
+ for drawing current glyph */\r
+ HB_Bool new_advance; /* if set, the advance width values are\r
+ absolute, i.e., they won't be\r
+ added to the original glyph's value\r
+ but rather replace them. */\r
+ HB_Short cursive_chain; /* character to which this connects,\r
+ may be positive or negative; used\r
+ only internally */\r
+} HB_PositionRec, *HB_Position;\r
+\r
+\r
+typedef struct HB_BufferRec_{ \r
+ HB_UInt allocated;\r
+\r
+ HB_UInt in_length;\r
+ HB_UInt out_length;\r
+ HB_UInt in_pos;\r
+ HB_UInt out_pos;\r
+ \r
+ HB_Bool separate_out;\r
+ HB_GlyphItem in_string;\r
+ HB_GlyphItem out_string;\r
+ HB_GlyphItem alt_string;\r
+ HB_Position positions;\r
+ HB_UShort max_ligID;\r
+} HB_BufferRec, *HB_Buffer;\r
+\r
+HB_Error\r
+hb_buffer_new( HB_Buffer *buffer );\r
+\r
+void\r
+hb_buffer_free( HB_Buffer buffer );\r
+\r
+void\r
+hb_buffer_clear( HB_Buffer buffer );\r
+\r
+HB_Error\r
+hb_buffer_add_glyph( HB_Buffer buffer,\r
+ HB_UInt glyph_index,\r
+ HB_UInt properties,\r
+ HB_UInt cluster );\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_BUFFER_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 2000, 2007 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Owen Taylor, Behdad Esfahbod\r
+ */\r
+\r
+#ifndef HARFBUZZ_DUMP_H\r
+#define HARFBUZZ_DUMP_H\r
+\r
+#include <stdio.h>\r
+#include "harfbuzz-gsub.h"\r
+#include "harfbuzz-gpos.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+void HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream);\r
+void HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream);\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_DUMP_H */\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_EXTERNAL_H\r
+#define HARFBUZZ_EXTERNAL_H\r
+\r
+#include "harfbuzz-global.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+/* This header contains some methods that are not part of\r
+ Harfbuzz itself, but referenced by it.\r
+ They need to be provided by the application/library\r
+*/\r
+\r
+\r
+/*\r
+ see http://www.unicode.org/reports/tr14/tr14-19.html\r
+ we don't use the XX, AI and CB properties and map them to AL instead.\r
+ as we don't support any EBDIC based OS'es, NL is ignored and mapped to AL as well.\r
+*/\r
+typedef enum {\r
+ HB_LineBreak_OP, HB_LineBreak_CL, HB_LineBreak_QU, HB_LineBreak_GL, HB_LineBreak_NS,\r
+ HB_LineBreak_EX, HB_LineBreak_SY, HB_LineBreak_IS, HB_LineBreak_PR, HB_LineBreak_PO,\r
+ HB_LineBreak_NU, HB_LineBreak_AL, HB_LineBreak_ID, HB_LineBreak_IN, HB_LineBreak_HY,\r
+ HB_LineBreak_BA, HB_LineBreak_BB, HB_LineBreak_B2, HB_LineBreak_ZW, HB_LineBreak_CM,\r
+ HB_LineBreak_WJ, HB_LineBreak_H2, HB_LineBreak_H3, HB_LineBreak_JL, HB_LineBreak_JV,\r
+ HB_LineBreak_JT, HB_LineBreak_SA, HB_LineBreak_SG,\r
+ HB_LineBreak_SP, HB_LineBreak_CR, HB_LineBreak_LF, HB_LineBreak_BK\r
+} HB_LineBreakClass;\r
+\r
+typedef enum \r
+{\r
+ HB_NoCategory,\r
+\r
+ HB_Mark_NonSpacing, /* Mn */\r
+ HB_Mark_SpacingCombining, /* Mc */\r
+ HB_Mark_Enclosing, /* Me */\r
+\r
+ HB_Number_DecimalDigit, /* Nd */\r
+ HB_Number_Letter, /* Nl */\r
+ HB_Number_Other, /* No */\r
+\r
+ HB_Separator_Space, /* Zs */\r
+ HB_Separator_Line, /* Zl */\r
+ HB_Separator_Paragraph, /* Zp */\r
+\r
+ HB_Other_Control, /* Cc */\r
+ HB_Other_Format, /* Cf */\r
+ HB_Other_Surrogate, /* Cs */\r
+ HB_Other_PrivateUse, /* Co */\r
+ HB_Other_NotAssigned, /* Cn */\r
+\r
+ HB_Letter_Uppercase, /* Lu */\r
+ HB_Letter_Lowercase, /* Ll */\r
+ HB_Letter_Titlecase, /* Lt */\r
+ HB_Letter_Modifier, /* Lm */\r
+ HB_Letter_Other, /* Lo */\r
+\r
+ HB_Punctuation_Connector, /* Pc */\r
+ HB_Punctuation_Dash, /* Pd */\r
+ HB_Punctuation_Open, /* Ps */\r
+ HB_Punctuation_Close, /* Pe */\r
+ HB_Punctuation_InitialQuote, /* Pi */\r
+ HB_Punctuation_FinalQuote, /* Pf */\r
+ HB_Punctuation_Other, /* Po */\r
+\r
+ HB_Symbol_Math, /* Sm */\r
+ HB_Symbol_Currency, /* Sc */\r
+ HB_Symbol_Modifier, /* Sk */\r
+ HB_Symbol_Other /* So */\r
+} HB_CharCategory;\r
+\r
+typedef enum\r
+{\r
+ HB_Grapheme_Other, \r
+ HB_Grapheme_CR,\r
+ HB_Grapheme_LF,\r
+ HB_Grapheme_Control,\r
+ HB_Grapheme_Extend,\r
+ HB_Grapheme_L, \r
+ HB_Grapheme_V, \r
+ HB_Grapheme_T, \r
+ HB_Grapheme_LV, \r
+ HB_Grapheme_LVT\r
+} HB_GraphemeClass;\r
+\r
+\r
+typedef enum\r
+{\r
+ HB_Word_Other,\r
+ HB_Word_Format,\r
+ HB_Word_Katakana,\r
+ HB_Word_ALetter,\r
+ HB_Word_MidLetter,\r
+ HB_Word_MidNum,\r
+ HB_Word_Numeric,\r
+ HB_Word_ExtendNumLet\r
+} HB_WordClass;\r
+\r
+\r
+typedef enum\r
+{\r
+ HB_Sentence_Other,\r
+ HB_Sentence_Sep,\r
+ HB_Sentence_Format,\r
+ HB_Sentence_Sp,\r
+ HB_Sentence_Lower,\r
+ HB_Sentence_Upper,\r
+ HB_Sentence_OLetter,\r
+ HB_Sentence_Numeric,\r
+ HB_Sentence_ATerm,\r
+ HB_Sentence_STerm,\r
+ HB_Sentence_Close\r
+} HB_SentenceClass;\r
+\r
+HB_GraphemeClass HB_GetGraphemeClass(HB_UChar32 ch);\r
+HB_WordClass HB_GetWordClass(HB_UChar32 ch);\r
+HB_SentenceClass HB_GetSentenceClass(HB_UChar32 ch);\r
+HB_LineBreakClass HB_GetLineBreakClass(HB_UChar32 ch);\r
+\r
+void HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *grapheme, HB_LineBreakClass *lineBreak);\r
+void HB_GetUnicodeCharProperties(HB_UChar32 ch, HB_CharCategory *category, int *combiningClass);\r
+HB_CharCategory HB_GetUnicodeCharCategory(HB_UChar32 ch);\r
+int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch);\r
+HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch);\r
+\r
+void *HB_Library_Resolve(const char *library, const char *symbol);\r
+\r
+void *HB_TextCodecForMib(int mib);\r
+char *HB_TextCodec_ConvertFromUnicode(void *codec, const HB_UChar16 *unicode, hb_uint32 length, hb_uint32 *outputLength);\r
+void HB_TextCodec_FreeResult(char *);\r
+\r
+HB_END_HEADER\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_GDEF_PRIVATE_H\r
+#define HARFBUZZ_GDEF_PRIVATE_H\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-stream-private.h"\r
+#include "harfbuzz-buffer-private.h"\r
+#include "harfbuzz-gdef.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+\r
+/* Attachment related structures */\r
+\r
+struct HB_AttachPoint_\r
+{\r
+ HB_UShort PointCount; /* size of the PointIndex array */\r
+ HB_UShort* PointIndex; /* array of contour points */\r
+};\r
+\r
+/* Ligature Caret related structures */\r
+\r
+struct HB_CaretValueFormat1_\r
+{\r
+ HB_Short Coordinate; /* x or y value (in design units) */\r
+};\r
+\r
+typedef struct HB_CaretValueFormat1_ HB_CaretValueFormat1;\r
+\r
+\r
+struct HB_CaretValueFormat2_\r
+{\r
+ HB_UShort CaretValuePoint; /* contour point index on glyph */\r
+};\r
+\r
+typedef struct HB_CaretValueFormat2_ HB_CaretValueFormat2;\r
+\r
+\r
+struct HB_CaretValueFormat3_\r
+{\r
+ HB_Short Coordinate; /* x or y value (in design units) */\r
+ HB_Device Device; /* Device table for x or y value */\r
+};\r
+\r
+typedef struct HB_CaretValueFormat3_ HB_CaretValueFormat3;\r
+\r
+\r
+struct HB_CaretValueFormat4_\r
+{\r
+ HB_UShort IdCaretValue; /* metric ID */\r
+};\r
+\r
+typedef struct HB_CaretValueFormat4_ HB_CaretValueFormat4;\r
+\r
+\r
+struct HB_CaretValue_\r
+{\r
+ HB_UShort CaretValueFormat; /* 1, 2, 3, or 4 */\r
+\r
+ union\r
+ {\r
+ HB_CaretValueFormat1 cvf1;\r
+ HB_CaretValueFormat2 cvf2;\r
+ HB_CaretValueFormat3 cvf3;\r
+ HB_CaretValueFormat4 cvf4;\r
+ } cvf;\r
+};\r
+\r
+typedef struct HB_CaretValue_ HB_CaretValue;\r
+\r
+\r
+struct HB_LigGlyph_\r
+{\r
+ HB_Bool loaded;\r
+\r
+ HB_UShort CaretCount; /* number of caret values */\r
+ HB_CaretValue* CaretValue; /* array of caret values */\r
+};\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,\r
+ HB_UShort glyphID,\r
+ HB_UShort property );\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GDEF_Check_Property( HB_GDEFHeader* gdef,\r
+ HB_GlyphItem item,\r
+ HB_UShort flags,\r
+ HB_UShort* property );\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,\r
+ HB_Stream input,\r
+ HB_Lookup* lo,\r
+ HB_UShort num_lookups );\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_GDEF_PRIVATE_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_GDEF_H\r
+#define HARFBUZZ_GDEF_H\r
+\r
+#include "harfbuzz-open.h"\r
+#include "harfbuzz-stream.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+/* GDEF glyph properties. Note that HB_GDEF_COMPONENT has no corresponding\r
+ * flag in the LookupFlag field. */\r
+#define HB_GDEF_BASE_GLYPH 0x0002\r
+#define HB_GDEF_LIGATURE 0x0004\r
+#define HB_GDEF_MARK 0x0008\r
+#define HB_GDEF_COMPONENT 0x0010\r
+\r
+\r
+typedef struct HB_AttachPoint_ HB_AttachPoint;\r
+\r
+\r
+struct HB_AttachList_\r
+{\r
+ HB_Bool loaded;\r
+\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort GlyphCount; /* number of glyphs with\r
+ attachments */\r
+ HB_AttachPoint* AttachPoint; /* array of AttachPoint tables */\r
+};\r
+\r
+typedef struct HB_AttachList_ HB_AttachList;\r
+\r
+typedef struct HB_LigGlyph_ HB_LigGlyph;\r
+\r
+struct HB_LigCaretList_\r
+{\r
+ HB_Bool loaded;\r
+\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort LigGlyphCount; /* number of ligature glyphs */\r
+ HB_LigGlyph* LigGlyph; /* array of LigGlyph tables */\r
+};\r
+\r
+typedef struct HB_LigCaretList_ HB_LigCaretList;\r
+\r
+\r
+\r
+/* The `NewGlyphClasses' field is not defined in the TTO specification.\r
+ We use it for fonts with a constructed `GlyphClassDef' structure\r
+ (i.e., which don't have a GDEF table) to collect glyph classes\r
+ assigned during the lookup process. The number of arrays in this\r
+ pointer array is GlyphClassDef->cd.cd2.ClassRangeCount+1; the nth\r
+ array then contains the glyph class values of the glyphs not covered\r
+ by the ClassRangeRecords structures with index n-1 and n. We store\r
+ glyph class values for four glyphs in a single array element.\r
+\r
+ `LastGlyph' is identical to the number of glyphs minus one in the\r
+ font; we need it only if `NewGlyphClasses' is not NULL (to have an\r
+ upper bound for the last array).\r
+\r
+ Note that we first store the file offset to the `MarkAttachClassDef'\r
+ field (which has been introduced in OpenType 1.2) -- since the\r
+ `Version' field value hasn't been increased to indicate that we have\r
+ one more field for some obscure reason, we must parse the GSUB table\r
+ to find out whether class values refer to this table. Only then we\r
+ can finally load the MarkAttachClassDef structure if necessary. */\r
+\r
+struct HB_GDEFHeader_\r
+{\r
+ HB_UInt offset;\r
+\r
+ HB_16Dot16 Version;\r
+\r
+ HB_ClassDefinition GlyphClassDef;\r
+ HB_AttachList AttachList;\r
+ HB_LigCaretList LigCaretList;\r
+ HB_UInt MarkAttachClassDef_offset;\r
+ HB_ClassDefinition MarkAttachClassDef; /* new in OT 1.2 */\r
+\r
+ HB_UShort LastGlyph;\r
+ HB_UShort** NewGlyphClasses;\r
+};\r
+\r
+typedef struct HB_GDEFHeader_ HB_GDEFHeader;\r
+typedef struct HB_GDEFHeader_* HB_GDEF;\r
+\r
+\r
+HB_Error HB_New_GDEF_Table( HB_GDEFHeader** retptr );\r
+ \r
+\r
+HB_Error HB_Load_GDEF_Table( HB_Stream stream,\r
+ HB_GDEFHeader** gdef );\r
+\r
+\r
+HB_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef );\r
+\r
+\r
+HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,\r
+ HB_UShort glyphID,\r
+ HB_UShort* property );\r
+\r
+HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,\r
+ HB_UShort num_glyphs,\r
+ HB_UShort glyph_count,\r
+ HB_UShort* glyph_array,\r
+ HB_UShort* class_array );\r
+\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_GDEF_H */\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ */\r
+\r
+#ifndef HARFBUZZ_GLOBAL_H\r
+#define HARFBUZZ_GLOBAL_H\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#ifdef __cplusplus\r
+#define HB_BEGIN_HEADER extern "C" {\r
+#define HB_END_HEADER }\r
+#else\r
+#define HB_BEGIN_HEADER /* nothing */\r
+#define HB_END_HEADER /* nothing */\r
+#endif\r
+\r
+HB_BEGIN_HEADER\r
+\r
+#ifndef FALSE\r
+#define FALSE 0\r
+#endif\r
+\r
+#ifndef TRUE\r
+#define TRUE (!FALSE)\r
+#endif\r
+\r
+#ifndef false\r
+#define false 0\r
+#endif\r
+\r
+#ifndef true\r
+#define true (!FALSE)\r
+#endif\r
+\r
+#define HB_MAKE_TAG( _x1, _x2, _x3, _x4 ) \\r
+ ( ( (HB_UInt)_x1 << 24 ) | \\r
+ ( (HB_UInt)_x2 << 16 ) | \\r
+ ( (HB_UInt)_x3 << 8 ) | \\r
+ (HB_UInt)_x4 )\r
+\r
+typedef char hb_int8;\r
+typedef unsigned char hb_uint8;\r
+typedef short hb_int16;\r
+typedef unsigned short hb_uint16;\r
+typedef int hb_int32;\r
+typedef unsigned int hb_uint32;\r
+\r
+typedef hb_uint8 HB_Bool;\r
+typedef hb_uint8 bool;\r
+\r
+typedef hb_uint8 HB_Byte;\r
+typedef hb_uint16 HB_UShort;\r
+typedef hb_uint32 HB_UInt;\r
+typedef hb_int8 HB_Char;\r
+typedef hb_int16 HB_Short;\r
+typedef hb_int32 HB_Int;\r
+\r
+typedef hb_uint16 HB_UChar16;\r
+typedef hb_uint32 HB_UChar32;\r
+typedef hb_uint32 HB_Glyph;\r
+typedef hb_int32 HB_Fixed; /* 26.6 */\r
+\r
+#define HB_FIXED_CONSTANT(v) ((v) * 64)\r
+#define HB_FIXED_ROUND(v) (((v)+32) & -64)\r
+\r
+typedef hb_int32 HB_16Dot16; /* 16.16 */\r
+\r
+typedef void * HB_Pointer;\r
+typedef hb_uint32 HB_Tag;\r
+\r
+typedef enum {\r
+ /* no error */\r
+ HB_Err_Ok = 0x0000,\r
+ HB_Err_Not_Covered = 0xFFFF,\r
+\r
+ /* _hb_err() is called whenever returning the following errors,\r
+ * and in a couple places for HB_Err_Not_Covered too. */\r
+\r
+ /* programmer error */\r
+ HB_Err_Invalid_Argument = 0x1A66,\r
+\r
+ /* font error */\r
+ HB_Err_Invalid_SubTable_Format = 0x157F,\r
+ HB_Err_Invalid_SubTable = 0x1570,\r
+ HB_Err_Read_Error = 0x6EAD,\r
+\r
+ /* system error */\r
+ HB_Err_Out_Of_Memory = 0xDEAD\r
+} HB_Error;\r
+\r
+typedef struct {\r
+ HB_Fixed x;\r
+ HB_Fixed y;\r
+} HB_FixedPoint;\r
+\r
+typedef struct HB_Font_ *HB_Font;\r
+typedef struct HB_StreamRec_ *HB_Stream;\r
+typedef struct HB_FaceRec_ *HB_Face;\r
+\r
+HB_END_HEADER\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_GPOS_PRIVATE_H\r
+#define HARFBUZZ_GPOS_PRIVATE_H\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-stream-private.h"\r
+#include "harfbuzz-gpos.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+\r
+/* shared tables */\r
+\r
+struct HB_ValueRecord_\r
+{\r
+ HB_Short XPlacement; /* horizontal adjustment for\r
+ placement */\r
+ HB_Short YPlacement; /* vertical adjustment for\r
+ placement */\r
+ HB_Short XAdvance; /* horizontal adjustment for\r
+ advance */\r
+ HB_Short YAdvance; /* vertical adjustment for\r
+ advance */\r
+ HB_Device XPlacementDevice; /* device table for horizontal\r
+ placement */\r
+ HB_Device YPlacementDevice; /* device table for vertical\r
+ placement */\r
+ HB_Device XAdvanceDevice; /* device table for horizontal\r
+ advance */\r
+ HB_Device YAdvanceDevice; /* device table for vertical\r
+ advance */\r
+ HB_UShort XIdPlacement; /* horizontal placement metric ID */\r
+ HB_UShort YIdPlacement; /* vertical placement metric ID */\r
+ HB_UShort XIdAdvance; /* horizontal advance metric ID */\r
+ HB_UShort YIdAdvance; /* vertical advance metric ID */\r
+};\r
+\r
+typedef struct HB_ValueRecord_ HB_ValueRecord;\r
+\r
+\r
+/* Mask values to scan the value format of the ValueRecord structure.\r
+ We always expand compressed ValueRecords of the font. */\r
+\r
+#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT 0x0001\r
+#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT 0x0002\r
+#define HB_GPOS_FORMAT_HAVE_X_ADVANCE 0x0004\r
+#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE 0x0008\r
+#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE 0x0010\r
+#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE 0x0020\r
+#define HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE 0x0040\r
+#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE 0x0080\r
+#define HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT 0x0100\r
+#define HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT 0x0200\r
+#define HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE 0x0400\r
+#define HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE 0x0800\r
+\r
+\r
+struct HB_AnchorFormat1_\r
+{\r
+ HB_Short XCoordinate; /* horizontal value */\r
+ HB_Short YCoordinate; /* vertical value */\r
+};\r
+\r
+typedef struct HB_AnchorFormat1_ HB_AnchorFormat1;\r
+\r
+\r
+struct HB_AnchorFormat2_\r
+{\r
+ HB_Short XCoordinate; /* horizontal value */\r
+ HB_Short YCoordinate; /* vertical value */\r
+ HB_UShort AnchorPoint; /* index to glyph contour point */\r
+};\r
+\r
+typedef struct HB_AnchorFormat2_ HB_AnchorFormat2;\r
+\r
+\r
+struct HB_AnchorFormat3_\r
+{\r
+ HB_Short XCoordinate; /* horizontal value */\r
+ HB_Short YCoordinate; /* vertical value */\r
+ HB_Device XDeviceTable; /* device table for X coordinate */\r
+ HB_Device YDeviceTable; /* device table for Y coordinate */\r
+};\r
+\r
+typedef struct HB_AnchorFormat3_ HB_AnchorFormat3;\r
+\r
+\r
+struct HB_AnchorFormat4_\r
+{\r
+ HB_UShort XIdAnchor; /* horizontal metric ID */\r
+ HB_UShort YIdAnchor; /* vertical metric ID */\r
+};\r
+\r
+typedef struct HB_AnchorFormat4_ HB_AnchorFormat4;\r
+\r
+\r
+struct HB_Anchor_\r
+{\r
+ HB_UShort PosFormat; /* 1, 2, 3, or 4 -- 0 indicates\r
+ that there is no Anchor table */\r
+\r
+ union\r
+ {\r
+ HB_AnchorFormat1 af1;\r
+ HB_AnchorFormat2 af2;\r
+ HB_AnchorFormat3 af3;\r
+ HB_AnchorFormat4 af4;\r
+ } af;\r
+};\r
+\r
+typedef struct HB_Anchor_ HB_Anchor;\r
+\r
+\r
+struct HB_MarkRecord_\r
+{\r
+ HB_UShort Class; /* mark class */\r
+ HB_Anchor MarkAnchor; /* anchor table */\r
+};\r
+\r
+typedef struct HB_MarkRecord_ HB_MarkRecord;\r
+\r
+\r
+struct HB_MarkArray_\r
+{\r
+ HB_UShort MarkCount; /* number of MarkRecord tables */\r
+ HB_MarkRecord* MarkRecord; /* array of MarkRecord tables */\r
+};\r
+\r
+typedef struct HB_MarkArray_ HB_MarkArray;\r
+\r
+\r
+/* LookupType 1 */\r
+\r
+struct HB_SinglePosFormat1_\r
+{\r
+ HB_ValueRecord Value; /* ValueRecord for all covered\r
+ glyphs */\r
+};\r
+\r
+typedef struct HB_SinglePosFormat1_ HB_SinglePosFormat1;\r
+\r
+\r
+struct HB_SinglePosFormat2_\r
+{\r
+ HB_UShort ValueCount; /* number of ValueRecord tables */\r
+ HB_ValueRecord* Value; /* array of ValueRecord tables */\r
+};\r
+\r
+typedef struct HB_SinglePosFormat2_ HB_SinglePosFormat2;\r
+\r
+\r
+struct HB_SinglePos_\r
+{\r
+ HB_UShort PosFormat; /* 1 or 2 */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+\r
+ HB_UShort ValueFormat; /* format of ValueRecord table */\r
+\r
+ union\r
+ {\r
+ HB_SinglePosFormat1 spf1;\r
+ HB_SinglePosFormat2 spf2;\r
+ } spf;\r
+};\r
+\r
+typedef struct HB_SinglePos_ HB_SinglePos;\r
+\r
+\r
+/* LookupType 2 */\r
+\r
+struct HB_PairValueRecord_\r
+{\r
+ HB_UShort SecondGlyph; /* glyph ID for second glyph */\r
+ HB_ValueRecord Value1; /* pos. data for first glyph */\r
+ HB_ValueRecord Value2; /* pos. data for second glyph */\r
+};\r
+\r
+typedef struct HB_PairValueRecord_ HB_PairValueRecord;\r
+\r
+\r
+struct HB_PairSet_\r
+{\r
+ HB_UShort PairValueCount;\r
+ /* number of PairValueRecord tables */\r
+ HB_PairValueRecord* PairValueRecord;\r
+ /* array of PairValueRecord tables */\r
+};\r
+\r
+typedef struct HB_PairSet_ HB_PairSet;\r
+\r
+\r
+struct HB_PairPosFormat1_\r
+{\r
+ HB_UShort PairSetCount; /* number of PairSet tables */\r
+ HB_PairSet* PairSet; /* array of PairSet tables */\r
+};\r
+\r
+typedef struct HB_PairPosFormat1_ HB_PairPosFormat1;\r
+\r
+\r
+struct HB_Class2Record_\r
+{\r
+ HB_ValueRecord Value1; /* pos. data for first glyph */\r
+ HB_ValueRecord Value2; /* pos. data for second glyph */\r
+};\r
+\r
+typedef struct HB_Class2Record_ HB_Class2Record;\r
+\r
+\r
+struct HB_Class1Record_\r
+{\r
+ HB_Class2Record* Class2Record; /* array of Class2Record tables */\r
+};\r
+\r
+typedef struct HB_Class1Record_ HB_Class1Record;\r
+\r
+\r
+struct HB_PairPosFormat2_\r
+{\r
+ HB_ClassDefinition ClassDef1; /* class def. for first glyph */\r
+ HB_ClassDefinition ClassDef2; /* class def. for second glyph */\r
+ HB_UShort Class1Count; /* number of classes in ClassDef1\r
+ table */\r
+ HB_UShort Class2Count; /* number of classes in ClassDef2\r
+ table */\r
+ HB_Class1Record* Class1Record; /* array of Class1Record tables */\r
+};\r
+\r
+typedef struct HB_PairPosFormat2_ HB_PairPosFormat2;\r
+\r
+\r
+struct HB_PairPos_\r
+{\r
+ HB_UShort PosFormat; /* 1 or 2 */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort ValueFormat1; /* format of ValueRecord table\r
+ for first glyph */\r
+ HB_UShort ValueFormat2; /* format of ValueRecord table\r
+ for second glyph */\r
+\r
+ union\r
+ {\r
+ HB_PairPosFormat1 ppf1;\r
+ HB_PairPosFormat2 ppf2;\r
+ } ppf;\r
+};\r
+\r
+typedef struct HB_PairPos_ HB_PairPos;\r
+\r
+\r
+/* LookupType 3 */\r
+\r
+struct HB_EntryExitRecord_\r
+{\r
+ HB_Anchor EntryAnchor; /* entry Anchor table */\r
+ HB_Anchor ExitAnchor; /* exit Anchor table */\r
+};\r
+\r
+\r
+typedef struct HB_EntryExitRecord_ HB_EntryExitRecord;\r
+\r
+struct HB_CursivePos_\r
+{\r
+ HB_UShort PosFormat; /* always 1 */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort EntryExitCount;\r
+ /* number of EntryExitRecord tables */\r
+ HB_EntryExitRecord* EntryExitRecord;\r
+ /* array of EntryExitRecord tables */\r
+};\r
+\r
+typedef struct HB_CursivePos_ HB_CursivePos;\r
+\r
+\r
+/* LookupType 4 */\r
+\r
+struct HB_BaseRecord_\r
+{\r
+ HB_Anchor* BaseAnchor; /* array of base glyph anchor\r
+ tables */\r
+};\r
+\r
+typedef struct HB_BaseRecord_ HB_BaseRecord;\r
+\r
+\r
+struct HB_BaseArray_\r
+{\r
+ HB_UShort BaseCount; /* number of BaseRecord tables */\r
+ HB_BaseRecord* BaseRecord; /* array of BaseRecord tables */\r
+};\r
+\r
+typedef struct HB_BaseArray_ HB_BaseArray;\r
+\r
+\r
+struct HB_MarkBasePos_\r
+{\r
+ HB_UShort PosFormat; /* always 1 */\r
+ HB_Coverage MarkCoverage; /* mark glyph coverage table */\r
+ HB_Coverage BaseCoverage; /* base glyph coverage table */\r
+ HB_UShort ClassCount; /* number of mark classes */\r
+ HB_MarkArray MarkArray; /* mark array table */\r
+ HB_BaseArray BaseArray; /* base array table */\r
+};\r
+\r
+typedef struct HB_MarkBasePos_ HB_MarkBasePos;\r
+\r
+\r
+/* LookupType 5 */\r
+\r
+struct HB_ComponentRecord_\r
+{\r
+ HB_Anchor* LigatureAnchor; /* array of ligature glyph anchor\r
+ tables */\r
+};\r
+\r
+typedef struct HB_ComponentRecord_ HB_ComponentRecord;\r
+\r
+\r
+struct HB_LigatureAttach_\r
+{\r
+ HB_UShort ComponentCount;\r
+ /* number of ComponentRecord tables */\r
+ HB_ComponentRecord* ComponentRecord;\r
+ /* array of ComponentRecord tables */\r
+};\r
+\r
+typedef struct HB_LigatureAttach_ HB_LigatureAttach;\r
+\r
+\r
+struct HB_LigatureArray_\r
+{\r
+ HB_UShort LigatureCount; /* number of LigatureAttach tables */\r
+ HB_LigatureAttach* LigatureAttach;\r
+ /* array of LigatureAttach tables */\r
+};\r
+\r
+typedef struct HB_LigatureArray_ HB_LigatureArray;\r
+\r
+\r
+struct HB_MarkLigPos_\r
+{\r
+ HB_UShort PosFormat; /* always 1 */\r
+ HB_Coverage MarkCoverage; /* mark glyph coverage table */\r
+ HB_Coverage LigatureCoverage;\r
+ /* ligature glyph coverage table */\r
+ HB_UShort ClassCount; /* number of mark classes */\r
+ HB_MarkArray MarkArray; /* mark array table */\r
+ HB_LigatureArray LigatureArray; /* ligature array table */\r
+};\r
+\r
+typedef struct HB_MarkLigPos_ HB_MarkLigPos;\r
+\r
+\r
+/* LookupType 6 */\r
+\r
+struct HB_Mark2Record_\r
+{\r
+ HB_Anchor* Mark2Anchor; /* array of mark glyph anchor\r
+ tables */\r
+};\r
+\r
+typedef struct HB_Mark2Record_ HB_Mark2Record;\r
+\r
+\r
+struct HB_Mark2Array_\r
+{\r
+ HB_UShort Mark2Count; /* number of Mark2Record tables */\r
+ HB_Mark2Record* Mark2Record; /* array of Mark2Record tables */\r
+};\r
+\r
+typedef struct HB_Mark2Array_ HB_Mark2Array;\r
+\r
+\r
+struct HB_MarkMarkPos_\r
+{\r
+ HB_UShort PosFormat; /* always 1 */\r
+ HB_Coverage Mark1Coverage; /* first mark glyph coverage table */\r
+ HB_Coverage Mark2Coverage; /* second mark glyph coverave table */\r
+ HB_UShort ClassCount; /* number of combining mark classes */\r
+ HB_MarkArray Mark1Array; /* MarkArray table for first mark */\r
+ HB_Mark2Array Mark2Array; /* MarkArray table for second mark */\r
+};\r
+\r
+typedef struct HB_MarkMarkPos_ HB_MarkMarkPos;\r
+\r
+\r
+/* needed by both lookup type 7 and 8 */\r
+\r
+struct HB_PosLookupRecord_\r
+{\r
+ HB_UShort SequenceIndex; /* index into current\r
+ glyph sequence */\r
+ HB_UShort LookupListIndex; /* Lookup to apply to that pos. */\r
+};\r
+\r
+typedef struct HB_PosLookupRecord_ HB_PosLookupRecord;\r
+\r
+\r
+/* LookupType 7 */\r
+\r
+struct HB_PosRule_\r
+{\r
+ HB_UShort GlyphCount; /* total number of input glyphs */\r
+ HB_UShort PosCount; /* number of PosLookupRecord tables */\r
+ HB_UShort* Input; /* array of input glyph IDs */\r
+ HB_PosLookupRecord* PosLookupRecord;\r
+ /* array of PosLookupRecord tables */\r
+};\r
+\r
+typedef struct HB_PosRule_ HB_PosRule;\r
+\r
+\r
+struct HB_PosRuleSet_\r
+{\r
+ HB_UShort PosRuleCount; /* number of PosRule tables */\r
+ HB_PosRule* PosRule; /* array of PosRule tables */\r
+};\r
+\r
+typedef struct HB_PosRuleSet_ HB_PosRuleSet;\r
+\r
+\r
+struct HB_ContextPosFormat1_\r
+{\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort PosRuleSetCount; /* number of PosRuleSet tables */\r
+ HB_PosRuleSet* PosRuleSet; /* array of PosRuleSet tables */\r
+};\r
+\r
+typedef struct HB_ContextPosFormat1_ HB_ContextPosFormat1;\r
+\r
+\r
+struct HB_PosClassRule_\r
+{\r
+ HB_UShort GlyphCount; /* total number of context classes */\r
+ HB_UShort PosCount; /* number of PosLookupRecord tables */\r
+ HB_UShort* Class; /* array of classes */\r
+ HB_PosLookupRecord* PosLookupRecord;\r
+ /* array of PosLookupRecord tables */\r
+};\r
+\r
+typedef struct HB_PosClassRule_ HB_PosClassRule;\r
+\r
+\r
+struct HB_PosClassSet_\r
+{\r
+ HB_UShort PosClassRuleCount;\r
+ /* number of PosClassRule tables */\r
+ HB_PosClassRule* PosClassRule; /* array of PosClassRule tables */\r
+};\r
+\r
+typedef struct HB_PosClassSet_ HB_PosClassSet;\r
+\r
+\r
+/* The `MaxContextLength' field is not defined in the TTO specification\r
+ but simplifies the implementation of this format. It holds the\r
+ maximal context length used in the context rules. */\r
+\r
+struct HB_ContextPosFormat2_\r
+{\r
+ HB_UShort MaxContextLength;\r
+ /* maximal context length */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_ClassDefinition ClassDef; /* ClassDef table */\r
+ HB_UShort PosClassSetCount;\r
+ /* number of PosClassSet tables */\r
+ HB_PosClassSet* PosClassSet; /* array of PosClassSet tables */\r
+};\r
+\r
+typedef struct HB_ContextPosFormat2_ HB_ContextPosFormat2;\r
+\r
+\r
+struct HB_ContextPosFormat3_\r
+{\r
+ HB_UShort GlyphCount; /* number of input glyphs */\r
+ HB_UShort PosCount; /* number of PosLookupRecord tables */\r
+ HB_Coverage* Coverage; /* array of Coverage tables */\r
+ HB_PosLookupRecord* PosLookupRecord;\r
+ /* array of PosLookupRecord tables */\r
+};\r
+\r
+typedef struct HB_ContextPosFormat3_ HB_ContextPosFormat3;\r
+\r
+\r
+struct HB_ContextPos_\r
+{\r
+ HB_UShort PosFormat; /* 1, 2, or 3 */\r
+\r
+ union\r
+ {\r
+ HB_ContextPosFormat1 cpf1;\r
+ HB_ContextPosFormat2 cpf2;\r
+ HB_ContextPosFormat3 cpf3;\r
+ } cpf;\r
+};\r
+\r
+typedef struct HB_ContextPos_ HB_ContextPos;\r
+\r
+\r
+/* LookupType 8 */\r
+\r
+struct HB_ChainPosRule_\r
+{\r
+ HB_UShort BacktrackGlyphCount;\r
+ /* total number of backtrack glyphs */\r
+ HB_UShort* Backtrack; /* array of backtrack glyph IDs */\r
+ HB_UShort InputGlyphCount;\r
+ /* total number of input glyphs */\r
+ HB_UShort* Input; /* array of input glyph IDs */\r
+ HB_UShort LookaheadGlyphCount;\r
+ /* total number of lookahead glyphs */\r
+ HB_UShort* Lookahead; /* array of lookahead glyph IDs */\r
+ HB_UShort PosCount; /* number of PosLookupRecords */\r
+ HB_PosLookupRecord* PosLookupRecord;\r
+ /* array of PosLookupRecords */\r
+};\r
+\r
+typedef struct HB_ChainPosRule_ HB_ChainPosRule;\r
+\r
+\r
+struct HB_ChainPosRuleSet_\r
+{\r
+ HB_UShort ChainPosRuleCount;\r
+ /* number of ChainPosRule tables */\r
+ HB_ChainPosRule* ChainPosRule; /* array of ChainPosRule tables */\r
+};\r
+\r
+typedef struct HB_ChainPosRuleSet_ HB_ChainPosRuleSet;\r
+\r
+\r
+struct HB_ChainContextPosFormat1_\r
+{\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort ChainPosRuleSetCount;\r
+ /* number of ChainPosRuleSet tables */\r
+ HB_ChainPosRuleSet* ChainPosRuleSet;\r
+ /* array of ChainPosRuleSet tables */\r
+};\r
+\r
+typedef struct HB_ChainContextPosFormat1_ HB_ChainContextPosFormat1;\r
+\r
+\r
+struct HB_ChainPosClassRule_\r
+{\r
+ HB_UShort BacktrackGlyphCount;\r
+ /* total number of backtrack\r
+ classes */\r
+ HB_UShort* Backtrack; /* array of backtrack classes */\r
+ HB_UShort InputGlyphCount;\r
+ /* total number of context classes */\r
+ HB_UShort* Input; /* array of context classes */\r
+ HB_UShort LookaheadGlyphCount;\r
+ /* total number of lookahead\r
+ classes */\r
+ HB_UShort* Lookahead; /* array of lookahead classes */\r
+ HB_UShort PosCount; /* number of PosLookupRecords */\r
+ HB_PosLookupRecord* PosLookupRecord;\r
+ /* array of substitution lookups */\r
+};\r
+\r
+typedef struct HB_ChainPosClassRule_ HB_ChainPosClassRule;\r
+\r
+\r
+struct HB_ChainPosClassSet_\r
+{\r
+ HB_UShort ChainPosClassRuleCount;\r
+ /* number of ChainPosClassRule\r
+ tables */\r
+ HB_ChainPosClassRule* ChainPosClassRule;\r
+ /* array of ChainPosClassRule\r
+ tables */\r
+};\r
+\r
+typedef struct HB_ChainPosClassSet_ HB_ChainPosClassSet;\r
+\r
+\r
+/* The `MaxXXXLength' fields are not defined in the TTO specification\r
+ but simplifies the implementation of this format. It holds the\r
+ maximal context length used in the specific context rules. */\r
+\r
+struct HB_ChainContextPosFormat2_\r
+{\r
+ HB_Coverage Coverage; /* Coverage table */\r
+\r
+ HB_UShort MaxBacktrackLength;\r
+ /* maximal backtrack length */\r
+ HB_ClassDefinition BacktrackClassDef;\r
+ /* BacktrackClassDef table */\r
+ HB_UShort MaxInputLength;\r
+ /* maximal input length */\r
+ HB_ClassDefinition InputClassDef;\r
+ /* InputClassDef table */\r
+ HB_UShort MaxLookaheadLength;\r
+ /* maximal lookahead length */\r
+ HB_ClassDefinition LookaheadClassDef;\r
+ /* LookaheadClassDef table */\r
+\r
+ HB_UShort ChainPosClassSetCount;\r
+ /* number of ChainPosClassSet\r
+ tables */\r
+ HB_ChainPosClassSet* ChainPosClassSet;\r
+ /* array of ChainPosClassSet\r
+ tables */\r
+};\r
+\r
+typedef struct HB_ChainContextPosFormat2_ HB_ChainContextPosFormat2;\r
+\r
+\r
+struct HB_ChainContextPosFormat3_\r
+{\r
+ HB_UShort BacktrackGlyphCount;\r
+ /* number of backtrack glyphs */\r
+ HB_Coverage* BacktrackCoverage;\r
+ /* array of backtrack Coverage\r
+ tables */\r
+ HB_UShort InputGlyphCount;\r
+ /* number of input glyphs */\r
+ HB_Coverage* InputCoverage;\r
+ /* array of input coverage\r
+ tables */\r
+ HB_UShort LookaheadGlyphCount;\r
+ /* number of lookahead glyphs */\r
+ HB_Coverage* LookaheadCoverage;\r
+ /* array of lookahead coverage\r
+ tables */\r
+ HB_UShort PosCount; /* number of PosLookupRecords */\r
+ HB_PosLookupRecord* PosLookupRecord;\r
+ /* array of substitution lookups */\r
+};\r
+\r
+typedef struct HB_ChainContextPosFormat3_ HB_ChainContextPosFormat3;\r
+\r
+\r
+struct HB_ChainContextPos_\r
+{\r
+ HB_UShort PosFormat; /* 1, 2, or 3 */\r
+\r
+ union\r
+ {\r
+ HB_ChainContextPosFormat1 ccpf1;\r
+ HB_ChainContextPosFormat2 ccpf2;\r
+ HB_ChainContextPosFormat3 ccpf3;\r
+ } ccpf;\r
+};\r
+\r
+typedef struct HB_ChainContextPos_ HB_ChainContextPos;\r
+\r
+\r
+#if 0\r
+/* LookupType 10 */\r
+struct HB_ExtensionPos_\r
+{\r
+ HB_UShort PosFormat; /* always 1 */\r
+ HB_UShort LookuptType; /* lookup-type of referenced subtable */\r
+ HB_GPOS_SubTable *subtable; /* referenced subtable */\r
+};\r
+\r
+typedef struct HB_ExtensionPos_ HB_ExtensionPos;\r
+#endif\r
+\r
+\r
+union HB_GPOS_SubTable_\r
+{\r
+ HB_SinglePos single;\r
+ HB_PairPos pair;\r
+ HB_CursivePos cursive;\r
+ HB_MarkBasePos markbase;\r
+ HB_MarkLigPos marklig;\r
+ HB_MarkMarkPos markmark;\r
+ HB_ContextPos context;\r
+ HB_ChainContextPos chain;\r
+};\r
+\r
+typedef union HB_GPOS_SubTable_ HB_GPOS_SubTable;\r
+\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,\r
+ HB_Stream stream,\r
+ HB_UShort lookup_type );\r
+\r
+HB_INTERNAL void\r
+_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,\r
+ HB_UShort lookup_type );\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_GPOS_PRIVATE_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_GPOS_H\r
+#define HARFBUZZ_GPOS_H\r
+\r
+#include "harfbuzz-gdef.h"\r
+#include "harfbuzz-buffer.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+\r
+/* Lookup types for glyph positioning */\r
+\r
+#define HB_GPOS_LOOKUP_SINGLE 1\r
+#define HB_GPOS_LOOKUP_PAIR 2\r
+#define HB_GPOS_LOOKUP_CURSIVE 3\r
+#define HB_GPOS_LOOKUP_MARKBASE 4\r
+#define HB_GPOS_LOOKUP_MARKLIG 5\r
+#define HB_GPOS_LOOKUP_MARKMARK 6\r
+#define HB_GPOS_LOOKUP_CONTEXT 7\r
+#define HB_GPOS_LOOKUP_CHAIN 8\r
+#define HB_GPOS_LOOKUP_EXTENSION 9\r
+\r
+/* A pointer to a function which accesses the PostScript interpreter.\r
+ Multiple Master fonts need this interface to convert a metric ID\r
+ (as stored in an OpenType font version 1.2 or higher) `metric_id'\r
+ into a metric value (returned in `metric_value').\r
+\r
+ `data' points to the user-defined structure specified during a\r
+ call to HB_GPOS_Register_MM_Function().\r
+\r
+ `metric_value' must be returned as a scaled value (but shouldn't\r
+ be rounded). */\r
+\r
+typedef HB_Error (*HB_MMFunction)(HB_Font font,\r
+ HB_UShort metric_id,\r
+ HB_Fixed* metric_value,\r
+ void* data );\r
+\r
+\r
+struct HB_GPOSHeader_\r
+{\r
+ HB_16Dot16 Version;\r
+\r
+ HB_ScriptList ScriptList;\r
+ HB_FeatureList FeatureList;\r
+ HB_LookupList LookupList;\r
+\r
+ HB_GDEFHeader* gdef;\r
+\r
+ /* this is OpenType 1.2 -- Multiple Master fonts need this\r
+ callback function to get various metric values from the\r
+ PostScript interpreter. */\r
+\r
+ HB_MMFunction mmfunc;\r
+ void* data;\r
+};\r
+\r
+typedef struct HB_GPOSHeader_ HB_GPOSHeader;\r
+typedef HB_GPOSHeader* HB_GPOS;\r
+\r
+\r
+HB_Error HB_Load_GPOS_Table( HB_Stream stream, \r
+ HB_GPOSHeader** gpos,\r
+ HB_GDEFHeader* gdef,\r
+ HB_Stream gdefStream );\r
+\r
+\r
+HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos );\r
+\r
+\r
+HB_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,\r
+ HB_UInt script_tag,\r
+ HB_UShort* script_index );\r
+\r
+HB_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,\r
+ HB_UInt language_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort* language_index,\r
+ HB_UShort* req_feature_index );\r
+\r
+HB_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,\r
+ HB_UInt feature_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UShort* feature_index );\r
+\r
+\r
+HB_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,\r
+ HB_UInt** script_tag_list );\r
+\r
+HB_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,\r
+ HB_UShort script_index,\r
+ HB_UInt** language_tag_list );\r
+\r
+HB_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UInt** feature_tag_list );\r
+\r
+\r
+HB_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,\r
+ HB_UShort feature_index,\r
+ HB_UInt property );\r
+\r
+HB_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos );\r
+\r
+\r
+HB_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,\r
+ HB_MMFunction mmfunc,\r
+ void* data );\r
+\r
+/* If `dvi' is TRUE, glyph contour points for anchor points and device\r
+ tables are ignored -- you will get device independent values. */\r
+\r
+\r
+HB_Error HB_GPOS_Apply_String( HB_Font font,\r
+ HB_GPOSHeader* gpos,\r
+ HB_UShort load_flags,\r
+ HB_Buffer buffer,\r
+ HB_Bool dvi,\r
+ HB_Bool r2l );\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_GPOS_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_GSUB_PRIVATE_H\r
+#define HARFBUZZ_GSUB_PRIVATE_H\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-stream-private.h"\r
+#include "harfbuzz-gsub.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+\r
+typedef union HB_GSUB_SubTable_ HB_GSUB_SubTable;\r
+\r
+/* LookupType 1 */\r
+\r
+struct HB_SingleSubstFormat1_\r
+{\r
+ HB_Short DeltaGlyphID; /* constant added to get\r
+ substitution glyph index */\r
+};\r
+\r
+typedef struct HB_SingleSubstFormat1_ HB_SingleSubstFormat1;\r
+\r
+\r
+struct HB_SingleSubstFormat2_\r
+{\r
+ HB_UShort GlyphCount; /* number of glyph IDs in\r
+ Substitute array */\r
+ HB_UShort* Substitute; /* array of substitute glyph IDs */\r
+};\r
+\r
+typedef struct HB_SingleSubstFormat2_ HB_SingleSubstFormat2;\r
+\r
+\r
+struct HB_SingleSubst_\r
+{\r
+ HB_UShort SubstFormat; /* 1 or 2 */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+\r
+ union\r
+ {\r
+ HB_SingleSubstFormat1 ssf1;\r
+ HB_SingleSubstFormat2 ssf2;\r
+ } ssf;\r
+};\r
+\r
+typedef struct HB_SingleSubst_ HB_SingleSubst;\r
+\r
+\r
+/* LookupType 2 */\r
+\r
+struct HB_Sequence_\r
+{\r
+ HB_UShort GlyphCount; /* number of glyph IDs in the\r
+ Substitute array */\r
+ HB_UShort* Substitute; /* string of glyph IDs to\r
+ substitute */\r
+};\r
+\r
+typedef struct HB_Sequence_ HB_Sequence;\r
+\r
+\r
+struct HB_MultipleSubst_\r
+{\r
+ HB_UShort SubstFormat; /* always 1 */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort SequenceCount; /* number of Sequence tables */\r
+ HB_Sequence* Sequence; /* array of Sequence tables */\r
+};\r
+\r
+typedef struct HB_MultipleSubst_ HB_MultipleSubst;\r
+\r
+\r
+/* LookupType 3 */\r
+\r
+struct HB_AlternateSet_\r
+{\r
+ HB_UShort GlyphCount; /* number of glyph IDs in the\r
+ Alternate array */\r
+ HB_UShort* Alternate; /* array of alternate glyph IDs */\r
+};\r
+\r
+typedef struct HB_AlternateSet_ HB_AlternateSet;\r
+\r
+\r
+struct HB_AlternateSubst_\r
+{\r
+ HB_UShort SubstFormat; /* always 1 */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort AlternateSetCount;\r
+ /* number of AlternateSet tables */\r
+ HB_AlternateSet* AlternateSet; /* array of AlternateSet tables */\r
+};\r
+\r
+typedef struct HB_AlternateSubst_ HB_AlternateSubst;\r
+\r
+\r
+/* LookupType 4 */\r
+\r
+struct HB_Ligature_\r
+{\r
+ HB_UShort LigGlyph; /* glyphID of ligature\r
+ to substitute */\r
+ HB_UShort ComponentCount; /* number of components in ligature */\r
+ HB_UShort* Component; /* array of component glyph IDs */\r
+};\r
+\r
+typedef struct HB_Ligature_ HB_Ligature;\r
+\r
+\r
+struct HB_LigatureSet_\r
+{\r
+ HB_UShort LigatureCount; /* number of Ligature tables */\r
+ HB_Ligature* Ligature; /* array of Ligature tables */\r
+};\r
+\r
+typedef struct HB_LigatureSet_ HB_LigatureSet;\r
+\r
+\r
+struct HB_LigatureSubst_\r
+{\r
+ HB_UShort SubstFormat; /* always 1 */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort LigatureSetCount; /* number of LigatureSet tables */\r
+ HB_LigatureSet* LigatureSet; /* array of LigatureSet tables */\r
+};\r
+\r
+typedef struct HB_LigatureSubst_ HB_LigatureSubst;\r
+\r
+\r
+/* needed by both lookup type 5 and 6 */\r
+\r
+struct HB_SubstLookupRecord_\r
+{\r
+ HB_UShort SequenceIndex; /* index into current\r
+ glyph sequence */\r
+ HB_UShort LookupListIndex; /* Lookup to apply to that pos. */\r
+};\r
+\r
+typedef struct HB_SubstLookupRecord_ HB_SubstLookupRecord;\r
+\r
+\r
+/* LookupType 5 */\r
+\r
+struct HB_SubRule_\r
+{\r
+ HB_UShort GlyphCount; /* total number of input glyphs */\r
+ HB_UShort SubstCount; /* number of SubstLookupRecord\r
+ tables */\r
+ HB_UShort* Input; /* array of input glyph IDs */\r
+ HB_SubstLookupRecord* SubstLookupRecord;\r
+ /* array of SubstLookupRecord\r
+ tables */\r
+};\r
+\r
+typedef struct HB_SubRule_ HB_SubRule;\r
+\r
+\r
+struct HB_SubRuleSet_\r
+{\r
+ HB_UShort SubRuleCount; /* number of SubRule tables */\r
+ HB_SubRule* SubRule; /* array of SubRule tables */\r
+};\r
+\r
+typedef struct HB_SubRuleSet_ HB_SubRuleSet;\r
+\r
+\r
+struct HB_ContextSubstFormat1_\r
+{\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort SubRuleSetCount; /* number of SubRuleSet tables */\r
+ HB_SubRuleSet* SubRuleSet; /* array of SubRuleSet tables */\r
+};\r
+\r
+typedef struct HB_ContextSubstFormat1_ HB_ContextSubstFormat1;\r
+\r
+\r
+struct HB_SubClassRule_\r
+{\r
+ HB_UShort GlyphCount; /* total number of context classes */\r
+ HB_UShort SubstCount; /* number of SubstLookupRecord\r
+ tables */\r
+ HB_UShort* Class; /* array of classes */\r
+ HB_SubstLookupRecord* SubstLookupRecord;\r
+ /* array of SubstLookupRecord\r
+ tables */\r
+};\r
+\r
+typedef struct HB_SubClassRule_ HB_SubClassRule;\r
+\r
+\r
+struct HB_SubClassSet_\r
+{\r
+ HB_UShort SubClassRuleCount;\r
+ /* number of SubClassRule tables */\r
+ HB_SubClassRule* SubClassRule; /* array of SubClassRule tables */\r
+};\r
+\r
+typedef struct HB_SubClassSet_ HB_SubClassSet;\r
+\r
+\r
+/* The `MaxContextLength' field is not defined in the TTO specification\r
+ but simplifies the implementation of this format. It holds the\r
+ maximal context length used in the context rules. */\r
+\r
+struct HB_ContextSubstFormat2_\r
+{\r
+ HB_UShort MaxContextLength;\r
+ /* maximal context length */\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_ClassDefinition ClassDef; /* ClassDef table */\r
+ HB_UShort SubClassSetCount;\r
+ /* number of SubClassSet tables */\r
+ HB_SubClassSet* SubClassSet; /* array of SubClassSet tables */\r
+};\r
+\r
+typedef struct HB_ContextSubstFormat2_ HB_ContextSubstFormat2;\r
+\r
+\r
+struct HB_ContextSubstFormat3_\r
+{\r
+ HB_UShort GlyphCount; /* number of input glyphs */\r
+ HB_UShort SubstCount; /* number of SubstLookupRecords */\r
+ HB_Coverage* Coverage; /* array of Coverage tables */\r
+ HB_SubstLookupRecord* SubstLookupRecord;\r
+ /* array of substitution lookups */\r
+};\r
+\r
+typedef struct HB_ContextSubstFormat3_ HB_ContextSubstFormat3;\r
+\r
+\r
+struct HB_ContextSubst_\r
+{\r
+ HB_UShort SubstFormat; /* 1, 2, or 3 */\r
+\r
+ union\r
+ {\r
+ HB_ContextSubstFormat1 csf1;\r
+ HB_ContextSubstFormat2 csf2;\r
+ HB_ContextSubstFormat3 csf3;\r
+ } csf;\r
+};\r
+\r
+typedef struct HB_ContextSubst_ HB_ContextSubst;\r
+\r
+\r
+/* LookupType 6 */\r
+\r
+struct HB_ChainSubRule_\r
+{\r
+ HB_UShort BacktrackGlyphCount;\r
+ /* total number of backtrack glyphs */\r
+ HB_UShort* Backtrack; /* array of backtrack glyph IDs */\r
+ HB_UShort InputGlyphCount;\r
+ /* total number of input glyphs */\r
+ HB_UShort* Input; /* array of input glyph IDs */\r
+ HB_UShort LookaheadGlyphCount;\r
+ /* total number of lookahead glyphs */\r
+ HB_UShort* Lookahead; /* array of lookahead glyph IDs */\r
+ HB_UShort SubstCount; /* number of SubstLookupRecords */\r
+ HB_SubstLookupRecord* SubstLookupRecord;\r
+ /* array of SubstLookupRecords */\r
+};\r
+\r
+typedef struct HB_ChainSubRule_ HB_ChainSubRule;\r
+\r
+\r
+struct HB_ChainSubRuleSet_\r
+{\r
+ HB_UShort ChainSubRuleCount;\r
+ /* number of ChainSubRule tables */\r
+ HB_ChainSubRule* ChainSubRule; /* array of ChainSubRule tables */\r
+};\r
+\r
+typedef struct HB_ChainSubRuleSet_ HB_ChainSubRuleSet;\r
+\r
+\r
+struct HB_ChainContextSubstFormat1_\r
+{\r
+ HB_Coverage Coverage; /* Coverage table */\r
+ HB_UShort ChainSubRuleSetCount;\r
+ /* number of ChainSubRuleSet tables */\r
+ HB_ChainSubRuleSet* ChainSubRuleSet;\r
+ /* array of ChainSubRuleSet tables */\r
+};\r
+\r
+typedef struct HB_ChainContextSubstFormat1_ HB_ChainContextSubstFormat1;\r
+\r
+\r
+struct HB_ChainSubClassRule_\r
+{\r
+ HB_UShort BacktrackGlyphCount;\r
+ /* total number of backtrack\r
+ classes */\r
+ HB_UShort* Backtrack; /* array of backtrack classes */\r
+ HB_UShort InputGlyphCount;\r
+ /* total number of context classes */\r
+ HB_UShort* Input; /* array of context classes */\r
+ HB_UShort LookaheadGlyphCount;\r
+ /* total number of lookahead\r
+ classes */\r
+ HB_UShort* Lookahead; /* array of lookahead classes */\r
+ HB_UShort SubstCount; /* number of SubstLookupRecords */\r
+ HB_SubstLookupRecord* SubstLookupRecord;\r
+ /* array of substitution lookups */\r
+};\r
+\r
+typedef struct HB_ChainSubClassRule_ HB_ChainSubClassRule;\r
+\r
+\r
+struct HB_ChainSubClassSet_\r
+{\r
+ HB_UShort ChainSubClassRuleCount;\r
+ /* number of ChainSubClassRule\r
+ tables */\r
+ HB_ChainSubClassRule* ChainSubClassRule;\r
+ /* array of ChainSubClassRule\r
+ tables */\r
+};\r
+\r
+typedef struct HB_ChainSubClassSet_ HB_ChainSubClassSet;\r
+\r
+\r
+/* The `MaxXXXLength' fields are not defined in the TTO specification\r
+ but simplifies the implementation of this format. It holds the\r
+ maximal context length used in the specific context rules. */\r
+\r
+struct HB_ChainContextSubstFormat2_\r
+{\r
+ HB_Coverage Coverage; /* Coverage table */\r
+\r
+ HB_UShort MaxBacktrackLength;\r
+ /* maximal backtrack length */\r
+ HB_ClassDefinition BacktrackClassDef;\r
+ /* BacktrackClassDef table */\r
+ HB_UShort MaxInputLength;\r
+ /* maximal input length */\r
+ HB_ClassDefinition InputClassDef;\r
+ /* InputClassDef table */\r
+ HB_UShort MaxLookaheadLength;\r
+ /* maximal lookahead length */\r
+ HB_ClassDefinition LookaheadClassDef;\r
+ /* LookaheadClassDef table */\r
+\r
+ HB_UShort ChainSubClassSetCount;\r
+ /* number of ChainSubClassSet\r
+ tables */\r
+ HB_ChainSubClassSet* ChainSubClassSet;\r
+ /* array of ChainSubClassSet\r
+ tables */\r
+};\r
+\r
+typedef struct HB_ChainContextSubstFormat2_ HB_ChainContextSubstFormat2;\r
+\r
+\r
+struct HB_ChainContextSubstFormat3_\r
+{\r
+ HB_UShort BacktrackGlyphCount;\r
+ /* number of backtrack glyphs */\r
+ HB_Coverage* BacktrackCoverage;\r
+ /* array of backtrack Coverage\r
+ tables */\r
+ HB_UShort InputGlyphCount;\r
+ /* number of input glyphs */\r
+ HB_Coverage* InputCoverage;\r
+ /* array of input coverage\r
+ tables */\r
+ HB_UShort LookaheadGlyphCount;\r
+ /* number of lookahead glyphs */\r
+ HB_Coverage* LookaheadCoverage;\r
+ /* array of lookahead coverage\r
+ tables */\r
+ HB_UShort SubstCount; /* number of SubstLookupRecords */\r
+ HB_SubstLookupRecord* SubstLookupRecord;\r
+ /* array of substitution lookups */\r
+};\r
+\r
+typedef struct HB_ChainContextSubstFormat3_ HB_ChainContextSubstFormat3;\r
+\r
+\r
+struct HB_ChainContextSubst_\r
+{\r
+ HB_UShort SubstFormat; /* 1, 2, or 3 */\r
+\r
+ union\r
+ {\r
+ HB_ChainContextSubstFormat1 ccsf1;\r
+ HB_ChainContextSubstFormat2 ccsf2;\r
+ HB_ChainContextSubstFormat3 ccsf3;\r
+ } ccsf;\r
+};\r
+\r
+typedef struct HB_ChainContextSubst_ HB_ChainContextSubst;\r
+\r
+\r
+#if 0\r
+/* LookupType 7 */\r
+struct HB_ExtensionSubst_\r
+{\r
+ HB_UShort SubstFormat; /* always 1 */\r
+ HB_UShort LookuptType; /* lookup-type of referenced subtable */\r
+ HB_GSUB_SubTable *subtable; /* referenced subtable */\r
+};\r
+\r
+typedef struct HB_ExtensionSubst_ HB_ExtensionSubst;\r
+#endif\r
+\r
+\r
+/* LookupType 8 */\r
+struct HB_ReverseChainContextSubst_\r
+{\r
+ HB_UShort SubstFormat; /* always 1 */\r
+ HB_Coverage Coverage; /* coverage table for input glyphs */\r
+ HB_UShort BacktrackGlyphCount; /* number of backtrack glyphs */\r
+ HB_Coverage* BacktrackCoverage; /* array of backtrack Coverage\r
+ tables */\r
+ HB_UShort LookaheadGlyphCount; /* number of lookahead glyphs */\r
+ HB_Coverage* LookaheadCoverage; /* array of lookahead Coverage\r
+ tables */\r
+ HB_UShort GlyphCount; /* number of Glyph IDs */\r
+ HB_UShort* Substitute; /* array of substitute Glyph ID */\r
+};\r
+\r
+typedef struct HB_ReverseChainContextSubst_ HB_ReverseChainContextSubst;\r
+\r
+\r
+union HB_GSUB_SubTable_\r
+{\r
+ HB_SingleSubst single;\r
+ HB_MultipleSubst multiple;\r
+ HB_AlternateSubst alternate;\r
+ HB_LigatureSubst ligature;\r
+ HB_ContextSubst context;\r
+ HB_ChainContextSubst chain;\r
+ HB_ReverseChainContextSubst reverse;\r
+};\r
+\r
+\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,\r
+ HB_Stream stream,\r
+ HB_UShort lookup_type );\r
+\r
+HB_INTERNAL void\r
+_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,\r
+ HB_UShort lookup_type );\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_GSUB_PRIVATE_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_GSUB_H\r
+#define HARFBUZZ_GSUB_H\r
+\r
+#include "harfbuzz-gdef.h"\r
+#include "harfbuzz-buffer.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+\r
+/* Lookup types for glyph substitution */\r
+\r
+#define HB_GSUB_LOOKUP_SINGLE 1\r
+#define HB_GSUB_LOOKUP_MULTIPLE 2\r
+#define HB_GSUB_LOOKUP_ALTERNATE 3\r
+#define HB_GSUB_LOOKUP_LIGATURE 4\r
+#define HB_GSUB_LOOKUP_CONTEXT 5\r
+#define HB_GSUB_LOOKUP_CHAIN 6\r
+#define HB_GSUB_LOOKUP_EXTENSION 7\r
+#define HB_GSUB_LOOKUP_REVERSE_CHAIN 8\r
+\r
+\r
+/* A pointer to a function which selects the alternate glyph. `pos' is\r
+ the position of the glyph with index `glyphID', `num_alternates'\r
+ gives the number of alternates in the `alternates' array. `data'\r
+ points to the user-defined structure specified during a call to\r
+ HB_GSUB_Register_Alternate_Function(). The function must return an\r
+ index into the `alternates' array. */\r
+\r
+typedef HB_UShort (*HB_AltFunction)(HB_UInt pos,\r
+ HB_UShort glyphID,\r
+ HB_UShort num_alternates,\r
+ HB_UShort* alternates,\r
+ void* data );\r
+\r
+\r
+struct HB_GSUBHeader_\r
+{\r
+ HB_UInt offset;\r
+\r
+ HB_16Dot16 Version;\r
+\r
+ HB_ScriptList ScriptList;\r
+ HB_FeatureList FeatureList;\r
+ HB_LookupList LookupList;\r
+\r
+ HB_GDEFHeader* gdef;\r
+\r
+ /* the next two fields are used for an alternate substitution callback\r
+ function to select the proper alternate glyph. */\r
+\r
+ HB_AltFunction altfunc;\r
+ void* data;\r
+};\r
+\r
+typedef struct HB_GSUBHeader_ HB_GSUBHeader;\r
+typedef HB_GSUBHeader* HB_GSUB;\r
+\r
+\r
+HB_Error HB_Load_GSUB_Table( HB_Stream stream,\r
+ HB_GSUBHeader** gsub,\r
+ HB_GDEFHeader* gdef,\r
+ HB_Stream gdefStream );\r
+\r
+\r
+HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub );\r
+\r
+\r
+HB_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,\r
+ HB_UInt script_tag,\r
+ HB_UShort* script_index );\r
+\r
+HB_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,\r
+ HB_UInt language_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort* language_index,\r
+ HB_UShort* req_feature_index );\r
+\r
+HB_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,\r
+ HB_UInt feature_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UShort* feature_index );\r
+\r
+\r
+HB_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,\r
+ HB_UInt** script_tag_list );\r
+\r
+HB_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,\r
+ HB_UShort script_index,\r
+ HB_UInt** language_tag_list );\r
+\r
+HB_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UInt** feature_tag_list );\r
+\r
+\r
+HB_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,\r
+ HB_UShort feature_index,\r
+ HB_UInt property );\r
+\r
+HB_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub );\r
+\r
+\r
+HB_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,\r
+ HB_AltFunction altfunc,\r
+ void* data );\r
+\r
+\r
+HB_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,\r
+ HB_Buffer buffer );\r
+\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_GSUB_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_IMPL_H\r
+#define HARFBUZZ_IMPL_H\r
+\r
+#include "harfbuzz-global.h"\r
+\r
+#include <stdlib.h>\r
+\r
+HB_BEGIN_HEADER\r
+\r
+#ifndef HB_INTERNAL\r
+# define HB_INTERNAL\r
+#endif\r
+\r
+#ifndef NULL\r
+# define NULL ((void *)0)\r
+#endif\r
+\r
+#ifndef FALSE\r
+# define FALSE 0\r
+#endif\r
+\r
+#ifndef TRUE\r
+# define TRUE 1\r
+#endif\r
+\r
+#ifndef TTAG_GDEF\r
+# define TTAG_GDEF HB_MAKE_TAG( 'G', 'D', 'E', 'F' )\r
+#endif\r
+#ifndef TTAG_GPOS\r
+# define TTAG_GPOS HB_MAKE_TAG( 'G', 'P', 'O', 'S' )\r
+#endif\r
+#ifndef TTAG_GSUB\r
+# define TTAG_GSUB HB_MAKE_TAG( 'G', 'S', 'U', 'B' )\r
+#endif\r
+\r
+#ifndef HB_UNUSED\r
+# define HB_UNUSED(arg) ((arg) = (arg))\r
+#endif\r
+\r
+#define HB_LIKELY(cond) (cond)\r
+#define HB_UNLIKELY(cond) (cond)\r
+\r
+#define ARRAY_LEN(Array) ((int)(sizeof (Array) / sizeof (Array)[0]))\r
+\r
+\r
+\r
+#define HB_IsHighSurrogate(ucs) \\r
+ (((ucs) & 0xfc00) == 0xd800)\r
+\r
+#define HB_IsLowSurrogate(ucs) \\r
+ (((ucs) & 0xfc00) == 0xdc00)\r
+\r
+#define HB_SurrogateToUcs4(high, low) \\r
+ (((HB_UChar32)(high))<<10) + (low) - 0x35fdc00;\r
+\r
+\r
+\r
+\r
+\r
+#define ALLOC(_ptr,_size,_type) \\r
+ ( (_ptr) = (_type)_hb_alloc( _size, &error ), error != 0 )\r
+\r
+#define REALLOC(_ptr,_newsz,_type) \\r
+ ( (_ptr) = (_type)_hb_realloc( (_ptr), (_newsz), &error ), error != 0 )\r
+\r
+#define FREE(_ptr) \\r
+ do { \\r
+ if ( (_ptr) ) \\r
+ { \\r
+ _hb_free( _ptr ); \\r
+ _ptr = NULL; \\r
+ } \\r
+ } while (0)\r
+\r
+#define ALLOC_ARRAY(_ptr,_count,_type) \\r
+ ALLOC(_ptr,(_count)*sizeof(_type),_type*)\r
+\r
+#define REALLOC_ARRAY(_ptr,_newcnt,_type) \\r
+ REALLOC(_ptr,(_newcnt)*sizeof(_type),_type*)\r
+\r
+#define MEM_Copy(dest,source,count) memcpy( (char*)(dest), (const char*)(source), (size_t)(count) )\r
+\r
+#define ERR_HB(err) _hb_err (err)\r
+\r
+\r
+//HB_INTERNAL\r
+HB_Pointer\r
+_hb_alloc( size_t size,\r
+ HB_Error *perror_ );\r
+\r
+//HB_INTERNAL\r
+ HB_Pointer\r
+_hb_realloc( HB_Pointer block,\r
+ size_t new_size,\r
+ HB_Error *perror_ );\r
+\r
+//HB_INTERNAL \r
+ void\r
+_hb_free( HB_Pointer block );\r
+\r
+\r
+/* helper func to set a breakpoint on */\r
+//HB_INTERNAL \r
+HB_Error\r
+_hb_err(HB_Error code);\r
+\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_IMPL_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_OPEN_PRIVATE_H\r
+#define HARFBUZZ_OPEN_PRIVATE_H\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-open.h"\r
+#include "harfbuzz-gsub-private.h"\r
+#include "harfbuzz-gpos-private.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+\r
+struct HB_SubTable_\r
+{\r
+ union\r
+ {\r
+ HB_GSUB_SubTable gsub;\r
+ HB_GPOS_SubTable gpos;\r
+ } st;\r
+};\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_ScriptList( HB_ScriptList* sl,\r
+ HB_Stream input );\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_FeatureList( HB_FeatureList* fl,\r
+ HB_Stream input );\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_LookupList( HB_LookupList* ll,\r
+ HB_Stream input,\r
+ HB_Type type );\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_Coverage( HB_Coverage* c,\r
+ HB_Stream input );\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,\r
+ HB_UShort limit,\r
+ HB_Stream input );\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,\r
+ HB_UShort limit,\r
+ HB_UInt class_offset,\r
+ HB_UInt base_offset,\r
+ HB_Stream input );\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_Device( HB_Device* d,\r
+ HB_Stream input );\r
+\r
+HB_INTERNAL void _HB_OPEN_Free_ScriptList( HB_ScriptList* sl );\r
+HB_INTERNAL void _HB_OPEN_Free_FeatureList( HB_FeatureList* fl );\r
+HB_INTERNAL void _HB_OPEN_Free_LookupList( HB_LookupList* ll,\r
+ HB_Type type );\r
+\r
+HB_INTERNAL void _HB_OPEN_Free_Coverage( HB_Coverage* c );\r
+HB_INTERNAL void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd );\r
+HB_INTERNAL void _HB_OPEN_Free_Device( HB_Device* d );\r
+\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Coverage_Index( HB_Coverage* c,\r
+ HB_UShort glyphID,\r
+ HB_UShort* index );\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Get_Class( HB_ClassDefinition* cd,\r
+ HB_UShort glyphID,\r
+ HB_UShort* klass,\r
+ HB_UShort* index );\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Get_Device( HB_Device* d,\r
+ HB_UShort size,\r
+ HB_Short* value );\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_OPEN_PRIVATE_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_OPEN_H\r
+#define HARFBUZZ_OPEN_H\r
+\r
+#include "harfbuzz-global.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+/* Use this if a feature applies to all glyphs */\r
+#define HB_ALL_GLYPHS 0xFFFF\r
+\r
+#define HB_DEFAULT_LANGUAGE 0xFFFF\r
+\r
+#define HB_MAX_NESTING_LEVEL 100\r
+\r
+\r
+/* Script list related structures */\r
+\r
+struct HB_LangSys_\r
+{\r
+ HB_UShort LookupOrderOffset; /* always 0 for TT Open 1.0 */\r
+ HB_UShort ReqFeatureIndex; /* required FeatureIndex */\r
+ HB_UShort FeatureCount; /* number of Feature indices */\r
+ HB_UShort* FeatureIndex; /* array of Feature indices */\r
+};\r
+\r
+typedef struct HB_LangSys_ HB_LangSys;\r
+\r
+\r
+struct HB_LangSysRecord_\r
+{\r
+ HB_UInt LangSysTag; /* LangSysTag identifier */\r
+ HB_LangSys LangSys; /* LangSys table */\r
+};\r
+\r
+typedef struct HB_LangSysRecord_ HB_LangSysRecord;\r
+\r
+\r
+struct HB_ScriptTable_\r
+{\r
+ HB_LangSys DefaultLangSys; /* DefaultLangSys table */\r
+ HB_UShort LangSysCount; /* number of LangSysRecords */\r
+ HB_LangSysRecord* LangSysRecord; /* array of LangSysRecords */\r
+};\r
+\r
+typedef struct HB_ScriptTable_ HB_ScriptTable;\r
+\r
+\r
+struct HB_ScriptRecord_\r
+{\r
+ HB_UInt ScriptTag; /* ScriptTag identifier */\r
+ HB_ScriptTable Script; /* Script table */\r
+};\r
+\r
+typedef struct HB_ScriptRecord_ HB_ScriptRecord;\r
+\r
+\r
+struct HB_ScriptList_\r
+{\r
+ HB_UShort ScriptCount; /* number of ScriptRecords */\r
+ HB_ScriptRecord* ScriptRecord; /* array of ScriptRecords */\r
+};\r
+\r
+typedef struct HB_ScriptList_ HB_ScriptList;\r
+\r
+\r
+/* Feature list related structures */\r
+\r
+struct HB_Feature_\r
+{\r
+ HB_UShort FeatureParams; /* always 0 for TT Open 1.0 */\r
+ HB_UShort LookupListCount; /* number of LookupList indices */\r
+ HB_UShort* LookupListIndex; /* array of LookupList indices */\r
+};\r
+\r
+typedef struct HB_Feature_ HB_Feature;\r
+\r
+\r
+struct HB_FeatureRecord_\r
+{\r
+ HB_UInt FeatureTag; /* FeatureTag identifier */\r
+ HB_Feature Feature; /* Feature table */\r
+};\r
+\r
+typedef struct HB_FeatureRecord_ HB_FeatureRecord;\r
+\r
+\r
+struct HB_FeatureList_\r
+{\r
+ HB_UShort FeatureCount; /* number of FeatureRecords */\r
+ HB_FeatureRecord* FeatureRecord; /* array of FeatureRecords */\r
+ HB_UShort* ApplyOrder; /* order to apply features */\r
+ HB_UShort ApplyCount; /* number of elements in ApplyOrder */\r
+};\r
+\r
+typedef struct HB_FeatureList_ HB_FeatureList;\r
+\r
+\r
+/* Lookup list related structures */\r
+\r
+typedef struct HB_SubTable_ HB_SubTable;\r
+\r
+\r
+struct HB_Lookup_\r
+{\r
+ HB_UShort LookupType; /* Lookup type */\r
+ HB_UShort LookupFlag; /* Lookup qualifiers */\r
+ HB_UShort SubTableCount; /* number of SubTables */\r
+ HB_SubTable* SubTable; /* array of SubTables */\r
+};\r
+\r
+typedef struct HB_Lookup_ HB_Lookup;\r
+\r
+\r
+/* The `Properties' field is not defined in the OpenType specification but\r
+ is needed for processing lookups. If properties[n] is > 0, the\r
+ functions HB_GSUB_Apply_String() resp. HB_GPOS_Apply_String() will\r
+ process Lookup[n] for glyphs which have the specific bit not set in\r
+ the `properties' field of the input string object. */\r
+\r
+struct HB_LookupList_\r
+{\r
+ HB_UShort LookupCount; /* number of Lookups */\r
+ HB_Lookup* Lookup; /* array of Lookup records */\r
+ HB_UInt* Properties; /* array of flags */\r
+};\r
+\r
+typedef struct HB_LookupList_ HB_LookupList;\r
+\r
+\r
+/* Possible LookupFlag bit masks. `HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS' comes from the\r
+ OpenType 1.2 specification; HB_LOOKUP_FLAG_RIGHT_TO_LEFT has been (re)introduced in\r
+ OpenType 1.3 -- if set, the last glyph in a cursive attachment\r
+ sequence has to be positioned on the baseline -- regardless of the\r
+ writing direction. */\r
+\r
+#define HB_LOOKUP_FLAG_RIGHT_TO_LEFT 0x0001\r
+#define HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS 0x0002\r
+#define HB_LOOKUP_FLAG_IGNORE_LIGATURES 0x0004\r
+#define HB_LOOKUP_FLAG_IGNORE_MARKS 0x0008\r
+#define HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS 0xFF00\r
+\r
+\r
+struct HB_CoverageFormat1_\r
+{\r
+ HB_UShort GlyphCount; /* number of glyphs in GlyphArray */\r
+ HB_UShort* GlyphArray; /* array of glyph IDs */\r
+};\r
+\r
+typedef struct HB_CoverageFormat1_ HB_CoverageFormat1;\r
+\r
+\r
+struct HB_RangeRecord_\r
+{\r
+ HB_UShort Start; /* first glyph ID in the range */\r
+ HB_UShort End; /* last glyph ID in the range */\r
+ HB_UShort StartCoverageIndex; /* coverage index of first\r
+ glyph ID in the range */\r
+};\r
+\r
+typedef struct HB_RangeRecord_ HB_RangeRecord;\r
+\r
+\r
+struct HB_CoverageFormat2_\r
+{\r
+ HB_UShort RangeCount; /* number of RangeRecords */\r
+ HB_RangeRecord* RangeRecord; /* array of RangeRecords */\r
+};\r
+\r
+typedef struct HB_CoverageFormat2_ HB_CoverageFormat2;\r
+\r
+\r
+struct HB_Coverage_\r
+{\r
+ HB_UShort CoverageFormat; /* 1 or 2 */\r
+\r
+ union\r
+ {\r
+ HB_CoverageFormat1 cf1;\r
+ HB_CoverageFormat2 cf2;\r
+ } cf;\r
+};\r
+\r
+typedef struct HB_Coverage_ HB_Coverage;\r
+\r
+\r
+struct HB_ClassDefFormat1_\r
+{\r
+ HB_UShort StartGlyph; /* first glyph ID of the\r
+ ClassValueArray */\r
+ HB_UShort GlyphCount; /* size of the ClassValueArray */\r
+ HB_UShort* ClassValueArray; /* array of class values */\r
+};\r
+\r
+typedef struct HB_ClassDefFormat1_ HB_ClassDefFormat1;\r
+\r
+\r
+struct HB_ClassRangeRecord_\r
+{\r
+ HB_UShort Start; /* first glyph ID in the range */\r
+ HB_UShort End; /* last glyph ID in the range */\r
+ HB_UShort Class; /* applied to all glyphs in range */\r
+};\r
+\r
+typedef struct HB_ClassRangeRecord_ HB_ClassRangeRecord;\r
+\r
+\r
+struct HB_ClassDefFormat2_\r
+{\r
+ HB_UShort ClassRangeCount;\r
+ /* number of ClassRangeRecords */\r
+ HB_ClassRangeRecord* ClassRangeRecord;\r
+ /* array of ClassRangeRecords */\r
+};\r
+\r
+typedef struct HB_ClassDefFormat2_ HB_ClassDefFormat2;\r
+\r
+\r
+struct HB_ClassDefinition_\r
+{\r
+ HB_Bool loaded;\r
+\r
+ HB_UShort ClassFormat; /* 1 or 2 */\r
+\r
+ union\r
+ {\r
+ HB_ClassDefFormat1 cd1;\r
+ HB_ClassDefFormat2 cd2;\r
+ } cd;\r
+};\r
+\r
+typedef struct HB_ClassDefinition_ HB_ClassDefinition;\r
+\r
+\r
+struct HB_Device_\r
+{\r
+ HB_UShort StartSize; /* smallest size to correct */\r
+ HB_UShort EndSize; /* largest size to correct */\r
+ HB_UShort DeltaFormat; /* DeltaValue array data format:\r
+ 1, 2, or 3 */\r
+ HB_UShort* DeltaValue; /* array of compressed data */\r
+};\r
+\r
+typedef struct HB_Device_ HB_Device;\r
+\r
+\r
+enum HB_Type_\r
+{\r
+ HB_Type_GSUB,\r
+ HB_Type_GPOS\r
+};\r
+\r
+typedef enum HB_Type_ HB_Type;\r
+\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_OPEN_H */\r
--- /dev/null
+/*\r
+ * Copyright (C) 2006 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Owen Taylor\r
+ */\r
+\r
+#include <stdint.h>\r
+\r
+/* Base Types */\r
+\r
+typedef hb_uint16 HB_CodePoint; /* UTF-16 codepoint (not character ) */\r
+typedef char HB_Boolean;\r
+typedef hb_uint32 HB_Fixed; /* 26.6 */\r
+typedef hb_uint32 HB_Glyph;\r
+typedef hb_uint32 HB_Unichar;\r
+\r
+/* Metrics reported by the font backend for use of the shaper */\r
+typedef struct _HB_GlyphMetrics HB_GlyphMetrics;\r
+struct _HB_GlyphMetrics\r
+{\r
+ HB_Fixed advance;\r
+ \r
+ /* Do we need ink/logical extents for the glyph here? */\r
+};\r
+\r
+/*\r
+ * HB_Font: Abstract font interface.\r
+ * First pass of this might just have FT_Face *getFace();\r
+ */\r
+typedef struct _HB_Font HB_Font;\r
+typedef struct _HB_FontClass HB_FontClass;\r
+\r
+struct HB_FontClass {\r
+ HB_Glyph (*charToGlyph)(HB_Font *font, HB_Unichar chr);\r
+ void (*getMetrics)(HB_Font *font, HB_Glyph glyph, HB_GlyphMetrics *metrics);\r
+ HB_Boolean (*getSFontTable)(HB_Font *font, void **cookie, char **start, int *len);\r
+ HB_Boolean (*freeSFontTable)(void **cookie);\r
+};\r
+\r
+struct _HB_Font {\r
+ HB_FontClass *clazz;\r
+};\r
+\r
+/*\r
+ * Language tags, of the form en-us; represented as interned, canonicalized\r
+ * strings. hb_language_from_string("en_US"), hb_language_from_string("en-us")\r
+ * both return the same (pointer-comparable) HB_Language).\r
+ */\r
+typedef struct HB_Language_ *HB_Language;\r
+\r
+HB_Language hb_language_from_string(const char *str);\r
+const char *hb_language_to_string(HB_Language language);\r
+\r
+/* Special treatment for the edges of runs.\r
+ */\r
+typedef enum {\r
+ HB_RUN_EDGE_LINE_VISUAL_EDGE = 1 << 0,\r
+ HB_RUN_EDGE_LINE_LOGICAL_EDGE = 1 << 1,\r
+ HB_RUN_EDGE_LINE_ADD_HYPHEN = 1 << 2 /* ???? */\r
+} HB_RunEdge;\r
+\r
+/* Defines optional informaiton in HB_ShapeInput; this allows extension\r
+ * of HB_ShapeInput while keeping binary compatibility\r
+ */\r
+typedef enum {\r
+ HB_SHAPE_START_TYPE = 1 << 0,\r
+ HB_SHAPE_END_TYPE = 1 << 1\r
+} HB_ShapeFlags;\r
+\r
+/* Attributes types are described by "interned strings"; this is a little\r
+ * annoying if you want to write a switch statement, but keeps things\r
+ * simple.\r
+ */\r
+typedef struct _HB_AttributeType *HB_AttributeType;\r
+\r
+HB_AttributeType hb_attribute_type_from_string(const char *str);\r
+const char *hb_attribute_type_to_string(HB_AttributeType attribute_type);\r
+\r
+struct HB_Attribute {\r
+ HB_AttributeType type;\r
+ int start; \r
+ int end;\r
+};\r
+\r
+\r
+/**\r
+ * You could handle this like HB_Language, but an enum seems a little nicer;\r
+ * another approach would be to use OpenType script tags.\r
+ */\r
+typedef enum {\r
+ HB_SCRIPT_LATIN\r
+ /* ... */\r
+} HB_ShapeScript;\r
+\r
+/* This is just the subset of direction information needed by the shaper */\r
+typedef enum {\r
+ HB_DIRECTION_LTR,\r
+ HB_DIRECTION_RTL,\r
+ HB_DIRECTION_TTB\r
+} HB_Direction;\r
+\r
+typedef struct _HB_ShapeInput HB_ShapeInput;\r
+struct _HB_ShapeInput {\r
+ /* Defines what fields the caller has initialized - fields not in\r
+ * the enum are mandatory.\r
+ */\r
+ HB_ShapeFlags flags;\r
+ \r
+ HB_CodePoint *text;\r
+ int length; /* total length of text to shape */\r
+ int shape_offset; /* start of section to shape */\r
+ int shape_length; /* number of code points to shape */\r
+\r
+ HB_Direction direction;\r
+ HB_ShapeScript script;\r
+ HB_Language language;\r
+\r
+ HB_AttributeType *attributes;\r
+ int n_attributes;\r
+\r
+ HB_RunEdge start_type;\r
+ HB_RunEdge end_type;\r
+};\r
+\r
+struct HB_GlyphItem {\r
+ HB_Glyph glyph;\r
+ \r
+ HB_Fixed x_offset;\r
+ HB_Fixed y_offset;\r
+ HB_Fixed advance;\r
+\r
+ /* Add kashida information, etc, here */\r
+};\r
+\r
+typedef enum {\r
+ HB_RESULT_SUCCESS,\r
+ HB_RESULT_NO_MEMORY,\r
+ HB_SHAPE_RESULT_FAILED\r
+} HB_Result;\r
+\r
+/*\r
+ * Buffer for output \r
+ */\r
+typedef struct _HB_GlyphBuffer HB_GlyphBuffer;\r
+struct _HB_GlyphBuffer {\r
+ int glyph_item_size;\r
+ int total_glyphs;\r
+ \r
+ int *log_clusters; /* Uniscribe style */\r
+ int cluster_space;\r
+ \r
+ int glyph_space;\r
+ void *glyph_buffer;\r
+};\r
+\r
+/* Making this self-allocating simplifies writing shapers and\r
+ * also keeps things easier for caller. item_size passed in\r
+ * must be at least sizeof(HB_GlyphItem) but can be bigger,\r
+ * to accomodate application structures that extend HB_GlyphItem.\r
+ * The allocated items will be zero-initialized.\r
+ *\r
+ * (Hack: Harfbuzz could choose to use even a *bigger* item size\r
+ * and stick internal information before the public item structure.\r
+ * This hack could possibly be used to unify this with HB_Buffer)\r
+ */\r
+HB_GlyphBuffer *hb_glyph_buffer_new (size_t item_size);\r
+void hb_glyph_buffer_clear (HB_GlyphBuffer *buf);\r
+HB_Result hb_glyph_buffer_extend_glyphs (HB_GlyphBuffer *buf, int n_items);\r
+HB_Result hb_glyph_buffer_extend_clusters (HB_GlyphBuffer *buf, int n_clusters);\r
+void hb_glyph_buffer_free (HB_GlyphBuffer *buf);\r
+\r
+\r
+/* Accessor for a particular glyph */\r
+#define HB_GLYPH_BUFFER_ITEM(buffer, index)\r
+\r
+/*\r
+ * Main shaping function\r
+ */\r
+HB_Result hb_shape(HB_ShapeInput *input, HB_GlyphBuffer *output);\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_SHAPER_PRIVATE_H\r
+#define HARFBUZZ_SHAPER_PRIVATE_H\r
+\r
+HB_BEGIN_HEADER\r
+enum {\r
+ C_DOTTED_CIRCLE = 0x25CC\r
+};\r
+\r
+typedef enum \r
+{\r
+ HB_Combining_BelowLeftAttached = 200,\r
+ HB_Combining_BelowAttached = 202,\r
+ HB_Combining_BelowRightAttached = 204,\r
+ HB_Combining_LeftAttached = 208,\r
+ HB_Combining_RightAttached = 210,\r
+ HB_Combining_AboveLeftAttached = 212,\r
+ HB_Combining_AboveAttached = 214,\r
+ HB_Combining_AboveRightAttached = 216,\r
+\r
+ HB_Combining_BelowLeft = 218,\r
+ HB_Combining_Below = 220,\r
+ HB_Combining_BelowRight = 222,\r
+ HB_Combining_Left = 224,\r
+ HB_Combining_Right = 226,\r
+ HB_Combining_AboveLeft = 228,\r
+ HB_Combining_Above = 230,\r
+ HB_Combining_AboveRight = 232,\r
+\r
+ HB_Combining_DoubleBelow = 233,\r
+ HB_Combining_DoubleAbove = 234,\r
+ HB_Combining_IotaSubscript = 240\r
+} HB_CombiningClass;\r
+\r
+typedef enum {\r
+ CcmpProperty = 0x1,\r
+ InitProperty = 0x2,\r
+ IsolProperty = 0x4,\r
+ FinaProperty = 0x8,\r
+ MediProperty = 0x10,\r
+ RligProperty = 0x20,\r
+ CaltProperty = 0x40,\r
+ LigaProperty = 0x80,\r
+ DligProperty = 0x100,\r
+ CswhProperty = 0x200,\r
+ MsetProperty = 0x400,\r
+\r
+ /* used by indic and myanmar shaper */\r
+ NuktaProperty = 0x4,\r
+ AkhantProperty = 0x8,\r
+ RephProperty = 0x10,\r
+ PreFormProperty = 0x20,\r
+ BelowFormProperty = 0x40,\r
+ AboveFormProperty = 0x80,\r
+ HalfFormProperty = 0x100,\r
+ PostFormProperty = 0x200,\r
+ VattuProperty = 0x400,\r
+ PreSubstProperty = 0x800,\r
+ BelowSubstProperty = 0x1000,\r
+ AboveSubstProperty = 0x2000,\r
+ PostSubstProperty = 0x4000,\r
+ HalantProperty = 0x8000,\r
+ CligProperty = 0x10000\r
+\r
+} HB_OpenTypeProperty;\r
+\r
+/* return true if ok. */\r
+typedef HB_Bool (*HB_ShapeFunction)(HB_ShaperItem *shaper_item);\r
+typedef void (*HB_AttributeFunction)(HB_Script script, const HB_UChar16 *string, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes);\r
+\r
+typedef struct {\r
+ HB_ShapeFunction shape;\r
+ HB_AttributeFunction charAttributes;\r
+} HB_ScriptEngine;\r
+\r
+extern const HB_ScriptEngine HB_ScriptEngines[];\r
+\r
+extern HB_Bool HB_BasicShape(HB_ShaperItem *shaper_item);\r
+extern HB_Bool HB_TibetanShape(HB_ShaperItem *shaper_item);\r
+extern HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item);\r
+extern HB_Bool HB_ArabicShape(HB_ShaperItem *shaper_item);\r
+extern HB_Bool HB_HangulShape(HB_ShaperItem *shaper_item);\r
+extern HB_Bool HB_MyanmarShape(HB_ShaperItem *shaper_item);\r
+extern HB_Bool HB_KhmerShape(HB_ShaperItem *shaper_item);\r
+extern HB_Bool HB_IndicShape(HB_ShaperItem *shaper_item);\r
+\r
+extern void HB_TibetanAttributes(HB_Script script, const HB_UChar16 *string, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes);\r
+\r
+extern void HB_MyanmarAttributes(HB_Script script, const HB_UChar16 *string, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes);\r
+\r
+extern void HB_KhmerAttributes(HB_Script script, const HB_UChar16 *string, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes);\r
+\r
+extern void HB_IndicAttributes(HB_Script script, const HB_UChar16 *string, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes);\r
+\r
+extern void HB_ThaiAttributes(HB_Script script, const HB_UChar16 *string, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes);\r
+\r
+typedef struct {\r
+ hb_uint32 tag;\r
+ hb_uint32 property;\r
+} HB_OpenTypeFeature;\r
+\r
+#define PositioningProperties 0x80000000\r
+\r
+HB_Bool HB_SelectScript(HB_ShaperItem *item, const HB_OpenTypeFeature *features);\r
+\r
+HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties);\r
+HB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool doLogClusters);\r
+\r
+void HB_HeuristicPosition(HB_ShaperItem *item);\r
+void HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item);\r
+\r
+#define HB_IsControlChar(uc) \\r
+ ((uc >= 0x200b && uc <= 0x200f /* ZW Space, ZWNJ, ZWJ, LRM and RLM */) \\r
+ || (uc >= 0x2028 && uc <= 0x202f /* LS, PS, LRE, RLE, PDF, LRO, RLO, NNBSP */) \\r
+ || (uc >= 0x206a && uc <= 0x206f /* ISS, ASS, IAFS, AFS, NADS, NODS */))\r
+\r
+HB_Bool HB_ConvertStringToGlyphIndices(HB_ShaperItem *shaper_item);\r
+\r
+#define HB_GetGlyphAdvances(shaper_item) \\r
+ shaper_item->font->klass->getGlyphAdvances(shaper_item->font, \\r
+ shaper_item->glyphs, shaper_item->num_glyphs, \\r
+ shaper_item->advances, \\r
+ shaper_item->face->current_flags);\r
+\r
+#define HB_DECLARE_STACKARRAY(Type, Name) \\r
+ Type stack##Name[64]; \ \r
+ Type *Name = stack##Name;\r
+\r
+#define HB_INIT_STACKARRAY(Type, Name, Length) \\r
+ if ((Length) >= 64) \\r
+ Name = (Type *)malloc((Length) * sizeof(Type));\r
+\r
+#define HB_STACKARRAY(Type, Name, Length) \\r
+ HB_DECLARE_STACKARRAY(Type, Name) \\r
+ HB_INIT_STACKARRAY(Type, Name, Length)\r
+\r
+#define HB_FREE_STACKARRAY(Name) \\r
+ if (stack##Name != Name) \\r
+ free(Name);\r
+\r
+HB_END_HEADER\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_SHAPER_H\r
+#define HARFBUZZ_SHAPER_H\r
+\r
+#include "harfbuzz-global.h"\r
+#include "harfbuzz-gdef.h"\r
+#include "harfbuzz-gpos.h"\r
+#include "harfbuzz-gsub.h"\r
+#include "harfbuzz-external.h" \r
+#include "harfbuzz-stream-private.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+typedef enum {\r
+ HB_Script_Common,\r
+ HB_Script_Greek,\r
+ HB_Script_Cyrillic,\r
+ HB_Script_Armenian,\r
+ HB_Script_Hebrew,\r
+ HB_Script_Arabic,\r
+ HB_Script_Syriac,\r
+ HB_Script_Thaana,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Bengali,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Oriya,\r
+ HB_Script_Tamil,\r
+ HB_Script_Telugu,\r
+ HB_Script_Kannada,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Thai,\r
+ HB_Script_Lao,\r
+ HB_Script_Tibetan,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Georgian,\r
+ HB_Script_Hangul,\r
+ HB_Script_Ogham,\r
+ HB_Script_Runic,\r
+ HB_Script_Khmer,\r
+ HB_Script_Nko,\r
+ HB_Script_Inherited,\r
+ HB_ScriptCount = HB_Script_Inherited\r
+ /*\r
+ HB_Script_Latin = Common,\r
+ HB_Script_Ethiopic = Common,\r
+ HB_Script_Cherokee = Common,\r
+ HB_Script_CanadianAboriginal = Common,\r
+ HB_Script_Mongolian = Common,\r
+ HB_Script_Hiragana = Common,\r
+ HB_Script_Katakana = Common,\r
+ HB_Script_Bopomofo = Common,\r
+ HB_Script_Han = Common,\r
+ HB_Script_Yi = Common,\r
+ HB_Script_OldItalic = Common,\r
+ HB_Script_Gothic = Common,\r
+ HB_Script_Deseret = Common,\r
+ HB_Script_Tagalog = Common,\r
+ HB_Script_Hanunoo = Common,\r
+ HB_Script_Buhid = Common,\r
+ HB_Script_Tagbanwa = Common,\r
+ HB_Script_Limbu = Common,\r
+ HB_Script_TaiLe = Common,\r
+ HB_Script_LinearB = Common,\r
+ HB_Script_Ugaritic = Common,\r
+ HB_Script_Shavian = Common,\r
+ HB_Script_Osmanya = Common,\r
+ HB_Script_Cypriot = Common,\r
+ HB_Script_Braille = Common,\r
+ HB_Script_Buginese = Common,\r
+ HB_Script_Coptic = Common,\r
+ HB_Script_NewTaiLue = Common,\r
+ HB_Script_Glagolitic = Common,\r
+ HB_Script_Tifinagh = Common,\r
+ HB_Script_SylotiNagri = Common,\r
+ HB_Script_OldPersian = Common,\r
+ HB_Script_Kharoshthi = Common,\r
+ HB_Script_Balinese = Common,\r
+ HB_Script_Cuneiform = Common,\r
+ HB_Script_Phoenician = Common,\r
+ HB_Script_PhagsPa = Common,\r
+ */\r
+} HB_Script;\r
+\r
+typedef struct\r
+{\r
+ hb_uint32 pos;\r
+ hb_uint32 length;\r
+ HB_Script script;\r
+ hb_uint8 bidiLevel;\r
+} HB_ScriptItem;\r
+\r
+typedef enum {\r
+ HB_NoBreak,\r
+ HB_SoftHyphen,\r
+ HB_Break,\r
+ HB_ForcedBreak\r
+} HB_LineBreakType;\r
+\r
+\r
+typedef struct {\r
+ /*HB_LineBreakType*/ unsigned lineBreakType :2;\r
+ /*HB_Bool*/ unsigned whiteSpace :1; /* A unicode whitespace character, except NBSP, ZWNBSP */\r
+ /*HB_Bool*/ unsigned charStop :1; /* Valid cursor position (for left/right arrow) */\r
+ /*HB_Bool*/ unsigned wordBoundary :1;\r
+ /*HB_Bool*/ unsigned sentenceBoundary :1;\r
+ unsigned unused :2;\r
+} HB_CharAttributes;\r
+\r
+void HB_GetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,\r
+ const HB_ScriptItem *items, hb_uint32 numItems,\r
+ HB_CharAttributes *attributes);\r
+\r
+/* requires HB_GetCharAttributes to be called before */\r
+void HB_GetWordBoundaries(const HB_UChar16 *string, hb_uint32 stringLength,\r
+ const HB_ScriptItem *items, hb_uint32 numItems,\r
+ HB_CharAttributes *attributes);\r
+\r
+/* requires HB_GetCharAttributes to be called before */\r
+void HB_GetSentenceBoundaries(const HB_UChar16 *string, hb_uint32 stringLength,\r
+ const HB_ScriptItem *items, hb_uint32 numItems,\r
+ HB_CharAttributes *attributes);\r
+\r
+\r
+typedef enum {\r
+ HB_LeftToRight = 0,\r
+ HB_RightToLeft = 1\r
+} HB_StringToGlyphsFlags;\r
+\r
+typedef enum {\r
+ HB_ShaperFlag_Default = 0,\r
+ HB_ShaperFlag_NoKerning = 1,\r
+ HB_ShaperFlag_UseDesignMetrics = 2\r
+} HB_ShaperFlag;\r
+\r
+/* \r
+ highest value means highest priority for justification. Justification is done by first inserting kashidas\r
+ starting with the highest priority positions, then stretching spaces, afterwards extending inter char\r
+ spacing, and last spacing between arabic words.\r
+ NoJustification is for example set for arabic where no Kashida can be inserted or for diacritics.\r
+*/\r
+typedef enum {\r
+ HB_NoJustification= 0, /* Justification can't be applied after this glyph */\r
+ HB_Arabic_Space = 1, /* This glyph represents a space inside arabic text */\r
+ HB_Character = 2, /* Inter-character justification point follows this glyph */\r
+ HB_Space = 4, /* This glyph represents a blank outside an Arabic run */\r
+ HB_Arabic_Normal = 7, /* Normal Middle-Of-Word glyph that connects to the right (begin) */\r
+ HB_Arabic_Waw = 8, /* Next character is final form of Waw/Ain/Qaf/Fa */\r
+ HB_Arabic_BaRa = 9, /* Next two chars are Ba + Ra/Ya/AlefMaksura */\r
+ HB_Arabic_Alef = 10, /* Next character is final form of Alef/Tah/Lam/Kaf/Gaf */\r
+ HB_Arabic_HaaDal = 11, /* Next character is final form of Haa/Dal/Taa Marbutah */\r
+ HB_Arabic_Seen = 12, /* Initial or Medial form Of Seen/Sad */\r
+ HB_Arabic_Kashida = 13 /* Kashida(U+640) in middle of word */\r
+} HB_JustificationClass;\r
+\r
+/* This structure is binary compatible with Uniscribe's SCRIPT_VISATTR. Would be nice to keep\r
+ * it like that. If this is a problem please tell Trolltech :)\r
+ */\r
+typedef struct {\r
+ unsigned justification :4; /* Justification class */\r
+ unsigned clusterStart :1; /* First glyph of representation of cluster */\r
+ unsigned mark :1; /* needs to be positioned around base char */\r
+ unsigned zeroWidth :1; /* ZWJ, ZWNJ etc, with no width */\r
+ unsigned dontPrint :1;\r
+ unsigned combiningClass :8;\r
+} HB_GlyphAttributes;\r
+\r
+typedef struct HB_FaceRec_ {\r
+ HB_Bool isSymbolFont;\r
+\r
+ HB_GDEF gdef;\r
+ HB_GSUB gsub;\r
+ HB_GPOS gpos;\r
+ HB_Bool supported_scripts[HB_ScriptCount];\r
+ HB_Buffer buffer;\r
+ HB_Script current_script;\r
+ int current_flags; /* HB_ShaperFlags */\r
+ HB_Bool has_opentype_kerning;\r
+ HB_Bool glyphs_substituted;\r
+ HB_GlyphAttributes *tmpAttributes;\r
+ unsigned int *tmpLogClusters;\r
+ int length;\r
+ int orig_nglyphs;\r
+} HB_FaceRec;\r
+\r
+typedef HB_Error (*HB_GetFontTableFunc)(void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length);\r
+\r
+HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc);\r
+void HB_FreeFace(HB_Face face);\r
+\r
+typedef struct {\r
+ HB_Fixed x, y;\r
+ HB_Fixed width, height;\r
+ HB_Fixed xOffset, yOffset;\r
+} HB_GlyphMetrics;\r
+\r
+typedef enum {\r
+ HB_FontAscent\r
+} HB_FontMetric;\r
+\r
+typedef struct {\r
+ HB_Bool (*convertStringToGlyphIndices)(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft);\r
+ void (*getGlyphAdvances)(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags /*HB_ShaperFlag*/);\r
+ HB_Bool (*canRender)(HB_Font font, const HB_UChar16 *string, hb_uint32 length);\r
+ /* implementation needs to make sure to load a scaled glyph, so /no/ FT_LOAD_NO_SCALE */\r
+ HB_Error (*getPointInOutline)(HB_Font font, HB_Glyph glyph, int flags /*HB_ShaperFlag*/, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);\r
+ void (*getGlyphMetrics)(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics);\r
+ HB_Fixed (*getFontMetric)(HB_Font font, HB_FontMetric metric);\r
+} HB_FontClass;\r
+\r
+typedef struct HB_Font_ {\r
+ const HB_FontClass *klass;\r
+\r
+ /* Metrics */\r
+ HB_UShort x_ppem, y_ppem;\r
+ HB_16Dot16 x_scale, y_scale;\r
+\r
+ void *userData;\r
+} HB_FontRec;\r
+\r
+typedef struct HB_ShaperItem_ HB_ShaperItem;\r
+\r
+struct HB_ShaperItem_ {\r
+ const HB_UChar16 *string; /* input: the Unicode UTF16 text to be shaped */\r
+ hb_uint32 stringLength; /* input: the length of the input in 16-bit words */\r
+ HB_ScriptItem item; /* input: the current run to be shaped: a run of text all in the same script that is a substring of <string> */\r
+ HB_Font font; /* input: the font: scale, units and function pointers supplying glyph indices and metrics */\r
+ HB_Face face; /* input: the shaper state; current script, access to the OpenType tables , etc. */\r
+ int shaperFlags; /* input (unused) should be set to 0; intended to support flags defined in HB_ShaperFlag */\r
+ HB_Bool glyphIndicesPresent; /* input: true if the <glyphs> array contains glyph indices ready to be shaped */\r
+ hb_uint32 initialGlyphCount; /* input: if glyphIndicesPresent is true, the number of glyph indices in the <glyphs> array */\r
+\r
+ hb_uint32 num_glyphs; /* input: capacity of output arrays <glyphs>, <attributes>, <advances>, <offsets>, and <log_clusters>; */\r
+ /* output: required capacity (may be larger than actual capacity) */\r
+\r
+ HB_Glyph *glyphs; /* output: <num_glyphs> indices of shaped glyphs */\r
+ HB_GlyphAttributes *attributes; /* output: <num_glyphs> glyph attributes */\r
+ HB_Fixed *advances; /* output: <num_glyphs> advances */\r
+ HB_FixedPoint *offsets; /* output: <num_glyphs> offsets */\r
+ unsigned short *log_clusters; /* output: for each output glyph, the index in the input of the start of its logical cluster */\r
+\r
+ /* internal */\r
+ HB_Bool kerning_applied; /* output: true if kerning was applied by the shaper */\r
+};\r
+\r
+HB_Bool HB_ShapeItem(HB_ShaperItem *item);\r
+\r
+\r
+extern int tibetan_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid) ;\r
+extern int myanmar_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid) ;\r
+extern int khmer_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid) ;\r
+//#ifdef __cplusplus\r
+//extern "C" //{ int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int start, int end, bool *invalid) ;\r
+//#endif\r
+\r
+extern int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int start, int end, HB_Bool *invalid) ;\r
+\r
+\r
+HB_END_HEADER\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_STREAM_PRIVATE_H\r
+#define HARFBUZZ_STREAM_PRIVATE_H\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-stream.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+HB_INTERNAL void\r
+_hb_close_stream( HB_Stream stream );\r
+\r
+HB_INTERNAL HB_Int\r
+_hb_stream_pos( HB_Stream stream );\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_stream_seek( HB_Stream stream,\r
+ HB_UInt pos );\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_stream_frame_enter( HB_Stream stream,\r
+ HB_UInt size );\r
+\r
+HB_INTERNAL void\r
+_hb_stream_frame_exit( HB_Stream stream );\r
+\r
+/* convenience macros */\r
+\r
+#define SET_ERR(c) ( (error = (c)) != 0 )\r
+\r
+#define GOTO_Table(tag) (0)\r
+#define FILE_Pos() _hb_stream_pos( stream )\r
+#define FILE_Seek(pos) SET_ERR( _hb_stream_seek( stream, pos ) )\r
+#define ACCESS_Frame(size) SET_ERR( _hb_stream_frame_enter( stream, size ) )\r
+#define FORGET_Frame() _hb_stream_frame_exit( stream )\r
+\r
+#define GET_Byte() (*stream->cursor++)\r
+#define GET_Short() (stream->cursor += 2, (HB_Short)( \\r
+ (*(((HB_Byte*)stream->cursor)-2) << 8) | \\r
+ *(((HB_Byte*)stream->cursor)-1) \\r
+ ))\r
+#define GET_Long() (stream->cursor += 4, (HB_Int)( \\r
+ (*(((HB_Byte*)stream->cursor)-4) << 24) | \\r
+ (*(((HB_Byte*)stream->cursor)-3) << 16) | \\r
+ (*(((HB_Byte*)stream->cursor)-2) << 8) | \\r
+ *(((HB_Byte*)stream->cursor)-1) \\r
+ ))\r
+\r
+\r
+#define GET_Char() ((HB_Char)GET_Byte())\r
+#define GET_UShort() ((HB_UShort)GET_Short())\r
+#define GET_ULong() ((HB_UInt)GET_Long())\r
+#define GET_Tag4() GET_ULong()\r
+\r
+HB_END_HEADER\r
+\r
+#endif /* HARFBUZZ_STREAM_PRIVATE_H */\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_STREAM_H\r
+#define HARFBUZZ_STREAM_H\r
+\r
+#include "harfbuzz-global.h"\r
+\r
+HB_BEGIN_HEADER\r
+\r
+typedef struct HB_StreamRec_\r
+{\r
+ HB_Byte* base;\r
+ HB_UInt size;\r
+ HB_UInt pos;\r
+ \r
+ HB_Byte* cursor;\r
+} HB_StreamRec;\r
+\r
+\r
+HB_END_HEADER\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef HARFBUZZ_H\r
+#define HARFBUZZ_H\r
+\r
+#include "harfbuzz-external.h"\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-global.h"\r
+#include "harfbuzz-buffer.h"\r
+#include "harfbuzz-gdef.h"\r
+#include "harfbuzz-gsub.h"\r
+#include "harfbuzz-gpos.h"\r
+#include "harfbuzz-open.h"\r
+#include "harfbuzz-shaper.h"\r
+\r
+#define HB_DOTTED_CIRCLE 0x25CC /** DottedCircle used with dependent Matras */\r
+#define HB_ZWJ 0x200D /** Zero Width Joiner */\r
+#define HB_ZWNJ 0x200C /** Zero Width Non-Joiner */\r
+\r
+#define HB_INITIAL_NO_OF_GLYPH 64\r
+\r
+extern HB_Error hb_getScriptID(HB_UShort value, HB_Script *scriptID) ;\r
+extern HB_Error hb_getTextWithScriptID(HB_UShort *text, int textLen, HB_Script *scriptID, int *scriptLen) ;\r
+extern int hb_getSyllableLength(HB_UShort *text, int textLen, HB_Script *scriptID) ;\r
+\r
+#endif /* HARFBUZZ_OPEN_H */\r
--- /dev/null
+\r
+/*\r
+ * Copyright (C) 2010 Samsung India Software Operations Pvt. Ltd.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#ifndef __hb_unicode_tables_h__\r
+#define __hb_unicode_tables_h__\r
+\r
+#include "math.h"\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+typedef struct\r
+{\r
+ HB_UShort scriptID;//it can be sript id if subtable is null, else size of subtable\r
+ HB_Script *pSubTable;\r
+\r
+}unicodeScriptTableStruct;\r
+\r
+HB_Script subTableThanaSyriac[] = \r
+{\r
+ HB_Script_Syriac,//0x00\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,//0x08\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+\r
+ HB_Script_Syriac,//0x10\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+\r
+ HB_Script_Syriac,//0x18\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+\r
+ HB_Script_Syriac,//0x20\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,//0x28\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+\r
+ HB_Script_Syriac,//0x30\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,//0x38\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,//0x40\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+\r
+ HB_Script_Syriac,//0x48\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,\r
+ HB_Script_Syriac,//0x4f\r
+\r
+ HB_Script_Common,//0x50\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,//0x58\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,//0x60\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,//0x68\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,//0x70\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,//0x78\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+ HB_Script_Common,\r
+\r
+ HB_Script_Thaana,//0x80\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,//0x88\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,//0x90\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,//0x98\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,//0xa0\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,//0xa8\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,//0xb0\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,//0xb8\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,\r
+ HB_Script_Thaana,//0xbf\r
+};\r
+\r
+HB_Script subTableDevaBengali[] = \r
+{\r
+ HB_Script_Devanagari,//0x00\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,//0x08\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x10\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x18\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x20\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,//0x28\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x30\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,//0x38\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,//0x40\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x48\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,//0x4f\r
+\r
+ HB_Script_Devanagari,//0x50\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,//0x58\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x60\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x68\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+\r
+ HB_Script_Devanagari,//0x70\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,//0x78\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,\r
+ HB_Script_Devanagari,//0x7f\r
+\r
+\r
+ HB_Script_Bengali,//0x80\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0x88\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0x90\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+\r
+ HB_Script_Bengali,//0x98\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xa0\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xa8\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xb0\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+\r
+ HB_Script_Bengali,//0xb8\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xc0\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+\r
+ HB_Script_Bengali,//0xc8\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xd0\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xd8\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xe0\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+\r
+ HB_Script_Bengali,//0xe8\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xf0\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,//0xf8\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,\r
+ HB_Script_Bengali,//0xff\r
+\r
+};\r
+\r
+\r
+HB_Script subTableGuruGuarati[]=\r
+{\r
+ HB_Script_Gurmukhi,//0x00\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,//0x08\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x10\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x18\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x20\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,//0x28\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x30\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,//0x38\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,//0x40\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x48\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,//0x4f\r
+\r
+ HB_Script_Gurmukhi,//0x50\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,//0x58\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x60\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x68\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+\r
+ HB_Script_Gurmukhi,//0x70\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,//0x78\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,\r
+ HB_Script_Gurmukhi,//0x7f\r
+\r
+\r
+ HB_Script_Gujarati,//0x80\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0x88\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0x90\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+\r
+ HB_Script_Gujarati,//0x98\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xa0\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xa8\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xb0\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+\r
+ HB_Script_Gujarati,//0xb8\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xc0\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+\r
+ HB_Script_Gujarati,//0xc8\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xd0\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xd8\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xe0\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+\r
+ HB_Script_Gujarati,//0xe8\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xf0\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,//0xf8\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,\r
+ HB_Script_Gujarati,//0xff\r
+\r
+};\r
+\r
+HB_Script subTableOriyaTamil[]=\r
+{\r
+ HB_Script_Oriya,//0x00\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,//0x08\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x10\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x18\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x20\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,//0x28\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x30\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,//0x38\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,//0x40\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x48\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,//0x4f\r
+\r
+ HB_Script_Oriya,//0x50\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,//0x58\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x60\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x68\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+\r
+ HB_Script_Oriya,//0x70\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,//0x78\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,\r
+ HB_Script_Oriya,//0x7f\r
+\r
+\r
+ HB_Script_Tamil,//0x80\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0x88\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0x90\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+\r
+ HB_Script_Tamil,//0x98\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xa0\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xa8\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xb0\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+\r
+ HB_Script_Tamil,//0xb8\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xc0\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+\r
+ HB_Script_Tamil,//0xc8\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xd0\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xd8\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xe0\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+\r
+ HB_Script_Tamil,//0xe8\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xf0\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,//0xf8\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,\r
+ HB_Script_Tamil,//0xff\r
+\r
+};\r
+\r
+\r
+HB_Script subTableTelukannada[]=\r
+{\r
+ HB_Script_Telugu,//0x00\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,//0x08\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x10\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x18\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x20\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,//0x28\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x30\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,//0x38\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,//0x40\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x48\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,//0x4f\r
+\r
+ HB_Script_Telugu,//0x50\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,//0x58\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x60\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x68\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+\r
+ HB_Script_Telugu,//0x70\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,//0x78\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,\r
+ HB_Script_Telugu,//0x7f\r
+\r
+\r
+ HB_Script_Kannada,//0x80\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0x88\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0x90\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+\r
+ HB_Script_Kannada,//0x98\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xa0\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xa8\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xb0\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+\r
+ HB_Script_Kannada,//0xb8\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xc0\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+\r
+ HB_Script_Kannada,//0xc8\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xd0\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xd8\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xe0\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+\r
+ HB_Script_Kannada,//0xe8\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xf0\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,//0xf8\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,\r
+ HB_Script_Kannada,//0xff\r
+\r
+};\r
+\r
+HB_Script subTableMalSinhala[]=\r
+{\r
+ HB_Script_Malayalam,//0x00\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,//0x08\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x10\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x18\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x20\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,//0x28\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x30\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,//0x38\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,//0x40\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x48\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,//0x4f\r
+\r
+ HB_Script_Malayalam,//0x50\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,//0x58\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x60\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x68\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+\r
+ HB_Script_Malayalam,//0x70\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,//0x78\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,\r
+ HB_Script_Malayalam,//0x7f\r
+\r
+\r
+ HB_Script_Sinhala,//0x80\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0x88\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0x90\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+\r
+ HB_Script_Sinhala,//0x98\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xa0\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xa8\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xb0\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+\r
+ HB_Script_Sinhala,//0xb8\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xc0\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+\r
+ HB_Script_Sinhala,//0xc8\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xd0\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xd8\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xe0\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+\r
+ HB_Script_Sinhala,//0xe8\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xf0\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,//0xf8\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,\r
+ HB_Script_Sinhala,//0xff\r
+\r
+};\r
+\r
+HB_Script subTableThaiLao[]=\r
+{\r
+ HB_Script_Thai,//0x00\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,//0x08\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x10\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x18\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x20\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,//0x28\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x30\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,//0x38\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,//0x40\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x48\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,//0x4f\r
+\r
+ HB_Script_Thai,//0x50\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,//0x58\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x60\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x68\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+\r
+ HB_Script_Thai,//0x70\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,//0x78\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,\r
+ HB_Script_Thai,//0x7f\r
+\r
+\r
+ HB_Script_Lao,//0x80\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0x88\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0x90\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+\r
+ HB_Script_Lao,//0x98\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xa0\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xa8\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xb0\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+\r
+ HB_Script_Lao,//0xb8\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xc0\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+\r
+ HB_Script_Lao,//0xc8\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xd0\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xd8\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xe0\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+\r
+ HB_Script_Lao,//0xe8\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xf0\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,//0xf8\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,\r
+ HB_Script_Lao,//0xff\r
+\r
+};\r
+\r
+HB_Script subTableMyanGeorgian[] =\r
+{\r
+ HB_Script_Myanmar,//0x00\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x08\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x10\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x18\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x20\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x28\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x30\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x38\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x40\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x48\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,//0x4f\r
+\r
+ HB_Script_Myanmar,//0x50\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x58\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x60\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x68\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x70\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x78\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,//0x7f\r
+\r
+\r
+ HB_Script_Myanmar,//0x80\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x88\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,//0x90\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+\r
+ HB_Script_Myanmar,//0x98\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+ HB_Script_Myanmar,\r
+\r
+ HB_Script_Georgian,//0xa0\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xa8\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xb0\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+\r
+ HB_Script_Georgian,//0xb8\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xc0\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+\r
+ HB_Script_Georgian,//0xc8\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xd0\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xd8\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xe0\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+\r
+ HB_Script_Georgian,//0xe8\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xf0\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,//0xf8\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,\r
+ HB_Script_Georgian,//0xff\r
+\r
+};\r
+\r
+HB_Script subTableOghamRunic[] = \r
+{\r
+ HB_Script_Ogham,//0x00\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x08\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x10\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x18\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x20\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x28\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x30\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x38\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x40\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x48\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,//0x4f\r
+\r
+ HB_Script_Ogham,//0x50\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x58\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x60\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x68\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x70\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x78\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,//0x7f\r
+\r
+\r
+ HB_Script_Ogham,//0x80\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x88\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,//0x90\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+\r
+ HB_Script_Ogham,//0x98\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+ HB_Script_Ogham,\r
+\r
+ HB_Script_Runic,//0xa0\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xa8\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xb0\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+\r
+ HB_Script_Runic,//0xb8\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xc0\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+\r
+ HB_Script_Runic,//0xc8\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xd0\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xd8\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xe0\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+\r
+ HB_Script_Runic,//0xe8\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xf0\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,//0xf8\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,\r
+ HB_Script_Runic,//0xff\r
+\r
+};\r
+\r
+#define VFE_UNICODE_MAX_SCRIPT 256\r
+\r
+static const unicodeScriptTableStruct scriptTableStruct[VFE_UNICODE_MAX_SCRIPT]=\r
+{\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Greek, 0},\r
+\r
+ {HB_Script_Cyrillic, 0},//0x04\r
+ {HB_Script_Armenian, 0},\r
+ {HB_Script_Arabic, 0},\r
+ {0xc0, subTableThanaSyriac},\r
+\r
+ {HB_Script_Common, 0},//0x08\r
+ {0x100, subTableDevaBengali},\r
+ {0x100, subTableGuruGuarati},\r
+ {0x100, subTableOriyaTamil},\r
+ \r
+ {0x100, subTableTelukannada},//0x0c\r
+ {0x100, subTableMalSinhala},\r
+ {0x100, subTableThaiLao},\r
+ {HB_Script_Tibetan, 0},\r
+\r
+ {0x100, subTableMyanGeorgian},//0x10\r
+ {HB_Script_Hangul, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x14\r
+ {HB_Script_Common, 0},\r
+ {0x100, subTableOghamRunic},\r
+ {HB_Script_Khmer, 0},\r
+\r
+ {HB_Script_Common, 0},//0x18\r
+ {HB_Script_Khmer, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x1c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x20\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x24\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x28\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x2c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x30\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x34\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x38\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x3c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x40\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x44\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x48\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x4c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x50\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x54\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x58\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x5c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x60\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x64\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x68\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x6c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x70\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x74\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x78\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x7c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x80\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x84\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x88\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x8c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x40\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x94\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x98\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0x9c\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xa0\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xa4\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xa8\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xac\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xb0\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xb4\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xb8\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xbc\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xc0\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xc4\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xc8\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xcc\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xd0\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xd4\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xd8\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xdc\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xe0\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xe4\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xe8\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xec\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xf0\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xf4\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xf8\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+\r
+ {HB_Script_Common, 0},//0xfc\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},\r
+ {HB_Script_Common, 0},//ff\r
+};\r
+\r
+#endif /* __hb_unicode_tables_h__ */\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+#include <assert.h>\r
+\r
+static const HB_UChar16 ReplacementCharacter = 0xfffd;\r
+\r
+typedef struct {\r
+ unsigned char shape;\r
+ unsigned char justification;\r
+} HB_ArabicProperties;\r
+\r
+typedef enum {\r
+ XIsolated,\r
+ XFinal,\r
+ XInitial,\r
+ XMedial,\r
+ /* intermediate state */\r
+ XCausing\r
+} ArabicShape;\r
+\r
+/*\r
+// these groups correspond to the groups defined in the Unicode standard.\r
+// Some of these groups are equal with regards to both joining and line breaking behaviour,\r
+// and thus have the same enum value\r
+//\r
+// I'm not sure the mapping of syriac to arabic enums is correct with regards to justification, but as\r
+// I couldn't find any better document I'll hope for the best.\r
+*/\r
+typedef enum {\r
+ /* NonJoining */\r
+ ArabicNone,\r
+ ArabicSpace,\r
+ /* Transparent */\r
+ Transparent,\r
+ /* Causing */\r
+ Center,\r
+ Kashida,\r
+\r
+ /* Arabic */\r
+ /* Dual */\r
+ Beh,\r
+ Noon,\r
+ Meem = Noon,\r
+ Heh = Noon,\r
+ KnottedHeh = Noon,\r
+ HehGoal = Noon,\r
+ SwashKaf = Noon,\r
+ Yeh,\r
+ Hah,\r
+ Seen,\r
+ Sad = Seen,\r
+ Tah,\r
+ Kaf = Tah,\r
+ Gaf = Tah,\r
+ Lam = Tah,\r
+ Ain,\r
+ Feh = Ain,\r
+ Qaf = Ain,\r
+ /* Right */\r
+ Alef,\r
+ Waw,\r
+ Dal,\r
+ TehMarbuta = Dal,\r
+ Reh,\r
+ HamzaOnHehGoal,\r
+ YehWithTail = HamzaOnHehGoal,\r
+ YehBarre = HamzaOnHehGoal,\r
+\r
+ /* Syriac */\r
+ /* Dual */\r
+ Beth = Beh,\r
+ Gamal = Ain,\r
+ Heth = Noon,\r
+ Teth = Hah,\r
+ Yudh = Noon,\r
+ Kaph = Noon,\r
+ Lamadh = Lam,\r
+ Mim = Noon,\r
+ Nun = Noon,\r
+ Semakh = Noon,\r
+ FinalSemakh = Noon,\r
+ SyriacE = Ain,\r
+ Pe = Ain,\r
+ ReversedPe = Hah,\r
+ Qaph = Noon,\r
+ Shin = Noon,\r
+ Fe = Ain,\r
+\r
+ /* Right */\r
+ Alaph = Alef,\r
+ Dalath = Dal,\r
+ He = Dal,\r
+ SyriacWaw = Waw,\r
+ Zain = Alef,\r
+ YudhHe = Waw,\r
+ Sadhe = HamzaOnHehGoal,\r
+ Taw = Dal,\r
+\r
+ /* Compiler bug? Otherwise ArabicGroupsEnd would be equal to Dal + 1. */\r
+ Dummy = HamzaOnHehGoal,\r
+ ArabicGroupsEnd\r
+} ArabicGroup;\r
+\r
+static const unsigned char arabic_group[0x150] = {\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, Transparent, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+\r
+ ArabicNone, ArabicNone, Alef, Alef,\r
+ Waw, Alef, Yeh, Alef,\r
+ Beh, TehMarbuta, Beh, Beh,\r
+ Hah, Hah, Hah, Dal,\r
+\r
+ Dal, Reh, Reh, Seen,\r
+ Seen, Sad, Sad, Tah,\r
+ Tah, Ain, Ain, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+\r
+ /* 0x640 */\r
+ Kashida, Feh, Qaf, Kaf,\r
+ Lam, Meem, Noon, Heh,\r
+ Waw, Yeh, Yeh, Transparent,\r
+ Transparent, Transparent, Transparent, Transparent,\r
+\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, Beh, Qaf,\r
+\r
+ Transparent, Alef, Alef, Alef,\r
+ ArabicNone, Alef, Waw, Waw,\r
+ Yeh, Beh, Beh, Beh,\r
+ Beh, Beh, Beh, Beh,\r
+\r
+ /* 0x680 */\r
+ Beh, Hah, Hah, Hah,\r
+ Hah, Hah, Hah, Hah,\r
+ Dal, Dal, Dal, Dal,\r
+ Dal, Dal, Dal, Dal,\r
+\r
+ Dal, Reh, Reh, Reh,\r
+ Reh, Reh, Reh, Reh,\r
+ Reh, Reh, Seen, Seen,\r
+ Seen, Sad, Sad, Tah,\r
+\r
+ Ain, Feh, Feh, Feh,\r
+ Feh, Feh, Feh, Qaf,\r
+ Qaf, Gaf, SwashKaf, Gaf,\r
+ Kaf, Kaf, Kaf, Gaf,\r
+\r
+ Gaf, Gaf, Gaf, Gaf,\r
+ Gaf, Lam, Lam, Lam,\r
+ Lam, Noon, Noon, Noon,\r
+ Noon, Noon, KnottedHeh, Hah,\r
+\r
+ /* 0x6c0 */\r
+ TehMarbuta, HehGoal, HamzaOnHehGoal, HamzaOnHehGoal,\r
+ Waw, Waw, Waw, Waw,\r
+ Waw, Waw, Waw, Waw,\r
+ Yeh, YehWithTail, Yeh, Waw,\r
+\r
+ Yeh, Yeh, YehBarre, YehBarre,\r
+ ArabicNone, TehMarbuta, Transparent, Transparent,\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, ArabicNone, ArabicNone, Transparent,\r
+\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, ArabicNone, ArabicNone, Transparent,\r
+ Transparent, ArabicNone, Transparent, Transparent,\r
+ Transparent, Transparent, Dal, Reh,\r
+\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, Seen, Sad,\r
+ Ain, ArabicNone, ArabicNone, KnottedHeh,\r
+\r
+ /* 0x700 */\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+ ArabicNone, ArabicNone, ArabicNone, ArabicNone,\r
+\r
+ Alaph, Transparent, Beth, Gamal,\r
+ Gamal, Dalath, Dalath, He,\r
+ SyriacWaw, Zain, Heth, Teth,\r
+ Teth, Yudh, YudhHe, Kaph,\r
+\r
+ Lamadh, Mim, Nun, Semakh,\r
+ FinalSemakh, SyriacE, Pe, ReversedPe,\r
+ Sadhe, Qaph, Dalath, Shin,\r
+ Taw, Beth, Gamal, Dalath,\r
+\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, Transparent, Transparent, Transparent,\r
+\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, Transparent, Transparent, Transparent,\r
+ Transparent, Transparent, Transparent, ArabicNone,\r
+ ArabicNone, Zain, Kaph, Fe,\r
+};\r
+\r
+static ArabicGroup arabicGroup(unsigned short uc)\r
+{\r
+ if (uc >= 0x0600 && uc < 0x750)\r
+ return (ArabicGroup) arabic_group[uc-0x600];\r
+ else if (uc == 0x200d)\r
+ return Center;\r
+ else if (HB_GetUnicodeCharCategory(uc) == HB_Separator_Space)\r
+ return ArabicSpace;\r
+ else\r
+ return ArabicNone;\r
+}\r
+\r
+\r
+/*\r
+ Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on\r
+ arabic).\r
+\r
+ Each unicode char has a joining class (right, dual (left&right), center (joincausing) or transparent).\r
+ transparent joining is not encoded in HB_UChar16::joining(), but applies to all combining marks and format marks.\r
+\r
+ Right join-causing: dual + center\r
+ Left join-causing: dual + right + center\r
+\r
+ Rules are as follows (for a string already in visual order, as we have it here):\r
+\r
+ R1 Transparent characters do not affect joining behaviour.\r
+ R2 A right joining character, that has a right join-causing char on the right will get form XRight\r
+ (R3 A left joining character, that has a left join-causing char on the left will get form XLeft)\r
+ Note: the above rule is meaningless, as there are no pure left joining characters defined in Unicode\r
+ R4 A dual joining character, that has a left join-causing char on the left and a right join-causing char on\r
+ the right will get form XMedial\r
+ R5 A dual joining character, that has a right join causing char on the right, and no left join causing char on the left\r
+ will get form XRight\r
+ R6 A dual joining character, that has a left join causing char on the left, and no right join causing char on the right\r
+ will get form XLeft\r
+ R7 Otherwise the character will get form XIsolated\r
+\r
+ Additionally we have to do the minimal ligature support for lam-alef ligatures:\r
+\r
+ L1 Transparent characters do not affect ligature behaviour.\r
+ L2 Any sequence of Alef(XRight) + Lam(XMedial) will form the ligature Alef.Lam(XLeft)\r
+ L3 Any sequence of Alef(XRight) + Lam(XLeft) will form the ligature Alef.Lam(XIsolated)\r
+\r
+ The state table below handles rules R1-R7.\r
+*/\r
+\r
+typedef enum {\r
+ JNone,\r
+ JCausing,\r
+ JDual,\r
+ JRight,\r
+ JTransparent\r
+} Joining;\r
+\r
+static const Joining joining_for_group[ArabicGroupsEnd] = {\r
+ /* NonJoining */\r
+ JNone, /* ArabicNone */\r
+ JNone, /* ArabicSpace */\r
+ /* Transparent */\r
+ JTransparent, /* Transparent */\r
+ /* Causing */\r
+ JCausing, /* Center */\r
+ JCausing, /* Kashida */\r
+ /* Dual */\r
+ JDual, /* Beh */\r
+ JDual, /* Noon */\r
+ JDual, /* Yeh */\r
+ JDual, /* Hah */\r
+ JDual, /* Seen */\r
+ JDual, /* Tah */\r
+ JDual, /* Ain */\r
+ /* Right */\r
+ JRight, /* Alef */\r
+ JRight, /* Waw */\r
+ JRight, /* Dal */\r
+ JRight, /* Reh */\r
+ JRight /* HamzaOnHehGoal */\r
+};\r
+\r
+\r
+typedef struct {\r
+ ArabicShape form1;\r
+ ArabicShape form2;\r
+} JoiningPair;\r
+\r
+static const JoiningPair joining_table[5][4] =\r
+/* None, Causing, Dual, Right */\r
+{\r
+ { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XInitial }, { XIsolated, XIsolated } }, /* XIsolated */\r
+ { { XFinal, XIsolated }, { XFinal, XCausing }, { XFinal, XInitial }, { XFinal, XIsolated } }, /* XFinal */\r
+ { { XIsolated, XIsolated }, { XInitial, XCausing }, { XInitial, XMedial }, { XInitial, XFinal } }, /* XInitial */\r
+ { { XFinal, XIsolated }, { XMedial, XCausing }, { XMedial, XMedial }, { XMedial, XFinal } }, /* XMedial */\r
+ { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XMedial }, { XIsolated, XFinal } }, /* XCausing */\r
+};\r
+\r
+\r
+/*\r
+According to http://www.microsoft.com/middleeast/Arabicdev/IE6/KBase.asp\r
+\r
+1. Find the priority of the connecting opportunities in each word\r
+2. Add expansion at the highest priority connection opportunity\r
+3. If more than one connection opportunity have the same highest value,\r
+ use the opportunity closest to the end of the word.\r
+\r
+Following is a chart that provides the priority for connection\r
+opportunities and where expansion occurs. The character group names\r
+are those in table 6.6 of the UNICODE 2.0 book.\r
+\r
+\r
+PrioritY Glyph Condition Kashida Location\r
+\r
+Arabic_Kashida User inserted Kashida The user entered a Kashida in a position. After the user\r
+ (Shift+j or Shift+[E with hat]) Thus, it is the highest priority to insert an inserted kashida\r
+ automatic kashida.\r
+\r
+Arabic_Seen Seen, Sad Connecting to the next character. After the character.\r
+ (Initial or medial form).\r
+\r
+Arabic_HaaDal Teh Marbutah, Haa, Dal Connecting to previous character. Before the final form\r
+ of these characters.\r
+\r
+Arabic_Alef Alef, Tah, Lam, Connecting to previous character. Before the final form\r
+ Kaf and Gaf of these characters.\r
+\r
+Arabic_BaRa Reh, Yeh Connected to medial Beh Before preceding medial Baa\r
+\r
+Arabic_Waw Waw, Ain, Qaf, Feh Connecting to previous character. Before the final form of\r
+ these characters.\r
+\r
+Arabic_Normal Other connecting Connecting to previous character. Before the final form\r
+ characters of these characters.\r
+\r
+\r
+\r
+This seems to imply that we have at most one kashida point per arabic word.\r
+\r
+*/\r
+\r
+static void getArabicProperties(const unsigned short *chars, int len, HB_ArabicProperties *properties)\r
+{\r
+/* qDebug("arabicSyriacOpenTypeShape: properties:"); */\r
+ int lastPos = 0;\r
+ int lastGroup = ArabicNone;\r
+ int i = 0;\r
+\r
+ ArabicGroup group = arabicGroup(chars[0]);\r
+ Joining j = joining_for_group[group];\r
+ ArabicShape shape = joining_table[XIsolated][j].form2;\r
+ properties[0].justification = HB_NoJustification;\r
+\r
+ for (i = 1; i < len; ++i) {\r
+ /* #### fix handling for spaces and punktuation */\r
+ properties[i].justification = HB_NoJustification;\r
+\r
+ group = arabicGroup(chars[i]);\r
+ j = joining_for_group[group];\r
+\r
+ if (j == JTransparent) {\r
+ properties[i].shape = XIsolated;\r
+ continue;\r
+ }\r
+\r
+ properties[lastPos].shape = joining_table[shape][j].form1;\r
+ shape = joining_table[shape][j].form2;\r
+\r
+ switch(lastGroup) {\r
+ case Seen:\r
+ if (properties[lastPos].shape == XInitial || properties[lastPos].shape == XMedial)\r
+ properties[i-1].justification = HB_Arabic_Seen;\r
+ break;\r
+ case Hah:\r
+ if (properties[lastPos].shape == XFinal)\r
+ properties[lastPos-1].justification = HB_Arabic_HaaDal;\r
+ break;\r
+ case Alef:\r
+ if (properties[lastPos].shape == XFinal)\r
+ properties[lastPos-1].justification = HB_Arabic_Alef;\r
+ break;\r
+ case Ain:\r
+ if (properties[lastPos].shape == XFinal)\r
+ properties[lastPos-1].justification = HB_Arabic_Waw;\r
+ break;\r
+ case Noon:\r
+ if (properties[lastPos].shape == XFinal)\r
+ properties[lastPos-1].justification = HB_Arabic_Normal;\r
+ break;\r
+ case ArabicNone:\r
+ break;\r
+\r
+ default:\r
+ assert(FALSE);\r
+ }\r
+\r
+ lastGroup = ArabicNone;\r
+\r
+ switch(group) {\r
+ case ArabicNone:\r
+ case Transparent:\r
+ /* ### Center should probably be treated as transparent when it comes to justification. */\r
+ case Center:\r
+ break;\r
+ case ArabicSpace:\r
+ properties[i].justification = HB_Arabic_Space;\r
+ break;\r
+ case Kashida:\r
+ properties[i].justification = HB_Arabic_Kashida;\r
+ break;\r
+ case Seen:\r
+ lastGroup = Seen;\r
+ break;\r
+\r
+ case Hah:\r
+ case Dal:\r
+ lastGroup = Hah;\r
+ break;\r
+\r
+ case Alef:\r
+ case Tah:\r
+ lastGroup = Alef;\r
+ break;\r
+\r
+ case Yeh:\r
+ case Reh:\r
+ if (properties[lastPos].shape == XMedial && arabicGroup(chars[lastPos]) == Beh)\r
+ properties[lastPos-1].justification = HB_Arabic_BaRa;\r
+ break;\r
+\r
+ case Ain:\r
+ case Waw:\r
+ lastGroup = Ain;\r
+ break;\r
+\r
+ case Noon:\r
+ case Beh:\r
+ case HamzaOnHehGoal:\r
+ lastGroup = Noon;\r
+ break;\r
+ case ArabicGroupsEnd:\r
+ assert(FALSE);\r
+ }\r
+\r
+ lastPos = i;\r
+ }\r
+ properties[lastPos].shape = joining_table[shape][JNone].form1;\r
+\r
+\r
+ /*\r
+ for (int i = 0; i < len; ++i)\r
+ qDebug("arabic properties(%d): uc=%x shape=%d, justification=%d", i, chars[i], properties[i].shape, properties[i].justification);\r
+ */\r
+}\r
+\r
+static Joining getNkoJoining(unsigned short uc)\r
+{\r
+ if (uc < 0x7ca)\r
+ return JNone;\r
+ if (uc <= 0x7ea)\r
+ return JDual;\r
+ if (uc <= 0x7f3)\r
+ return JTransparent;\r
+ if (uc <= 0x7f9)\r
+ return JNone;\r
+ if (uc == 0x7fa)\r
+ return JCausing;\r
+ return JNone;\r
+}\r
+\r
+static void getNkoProperties(const unsigned short *chars, int len, HB_ArabicProperties *properties)\r
+{\r
+ int lastPos = 0;\r
+ int i = 0;\r
+\r
+ Joining j = getNkoJoining(chars[0]);\r
+ ArabicShape shape = joining_table[XIsolated][j].form2;\r
+ properties[0].justification = HB_NoJustification;\r
+\r
+ for (i = 1; i < len; ++i) {\r
+ properties[i].justification = (HB_GetUnicodeCharCategory(chars[i]) == HB_Separator_Space) ?\r
+ ArabicSpace : ArabicNone;\r
+\r
+ j = getNkoJoining(chars[i]);\r
+\r
+ if (j == JTransparent) {\r
+ properties[i].shape = XIsolated;\r
+ continue;\r
+ }\r
+\r
+ properties[lastPos].shape = joining_table[shape][j].form1;\r
+ shape = joining_table[shape][j].form2;\r
+\r
+\r
+ lastPos = i;\r
+ }\r
+ properties[lastPos].shape = joining_table[shape][JNone].form1;\r
+\r
+\r
+ /*\r
+ for (int i = 0; i < len; ++i)\r
+ qDebug("nko properties(%d): uc=%x shape=%d, justification=%d", i, chars[i], properties[i].shape, properties[i].justification);\r
+ */\r
+}\r
+\r
+/*\r
+// The unicode to unicode shaping codec.\r
+// does only presentation forms B at the moment, but that should be enough for\r
+// simple display\r
+*/\r
+static const hb_uint16 arabicUnicodeMapping[256][2] = {\r
+ /* base of shaped forms, and number-1 of them (0 for non shaping,\r
+ 1 for right binding and 3 for dual binding */\r
+\r
+ /* These are just the glyphs available in Unicode,\r
+ some characters are in R class, but have no glyphs in Unicode. */\r
+\r
+ { 0x0600, 0 }, /* 0x0600 */\r
+ { 0x0601, 0 }, /* 0x0601 */\r
+ { 0x0602, 0 }, /* 0x0602 */\r
+ { 0x0603, 0 }, /* 0x0603 */\r
+ { 0x0604, 0 }, /* 0x0604 */\r
+ { 0x0605, 0 }, /* 0x0605 */\r
+ { 0x0606, 0 }, /* 0x0606 */\r
+ { 0x0607, 0 }, /* 0x0607 */\r
+ { 0x0608, 0 }, /* 0x0608 */\r
+ { 0x0609, 0 }, /* 0x0609 */\r
+ { 0x060A, 0 }, /* 0x060A */\r
+ { 0x060B, 0 }, /* 0x060B */\r
+ { 0x060C, 0 }, /* 0x060C */\r
+ { 0x060D, 0 }, /* 0x060D */\r
+ { 0x060E, 0 }, /* 0x060E */\r
+ { 0x060F, 0 }, /* 0x060F */\r
+\r
+ { 0x0610, 0 }, /* 0x0610 */\r
+ { 0x0611, 0 }, /* 0x0611 */\r
+ { 0x0612, 0 }, /* 0x0612 */\r
+ { 0x0613, 0 }, /* 0x0613 */\r
+ { 0x0614, 0 }, /* 0x0614 */\r
+ { 0x0615, 0 }, /* 0x0615 */\r
+ { 0x0616, 0 }, /* 0x0616 */\r
+ { 0x0617, 0 }, /* 0x0617 */\r
+ { 0x0618, 0 }, /* 0x0618 */\r
+ { 0x0619, 0 }, /* 0x0619 */\r
+ { 0x061A, 0 }, /* 0x061A */\r
+ { 0x061B, 0 }, /* 0x061B */\r
+ { 0x061C, 0 }, /* 0x061C */\r
+ { 0x061D, 0 }, /* 0x061D */\r
+ { 0x061E, 0 }, /* 0x061E */\r
+ { 0x061F, 0 }, /* 0x061F */\r
+\r
+ { 0x0620, 0 }, /* 0x0620 */\r
+ { 0xFE80, 0 }, /* 0x0621 HAMZA */\r
+ { 0xFE81, 1 }, /* 0x0622 R ALEF WITH MADDA ABOVE */\r
+ { 0xFE83, 1 }, /* 0x0623 R ALEF WITH HAMZA ABOVE */\r
+ { 0xFE85, 1 }, /* 0x0624 R WAW WITH HAMZA ABOVE */\r
+ { 0xFE87, 1 }, /* 0x0625 R ALEF WITH HAMZA BELOW */\r
+ { 0xFE89, 3 }, /* 0x0626 D YEH WITH HAMZA ABOVE */\r
+ { 0xFE8D, 1 }, /* 0x0627 R ALEF */\r
+ { 0xFE8F, 3 }, /* 0x0628 D BEH */\r
+ { 0xFE93, 1 }, /* 0x0629 R TEH MARBUTA */\r
+ { 0xFE95, 3 }, /* 0x062A D TEH */\r
+ { 0xFE99, 3 }, /* 0x062B D THEH */\r
+ { 0xFE9D, 3 }, /* 0x062C D JEEM */\r
+ { 0xFEA1, 3 }, /* 0x062D D HAH */\r
+ { 0xFEA5, 3 }, /* 0x062E D KHAH */\r
+ { 0xFEA9, 1 }, /* 0x062F R DAL */\r
+\r
+ { 0xFEAB, 1 }, /* 0x0630 R THAL */\r
+ { 0xFEAD, 1 }, /* 0x0631 R REH */\r
+ { 0xFEAF, 1 }, /* 0x0632 R ZAIN */\r
+ { 0xFEB1, 3 }, /* 0x0633 D SEEN */\r
+ { 0xFEB5, 3 }, /* 0x0634 D SHEEN */\r
+ { 0xFEB9, 3 }, /* 0x0635 D SAD */\r
+ { 0xFEBD, 3 }, /* 0x0636 D DAD */\r
+ { 0xFEC1, 3 }, /* 0x0637 D TAH */\r
+ { 0xFEC5, 3 }, /* 0x0638 D ZAH */\r
+ { 0xFEC9, 3 }, /* 0x0639 D AIN */\r
+ { 0xFECD, 3 }, /* 0x063A D GHAIN */\r
+ { 0x063B, 0 }, /* 0x063B */\r
+ { 0x063C, 0 }, /* 0x063C */\r
+ { 0x063D, 0 }, /* 0x063D */\r
+ { 0x063E, 0 }, /* 0x063E */\r
+ { 0x063F, 0 }, /* 0x063F */\r
+\r
+ { 0x0640, 0 }, /* 0x0640 C TATWEEL // ### Join Causing, only one glyph */\r
+ { 0xFED1, 3 }, /* 0x0641 D FEH */\r
+ { 0xFED5, 3 }, /* 0x0642 D QAF */\r
+ { 0xFED9, 3 }, /* 0x0643 D KAF */\r
+ { 0xFEDD, 3 }, /* 0x0644 D LAM */\r
+ { 0xFEE1, 3 }, /* 0x0645 D MEEM */\r
+ { 0xFEE5, 3 }, /* 0x0646 D NOON */\r
+ { 0xFEE9, 3 }, /* 0x0647 D HEH */\r
+ { 0xFEED, 1 }, /* 0x0648 R WAW */\r
+ { 0x0649, 3 }, /* 0x0649 ALEF MAKSURA // ### Dual, glyphs not consecutive, handle in code. */\r
+ { 0xFEF1, 3 }, /* 0x064A D YEH */\r
+ { 0x064B, 0 }, /* 0x064B */\r
+ { 0x064C, 0 }, /* 0x064C */\r
+ { 0x064D, 0 }, /* 0x064D */\r
+ { 0x064E, 0 }, /* 0x064E */\r
+ { 0x064F, 0 }, /* 0x064F */\r
+\r
+ { 0x0650, 0 }, /* 0x0650 */\r
+ { 0x0651, 0 }, /* 0x0651 */\r
+ { 0x0652, 0 }, /* 0x0652 */\r
+ { 0x0653, 0 }, /* 0x0653 */\r
+ { 0x0654, 0 }, /* 0x0654 */\r
+ { 0x0655, 0 }, /* 0x0655 */\r
+ { 0x0656, 0 }, /* 0x0656 */\r
+ { 0x0657, 0 }, /* 0x0657 */\r
+ { 0x0658, 0 }, /* 0x0658 */\r
+ { 0x0659, 0 }, /* 0x0659 */\r
+ { 0x065A, 0 }, /* 0x065A */\r
+ { 0x065B, 0 }, /* 0x065B */\r
+ { 0x065C, 0 }, /* 0x065C */\r
+ { 0x065D, 0 }, /* 0x065D */\r
+ { 0x065E, 0 }, /* 0x065E */\r
+ { 0x065F, 0 }, /* 0x065F */\r
+\r
+ { 0x0660, 0 }, /* 0x0660 */\r
+ { 0x0661, 0 }, /* 0x0661 */\r
+ { 0x0662, 0 }, /* 0x0662 */\r
+ { 0x0663, 0 }, /* 0x0663 */\r
+ { 0x0664, 0 }, /* 0x0664 */\r
+ { 0x0665, 0 }, /* 0x0665 */\r
+ { 0x0666, 0 }, /* 0x0666 */\r
+ { 0x0667, 0 }, /* 0x0667 */\r
+ { 0x0668, 0 }, /* 0x0668 */\r
+ { 0x0669, 0 }, /* 0x0669 */\r
+ { 0x066A, 0 }, /* 0x066A */\r
+ { 0x066B, 0 }, /* 0x066B */\r
+ { 0x066C, 0 }, /* 0x066C */\r
+ { 0x066D, 0 }, /* 0x066D */\r
+ { 0x066E, 0 }, /* 0x066E */\r
+ { 0x066F, 0 }, /* 0x066F */\r
+\r
+ { 0x0670, 0 }, /* 0x0670 */\r
+ { 0xFB50, 1 }, /* 0x0671 R ALEF WASLA */\r
+ { 0x0672, 0 }, /* 0x0672 */\r
+ { 0x0673, 0 }, /* 0x0673 */\r
+ { 0x0674, 0 }, /* 0x0674 */\r
+ { 0x0675, 0 }, /* 0x0675 */\r
+ { 0x0676, 0 }, /* 0x0676 */\r
+ { 0x0677, 0 }, /* 0x0677 */\r
+ { 0x0678, 0 }, /* 0x0678 */\r
+ { 0xFB66, 3 }, /* 0x0679 D TTEH */\r
+ { 0xFB5E, 3 }, /* 0x067A D TTEHEH */\r
+ { 0xFB52, 3 }, /* 0x067B D BEEH */\r
+ { 0x067C, 0 }, /* 0x067C */\r
+ { 0x067D, 0 }, /* 0x067D */\r
+ { 0xFB56, 3 }, /* 0x067E D PEH */\r
+ { 0xFB62, 3 }, /* 0x067F D TEHEH */\r
+\r
+ { 0xFB5A, 3 }, /* 0x0680 D BEHEH */\r
+ { 0x0681, 0 }, /* 0x0681 */\r
+ { 0x0682, 0 }, /* 0x0682 */\r
+ { 0xFB76, 3 }, /* 0x0683 D NYEH */\r
+ { 0xFB72, 3 }, /* 0x0684 D DYEH */\r
+ { 0x0685, 0 }, /* 0x0685 */\r
+ { 0xFB7A, 3 }, /* 0x0686 D TCHEH */\r
+ { 0xFB7E, 3 }, /* 0x0687 D TCHEHEH */\r
+ { 0xFB88, 1 }, /* 0x0688 R DDAL */\r
+ { 0x0689, 0 }, /* 0x0689 */\r
+ { 0x068A, 0 }, /* 0x068A */\r
+ { 0x068B, 0 }, /* 0x068B */\r
+ { 0xFB84, 1 }, /* 0x068C R DAHAL */\r
+ { 0xFB82, 1 }, /* 0x068D R DDAHAL */\r
+ { 0xFB86, 1 }, /* 0x068E R DUL */\r
+ { 0x068F, 0 }, /* 0x068F */\r
+\r
+ { 0x0690, 0 }, /* 0x0690 */\r
+ { 0xFB8C, 1 }, /* 0x0691 R RREH */\r
+ { 0x0692, 0 }, /* 0x0692 */\r
+ { 0x0693, 0 }, /* 0x0693 */\r
+ { 0x0694, 0 }, /* 0x0694 */\r
+ { 0x0695, 0 }, /* 0x0695 */\r
+ { 0x0696, 0 }, /* 0x0696 */\r
+ { 0x0697, 0 }, /* 0x0697 */\r
+ { 0xFB8A, 1 }, /* 0x0698 R JEH */\r
+ { 0x0699, 0 }, /* 0x0699 */\r
+ { 0x069A, 0 }, /* 0x069A */\r
+ { 0x069B, 0 }, /* 0x069B */\r
+ { 0x069C, 0 }, /* 0x069C */\r
+ { 0x069D, 0 }, /* 0x069D */\r
+ { 0x069E, 0 }, /* 0x069E */\r
+ { 0x069F, 0 }, /* 0x069F */\r
+\r
+ { 0x06A0, 0 }, /* 0x06A0 */\r
+ { 0x06A1, 0 }, /* 0x06A1 */\r
+ { 0x06A2, 0 }, /* 0x06A2 */\r
+ { 0x06A3, 0 }, /* 0x06A3 */\r
+ { 0xFB6A, 3 }, /* 0x06A4 D VEH */\r
+ { 0x06A5, 0 }, /* 0x06A5 */\r
+ { 0xFB6E, 3 }, /* 0x06A6 D PEHEH */\r
+ { 0x06A7, 0 }, /* 0x06A7 */\r
+ { 0x06A8, 0 }, /* 0x06A8 */\r
+ { 0xFB8E, 3 }, /* 0x06A9 D KEHEH */\r
+ { 0x06AA, 0 }, /* 0x06AA */\r
+ { 0x06AB, 0 }, /* 0x06AB */\r
+ { 0x06AC, 0 }, /* 0x06AC */\r
+ { 0xFBD3, 3 }, /* 0x06AD D NG */\r
+ { 0x06AE, 0 }, /* 0x06AE */\r
+ { 0xFB92, 3 }, /* 0x06AF D GAF */\r
+\r
+ { 0x06B0, 0 }, /* 0x06B0 */\r
+ { 0xFB9A, 3 }, /* 0x06B1 D NGOEH */\r
+ { 0x06B2, 0 }, /* 0x06B2 */\r
+ { 0xFB96, 3 }, /* 0x06B3 D GUEH */\r
+ { 0x06B4, 0 }, /* 0x06B4 */\r
+ { 0x06B5, 0 }, /* 0x06B5 */\r
+ { 0x06B6, 0 }, /* 0x06B6 */\r
+ { 0x06B7, 0 }, /* 0x06B7 */\r
+ { 0x06B8, 0 }, /* 0x06B8 */\r
+ { 0x06B9, 0 }, /* 0x06B9 */\r
+ { 0xFB9E, 1 }, /* 0x06BA R NOON GHUNNA */\r
+ { 0xFBA0, 3 }, /* 0x06BB D RNOON */\r
+ { 0x06BC, 0 }, /* 0x06BC */\r
+ { 0x06BD, 0 }, /* 0x06BD */\r
+ { 0xFBAA, 3 }, /* 0x06BE D HEH DOACHASHMEE */\r
+ { 0x06BF, 0 }, /* 0x06BF */\r
+\r
+ { 0xFBA4, 1 }, /* 0x06C0 R HEH WITH YEH ABOVE */\r
+ { 0xFBA6, 3 }, /* 0x06C1 D HEH GOAL */\r
+ { 0x06C2, 0 }, /* 0x06C2 */\r
+ { 0x06C3, 0 }, /* 0x06C3 */\r
+ { 0x06C4, 0 }, /* 0x06C4 */\r
+ { 0xFBE0, 1 }, /* 0x06C5 R KIRGHIZ OE */\r
+ { 0xFBD9, 1 }, /* 0x06C6 R OE */\r
+ { 0xFBD7, 1 }, /* 0x06C7 R U */\r
+ { 0xFBDB, 1 }, /* 0x06C8 R YU */\r
+ { 0xFBE2, 1 }, /* 0x06C9 R KIRGHIZ YU */\r
+ { 0x06CA, 0 }, /* 0x06CA */\r
+ { 0xFBDE, 1 }, /* 0x06CB R VE */\r
+ { 0xFBFC, 3 }, /* 0x06CC D FARSI YEH */\r
+ { 0x06CD, 0 }, /* 0x06CD */\r
+ { 0x06CE, 0 }, /* 0x06CE */\r
+ { 0x06CF, 0 }, /* 0x06CF */\r
+\r
+ { 0xFBE4, 3 }, /* 0x06D0 D E */\r
+ { 0x06D1, 0 }, /* 0x06D1 */\r
+ { 0xFBAE, 1 }, /* 0x06D2 R YEH BARREE */\r
+ { 0xFBB0, 1 }, /* 0x06D3 R YEH BARREE WITH HAMZA ABOVE */\r
+ { 0x06D4, 0 }, /* 0x06D4 */\r
+ { 0x06D5, 0 }, /* 0x06D5 */\r
+ { 0x06D6, 0 }, /* 0x06D6 */\r
+ { 0x06D7, 0 }, /* 0x06D7 */\r
+ { 0x06D8, 0 }, /* 0x06D8 */\r
+ { 0x06D9, 0 }, /* 0x06D9 */\r
+ { 0x06DA, 0 }, /* 0x06DA */\r
+ { 0x06DB, 0 }, /* 0x06DB */\r
+ { 0x06DC, 0 }, /* 0x06DC */\r
+ { 0x06DD, 0 }, /* 0x06DD */\r
+ { 0x06DE, 0 }, /* 0x06DE */\r
+ { 0x06DF, 0 }, /* 0x06DF */\r
+\r
+ { 0x06E0, 0 }, /* 0x06E0 */\r
+ { 0x06E1, 0 }, /* 0x06E1 */\r
+ { 0x06E2, 0 }, /* 0x06E2 */\r
+ { 0x06E3, 0 }, /* 0x06E3 */\r
+ { 0x06E4, 0 }, /* 0x06E4 */\r
+ { 0x06E5, 0 }, /* 0x06E5 */\r
+ { 0x06E6, 0 }, /* 0x06E6 */\r
+ { 0x06E7, 0 }, /* 0x06E7 */\r
+ { 0x06E8, 0 }, /* 0x06E8 */\r
+ { 0x06E9, 0 }, /* 0x06E9 */\r
+ { 0x06EA, 0 }, /* 0x06EA */\r
+ { 0x06EB, 0 }, /* 0x06EB */\r
+ { 0x06EC, 0 }, /* 0x06EC */\r
+ { 0x06ED, 0 }, /* 0x06ED */\r
+ { 0x06EE, 0 }, /* 0x06EE */\r
+ { 0x06EF, 0 }, /* 0x06EF */\r
+\r
+ { 0x06F0, 0 }, /* 0x06F0 */\r
+ { 0x06F1, 0 }, /* 0x06F1 */\r
+ { 0x06F2, 0 }, /* 0x06F2 */\r
+ { 0x06F3, 0 }, /* 0x06F3 */\r
+ { 0x06F4, 0 }, /* 0x06F4 */\r
+ { 0x06F5, 0 }, /* 0x06F5 */\r
+ { 0x06F6, 0 }, /* 0x06F6 */\r
+ { 0x06F7, 0 }, /* 0x06F7 */\r
+ { 0x06F8, 0 }, /* 0x06F8 */\r
+ { 0x06F9, 0 }, /* 0x06F9 */\r
+ { 0x06FA, 0 }, /* 0x06FA */\r
+ { 0x06FB, 0 }, /* 0x06FB */\r
+ { 0x06FC, 0 }, /* 0x06FC */\r
+ { 0x06FD, 0 }, /* 0x06FD */\r
+ { 0x06FE, 0 }, /* 0x06FE */\r
+ { 0x06FF, 0 } /* 0x06FF */\r
+};\r
+\r
+/* the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, this table does */\r
+static const hb_uint16 alefMaksura[4] = {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9};\r
+\r
+/*\r
+// this is a bit tricky. Alef always binds to the right, so the second parameter descibing the shape\r
+// of the lam can be either initial of medial. So initial maps to the isolated form of the ligature,\r
+// medial to the final form\r
+*/\r
+static const hb_uint16 arabicUnicodeLamAlefMapping[6][4] = {\r
+ { 0xfffd, 0xfffd, 0xfef5, 0xfef6 }, /* 0x622 R Alef with Madda above */\r
+ { 0xfffd, 0xfffd, 0xfef7, 0xfef8 }, /* 0x623 R Alef with Hamza above */\r
+ { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, /* 0x624 // Just to fill the table ;-) */\r
+ { 0xfffd, 0xfffd, 0xfef9, 0xfefa }, /* 0x625 R Alef with Hamza below */\r
+ { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, /* 0x626 // Just to fill the table ;-) */\r
+ { 0xfffd, 0xfffd, 0xfefb, 0xfefc } /* 0x627 R Alef */\r
+};\r
+\r
+static int getShape(hb_uint8 cell, int shape)\r
+{\r
+ /* the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, handle this here */\r
+ int ch = (cell != 0x49)\r
+ ? (shape ? arabicUnicodeMapping[cell][0] + shape : 0x600+cell)\r
+ : alefMaksura[shape] ;\r
+ return ch;\r
+}\r
+\r
+\r
+/*\r
+ Two small helper functions for arabic shaping.\r
+*/\r
+static HB_UChar16 prevChar(const HB_UChar16 *str, int pos)\r
+{\r
+ /*qDebug("leftChar: pos=%d", pos); */\r
+ const HB_UChar16 *ch = str + pos - 1;\r
+ pos--;\r
+ while(pos > -1) {\r
+ if(HB_GetUnicodeCharCategory(*ch) != HB_Mark_NonSpacing)\r
+ return *ch;\r
+ pos--;\r
+ ch--;\r
+ }\r
+ return ReplacementCharacter;\r
+}\r
+\r
+static HB_UChar16 nextChar(const HB_UChar16 *str, hb_uint32 len, hb_uint32 pos)\r
+{\r
+ const HB_UChar16 *ch = str + pos + 1;\r
+ pos++;\r
+ while(pos < len) {\r
+ /*qDebug("rightChar: %d isLetter=%d, joining=%d", pos, ch.isLetter(), ch.joining()); */\r
+ if(HB_GetUnicodeCharCategory(*ch) != HB_Mark_NonSpacing)\r
+ return *ch;\r
+ /* assume it's a transparent char, this might not be 100% correct */\r
+ pos++;\r
+ ch++;\r
+ }\r
+ return ReplacementCharacter;\r
+}\r
+\r
+static void shapedString(const HB_UChar16 *uc, hb_uint32 stringLength, hb_uint32 from, hb_uint32 len, HB_UChar16 *shapeBuffer, int *shapedLength,\r
+ HB_Bool reverse, HB_GlyphAttributes *attributes, unsigned short *logClusters)\r
+{\r
+ HB_ArabicProperties *properties;\r
+ hb_int32 f = from;\r
+ hb_uint32 l = len;\r
+ const HB_UChar16 *ch;\r
+ HB_UChar16 *data;\r
+ int clusterStart;\r
+ hb_uint32 i;\r
+ HB_STACKARRAY(HB_ArabicProperties, props, len + 2);\r
+ properties = props;\r
+\r
+ assert(stringLength >= from + len);\r
+\r
+ if(len == 0) {\r
+ *shapedLength = 0;\r
+ return;\r
+ }\r
+\r
+ if (from > 0) {\r
+ --f;\r
+ ++l;\r
+ ++properties;\r
+ }\r
+ if (f + l < stringLength)\r
+ ++l;\r
+ getArabicProperties(uc+f, l, props);\r
+\r
+ ch = uc + from;\r
+ data = shapeBuffer;\r
+ clusterStart = 0;\r
+\r
+ for (i = 0; i < len; i++) {\r
+ hb_uint8 r = *ch >> 8;\r
+ int gpos = data - shapeBuffer;\r
+\r
+ if (r != 0x06) {\r
+ if (r == 0x20) {\r
+ if (*ch == 0x200c || *ch == 0x200d)\r
+ /* remove ZWJ and ZWNJ */\r
+ goto skip;\r
+ }\r
+ if (reverse)\r
+ *data = HB_GetMirroredChar(*ch);\r
+ else\r
+ *data = *ch;\r
+ } else {\r
+ hb_uint8 c = *ch & 0xff;\r
+ int pos = i + from;\r
+ int shape = properties[i].shape;\r
+/* qDebug("mapping U+%x to shape %d glyph=0x%x", ch->unicode(), shape, getShape(c, shape)); */\r
+ /* take care of lam-alef ligatures (lam right of alef) */\r
+ hb_uint16 map;\r
+ switch (c) {\r
+ case 0x44: { /* lam */\r
+ const HB_UChar16 pch = nextChar(uc, stringLength, pos);\r
+ if ((pch >> 8) == 0x06) {\r
+ switch (pch & 0xff) {\r
+ case 0x22:\r
+ case 0x23:\r
+ case 0x25:\r
+ case 0x27:\r
+/* qDebug(" lam of lam-alef ligature"); */\r
+ map = arabicUnicodeLamAlefMapping[(pch & 0xff) - 0x22][shape];\r
+ goto next;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ case 0x22: /* alef with madda */\r
+ case 0x23: /* alef with hamza above */\r
+ case 0x25: /* alef with hamza below */\r
+ case 0x27: /* alef */\r
+ if (prevChar(uc, pos) == 0x0644) {\r
+ /* have a lam alef ligature */\r
+ /*qDebug(" alef of lam-alef ligature"); */\r
+ goto skip;\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ map = getShape(c, shape);\r
+ next:\r
+ *data = map;\r
+ }\r
+ /* ##### Fixme */\r
+ /*glyphs[gpos].attributes.zeroWidth = zeroWidth; */\r
+ if (HB_GetUnicodeCharCategory(*ch) == HB_Mark_NonSpacing) {\r
+ attributes[gpos].mark = TRUE;\r
+/* qDebug("glyph %d (char %d) is mark!", gpos, i); */\r
+ } else {\r
+ attributes[gpos].mark = FALSE;\r
+ clusterStart = data - shapeBuffer;\r
+ }\r
+ attributes[gpos].clusterStart = !attributes[gpos].mark;\r
+ attributes[gpos].combiningClass = HB_GetUnicodeCharCombiningClass(*ch);\r
+ attributes[gpos].justification = properties[i].justification;\r
+/* qDebug("data[%d] = %x (from %x)", gpos, (uint)data->unicode(), ch->unicode());*/\r
+ data++;\r
+ skip:\r
+ ch++;\r
+ logClusters[i] = clusterStart;\r
+ }\r
+ *shapedLength = data - shapeBuffer;\r
+\r
+ HB_FREE_STACKARRAY(props);\r
+}\r
+\r
+#ifndef NO_OPENTYPE\r
+\r
+static const HB_OpenTypeFeature arabic_features[] = {\r
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },\r
+ { HB_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty },\r
+ { HB_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty },\r
+ { HB_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty },\r
+ { HB_MAKE_TAG('i', 'n', 'i', 't'), InitProperty },\r
+ { HB_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty },\r
+ { HB_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty },\r
+ { HB_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty },\r
+ { HB_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty },\r
+ { HB_MAKE_TAG('c', 's', 'w', 'h'), CswhProperty },\r
+ /* mset is used in old Win95 fonts that don't have a 'mark' positioning table. */\r
+ { HB_MAKE_TAG('m', 's', 'e', 't'), MsetProperty },\r
+ {0, 0}\r
+};\r
+\r
+static const HB_OpenTypeFeature syriac_features[] = {\r
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },\r
+ { HB_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty },\r
+ { HB_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty },\r
+ { HB_MAKE_TAG('f', 'i', 'n', '2'), FinaProperty },\r
+ { HB_MAKE_TAG('f', 'i', 'n', '3'), FinaProperty },\r
+ { HB_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty },\r
+ { HB_MAKE_TAG('m', 'e', 'd', '2'), MediProperty },\r
+ { HB_MAKE_TAG('i', 'n', 'i', 't'), InitProperty },\r
+ { HB_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty },\r
+ { HB_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty },\r
+ { HB_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty },\r
+ { HB_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty },\r
+ {0, 0}\r
+};\r
+\r
+static HB_Bool arabicSyriacOpenTypeShape(HB_ShaperItem *item, HB_Bool *ot_ok)\r
+{\r
+ const HB_UChar16 *uc;\r
+ const int nglyphs = item->num_glyphs;\r
+ hb_int32 f;\r
+ hb_uint32 l;\r
+ HB_ArabicProperties *properties;\r
+ HB_DECLARE_STACKARRAY(HB_ArabicProperties, props)\r
+ HB_DECLARE_STACKARRAY(hb_uint32, apply)\r
+ HB_Bool shaped;\r
+ HB_Bool positioned;\r
+ int i = 0;\r
+\r
+ *ot_ok = TRUE;\r
+\r
+ if (!HB_ConvertStringToGlyphIndices(item))\r
+ return FALSE;\r
+ HB_HeuristicSetGlyphAttributes(item);\r
+\r
+ HB_INIT_STACKARRAY(HB_ArabicProperties, props, item->item.length + 2);\r
+ HB_INIT_STACKARRAY(hb_uint32, apply, item->num_glyphs);\r
+\r
+ uc = item->string + item->item.pos;\r
+\r
+ properties = props;\r
+ f = 0;\r
+ l = item->item.length;\r
+ if (item->item.pos > 0) {\r
+ --f;\r
+ ++l;\r
+ ++properties;\r
+ }\r
+ if (f + l + item->item.pos < item->stringLength) {\r
+ ++l;\r
+ }\r
+ if (item->item.script == HB_Script_Nko)\r
+ getNkoProperties(uc+f, l, props);\r
+ else\r
+ getArabicProperties(uc+f, l, props);\r
+\r
+ for (i = 0; i < (int)item->num_glyphs; i++) {\r
+ apply[i] = 0;\r
+\r
+ if (properties[i].shape == XIsolated)\r
+ apply[i] |= MediProperty|FinaProperty|InitProperty;\r
+ else if (properties[i].shape == XMedial)\r
+ apply[i] |= IsolProperty|FinaProperty|InitProperty;\r
+ else if (properties[i].shape == XFinal)\r
+ apply[i] |= IsolProperty|MediProperty|InitProperty;\r
+ else if (properties[i].shape == XInitial)\r
+ apply[i] |= IsolProperty|MediProperty|FinaProperty;\r
+\r
+ item->attributes[i].justification = properties[i].justification;\r
+ }\r
+\r
+ HB_FREE_STACKARRAY(props);\r
+\r
+ shaped = HB_OpenTypeShape(item, apply);\r
+\r
+ HB_FREE_STACKARRAY(apply);\r
+\r
+ if (!shaped) {\r
+ *ot_ok = FALSE;\r
+ return FALSE;\r
+ }\r
+\r
+ positioned = HB_OpenTypePosition(item, nglyphs, /*doLogClusters*/TRUE);\r
+\r
+ /* SAMSUNG bug fix for Arabic - Start */\r
+ if(TRUE == item->item.bidiLevel)\r
+ {\r
+ int j = item->num_glyphs/2;\r
+\r
+ for(i=0; i<j; i++)\r
+ {\r
+ HB_Glyph glyph = item->glyphs[i];\r
+ HB_Fixed advance = item->advances[i];\r
+ HB_FixedPoint offset = item->offsets[i];\r
+ int k = (item->num_glyphs-1)-i;\r
+\r
+ item->glyphs[i] = item->glyphs[k];\r
+ item->advances[i] = item->advances[k];\r
+ item->offsets[i] = item->offsets[k];\r
+\r
+ item->glyphs[k] = glyph;\r
+ item->advances[k] = advance;\r
+ item->offsets[k] = offset;\r
+ }\r
+ }\r
+\r
+ /* SAMSUNG bug fix for Arabic - End */\r
+\r
+ return positioned;\r
+}\r
+\r
+#endif\r
+\r
+/* #### stil missing: identify invalid character combinations */\r
+HB_Bool HB_ArabicShape(HB_ShaperItem *item)\r
+{\r
+ int slen;\r
+ HB_Bool haveGlyphs;\r
+ HB_STACKARRAY(HB_UChar16, shapedChars, item->item.length);\r
+\r
+ assert(item->item.script == HB_Script_Arabic || item->item.script == HB_Script_Syriac\r
+ || item->item.script == HB_Script_Nko);\r
+\r
+#ifndef NO_OPENTYPE\r
+\r
+ if (HB_SelectScript(item, item->item.script == HB_Script_Arabic ? arabic_features : syriac_features)) {\r
+ HB_Bool ot_ok;\r
+ if (arabicSyriacOpenTypeShape(item, &ot_ok))\r
+ return TRUE;\r
+ if (ot_ok)\r
+ return FALSE;\r
+ /* fall through to the non OT code*/\r
+ }\r
+#endif\r
+\r
+ if (item->item.script != HB_Script_Arabic)\r
+ return HB_BasicShape(item);\r
+\r
+ shapedString(item->string, item->stringLength, item->item.pos, item->item.length, shapedChars, &slen,\r
+ item->item.bidiLevel % 2,\r
+ item->attributes, item->log_clusters);\r
+\r
+ haveGlyphs = item->font->klass\r
+ ->convertStringToGlyphIndices(item->font,\r
+ shapedChars, slen,\r
+ item->glyphs, &item->num_glyphs,\r
+ item->item.bidiLevel % 2);\r
+\r
+ HB_FREE_STACKARRAY(shapedChars);\r
+\r
+ if (!haveGlyphs)\r
+ return FALSE;\r
+\r
+ HB_HeuristicPosition(item);\r
+ return TRUE;\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2004,2007 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Owen Taylor, Behdad Esfahbod\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-buffer-private.h"\r
+#include "harfbuzz-gsub-private.h"\r
+#include "harfbuzz-gpos-private.h"\r
+\r
+/* Here is how the buffer works internally:\r
+ *\r
+ * There are two string pointers: in_string and out_string. They\r
+ * always have same allocated size, but different length and positions.\r
+ *\r
+ * As an optimization, both in_string and out_string may point to the\r
+ * same piece of memory, which is owned by in_string. This remains the\r
+ * case as long as:\r
+ *\r
+ * - copy_glyph() is called\r
+ * - replace_glyph() is called with inplace=TRUE\r
+ * - add_output_glyph() and add_output_glyphs() are not called\r
+ *\r
+ * In that case swap(), and copy_glyph(), and replace_glyph() are all\r
+ * mostly no-op.\r
+ *\r
+ * As soon an add_output_glyph[s]() or replace_glyph() with inplace=FALSE is\r
+ * called, out_string is moved over to an alternate buffer (alt_string), and\r
+ * its current contents (out_length entries) are copied to the alt buffer.\r
+ * This should all remain transparent to the user. swap() then switches\r
+ * in_string and alt_string. alt_string is not allocated until its needed,\r
+ * but after that it's grown with in_string unconditionally.\r
+ *\r
+ * The buffer->separate_out boolean keeps status of whether out_string points\r
+ * to in_string (FALSE) or alt_string (TRUE).\r
+ */\r
+\r
+/* Internal API */\r
+\r
+static HB_Error\r
+hb_buffer_ensure( HB_Buffer buffer,\r
+ HB_UInt size )\r
+{\r
+ HB_UInt new_allocated = buffer->allocated;\r
+\r
+ if (size > new_allocated)\r
+ {\r
+ HB_Error error;\r
+\r
+ while (size > new_allocated)\r
+ new_allocated += (new_allocated >> 1) + 8;\r
+ \r
+ if ( buffer->positions )\r
+ {\r
+ if ( REALLOC_ARRAY( buffer->positions, new_allocated, HB_PositionRec ) )\r
+ return error;\r
+ }\r
+\r
+ if ( REALLOC_ARRAY( buffer->in_string, new_allocated, HB_GlyphItemRec ) )\r
+ return error;\r
+\r
+ if ( buffer->separate_out )\r
+ {\r
+ if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )\r
+ return error;\r
+\r
+ buffer->out_string = buffer->alt_string;\r
+ }\r
+ else\r
+ {\r
+ buffer->out_string = buffer->in_string;\r
+\r
+ if ( buffer->alt_string )\r
+ {\r
+ if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )\r
+ return error;\r
+ }\r
+ }\r
+\r
+ buffer->allocated = new_allocated;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+static HB_Error\r
+hb_buffer_duplicate_out_buffer( HB_Buffer buffer )\r
+{\r
+ if ( !buffer->alt_string )\r
+ {\r
+ HB_Error error;\r
+\r
+ if ( ALLOC_ARRAY( buffer->alt_string, buffer->allocated, HB_GlyphItemRec ) )\r
+ return error;\r
+ }\r
+\r
+ buffer->out_string = buffer->alt_string;\r
+ memcpy( buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]) );\r
+ buffer->separate_out = TRUE;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+/* Public API */\r
+\r
+HB_Error\r
+hb_buffer_new( HB_Buffer *pbuffer )\r
+{\r
+ HB_Buffer buffer;\r
+ HB_Error error;\r
+\r
+ if ( ALLOC( buffer, sizeof( HB_BufferRec ), HB_Buffer) )\r
+ return error;\r
+\r
+ buffer->allocated = 0;\r
+ buffer->in_string = NULL;\r
+ buffer->alt_string = NULL;\r
+ buffer->positions = NULL;\r
+\r
+ hb_buffer_clear( buffer );\r
+\r
+ *pbuffer = buffer;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+void\r
+hb_buffer_free( HB_Buffer buffer )\r
+{\r
+ FREE( buffer->in_string );\r
+ FREE( buffer->alt_string );\r
+ buffer->out_string = NULL;\r
+ FREE( buffer->positions );\r
+ FREE( buffer );\r
+}\r
+\r
+void\r
+hb_buffer_clear( HB_Buffer buffer )\r
+{\r
+ buffer->in_length = 0;\r
+ buffer->out_length = 0;\r
+ buffer->in_pos = 0;\r
+ buffer->out_pos = 0;\r
+ buffer->out_string = buffer->in_string;\r
+ buffer->separate_out = FALSE;\r
+ buffer->max_ligID = 0;\r
+}\r
+\r
+HB_Error\r
+hb_buffer_add_glyph( HB_Buffer buffer,\r
+ HB_UInt glyph_index,\r
+ HB_UInt properties,\r
+ HB_UInt cluster )\r
+{\r
+ HB_Error error;\r
+ HB_GlyphItem glyph;\r
+ \r
+ error = hb_buffer_ensure( buffer, buffer->in_length + 1 );\r
+ if ( error )\r
+ return error;\r
+\r
+ glyph = &buffer->in_string[buffer->in_length];\r
+ glyph->gindex = glyph_index;\r
+ glyph->properties = properties;\r
+ glyph->cluster = cluster;\r
+ glyph->component = 0;\r
+ glyph->ligID = 0;\r
+ glyph->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;\r
+ \r
+ buffer->in_length++;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+/* HarfBuzz-Internal API */\r
+\r
+HB_INTERNAL void\r
+_hb_buffer_clear_output( HB_Buffer buffer )\r
+{\r
+ buffer->out_length = 0;\r
+ buffer->out_pos = 0;\r
+ buffer->out_string = buffer->in_string;\r
+ buffer->separate_out = FALSE;\r
+}\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_clear_positions( HB_Buffer buffer )\r
+{\r
+ if ( !buffer->positions )\r
+ {\r
+ HB_Error error;\r
+\r
+ if ( ALLOC_ARRAY( buffer->positions, buffer->allocated, HB_PositionRec ) )\r
+ return error;\r
+ }\r
+\r
+ memset (buffer->positions, 0, sizeof (buffer->positions[0]) * buffer->in_length);\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+HB_INTERNAL void\r
+_hb_buffer_swap( HB_Buffer buffer )\r
+{\r
+ HB_GlyphItem tmp_string;\r
+ int tmp_length;\r
+ int tmp_pos;\r
+\r
+ if ( buffer->separate_out )\r
+ {\r
+ tmp_string = buffer->in_string;\r
+ buffer->in_string = buffer->out_string;\r
+ buffer->out_string = tmp_string;\r
+ buffer->alt_string = buffer->out_string;\r
+ }\r
+\r
+ tmp_length = buffer->in_length;\r
+ buffer->in_length = buffer->out_length;\r
+ buffer->out_length = tmp_length;\r
+\r
+ tmp_pos = buffer->in_pos;\r
+ buffer->in_pos = buffer->out_pos;\r
+ buffer->out_pos = tmp_pos;\r
+}\r
+\r
+/* The following function copies `num_out' elements from `glyph_data'\r
+ to `buffer->out_string', advancing the in array pointer in the structure\r
+ by `num_in' elements, and the out array pointer by `num_out' elements.\r
+ Finally, it sets the `length' field of `out' equal to\r
+ `pos' of the `out' structure.\r
+\r
+ If `component' is 0xFFFF, the component value from buffer->in_pos\r
+ will copied `num_out' times, otherwise `component' itself will\r
+ be used to fill the `component' fields.\r
+\r
+ If `ligID' is 0xFFFF, the ligID value from buffer->in_pos\r
+ will copied `num_out' times, otherwise `ligID' itself will\r
+ be used to fill the `ligID' fields.\r
+\r
+ The properties for all replacement glyphs are taken\r
+ from the glyph at position `buffer->in_pos'.\r
+\r
+ The cluster value for the glyph at position buffer->in_pos is used\r
+ for all replacement glyphs */\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_add_output_glyphs( HB_Buffer buffer,\r
+ HB_UShort num_in,\r
+ HB_UShort num_out,\r
+ HB_UShort *glyph_data,\r
+ HB_UShort component,\r
+ HB_UShort ligID )\r
+{\r
+ HB_Error error;\r
+ HB_UShort i;\r
+ HB_UInt properties;\r
+ HB_UInt cluster;\r
+\r
+ error = hb_buffer_ensure( buffer, buffer->out_pos + num_out );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( !buffer->separate_out )\r
+ {\r
+ error = hb_buffer_duplicate_out_buffer( buffer );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ properties = buffer->in_string[buffer->in_pos].properties;\r
+ cluster = buffer->in_string[buffer->in_pos].cluster;\r
+ if ( component == 0xFFFF )\r
+ component = buffer->in_string[buffer->in_pos].component;\r
+ if ( ligID == 0xFFFF )\r
+ ligID = buffer->in_string[buffer->in_pos].ligID;\r
+\r
+ for ( i = 0; i < num_out; i++ )\r
+ {\r
+ HB_GlyphItem item = &buffer->out_string[buffer->out_pos + i];\r
+\r
+ item->gindex = glyph_data[i];\r
+ item->properties = properties;\r
+ item->cluster = cluster;\r
+ item->component = component;\r
+ item->ligID = ligID;\r
+ item->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;\r
+ }\r
+\r
+ buffer->in_pos += num_in;\r
+ buffer->out_pos += num_out;\r
+\r
+ buffer->out_length = buffer->out_pos;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_add_output_glyph( HB_Buffer buffer,\r
+ HB_UInt glyph_index,\r
+ HB_UShort component,\r
+ HB_UShort ligID )\r
+{\r
+ HB_UShort glyph_data = glyph_index;\r
+\r
+ return _hb_buffer_add_output_glyphs ( buffer, 1, 1,\r
+ &glyph_data, component, ligID );\r
+}\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_copy_output_glyph ( HB_Buffer buffer )\r
+{ \r
+ HB_Error error;\r
+\r
+ error = hb_buffer_ensure( buffer, buffer->out_pos + 1 );\r
+ if ( error )\r
+ return error;\r
+ \r
+ if ( buffer->separate_out )\r
+ {\r
+ buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];\r
+ }\r
+\r
+ buffer->in_pos++;\r
+ buffer->out_pos++;\r
+ buffer->out_length = buffer->out_pos;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_buffer_replace_output_glyph( HB_Buffer buffer,\r
+ HB_UInt glyph_index,\r
+ HB_Bool inplace )\r
+{\r
+\r
+ HB_Error error;\r
+\r
+ if ( inplace )\r
+ {\r
+ error = _hb_buffer_copy_output_glyph ( buffer );\r
+ if ( error )\r
+ return error;\r
+\r
+ buffer->out_string[buffer->out_pos-1].gindex = glyph_index;\r
+ }\r
+ else\r
+ {\r
+ return _hb_buffer_add_output_glyph( buffer, glyph_index, 0xFFFF, 0xFFFF );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+HB_INTERNAL HB_UShort\r
+_hb_buffer_allocate_ligid( HB_Buffer buffer )\r
+{\r
+ buffer->max_ligID++;\r
+ if (HB_UNLIKELY (buffer->max_ligID == 0))\r
+ buffer->max_ligID++;\r
+\r
+ return buffer->max_ligID;\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2000, 2007 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Owen Taylor, Behdad Esfahbod\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-dump.h"\r
+#include "harfbuzz-gdef-private.h"\r
+#include "harfbuzz-gsub-private.h"\r
+#include "harfbuzz-gpos-private.h"\r
+#include "harfbuzz-open-private.h"\r
+#include <stdarg.h>\r
+\r
+#define DUMP(format) dump (stream, indent, format)\r
+#define DUMP1(format, arg1) dump (stream, indent, format, arg1)\r
+#define DUMP2(format, arg1, arg2) dump (stream, indent, format, arg1, arg2)\r
+#define DUMP3(format, arg1, arg2, arg3) dump (stream, indent, format, arg1, arg2, arg3)\r
+\r
+#define DUMP_FINT(strct,fld) dump (stream, indent, "<" #fld ">%d</" #fld ">\n", (strct)->fld)\r
+#define DUMP_FUINT(strct,fld) dump (stream, indent, "<" #fld ">%u</" #fld ">\n", (strct)->fld)\r
+#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x</" #fld ">\n", (strct)->fld)\r
+#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x</" #fld ">\n", (strct)->fld)\r
+#define DUMP_USHORT_ARRAY(strct,fld,cnt) Dump_UShort_Array ((strct)->fld, cnt, #fld, stream, indent);\r
+\r
+#define DEF_DUMP(type) static void Dump_ ## type (HB_ ## type *type, FILE *stream, int indent, HB_Type hb_type)\r
+#define RECURSE(name, type, val) do { DUMP ("<" #name ">\n"); Dump_ ## type (val, stream, indent + 1, hb_type); DUMP ("</" #name ">\n"); } while (0)\r
+#define RECURSE_NUM(name, i, type, val) do { DUMP1 ("<" #name "> <!-- %d -->\n", i); Dump_ ## type (val, stream, indent + 1, hb_type); DUMP ("</" #name ">\n"); } while (0)\r
+#define DUMP_VALUE_RECORD(val, frmt) do { DUMP ("<ValueRecord>\n"); Dump_ValueRecord (val, stream, indent + 1, hb_type, frmt); DUMP ("</ValueRecord>\n"); } while (0)\r
+\r
+static void\r
+do_indent (FILE *stream, int indent)\r
+{\r
+ fprintf (stream, "%*s", indent * 3, "");\r
+}\r
+\r
+static void\r
+dump (FILE *stream, int indent, const char *format, ...)\r
+{\r
+ va_list list;\r
+\r
+ do_indent (stream, indent);\r
+\r
+ va_start (list, format);\r
+ vfprintf (stream, format, list);\r
+ va_end (list);\r
+}\r
+\r
+static void\r
+Dump_UShort_Array (HB_UShort *array, int count, const char *name, FILE *stream, int indent)\r
+{\r
+ int i;\r
+\r
+ do_indent (stream, indent);\r
+\r
+ fprintf (stream, "<%s>", name);\r
+ for (i = 0; i < count; i++)\r
+ fprintf (stream, "%d%s", array[i], i == 0 ? "" : " ");\r
+ fprintf (stream, "</%s>\n", name);\r
+}\r
+\r
+static void\r
+Print_Tag (HB_UInt tag, FILE *stream)\r
+{\r
+ fprintf (stream, "%c%c%c%c",\r
+ (unsigned char)(tag >> 24),\r
+ (unsigned char)((tag >> 16) & 0xff),\r
+ (unsigned char)((tag >> 8) & 0xff),\r
+ (unsigned char)(tag & 0xff));\r
+}\r
+\r
+DEF_DUMP (LangSys)\r
+{\r
+ int i;\r
+\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FUINT (LangSys, LookupOrderOffset);\r
+ DUMP_FUINT (LangSys, ReqFeatureIndex);\r
+ DUMP_FUINT (LangSys, FeatureCount);\r
+\r
+ for (i=0; i < LangSys->FeatureCount; i++)\r
+ DUMP1("<FeatureIndex>%d</FeatureIndex>\n", LangSys->FeatureIndex[i]);\r
+}\r
+\r
+DEF_DUMP (ScriptTable)\r
+{\r
+ int i;\r
+\r
+ RECURSE (DefaultLangSys, LangSys, &ScriptTable->DefaultLangSys);\r
+\r
+ DUMP_FUINT (ScriptTable, LangSysCount);\r
+\r
+ for (i=0; i < ScriptTable->LangSysCount; i++)\r
+ {\r
+ do_indent (stream, indent);\r
+ fprintf (stream, "<LangSysTag>");\r
+ Print_Tag (ScriptTable->LangSysRecord[i].LangSysTag, stream);\r
+ fprintf (stream, "</LangSysTag>\n");\r
+ RECURSE_NUM (LangSys, i, LangSys, &ScriptTable->LangSysRecord[i].LangSys);\r
+ }\r
+}\r
+\r
+DEF_DUMP (ScriptList)\r
+{\r
+ int i;\r
+\r
+ DUMP_FUINT (ScriptList, ScriptCount);\r
+\r
+ for (i=0; i < ScriptList->ScriptCount; i++)\r
+ {\r
+ do_indent (stream, indent);\r
+ fprintf (stream, "<ScriptTag>");\r
+ Print_Tag (ScriptList->ScriptRecord[i].ScriptTag, stream);\r
+ fprintf (stream, "</ScriptTag>\n");\r
+ RECURSE_NUM (Script, i, ScriptTable, &ScriptList->ScriptRecord[i].Script);\r
+ }\r
+}\r
+\r
+DEF_DUMP (Feature)\r
+{\r
+ int i;\r
+\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FUINT (Feature, FeatureParams);\r
+ DUMP_FUINT (Feature, LookupListCount);\r
+\r
+ for (i=0; i < Feature->LookupListCount; i++)\r
+ DUMP1("<LookupIndex>%d</LookupIndex>\n", Feature->LookupListIndex[i]);\r
+}\r
+\r
+DEF_DUMP (MarkRecord)\r
+{\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FUINT (MarkRecord, Class);\r
+ DUMP1("<Anchor>%d</Anchor>\n", MarkRecord->MarkAnchor.PosFormat );\r
+}\r
+\r
+DEF_DUMP (MarkArray)\r
+{\r
+ int i;\r
+\r
+ DUMP_FUINT (MarkArray, MarkCount);\r
+\r
+ for (i=0; i < MarkArray->MarkCount; i++)\r
+ RECURSE_NUM (MarkRecord, i, MarkRecord, &MarkArray->MarkRecord[i]);\r
+}\r
+\r
+DEF_DUMP (FeatureList)\r
+{\r
+ int i;\r
+\r
+ DUMP_FUINT (FeatureList, FeatureCount);\r
+\r
+ for (i=0; i < FeatureList->FeatureCount; i++)\r
+ {\r
+ do_indent (stream, indent);\r
+ fprintf (stream, "<FeatureTag>");\r
+ Print_Tag (FeatureList->FeatureRecord[i].FeatureTag, stream);\r
+ fprintf (stream, "</FeatureTag> <!-- %d -->\n", i);\r
+ RECURSE_NUM (Feature, i, Feature, &FeatureList->FeatureRecord[i].Feature);\r
+ }\r
+}\r
+\r
+DEF_DUMP (Coverage)\r
+{\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FUINT (Coverage, CoverageFormat);\r
+\r
+ if (Coverage->CoverageFormat == 1)\r
+ {\r
+ int i;\r
+ DUMP_FUINT (&Coverage->cf.cf1, GlyphCount);\r
+\r
+ for (i = 0; i < Coverage->cf.cf1.GlyphCount; i++)\r
+ DUMP2("<Glyph>%#06x</Glyph> <!-- %d -->\n",\r
+ Coverage->cf.cf1.GlyphArray[i], i);\r
+ }\r
+ else\r
+ {\r
+ int i;\r
+ DUMP_FUINT (&Coverage->cf.cf2, RangeCount);\r
+\r
+ for ( i = 0; i < Coverage->cf.cf2.RangeCount; i++ )\r
+ DUMP3("<Glyph>%#06x - %#06x</Glyph> <!-- %d -->\n",\r
+ Coverage->cf.cf2.RangeRecord[i].Start,\r
+ Coverage->cf.cf2.RangeRecord[i].End, i);\r
+ }\r
+}\r
+\r
+DEF_DUMP (ClassRangeRecord)\r
+{\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FGLYPH (ClassRangeRecord, Start);\r
+ DUMP_FGLYPH (ClassRangeRecord, End);\r
+ DUMP_FUINT (ClassRangeRecord, Class);\r
+}\r
+\r
+DEF_DUMP (ClassDefinition)\r
+{\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FUINT( ClassDefinition, ClassFormat);\r
+ DUMP_FUINT( ClassDefinition, loaded);\r
+\r
+ if (ClassDefinition->ClassFormat == 1)\r
+ {\r
+ int i;\r
+ HB_ClassDefFormat1 *ClassDefFormat1 = &ClassDefinition->cd.cd1;\r
+ DUMP("<ClassDefinition>\n");\r
+ DUMP_FUINT (ClassDefFormat1, StartGlyph );\r
+ DUMP_FUINT (ClassDefFormat1, GlyphCount );\r
+ for (i = 0; i < ClassDefFormat1->GlyphCount; i++)\r
+ DUMP2(" <Class>%d</Class> <!-- %#06x -->", ClassDefFormat1->ClassValueArray[i],\r
+ ClassDefFormat1->StartGlyph+i );\r
+ }\r
+ else if (ClassDefinition->ClassFormat == 2)\r
+ {\r
+ int i;\r
+ HB_ClassDefFormat2 *ClassDefFormat2 = &ClassDefinition->cd.cd2;\r
+ DUMP_FUINT (ClassDefFormat2, ClassRangeCount);\r
+\r
+ for (i = 0; i < ClassDefFormat2->ClassRangeCount; i++)\r
+ RECURSE_NUM (ClassRangeRecord, i, ClassRangeRecord, &ClassDefFormat2->ClassRangeRecord[i]);\r
+ }\r
+ else\r
+ fprintf(stderr, "invalid class def table!!!\n");\r
+}\r
+\r
+DEF_DUMP (SubstLookupRecord)\r
+{\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FUINT (SubstLookupRecord, SequenceIndex);\r
+ DUMP_FUINT (SubstLookupRecord, LookupListIndex);\r
+}\r
+\r
+DEF_DUMP (ChainSubClassRule)\r
+{\r
+ int i;\r
+\r
+ DUMP_USHORT_ARRAY (ChainSubClassRule, Backtrack, ChainSubClassRule->BacktrackGlyphCount);\r
+ DUMP_USHORT_ARRAY (ChainSubClassRule, Input, ChainSubClassRule->InputGlyphCount - 1);\r
+ DUMP_USHORT_ARRAY (ChainSubClassRule, Lookahead, ChainSubClassRule->LookaheadGlyphCount);\r
+\r
+ for (i = 0; i < ChainSubClassRule->SubstCount; i++)\r
+ RECURSE_NUM (SubstLookupRecord, i, SubstLookupRecord, &ChainSubClassRule->SubstLookupRecord[i]);\r
+\r
+ indent--;\r
+}\r
+\r
+DEF_DUMP (ChainSubClassSet)\r
+{\r
+ int i;\r
+\r
+ DUMP_FUINT( ChainSubClassSet, ChainSubClassRuleCount );\r
+ for (i = 0; i < ChainSubClassSet->ChainSubClassRuleCount; i++)\r
+ RECURSE_NUM (ChainSubClassRule, i, ChainSubClassRule, &ChainSubClassSet->ChainSubClassRule[i]);\r
+}\r
+\r
+static void\r
+Dump_GSUB_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ HB_SingleSubst *SingleSubst = &subtable->st.gsub.single;\r
+\r
+ DUMP_FUINT (SingleSubst, SubstFormat);\r
+ RECURSE (Coverage, Coverage, &SingleSubst->Coverage);\r
+\r
+ if (SingleSubst->SubstFormat == 1)\r
+ {\r
+ DUMP_FINT (&SingleSubst->ssf.ssf1, DeltaGlyphID);\r
+ }\r
+ else\r
+ {\r
+ int i;\r
+\r
+ DUMP_FINT (&SingleSubst->ssf.ssf2, GlyphCount);\r
+ for (i=0; i < SingleSubst->ssf.ssf2.GlyphCount; i++)\r
+ DUMP2("<Substitute>%#06x</Substitute> <!-- %d -->\n", SingleSubst->ssf.ssf2.Substitute[i], i);\r
+ }\r
+}\r
+\r
+DEF_DUMP (Ligature)\r
+{\r
+ int i;\r
+\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FGLYPH (Ligature, LigGlyph);\r
+ DUMP_FUINT (Ligature, ComponentCount);\r
+\r
+ for (i=0; i < Ligature->ComponentCount - 1; i++)\r
+ DUMP1("<Component>%#06x</Component>\n", Ligature->Component[i]);\r
+}\r
+\r
+DEF_DUMP (LigatureSet)\r
+{\r
+ int i;\r
+\r
+ DUMP_FUINT (LigatureSet, LigatureCount);\r
+\r
+ for (i=0; i < LigatureSet->LigatureCount; i++)\r
+ RECURSE_NUM (Ligature, i, Ligature, &LigatureSet->Ligature[i]);\r
+}\r
+\r
+static void\r
+Dump_GSUB_Lookup_Ligature (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ int i;\r
+ HB_LigatureSubst *LigatureSubst = &subtable->st.gsub.ligature;\r
+\r
+ DUMP_FUINT (LigatureSubst, SubstFormat);\r
+ RECURSE (Coverage, Coverage, &LigatureSubst->Coverage);\r
+\r
+ DUMP_FUINT (LigatureSubst, LigatureSetCount);\r
+\r
+ for (i=0; i < LigatureSubst->LigatureSetCount; i++)\r
+ RECURSE_NUM (LigatureSet, i, LigatureSet, &LigatureSubst->LigatureSet[i]);\r
+}\r
+\r
+DEF_DUMP (ContextSubstFormat1)\r
+{\r
+ HB_UNUSED(hb_type);\r
+ HB_UNUSED(ContextSubstFormat1);\r
+\r
+\r
+ DUMP("<!-- Not implemented!!! -->\n");\r
+}\r
+\r
+DEF_DUMP (ContextSubstFormat2)\r
+{\r
+ DUMP_FUINT (ContextSubstFormat2, MaxContextLength);\r
+ RECURSE (Coverage, Coverage, &ContextSubstFormat2->Coverage);\r
+ RECURSE (ClassDefinition, ClassDefinition, &ContextSubstFormat2->ClassDef);\r
+}\r
+\r
+DEF_DUMP (ContextSubstFormat3)\r
+{\r
+ HB_UNUSED(hb_type);\r
+ HB_UNUSED(ContextSubstFormat3);\r
+\r
+ DUMP("<!-- Not implemented!!! -->\n");\r
+}\r
+\r
+static void\r
+Dump_GSUB_Lookup_Context (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ HB_ContextSubst *ContextSubst = &subtable->st.gsub.context;\r
+\r
+ DUMP_FUINT (ContextSubst, SubstFormat);\r
+ switch( ContextSubst->SubstFormat )\r
+ {\r
+ case 1:\r
+ Dump_ContextSubstFormat1 (&ContextSubst->csf.csf1, stream, indent+2, hb_type);\r
+ break;\r
+ case 2:\r
+ Dump_ContextSubstFormat2 (&ContextSubst->csf.csf2, stream, indent+2, hb_type);\r
+ break;\r
+ case 3:\r
+ Dump_ContextSubstFormat3 (&ContextSubst->csf.csf3, stream, indent+2, hb_type);\r
+ break;\r
+ default:\r
+ fprintf(stderr, "invalid subformat!!!!!\n");\r
+ }\r
+}\r
+\r
+DEF_DUMP (ChainContextSubstFormat1)\r
+{\r
+ HB_UNUSED(hb_type);\r
+ HB_UNUSED(ChainContextSubstFormat1);\r
+\r
+ DUMP("<!-- Not implemented!!! -->\n");\r
+}\r
+\r
+DEF_DUMP (ChainContextSubstFormat2)\r
+{\r
+ int i;\r
+\r
+ RECURSE (Coverage, Coverage, &ChainContextSubstFormat2->Coverage);\r
+ DUMP_FUINT (ChainContextSubstFormat2, MaxBacktrackLength);\r
+ RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->BacktrackClassDef);\r
+ DUMP_FUINT (ChainContextSubstFormat2, MaxInputLength);\r
+ RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->InputClassDef);\r
+ DUMP_FUINT (ChainContextSubstFormat2, MaxLookaheadLength);\r
+ RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->LookaheadClassDef);\r
+\r
+ DUMP_FUINT (ChainContextSubstFormat2, ChainSubClassSetCount);\r
+ for (i = 0; i < ChainContextSubstFormat2->ChainSubClassSetCount; i++)\r
+ RECURSE (ChainSubClassSet, ChainSubClassSet, &ChainContextSubstFormat2->ChainSubClassSet[i]);\r
+}\r
+\r
+DEF_DUMP (ChainContextSubstFormat3)\r
+{\r
+ int i;\r
+\r
+ DUMP_FUINT (ChainContextSubstFormat3, BacktrackGlyphCount);\r
+ for (i = 0; i < ChainContextSubstFormat3->BacktrackGlyphCount; i++)\r
+ RECURSE (BacktrackCoverage, Coverage, &ChainContextSubstFormat3->BacktrackCoverage[i]);\r
+ DUMP_FUINT (ChainContextSubstFormat3, InputGlyphCount);\r
+ for (i = 0; i < ChainContextSubstFormat3->InputGlyphCount; i++)\r
+ RECURSE (InputCoverage, Coverage, &ChainContextSubstFormat3->InputCoverage[i]);\r
+ DUMP_FUINT (ChainContextSubstFormat3, LookaheadGlyphCount);\r
+ for (i = 0; i < ChainContextSubstFormat3->LookaheadGlyphCount; i++)\r
+ RECURSE (LookaheadCoverage, Coverage, &ChainContextSubstFormat3->LookaheadCoverage[i]);\r
+\r
+ for (i = 0; i < ChainContextSubstFormat3->SubstCount; i++)\r
+ RECURSE_NUM (SubstLookupRecord, i, SubstLookupRecord, &ChainContextSubstFormat3->SubstLookupRecord[i]);\r
+\r
+}\r
+\r
+static void\r
+Dump_GSUB_Lookup_Chain (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ HB_ChainContextSubst *chain = &subtable->st.gsub.chain;\r
+\r
+ DUMP_FUINT (chain, SubstFormat);\r
+ switch (chain->SubstFormat)\r
+ {\r
+ case 1:\r
+ Dump_ChainContextSubstFormat1 (&chain->ccsf.ccsf1, stream, indent+2, hb_type);\r
+ break;\r
+ case 2:\r
+ Dump_ChainContextSubstFormat2 (&chain->ccsf.ccsf2, stream, indent+2, hb_type);\r
+ break;\r
+ case 3:\r
+ Dump_ChainContextSubstFormat3 (&chain->ccsf.ccsf3, stream, indent+2, hb_type);\r
+ break;\r
+ default:\r
+ fprintf(stderr, "invalid subformat!!!!!\n");\r
+ }\r
+}\r
+\r
+static void\r
+Dump_Device (HB_Device *Device, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ int i;\r
+ int bits;\r
+ int n_per;\r
+ unsigned int mask;\r
+\r
+ HB_UNUSED(hb_type);\r
+\r
+ DUMP_FUINT (Device, StartSize);\r
+ DUMP_FUINT (Device, EndSize);\r
+ DUMP_FUINT (Device, DeltaFormat);\r
+ switch (Device->DeltaFormat)\r
+ {\r
+ case 1:\r
+ bits = 2;\r
+ break;\r
+ case 2:\r
+ bits = 4;\r
+ break;\r
+ case 3:\r
+ bits = 8;\r
+ break;\r
+ default:\r
+ bits = 0;\r
+ break;\r
+ }\r
+\r
+ DUMP ("<DeltaValue>");\r
+ if (!bits)\r
+ {\r
+\r
+ fprintf(stderr, "invalid DeltaFormat!!!!!\n");\r
+ }\r
+ else\r
+ {\r
+ n_per = 16 / bits;\r
+ mask = (1 << bits) - 1;\r
+ mask = mask << (16 - bits);\r
+\r
+ for (i = Device->StartSize; i <= Device->EndSize ; i++)\r
+ {\r
+ HB_UShort val = Device->DeltaValue[i / n_per];\r
+ HB_Short signed_val = ((val << ((i % n_per) * bits)) & mask);\r
+ dump (stream, indent, "%d", signed_val >> (16 - bits));\r
+ if (i != Device->EndSize)\r
+ DUMP (", ");\r
+ }\r
+ }\r
+ DUMP ("</DeltaValue>\n");\r
+}\r
+\r
+static void\r
+Dump_ValueRecord (HB_ValueRecord *ValueRecord, FILE *stream, int indent, HB_Type hb_type, HB_UShort value_format)\r
+{\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT)\r
+ DUMP_FINT (ValueRecord, XPlacement);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT)\r
+ DUMP_FINT (ValueRecord, YPlacement);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE)\r
+ DUMP_FINT (ValueRecord, XAdvance);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE)\r
+ DUMP_FINT (ValueRecord, XAdvance);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE)\r
+ RECURSE (Device, Device, &ValueRecord->XPlacementDevice);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE)\r
+ RECURSE (Device, Device, &ValueRecord->YPlacementDevice);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE)\r
+ RECURSE (Device, Device, &ValueRecord->XAdvanceDevice);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE)\r
+ RECURSE (Device, Device, &ValueRecord->YAdvanceDevice);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT)\r
+ DUMP_FUINT (ValueRecord, XIdPlacement);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT)\r
+ DUMP_FUINT (ValueRecord, YIdPlacement);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE)\r
+ DUMP_FUINT (ValueRecord, XIdAdvance);\r
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE)\r
+ DUMP_FUINT (ValueRecord, XIdAdvance);\r
+}\r
+\r
+static void\r
+Dump_GPOS_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ HB_SinglePos *SinglePos = &subtable->st.gpos.single;\r
+\r
+ DUMP_FUINT (SinglePos, PosFormat);\r
+ RECURSE (Coverage, Coverage, &SinglePos->Coverage);\r
+\r
+ DUMP_FUINT (SinglePos, ValueFormat);\r
+\r
+ if (SinglePos->PosFormat == 1)\r
+ {\r
+ DUMP_VALUE_RECORD (&SinglePos->spf.spf1.Value, SinglePos->ValueFormat);\r
+ }\r
+ else\r
+ {\r
+ int i;\r
+\r
+ DUMP_FUINT (&SinglePos->spf.spf2, ValueCount);\r
+ for (i = 0; i < SinglePos->spf.spf2.ValueCount; i++)\r
+ DUMP_VALUE_RECORD (&SinglePos->spf.spf2.Value[i], SinglePos->ValueFormat);\r
+ }\r
+}\r
+\r
+static void\r
+Dump_PairValueRecord (HB_PairValueRecord *PairValueRecord, FILE *stream, int indent, HB_Type hb_type, HB_UShort ValueFormat1, HB_UShort ValueFormat2)\r
+{\r
+ DUMP_FUINT (PairValueRecord, SecondGlyph);\r
+ DUMP_VALUE_RECORD (&PairValueRecord->Value1, ValueFormat1);\r
+ DUMP_VALUE_RECORD (&PairValueRecord->Value2, ValueFormat2);\r
+}\r
+\r
+static void\r
+Dump_PairSet (HB_PairSet *PairSet, FILE *stream, int indent, HB_Type hb_type, HB_UShort ValueFormat1, HB_UShort ValueFormat2)\r
+{\r
+ int i;\r
+ DUMP_FUINT (PairSet, PairValueCount);\r
+\r
+ for (i = 0; i < PairSet->PairValueCount; i++)\r
+ {\r
+ DUMP ("<PairValueRecord>\n");\r
+ Dump_PairValueRecord (&PairSet->PairValueRecord[i], stream, indent + 1, hb_type, ValueFormat1, ValueFormat2);\r
+ DUMP ("</PairValueRecord>\n");\r
+ }\r
+}\r
+\r
+static void\r
+Dump_GPOS_Lookup_Pair (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ HB_PairPos *PairPos = &subtable->st.gpos.pair;\r
+\r
+ DUMP_FUINT (PairPos, PosFormat);\r
+ RECURSE (Coverage, Coverage, &PairPos->Coverage);\r
+\r
+ DUMP_FUINT (PairPos, ValueFormat1);\r
+ DUMP_FUINT (PairPos, ValueFormat2);\r
+\r
+ if (PairPos->PosFormat == 1)\r
+ {\r
+ int i;\r
+\r
+ DUMP_FUINT (&PairPos->ppf.ppf1, PairSetCount);\r
+ for (i = 0; i < PairPos->ppf.ppf1.PairSetCount; i++)\r
+ {\r
+ DUMP ("<PairSet>\n");\r
+ Dump_PairSet (&PairPos->ppf.ppf1.PairSet[i], stream, indent + 1, hb_type, PairPos->ValueFormat1, PairPos->ValueFormat2);\r
+ DUMP ("</PairSet>\n");\r
+ }\r
+ }\r
+ else\r
+ {\r
+ }\r
+}\r
+\r
+static void\r
+Dump_GPOS_Lookup_Markbase (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)\r
+{\r
+ int i;\r
+ HB_MarkBasePos *markbase = &subtable->st.gpos.markbase;\r
+\r
+ DUMP_FUINT (markbase, PosFormat);\r
+ RECURSE (Coverage, Coverage, &markbase->MarkCoverage);\r
+ RECURSE (Coverage, Coverage, &markbase->BaseCoverage);\r
+ DUMP_FUINT (markbase, ClassCount);\r
+ RECURSE (MarkArray, MarkArray, &markbase->MarkArray);\r
+\r
+ DUMP ("<BaseArray>\n");\r
+ indent++;\r
+\r
+ DUMP_FUINT (&markbase->BaseArray, BaseCount);\r
+ for (i = 0; i < markbase->BaseArray.BaseCount; i++)\r
+ {\r
+ int j;\r
+ HB_BaseRecord *r = &markbase->BaseArray.BaseRecord[i];\r
+ DUMP1 ("<BaseRecord> <!-- %d -->\n", i);\r
+ for (j = 0; j < markbase->ClassCount; j++)\r
+ DUMP1 (" <Anchor>%d</Anchor>\n", r->BaseAnchor->PosFormat);\r
+ DUMP ("<BaseRecord>\n");\r
+ }\r
+\r
+ indent--;\r
+ DUMP ("</BaseArray>\n");\r
+}\r
+\r
+DEF_DUMP (Lookup)\r
+{\r
+ int i;\r
+ const char *lookup_name;\r
+ void (*lookup_func) (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) = NULL;\r
+\r
+ if (hb_type == HB_Type_GSUB)\r
+ {\r
+ switch (Lookup->LookupType)\r
+ {\r
+ case HB_GSUB_LOOKUP_SINGLE:\r
+ lookup_name = "SINGLE";\r
+ lookup_func = Dump_GSUB_Lookup_Single;\r
+ break;\r
+ case HB_GSUB_LOOKUP_MULTIPLE:\r
+ lookup_name = "MULTIPLE";\r
+ break;\r
+ case HB_GSUB_LOOKUP_ALTERNATE:\r
+ lookup_name = "ALTERNATE";\r
+ break;\r
+ case HB_GSUB_LOOKUP_LIGATURE:\r
+ lookup_name = "LIGATURE";\r
+ lookup_func = Dump_GSUB_Lookup_Ligature;\r
+ break;\r
+ case HB_GSUB_LOOKUP_CONTEXT:\r
+ lookup_name = "CONTEXT";\r
+ lookup_func = Dump_GSUB_Lookup_Context;\r
+ break;\r
+ case HB_GSUB_LOOKUP_CHAIN:\r
+ lookup_name = "CHAIN";\r
+ lookup_func = Dump_GSUB_Lookup_Chain;\r
+ break;\r
+ default:\r
+ lookup_name = "(unknown)";\r
+ lookup_func = NULL;\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ switch (Lookup->LookupType)\r
+ {\r
+ case HB_GPOS_LOOKUP_SINGLE:\r
+ lookup_name = "SINGLE";\r
+ lookup_func = Dump_GPOS_Lookup_Single;\r
+ break;\r
+ case HB_GPOS_LOOKUP_PAIR:\r
+ lookup_name = "PAIR";\r
+ lookup_func = Dump_GPOS_Lookup_Pair;\r
+ break;\r
+ case HB_GPOS_LOOKUP_CURSIVE:\r
+ lookup_name = "CURSIVE";\r
+ break;\r
+ case HB_GPOS_LOOKUP_MARKBASE:\r
+ lookup_name = "MARKBASE";\r
+ lookup_func = Dump_GPOS_Lookup_Markbase;\r
+ break;\r
+ case HB_GPOS_LOOKUP_MARKLIG:\r
+ lookup_name = "MARKLIG";\r
+ break;\r
+ case HB_GPOS_LOOKUP_MARKMARK:\r
+ lookup_name = "MARKMARK";\r
+ break;\r
+ case HB_GPOS_LOOKUP_CONTEXT:\r
+ lookup_name = "CONTEXT";\r
+ break;\r
+ case HB_GPOS_LOOKUP_CHAIN:\r
+ lookup_name = "CHAIN";\r
+ break;\r
+ default:\r
+ lookup_name = "(unknown)";\r
+ lookup_func = NULL;\r
+ break;\r
+ }\r
+ }\r
+\r
+ DUMP2("<LookupType>%s</LookupType> <!-- %d -->\n", lookup_name, Lookup->LookupType);\r
+ DUMP1("<LookupFlag>%#06x</LookupFlag>\n", Lookup->LookupFlag);\r
+\r
+ for (i=0; i < Lookup->SubTableCount; i++)\r
+ {\r
+ DUMP ("<Subtable>\n");\r
+ if (lookup_func)\r
+ (*lookup_func) (&Lookup->SubTable[i], stream, indent + 1, hb_type);\r
+ DUMP ("</Subtable>\n");\r
+ }\r
+}\r
+\r
+DEF_DUMP (LookupList)\r
+{\r
+ int i;\r
+\r
+ DUMP_FUINT (LookupList, LookupCount);\r
+\r
+ for (i=0; i < LookupList->LookupCount; i++)\r
+ RECURSE_NUM (Lookup, i, Lookup, &LookupList->Lookup[i]);\r
+}\r
+\r
+void\r
+HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream)\r
+{\r
+ int indent = 1;\r
+ HB_Type hb_type = HB_Type_GSUB;\r
+\r
+ do_indent (stream, indent);\r
+ fprintf(stream, "<!-- GSUB -->\n");\r
+ RECURSE (ScriptList, ScriptList, &gsub->ScriptList);\r
+ RECURSE (FeatureList, FeatureList, &gsub->FeatureList);\r
+ RECURSE (LookupList, LookupList, &gsub->LookupList);\r
+}\r
+\r
+void\r
+HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream)\r
+{\r
+ int indent = 1;\r
+ HB_Type hb_type = HB_Type_GPOS;\r
+\r
+ do_indent (stream, indent);\r
+ fprintf(stream, "<!-- GPOS -->\n");\r
+ RECURSE (ScriptList, ScriptList, &gpos->ScriptList);\r
+ RECURSE (FeatureList, FeatureList, &gpos->FeatureList);\r
+ RECURSE (LookupList, LookupList, &gpos->LookupList);\r
+}\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+\r
+#include "harfbuzz-external.h"\r
+\r
+\r
+HB_GraphemeClass HB_GetGraphemeClass(HB_UChar32 ch){return 0;}\r
+HB_WordClass HB_GetWordClass(HB_UChar32 ch){return 0;}\r
+HB_SentenceClass HB_GetSentenceClass(HB_UChar32 ch){return 0;}\r
+HB_LineBreakClass HB_GetLineBreakClass(HB_UChar32 ch){return 0;}\r
+\r
+void HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *grapheme, HB_LineBreakClass *lineBreak){}\r
+void HB_GetUnicodeCharProperties(HB_UChar32 ch, HB_CharCategory *category, int *combiningClass){}\r
+HB_CharCategory HB_GetUnicodeCharCategory(HB_UChar32 ch){return 0;}\r
+int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch){return 0;}\r
+HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch){return 0;}\r
+\r
+void *HB_Library_Resolve(const char *library, const char *symbol){}\r
+\r
+void *HB_TextCodecForMib(int mib){}\r
+char *HB_TextCodec_ConvertFromUnicode(void *codec, const HB_UChar16 *unicode, hb_uint32 length, hb_uint32 *outputLength){return NULL;}\r
+void HB_TextCodec_FreeResult(char * text){}\r
+\r
+\r
+\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-gdef-private.h"\r
+#include "harfbuzz-open-private.h"\r
+\r
+static HB_Error Load_AttachList( HB_AttachList* al,\r
+ HB_Stream stream );\r
+static HB_Error Load_LigCaretList( HB_LigCaretList* lcl,\r
+ HB_Stream stream );\r
+\r
+static void Free_AttachList( HB_AttachList* al);\r
+static void Free_LigCaretList( HB_LigCaretList* lcl);\r
+\r
+static void Free_NewGlyphClasses( HB_GDEFHeader* gdef);\r
+\r
+\r
+\r
+/* GDEF glyph classes */\r
+\r
+#define UNCLASSIFIED_GLYPH 0\r
+#define SIMPLE_GLYPH 1\r
+#define LIGATURE_GLYPH 2\r
+#define MARK_GLYPH 3\r
+#define COMPONENT_GLYPH 4\r
+\r
+\r
+\r
+\r
+\r
+\r
+HB_Error HB_New_GDEF_Table( HB_GDEFHeader** retptr )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_GDEFHeader* gdef;\r
+\r
+ if ( !retptr )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ if ( ALLOC( gdef, sizeof( *gdef ), HB_GDEFHeader* ) )\r
+ return error;\r
+\r
+ gdef->GlyphClassDef.loaded = FALSE;\r
+ gdef->AttachList.loaded = FALSE;\r
+ gdef->LigCaretList.loaded = FALSE;\r
+ gdef->MarkAttachClassDef_offset = 0;\r
+ gdef->MarkAttachClassDef.loaded = FALSE;\r
+\r
+ gdef->LastGlyph = 0;\r
+ gdef->NewGlyphClasses = NULL;\r
+\r
+ *retptr = gdef;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+HB_Error HB_Load_GDEF_Table( HB_Stream stream, \r
+ HB_GDEFHeader** retptr )\r
+{\r
+ HB_Error error;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ if ( !retptr )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ if ( GOTO_Table( TTAG_GDEF ) )\r
+ return error;\r
+\r
+ if (( error = HB_New_GDEF_Table ( &gdef ) ))\r
+ return error;\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ /* skip version */\r
+\r
+ if ( FILE_Seek( base_offset + 4L ) ||\r
+ ACCESS_Frame( 2L ) )\r
+ goto Fail0;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ /* all GDEF subtables are optional */\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ /* only classes 1-4 are allowed here */\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail0;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_AttachList( &gdef->AttachList,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_LigCaretList( &gdef->LigCaretList,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We\r
+ first have to scan the LookupFlag values to find out whether we\r
+ must load it or not. Here we only store the offset of the table. */\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ gdef->MarkAttachClassDef_offset = new_offset + base_offset;\r
+ else\r
+ gdef->MarkAttachClassDef_offset = 0;\r
+\r
+ *retptr = gdef;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail3:\r
+ Free_LigCaretList( &gdef->LigCaretList );\r
+ \r
+Fail2:\r
+ Free_AttachList( &gdef->AttachList );\r
+\r
+Fail1:\r
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );\r
+\r
+Fail0:\r
+ FREE( gdef );\r
+\r
+ return error;\r
+}\r
+\r
+\r
+HB_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef ) \r
+{ \r
+ Free_LigCaretList( &gdef->LigCaretList );\r
+ Free_AttachList( &gdef->AttachList );\r
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );\r
+ _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef );\r
+ \r
+ Free_NewGlyphClasses( gdef );\r
+\r
+ FREE( gdef );\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+\r
+/*******************************\r
+ * AttachList related functions\r
+ *******************************/\r
+\r
+\r
+/* AttachPoint */\r
+\r
+static HB_Error Load_AttachPoint( HB_AttachPoint* ap,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* pi;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = ap->PointCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ap->PointIndex = NULL;\r
+\r
+ if ( count )\r
+ {\r
+ if ( ALLOC_ARRAY( ap->PointIndex, count, HB_UShort ) )\r
+ return error;\r
+\r
+ pi = ap->PointIndex;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( pi );\r
+ return error;\r
+ }\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ pi[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_AttachPoint( HB_AttachPoint* ap )\r
+{\r
+ FREE( ap->PointIndex );\r
+}\r
+\r
+\r
+/* AttachList */\r
+\r
+static HB_Error Load_AttachList( HB_AttachList* al,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_AttachPoint* ap;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = al->GlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ al->AttachPoint = NULL;\r
+\r
+ if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) )\r
+ goto Fail2;\r
+\r
+ ap = al->AttachPoint;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_AttachPoint( &ap[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ al->loaded = TRUE;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_AttachPoint( &ap[m] );\r
+\r
+ FREE( ap );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &al->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_AttachList( HB_AttachList* al)\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_AttachPoint* ap;\r
+\r
+\r
+ if ( !al->loaded )\r
+ return;\r
+\r
+ if ( al->AttachPoint )\r
+ {\r
+ count = al->GlyphCount;\r
+ ap = al->AttachPoint;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_AttachPoint( &ap[n] );\r
+\r
+ FREE( ap );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &al->Coverage );\r
+}\r
+\r
+\r
+\r
+/*********************************\r
+ * LigCaretList related functions\r
+ *********************************/\r
+\r
+\r
+/* CaretValueFormat1 */\r
+/* CaretValueFormat2 */\r
+/* CaretValueFormat3 */\r
+/* CaretValueFormat4 */\r
+\r
+static HB_Error Load_CaretValue( HB_CaretValue* cv,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cv->CaretValueFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( cv->CaretValueFormat )\r
+ {\r
+ case 1:\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cv->cvf.cvf1.Coordinate = GET_Short();\r
+\r
+ FORGET_Frame();\r
+\r
+ break;\r
+\r
+ case 2:\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cv->cvf.cvf2.CaretValuePoint = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ break;\r
+\r
+ case 3:\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ cv->cvf.cvf3.Coordinate = GET_Short();\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device,\r
+ stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ break;\r
+\r
+ case 4:\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cv->cvf.cvf4.IdCaretValue = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_CaretValue( HB_CaretValue* cv)\r
+{\r
+ if ( cv->CaretValueFormat == 3 )\r
+ _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device );\r
+}\r
+\r
+\r
+/* LigGlyph */\r
+\r
+static HB_Error Load_LigGlyph( HB_LigGlyph* lg,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_CaretValue* cv;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = lg->CaretCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ lg->CaretValue = NULL;\r
+\r
+ if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) )\r
+ return error;\r
+\r
+ cv = lg->CaretValue;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_CaretValue( &cv[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_CaretValue( &cv[m] );\r
+\r
+ FREE( cv );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_LigGlyph( HB_LigGlyph* lg)\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_CaretValue* cv;\r
+\r
+\r
+ if ( lg->CaretValue )\r
+ {\r
+ count = lg->CaretCount;\r
+ cv = lg->CaretValue;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_CaretValue( &cv[n] );\r
+\r
+ FREE( cv );\r
+ }\r
+}\r
+\r
+\r
+/* LigCaretList */\r
+\r
+static HB_Error Load_LigCaretList( HB_LigCaretList* lcl,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort m, n, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_LigGlyph* lg;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = lcl->LigGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ lcl->LigGlyph = NULL;\r
+\r
+ if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) )\r
+ goto Fail2;\r
+\r
+ lg = lcl->LigGlyph;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_LigGlyph( &lg[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ lcl->loaded = TRUE;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_LigGlyph( &lg[m] );\r
+\r
+ FREE( lg );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &lcl->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_LigCaretList( HB_LigCaretList* lcl )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_LigGlyph* lg;\r
+\r
+\r
+ if ( !lcl->loaded )\r
+ return;\r
+\r
+ if ( lcl->LigGlyph )\r
+ {\r
+ count = lcl->LigGlyphCount;\r
+ lg = lcl->LigGlyph;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_LigGlyph( &lg[n] );\r
+\r
+ FREE( lg );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &lcl->Coverage );\r
+}\r
+\r
+\r
+\r
+/***********\r
+ * GDEF API\r
+ ***********/\r
+\r
+\r
+static HB_UShort Get_New_Class( HB_GDEFHeader* gdef,\r
+ HB_UShort glyphID,\r
+ HB_UShort index )\r
+{\r
+ HB_UShort glyph_index, array_index, count;\r
+ HB_UShort byte, bits;\r
+ \r
+ HB_ClassRangeRecord* gcrr;\r
+ HB_UShort** ngc;\r
+\r
+\r
+ if ( glyphID >= gdef->LastGlyph )\r
+ return 0;\r
+\r
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;\r
+ gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;\r
+ ngc = gdef->NewGlyphClasses;\r
+\r
+ if ( index < count && glyphID < gcrr[index].Start )\r
+ {\r
+ array_index = index;\r
+ if ( index == 0 )\r
+ glyph_index = glyphID;\r
+ else\r
+ glyph_index = glyphID - gcrr[index - 1].End - 1;\r
+ }\r
+ else\r
+ {\r
+ array_index = index + 1;\r
+ glyph_index = glyphID - gcrr[index].End - 1;\r
+ }\r
+\r
+ byte = ngc[array_index][glyph_index / 4];\r
+ bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );\r
+\r
+ return bits & 0x000F;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,\r
+ HB_UShort glyphID,\r
+ HB_UShort* property )\r
+{\r
+ HB_UShort klass = 0, index = 0; /* shut compiler up */\r
+\r
+ HB_Error error;\r
+\r
+\r
+ if ( !gdef || !property )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ /* first, we check for mark attach classes */\r
+\r
+ if ( gdef->MarkAttachClassDef.loaded )\r
+ {\r
+ error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &klass, &index );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+ if ( !error )\r
+ {\r
+ *property = klass << 8;\r
+ return HB_Err_Ok;\r
+ }\r
+ }\r
+\r
+ error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &klass, &index );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ /* if we have a constructed klass table, check whether additional\r
+ values have been assigned */\r
+\r
+ if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses )\r
+ klass = Get_New_Class( gdef, glyphID, index );\r
+\r
+ switch ( klass )\r
+ {\r
+ default:\r
+ case UNCLASSIFIED_GLYPH:\r
+ *property = 0;\r
+ break;\r
+\r
+ case SIMPLE_GLYPH:\r
+ *property = HB_GDEF_BASE_GLYPH;\r
+ break;\r
+\r
+ case LIGATURE_GLYPH:\r
+ *property = HB_GDEF_LIGATURE;\r
+ break;\r
+\r
+ case MARK_GLYPH:\r
+ *property = HB_GDEF_MARK;\r
+ break;\r
+\r
+ case COMPONENT_GLYPH:\r
+ *property = HB_GDEF_COMPONENT;\r
+ break;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static HB_Error Make_ClassRange( HB_ClassDefinition* cd,\r
+ HB_UShort start,\r
+ HB_UShort end,\r
+ HB_UShort klass )\r
+{\r
+ HB_Error error;\r
+ HB_UShort index;\r
+\r
+ HB_ClassDefFormat2* cdf2;\r
+ HB_ClassRangeRecord* crr;\r
+\r
+\r
+ cdf2 = &cd->cd.cd2;\r
+\r
+ if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,\r
+ cdf2->ClassRangeCount + 1 ,\r
+ HB_ClassRangeRecord ) )\r
+ return error;\r
+\r
+ cdf2->ClassRangeCount++;\r
+\r
+ crr = cdf2->ClassRangeRecord;\r
+ index = cdf2->ClassRangeCount - 1;\r
+\r
+ crr[index].Start = start;\r
+ crr[index].End = end;\r
+ crr[index].Class = klass;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,\r
+ HB_UShort num_glyphs,\r
+ HB_UShort glyph_count,\r
+ HB_UShort* glyph_array,\r
+ HB_UShort* class_array )\r
+{\r
+ HB_UShort start, curr_glyph, curr_class;\r
+ HB_UShort n, m, count;\r
+ HB_Error error;\r
+\r
+ HB_ClassDefinition* gcd;\r
+ HB_ClassRangeRecord* gcrr;\r
+ HB_UShort** ngc;\r
+\r
+\r
+ if ( !gdef || !glyph_array || !class_array )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ gcd = &gdef->GlyphClassDef;\r
+\r
+ /* We build a format 2 table */\r
+\r
+ gcd->ClassFormat = 2;\r
+\r
+ gcd->cd.cd2.ClassRangeCount = 0;\r
+ gcd->cd.cd2.ClassRangeRecord = NULL;\r
+\r
+ start = glyph_array[0];\r
+ curr_class = class_array[0];\r
+ curr_glyph = start;\r
+\r
+ if ( curr_class >= 5 )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_Argument);\r
+ goto Fail4;\r
+ }\r
+\r
+ glyph_count--;\r
+\r
+ for ( n = 0; n < glyph_count + 1; n++ )\r
+ {\r
+ if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )\r
+ {\r
+ if ( n == glyph_count )\r
+ {\r
+ if ( ( error = Make_ClassRange( gcd, start,\r
+ curr_glyph,\r
+ curr_class) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ }\r
+ else\r
+ {\r
+ if ( curr_glyph == 0xFFFF )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_Argument);\r
+ goto Fail3;\r
+ }\r
+ else\r
+ curr_glyph++;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if ( ( error = Make_ClassRange( gcd, start,\r
+ curr_glyph - 1,\r
+ curr_class) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+\r
+ if ( curr_glyph > glyph_array[n] )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_Argument);\r
+ goto Fail3;\r
+ }\r
+\r
+ start = glyph_array[n];\r
+ curr_class = class_array[n];\r
+ curr_glyph = start;\r
+\r
+ if ( curr_class >= 5 )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_Argument);\r
+ goto Fail3;\r
+ }\r
+\r
+ if ( n == glyph_count )\r
+ {\r
+ if ( ( error = Make_ClassRange( gcd, start,\r
+ curr_glyph,\r
+ curr_class) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ }\r
+ else\r
+ {\r
+ if ( curr_glyph == 0xFFFF )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_Argument);\r
+ goto Fail3;\r
+ }\r
+ else\r
+ curr_glyph++;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* now prepare the arrays for klass values assigned during the lookup\r
+ process */\r
+\r
+ if ( ALLOC_ARRAY( gdef->NewGlyphClasses,\r
+ gcd->cd.cd2.ClassRangeCount + 1, HB_UShort* ) )\r
+ goto Fail3;\r
+\r
+ count = gcd->cd.cd2.ClassRangeCount;\r
+ gcrr = gcd->cd.cd2.ClassRangeRecord;\r
+ ngc = gdef->NewGlyphClasses;\r
+\r
+ /* We allocate arrays for all glyphs not covered by the klass range\r
+ records. Each element holds four klass values. */\r
+\r
+ if ( count > 0 )\r
+ {\r
+ if ( gcrr[0].Start )\r
+ {\r
+ if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, HB_UShort ) )\r
+ goto Fail2;\r
+ }\r
+\r
+ for ( n = 1; n < count; n++ )\r
+ {\r
+ if ( gcrr[n].Start - gcrr[n - 1].End > 1 )\r
+ if ( ALLOC_ARRAY( ngc[n],\r
+ ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4,\r
+ HB_UShort ) )\r
+ goto Fail1;\r
+ }\r
+\r
+ if ( gcrr[count - 1].End != num_glyphs - 1 )\r
+ {\r
+ if ( ALLOC_ARRAY( ngc[count],\r
+ ( num_glyphs - gcrr[count - 1].End + 2 ) / 4,\r
+ HB_UShort ) )\r
+ goto Fail1;\r
+ }\r
+ }\r
+ else if ( num_glyphs > 0 )\r
+ {\r
+ if ( ALLOC_ARRAY( ngc[count],\r
+ ( num_glyphs + 3 ) / 4,\r
+ HB_UShort ) )\r
+ goto Fail2;\r
+ }\r
+ \r
+ gdef->LastGlyph = num_glyphs - 1;\r
+\r
+ gdef->MarkAttachClassDef_offset = 0L;\r
+ gdef->MarkAttachClassDef.loaded = FALSE;\r
+\r
+ gcd->loaded = TRUE;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ FREE( ngc[m] );\r
+\r
+Fail2:\r
+ FREE( gdef->NewGlyphClasses );\r
+\r
+Fail3:\r
+ FREE( gcd->cd.cd2.ClassRangeRecord );\r
+\r
+Fail4:\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_NewGlyphClasses( HB_GDEFHeader* gdef )\r
+{\r
+ HB_UShort** ngc;\r
+ HB_UShort n, count;\r
+\r
+\r
+ if ( gdef->NewGlyphClasses )\r
+ {\r
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1;\r
+ ngc = gdef->NewGlyphClasses;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ FREE( ngc[n] );\r
+\r
+ FREE( ngc );\r
+ }\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,\r
+ HB_UShort glyphID,\r
+ HB_UShort property )\r
+{\r
+ HB_Error error;\r
+ HB_UShort klass, new_class, index = 0; /* shut compiler up */\r
+ HB_UShort byte, bits, mask;\r
+ HB_UShort array_index, glyph_index, count;\r
+\r
+ HB_ClassRangeRecord* gcrr;\r
+ HB_UShort** ngc;\r
+\r
+\r
+ error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &klass, &index );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ /* we don't accept glyphs covered in `GlyphClassDef' */\r
+\r
+ if ( !error )\r
+ return HB_Err_Not_Covered;\r
+\r
+ switch ( property )\r
+ {\r
+ case 0:\r
+ new_class = UNCLASSIFIED_GLYPH;\r
+ break;\r
+\r
+ case HB_GDEF_BASE_GLYPH:\r
+ new_class = SIMPLE_GLYPH;\r
+ break;\r
+\r
+ case HB_GDEF_LIGATURE:\r
+ new_class = LIGATURE_GLYPH;\r
+ break;\r
+\r
+ case HB_GDEF_MARK:\r
+ new_class = MARK_GLYPH;\r
+ break;\r
+\r
+ case HB_GDEF_COMPONENT:\r
+ new_class = COMPONENT_GLYPH;\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+ }\r
+\r
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;\r
+ gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;\r
+ ngc = gdef->NewGlyphClasses;\r
+\r
+ if ( index < count && glyphID < gcrr[index].Start )\r
+ {\r
+ array_index = index;\r
+ if ( index == 0 )\r
+ glyph_index = glyphID;\r
+ else\r
+ glyph_index = glyphID - gcrr[index - 1].End - 1;\r
+ }\r
+ else\r
+ {\r
+ array_index = index + 1;\r
+ glyph_index = glyphID - gcrr[index].End - 1;\r
+ }\r
+\r
+ byte = ngc[array_index][glyph_index / 4];\r
+ bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );\r
+ klass = bits & 0x000F;\r
+\r
+ /* we don't overwrite existing entries */\r
+\r
+ if ( !klass )\r
+ {\r
+ bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 );\r
+ mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) );\r
+\r
+ ngc[array_index][glyph_index / 4] &= mask;\r
+ ngc[array_index][glyph_index / 4] |= bits;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GDEF_Check_Property( HB_GDEFHeader* gdef,\r
+ HB_GlyphItem gitem,\r
+ HB_UShort flags,\r
+ HB_UShort* property )\r
+{\r
+ HB_Error error;\r
+\r
+ if ( gdef )\r
+ {\r
+ HB_UShort basic_glyph_class;\r
+ HB_UShort desired_attachment_class;\r
+\r
+ if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN )\r
+ {\r
+ error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ *property = gitem->gproperties;\r
+\r
+ /* If the glyph was found in the MarkAttachmentClass table,\r
+ * then that klass value is the high byte of the result,\r
+ * otherwise the low byte contains the basic type of the glyph\r
+ * as defined by the GlyphClassDef table.\r
+ */\r
+ if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )\r
+ basic_glyph_class = HB_GDEF_MARK;\r
+ else\r
+ basic_glyph_class = *property;\r
+\r
+ /* Return Not_Covered, if, for example, basic_glyph_class\r
+ * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES\r
+ */\r
+ if ( flags & basic_glyph_class )\r
+ return HB_Err_Not_Covered;\r
+ \r
+ /* The high byte of LookupFlags has the meaning\r
+ * "ignore marks of attachment type different than\r
+ * the attachment type specified."\r
+ */\r
+ desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS;\r
+ if ( desired_attachment_class )\r
+ {\r
+ if ( basic_glyph_class == HB_GDEF_MARK &&\r
+ *property != desired_attachment_class )\r
+ return HB_Err_Not_Covered;\r
+ }\r
+ } else {\r
+ *property = 0;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,\r
+ HB_Stream stream,\r
+ HB_Lookup* lo,\r
+ HB_UShort num_lookups)\r
+{\r
+ HB_Error error = HB_Err_Ok;\r
+ HB_UShort i;\r
+\r
+ /* We now check the LookupFlags for values larger than 0xFF to find\r
+ out whether we need to load the `MarkAttachClassDef' field of the\r
+ GDEF table -- this hack is necessary for OpenType 1.2 tables since\r
+ the version field of the GDEF table hasn't been incremented.\r
+\r
+ For constructed GDEF tables, we only load it if\r
+ `MarkAttachClassDef_offset' is not zero (nevertheless, a build of\r
+ a constructed mark attach table is not supported currently). */\r
+\r
+ if ( gdef &&\r
+ gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )\r
+ {\r
+ for ( i = 0; i < num_lookups; i++ )\r
+ {\r
+\r
+ if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )\r
+ {\r
+ if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||\r
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,\r
+ 256, stream ) ) != HB_Err_Ok )\r
+ goto Done;\r
+\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+Done:\r
+ return error;\r
+}\r
+\r
+/* END */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ * Copyright (C) 2007 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Behdad Esfahbod\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-gpos-private.h"\r
+#include "harfbuzz-open-private.h"\r
+#include "harfbuzz-gdef-private.h"\r
+#include "harfbuzz-shaper.h"\r
+\r
+struct GPOS_Instance_\r
+{\r
+ HB_GPOSHeader* gpos;\r
+ HB_Font font;\r
+ HB_Bool dvi;\r
+ HB_UShort load_flags; /* how the glyph should be loaded */\r
+ HB_Bool r2l;\r
+\r
+ HB_UShort last; /* the last valid glyph -- used\r
+ with cursive positioning */\r
+ HB_Fixed anchor_x; /* the coordinates of the anchor point */\r
+ HB_Fixed anchor_y; /* of the last valid glyph */\r
+};\r
+\r
+typedef struct GPOS_Instance_ GPOS_Instance;\r
+\r
+\r
+static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,\r
+ HB_UShort lookup_index,\r
+ HB_Buffer buffer,\r
+ HB_UShort context_length,\r
+ int nesting_level );\r
+\r
+\r
+\r
+/* the client application must replace this with something more\r
+ meaningful if multiple master fonts are to be supported. */\r
+\r
+static HB_Error default_mmfunc( HB_Font font,\r
+ HB_UShort metric_id,\r
+ HB_Fixed* metric_value,\r
+ void* data )\r
+{\r
+ HB_UNUSED(font);\r
+ HB_UNUSED(metric_id);\r
+ HB_UNUSED(metric_value);\r
+ HB_UNUSED(data);\r
+ return ERR_HB(HB_Err_Not_Covered); /* ERR_HB() call intended */\r
+}\r
+\r
+\r
+\r
+HB_Error HB_Load_GPOS_Table( HB_Stream stream, \r
+ HB_GPOSHeader** retptr,\r
+ HB_GDEFHeader* gdef,\r
+ HB_Stream gdefStream )\r
+{\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_GPOSHeader* gpos;\r
+\r
+ HB_Error error;\r
+\r
+\r
+ if ( !retptr )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ if ( GOTO_Table( TTAG_GPOS ) )\r
+ return error;\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ALLOC ( gpos, sizeof( *gpos ), HB_GPOSHeader* ) )\r
+ return error;\r
+\r
+ gpos->mmfunc = default_mmfunc;\r
+\r
+ /* skip version */\r
+\r
+ if ( FILE_Seek( base_offset + 4L ) ||\r
+ ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail4;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_FeatureList( &gpos->FeatureList,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_LookupList( &gpos->LookupList,\r
+ stream, HB_Type_GPOS ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+\r
+ gpos->gdef = gdef; /* can be NULL */\r
+\r
+ if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,\r
+ gpos->LookupList.Lookup,\r
+ gpos->LookupList.LookupCount ) ) )\r
+ goto Fail1;\r
+\r
+ *retptr = gpos;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_FeatureList( &gpos->FeatureList );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_ScriptList( &gpos->ScriptList );\r
+\r
+Fail4:\r
+ FREE( gpos );\r
+\r
+ return error;\r
+}\r
+\r
+\r
+HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos )\r
+{\r
+ _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );\r
+ _HB_OPEN_Free_FeatureList( &gpos->FeatureList );\r
+ _HB_OPEN_Free_ScriptList( &gpos->ScriptList );\r
+\r
+ FREE( gpos );\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/*****************************\r
+ * SubTable related functions\r
+ *****************************/\r
+\r
+/* shared tables */\r
+\r
+/* ValueRecord */\r
+\r
+/* There is a subtle difference in the specs between a `table' and a\r
+ `record' -- offsets for device tables in ValueRecords are taken from\r
+ the parent table and not the parent record. */\r
+\r
+static HB_Error Load_ValueRecord( HB_ValueRecord* vr,\r
+ HB_UShort format,\r
+ HB_UInt base_offset,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UInt cur_offset, new_offset;\r
+\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ vr->XPlacement = GET_Short();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->XPlacement = 0;\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ vr->YPlacement = GET_Short();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->YPlacement = 0;\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ vr->XAdvance = GET_Short();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->XAdvance = 0;\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ vr->YAdvance = GET_Short();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->YAdvance = 0;\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice,\r
+ stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ goto empty1;\r
+ }\r
+ else\r
+ {\r
+ empty1:\r
+ vr->XPlacementDevice.StartSize = 0;\r
+ vr->XPlacementDevice.EndSize = 0;\r
+ vr->XPlacementDevice.DeltaValue = NULL;\r
+ }\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ goto empty2;\r
+ }\r
+ else\r
+ {\r
+ empty2:\r
+ vr->YPlacementDevice.StartSize = 0;\r
+ vr->YPlacementDevice.EndSize = 0;\r
+ vr->YPlacementDevice.DeltaValue = NULL;\r
+ }\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ goto empty3;\r
+ }\r
+ else\r
+ {\r
+ empty3:\r
+ vr->XAdvanceDevice.StartSize = 0;\r
+ vr->XAdvanceDevice.EndSize = 0;\r
+ vr->XAdvanceDevice.DeltaValue = NULL;\r
+ }\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ goto empty4;\r
+ }\r
+ else\r
+ {\r
+ empty4:\r
+ vr->YAdvanceDevice.StartSize = 0;\r
+ vr->YAdvanceDevice.EndSize = 0;\r
+ vr->YAdvanceDevice.DeltaValue = NULL;\r
+ }\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ vr->XIdPlacement = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->XIdPlacement = 0;\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ vr->YIdPlacement = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->YIdPlacement = 0;\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ vr->XIdAdvance = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->XIdAdvance = 0;\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ vr->YIdAdvance = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ }\r
+ else\r
+ vr->YIdAdvance = 0;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ _HB_OPEN_Free_Device( &vr->YAdvanceDevice );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Device( &vr->XAdvanceDevice );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_Device( &vr->YPlacementDevice );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ValueRecord( HB_ValueRecord* vr,\r
+ HB_UShort format )\r
+{\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )\r
+ _HB_OPEN_Free_Device( &vr->YAdvanceDevice );\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )\r
+ _HB_OPEN_Free_Device( &vr->XAdvanceDevice );\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )\r
+ _HB_OPEN_Free_Device( &vr->YPlacementDevice );\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )\r
+ _HB_OPEN_Free_Device( &vr->XPlacementDevice );\r
+}\r
+\r
+\r
+static HB_Error Get_ValueRecord( GPOS_Instance* gpi,\r
+ HB_ValueRecord* vr,\r
+ HB_UShort format,\r
+ HB_Position gd )\r
+{\r
+ HB_Fixed value;\r
+ HB_Short pixel_value;\r
+ HB_Error error = HB_Err_Ok;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_UShort x_ppem, y_ppem;\r
+ HB_16Dot16 x_scale, y_scale;\r
+\r
+\r
+ if ( !format )\r
+ return HB_Err_Ok;\r
+\r
+ x_ppem = gpi->font->x_ppem;\r
+ y_ppem = gpi->font->y_ppem;\r
+ x_scale = gpi->font->x_scale;\r
+ y_scale = gpi->font->y_scale;\r
+\r
+ /* design units -> fractional pixel */\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )\r
+ gd->x_pos += x_scale * vr->XPlacement / 0x10000;\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )\r
+ gd->y_pos += y_scale * vr->YPlacement / 0x10000;\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )\r
+ gd->x_advance += x_scale * vr->XAdvance / 0x10000;\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )\r
+ gd->y_advance += y_scale * vr->YAdvance / 0x10000;\r
+\r
+ if ( !gpi->dvi )\r
+ {\r
+ /* pixel -> fractional pixel */\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )\r
+ {\r
+ _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );\r
+ gd->x_pos += pixel_value << 6;\r
+ }\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )\r
+ {\r
+ _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );\r
+ gd->y_pos += pixel_value << 6;\r
+ }\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )\r
+ {\r
+ _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );\r
+ gd->x_advance += pixel_value << 6;\r
+ }\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )\r
+ {\r
+ _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );\r
+ gd->y_advance += pixel_value << 6;\r
+ }\r
+ }\r
+\r
+ /* values returned from mmfunc() are already in fractional pixels */\r
+\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )\r
+ {\r
+ error = (gpos->mmfunc)( gpi->font, vr->XIdPlacement,\r
+ &value, gpos->data );\r
+ if ( error )\r
+ return error;\r
+ gd->x_pos += value;\r
+ }\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )\r
+ {\r
+ error = (gpos->mmfunc)( gpi->font, vr->YIdPlacement,\r
+ &value, gpos->data );\r
+ if ( error )\r
+ return error;\r
+ gd->y_pos += value;\r
+ }\r
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )\r
+ {\r
+ error = (gpos->mmfunc)( gpi->font, vr->XIdAdvance,\r
+ &value, gpos->data );\r
+ if ( error )\r
+ return error;\r
+ gd->x_advance += value;\r
+ }\r
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )\r
+ {\r
+ error = (gpos->mmfunc)( gpi->font, vr->YIdAdvance,\r
+ &value, gpos->data );\r
+ if ( error )\r
+ return error;\r
+ gd->y_advance += value;\r
+ }\r
+\r
+ return error;\r
+}\r
+\r
+\r
+/* AnchorFormat1 */\r
+/* AnchorFormat2 */\r
+/* AnchorFormat3 */\r
+/* AnchorFormat4 */\r
+\r
+static HB_Error Load_Anchor( HB_Anchor* an,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ an->PosFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( an->PosFormat )\r
+ {\r
+ case 1:\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ an->af.af1.XCoordinate = GET_Short();\r
+ an->af.af1.YCoordinate = GET_Short();\r
+\r
+ FORGET_Frame();\r
+ break;\r
+\r
+ case 2:\r
+ if ( ACCESS_Frame( 6L ) )\r
+ return error;\r
+\r
+ an->af.af2.XCoordinate = GET_Short();\r
+ an->af.af2.YCoordinate = GET_Short();\r
+ an->af.af2.AnchorPoint = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ break;\r
+\r
+ case 3:\r
+ if ( ACCESS_Frame( 6L ) )\r
+ return error;\r
+\r
+ an->af.af3.XCoordinate = GET_Short();\r
+ an->af.af3.YCoordinate = GET_Short();\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable,\r
+ stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ {\r
+ an->af.af3.XDeviceTable.StartSize = 0;\r
+ an->af.af3.XDeviceTable.EndSize = 0;\r
+ an->af.af3.XDeviceTable.DeltaValue = NULL;\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ {\r
+ an->af.af3.YDeviceTable.StartSize = 0;\r
+ an->af.af3.YDeviceTable.EndSize = 0;\r
+ an->af.af3.YDeviceTable.DeltaValue = NULL;\r
+ }\r
+ break;\r
+\r
+ case 4:\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ an->af.af4.XIdAnchor = GET_UShort();\r
+ an->af.af4.YIdAnchor = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_Anchor( HB_Anchor* an)\r
+{\r
+ if ( an->PosFormat == 3 )\r
+ {\r
+ _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable );\r
+ _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Get_Anchor( GPOS_Instance* gpi,\r
+ HB_Anchor* an,\r
+ HB_UShort glyph_index,\r
+ HB_Fixed* x_value,\r
+ HB_Fixed* y_value )\r
+{\r
+ HB_Error error = HB_Err_Ok;\r
+\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_UShort ap;\r
+\r
+ HB_Short pixel_value;\r
+\r
+ HB_UShort x_ppem, y_ppem;\r
+ HB_16Dot16 x_scale, y_scale;\r
+\r
+\r
+ x_ppem = gpi->font->x_ppem;\r
+ y_ppem = gpi->font->y_ppem;\r
+ x_scale = gpi->font->x_scale;\r
+ y_scale = gpi->font->y_scale;\r
+\r
+ switch ( an->PosFormat )\r
+ {\r
+ case 0:\r
+ /* The special case of an empty AnchorTable */\r
+ default:\r
+\r
+ return HB_Err_Not_Covered;\r
+\r
+ case 1:\r
+ *x_value = x_scale * an->af.af1.XCoordinate / 0x10000;\r
+ *y_value = y_scale * an->af.af1.YCoordinate / 0x10000;\r
+ break;\r
+\r
+ case 2:\r
+ if ( !gpi->dvi )\r
+ {\r
+ hb_uint32 n_points = 0;\r
+ ap = an->af.af2.AnchorPoint;\r
+ if (!gpi->font->klass->getPointInOutline)\r
+ goto no_contour_point;\r
+ error = gpi->font->klass->getPointInOutline(gpi->font, glyph_index, gpi->load_flags, ap, x_value, y_value, &n_points);\r
+ if (error)\r
+ return error;\r
+ /* if n_points is set to zero, we use the design coordinate value pair.\r
+ * This can happen e.g. for sbit glyphs. */\r
+ if (!n_points)\r
+ goto no_contour_point;\r
+ }\r
+ else\r
+ {\r
+ no_contour_point:\r
+ *x_value = x_scale * an->af.af3.XCoordinate / 0x10000;\r
+ *y_value = y_scale * an->af.af3.YCoordinate / 0x10000;\r
+ }\r
+ break;\r
+\r
+ case 3:\r
+ if ( !gpi->dvi )\r
+ {\r
+ _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );\r
+ *x_value = pixel_value << 6;\r
+ _HB_OPEN_Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value );\r
+ *y_value = pixel_value << 6;\r
+ }\r
+ else\r
+ *x_value = *y_value = 0;\r
+\r
+ *x_value += x_scale * an->af.af3.XCoordinate / 0x10000;\r
+ *y_value += y_scale * an->af.af3.YCoordinate / 0x10000;\r
+ break;\r
+\r
+ case 4:\r
+ error = (gpos->mmfunc)( gpi->font, an->af.af4.XIdAnchor,\r
+ x_value, gpos->data );\r
+ if ( error )\r
+ return error;\r
+\r
+ error = (gpos->mmfunc)( gpi->font, an->af.af4.YIdAnchor,\r
+ y_value, gpos->data );\r
+ if ( error )\r
+ return error;\r
+ break;\r
+ }\r
+\r
+ return error;\r
+}\r
+\r
+\r
+/* MarkArray */\r
+\r
+static HB_Error Load_MarkArray ( HB_MarkArray* ma,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_MarkRecord* mr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = ma->MarkCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ma->MarkRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ma->MarkRecord, count, HB_MarkRecord ) )\r
+ return error;\r
+\r
+ mr = ma->MarkRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 4L ) )\r
+ goto Fail;\r
+\r
+ mr[n].Class = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_Anchor( &mr[m].MarkAnchor );\r
+\r
+ FREE( mr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_MarkArray( HB_MarkArray* ma )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_MarkRecord* mr;\r
+\r
+\r
+ if ( ma->MarkRecord )\r
+ {\r
+ count = ma->MarkCount;\r
+ mr = ma->MarkRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_Anchor( &mr[n].MarkAnchor );\r
+\r
+ FREE( mr );\r
+ }\r
+}\r
+\r
+\r
+/* LookupType 1 */\r
+\r
+/* SinglePosFormat1 */\r
+/* SinglePosFormat2 */\r
+\r
+static HB_Error Load_SinglePos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_SinglePos* sp = &st->single;\r
+\r
+ HB_UShort n, m, count, format;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ValueRecord* vr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 6L ) )\r
+ return error;\r
+\r
+ sp->PosFormat = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ format = sp->ValueFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( !format )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ switch ( sp->PosFormat )\r
+ {\r
+ case 1:\r
+ error = Load_ValueRecord( &sp->spf.spf1.Value, format,\r
+ base_offset, stream );\r
+ if ( error )\r
+ goto Fail2;\r
+ break;\r
+\r
+ case 2:\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = sp->spf.spf2.ValueCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ sp->spf.spf2.Value = NULL;\r
+\r
+ if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, HB_ValueRecord ) )\r
+ goto Fail2;\r
+\r
+ vr = sp->spf.spf2.Value;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ error = Load_ValueRecord( &vr[n], format, base_offset, stream );\r
+ if ( error )\r
+ goto Fail1;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ValueRecord( &vr[m], format );\r
+\r
+ FREE( vr );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &sp->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_SinglePos( HB_GPOS_SubTable* st )\r
+{\r
+ HB_UShort n, count, format;\r
+ HB_SinglePos* sp = &st->single;\r
+\r
+ HB_ValueRecord* v;\r
+\r
+\r
+ format = sp->ValueFormat;\r
+\r
+ switch ( sp->PosFormat )\r
+ {\r
+ case 1:\r
+ Free_ValueRecord( &sp->spf.spf1.Value, format );\r
+ break;\r
+\r
+ case 2:\r
+ if ( sp->spf.spf2.Value )\r
+ {\r
+ count = sp->spf.spf2.ValueCount;\r
+ v = sp->spf.spf2.Value;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ValueRecord( &v[n], format );\r
+\r
+ FREE( v );\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &sp->Coverage );\r
+}\r
+\r
+static HB_Error Lookup_SinglePos( GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_SinglePos* sp = &st->single;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ switch ( sp->PosFormat )\r
+ {\r
+ case 1:\r
+ error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,\r
+ sp->ValueFormat, POSITION( buffer->in_pos ) );\r
+ if ( error )\r
+ return error;\r
+ break;\r
+\r
+ case 2:\r
+ if ( index >= sp->spf.spf2.ValueCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+ error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],\r
+ sp->ValueFormat, POSITION( buffer->in_pos ) );\r
+ if ( error )\r
+ return error;\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+ }\r
+\r
+ (buffer->in_pos)++;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 2 */\r
+\r
+/* PairSet */\r
+\r
+static HB_Error Load_PairSet ( HB_PairSet* ps,\r
+ HB_UShort format1,\r
+ HB_UShort format2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt base_offset;\r
+\r
+ HB_PairValueRecord* pvr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = ps->PairValueCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ps->PairValueRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) )\r
+ return error;\r
+\r
+ pvr = ps->PairValueRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ pvr[n].SecondGlyph = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( format1 )\r
+ {\r
+ error = Load_ValueRecord( &pvr[n].Value1, format1,\r
+ base_offset, stream );\r
+ if ( error )\r
+ goto Fail;\r
+ }\r
+ if ( format2 )\r
+ {\r
+ error = Load_ValueRecord( &pvr[n].Value2, format2,\r
+ base_offset, stream );\r
+ if ( error )\r
+ {\r
+ if ( format1 )\r
+ Free_ValueRecord( &pvr[n].Value1, format1 );\r
+ goto Fail;\r
+ }\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ {\r
+ if ( format1 )\r
+ Free_ValueRecord( &pvr[m].Value1, format1 );\r
+ if ( format2 )\r
+ Free_ValueRecord( &pvr[m].Value2, format2 );\r
+ }\r
+\r
+ FREE( pvr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PairSet( HB_PairSet* ps,\r
+ HB_UShort format1,\r
+ HB_UShort format2 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_PairValueRecord* pvr;\r
+\r
+\r
+ if ( ps->PairValueRecord )\r
+ {\r
+ count = ps->PairValueCount;\r
+ pvr = ps->PairValueRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( format1 )\r
+ Free_ValueRecord( &pvr[n].Value1, format1 );\r
+ if ( format2 )\r
+ Free_ValueRecord( &pvr[n].Value2, format2 );\r
+ }\r
+\r
+ FREE( pvr );\r
+ }\r
+}\r
+\r
+\r
+/* PairPosFormat1 */\r
+\r
+static HB_Error Load_PairPos1( HB_PairPosFormat1* ppf1,\r
+ HB_UShort format1,\r
+ HB_UShort format2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_PairSet* ps;\r
+\r
+\r
+ base_offset = FILE_Pos() - 8L;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = ppf1->PairSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ppf1->PairSet = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) )\r
+ return error;\r
+\r
+ ps = ppf1->PairSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_PairSet( &ps[n], format1,\r
+ format2, stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_PairSet( &ps[m], format1, format2 );\r
+\r
+ FREE( ps );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PairPos1( HB_PairPosFormat1* ppf1,\r
+ HB_UShort format1,\r
+ HB_UShort format2 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_PairSet* ps;\r
+\r
+\r
+ if ( ppf1->PairSet )\r
+ {\r
+ count = ppf1->PairSetCount;\r
+ ps = ppf1->PairSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_PairSet( &ps[n], format1, format2 );\r
+\r
+ FREE( ps );\r
+ }\r
+}\r
+\r
+\r
+/* PairPosFormat2 */\r
+\r
+static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,\r
+ HB_UShort format1,\r
+ HB_UShort format2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort m, n, k, count1, count2;\r
+ HB_UInt cur_offset, new_offset1, new_offset2, base_offset;\r
+\r
+ HB_Class1Record* c1r;\r
+ HB_Class2Record* c2r;\r
+\r
+\r
+ base_offset = FILE_Pos() - 8L;\r
+\r
+ if ( ACCESS_Frame( 8L ) )\r
+ return error;\r
+\r
+ new_offset1 = GET_UShort() + base_offset;\r
+ new_offset2 = GET_UShort() + base_offset;\r
+\r
+ /* `Class1Count' and `Class2Count' are the upper limits for klass\r
+ values, thus we read it now to make additional safety checks. */\r
+\r
+ count1 = ppf2->Class1Count = GET_UShort();\r
+ count2 = ppf2->Class2Count = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset1 ) ||\r
+ ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1,\r
+ stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ if ( FILE_Seek( new_offset2 ) ||\r
+ ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ ppf2->Class1Record = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) )\r
+ goto Fail2;\r
+\r
+ c1r = ppf2->Class1Record;\r
+\r
+ for ( m = 0; m < count1; m++ )\r
+ {\r
+ c1r[m].Class2Record = NULL;\r
+\r
+ if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )\r
+ goto Fail1;\r
+\r
+ c2r = c1r[m].Class2Record;\r
+\r
+ for ( n = 0; n < count2; n++ )\r
+ {\r
+ if ( format1 )\r
+ {\r
+ error = Load_ValueRecord( &c2r[n].Value1, format1,\r
+ base_offset, stream );\r
+ if ( error )\r
+ goto Fail0;\r
+ }\r
+ if ( format2 )\r
+ {\r
+ error = Load_ValueRecord( &c2r[n].Value2, format2,\r
+ base_offset, stream );\r
+ if ( error )\r
+ {\r
+ if ( format1 )\r
+ Free_ValueRecord( &c2r[n].Value1, format1 );\r
+ goto Fail0;\r
+ }\r
+ }\r
+ }\r
+\r
+ continue;\r
+\r
+ Fail0:\r
+ for ( k = 0; k < n; k++ )\r
+ {\r
+ if ( format1 )\r
+ Free_ValueRecord( &c2r[k].Value1, format1 );\r
+ if ( format2 )\r
+ Free_ValueRecord( &c2r[k].Value2, format2 );\r
+ }\r
+ goto Fail1;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( k = 0; k < m; k++ )\r
+ {\r
+ c2r = c1r[k].Class2Record;\r
+\r
+ for ( n = 0; n < count2; n++ )\r
+ {\r
+ if ( format1 )\r
+ Free_ValueRecord( &c2r[n].Value1, format1 );\r
+ if ( format2 )\r
+ Free_ValueRecord( &c2r[n].Value2, format2 );\r
+ }\r
+\r
+ FREE( c2r );\r
+ }\r
+\r
+ FREE( c1r );\r
+Fail2:\r
+\r
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PairPos2( HB_PairPosFormat2* ppf2,\r
+ HB_UShort format1,\r
+ HB_UShort format2)\r
+{\r
+ HB_UShort m, n, count1, count2;\r
+\r
+ HB_Class1Record* c1r;\r
+ HB_Class2Record* c2r;\r
+\r
+\r
+ if ( ppf2->Class1Record )\r
+ {\r
+ c1r = ppf2->Class1Record;\r
+ count1 = ppf2->Class1Count;\r
+ count2 = ppf2->Class2Count;\r
+\r
+ for ( m = 0; m < count1; m++ )\r
+ {\r
+ c2r = c1r[m].Class2Record;\r
+\r
+ for ( n = 0; n < count2; n++ )\r
+ {\r
+ if ( format1 )\r
+ Free_ValueRecord( &c2r[n].Value1, format1 );\r
+ if ( format2 )\r
+ Free_ValueRecord( &c2r[n].Value2, format2 );\r
+ }\r
+\r
+ FREE( c2r );\r
+ }\r
+\r
+ FREE( c1r );\r
+\r
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );\r
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Load_PairPos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_PairPos* pp = &st->pair;\r
+\r
+ HB_UShort format1, format2;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 8L ) )\r
+ return error;\r
+\r
+ pp->PosFormat = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ format1 = pp->ValueFormat1 = GET_UShort();\r
+ format2 = pp->ValueFormat2 = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ switch ( pp->PosFormat )\r
+ {\r
+ case 1:\r
+ error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );\r
+ if ( error )\r
+ goto Fail;\r
+ break;\r
+\r
+ case 2:\r
+ error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );\r
+ if ( error )\r
+ goto Fail;\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ _HB_OPEN_Free_Coverage( &pp->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PairPos( HB_GPOS_SubTable* st )\r
+{\r
+ HB_UShort format1, format2;\r
+ HB_PairPos* pp = &st->pair;\r
+\r
+\r
+ format1 = pp->ValueFormat1;\r
+ format2 = pp->ValueFormat2;\r
+\r
+ switch ( pp->PosFormat )\r
+ {\r
+ case 1:\r
+ Free_PairPos1( &pp->ppf.ppf1, format1, format2 );\r
+ break;\r
+\r
+ case 2:\r
+ Free_PairPos2( &pp->ppf.ppf2, format1, format2 );\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &pp->Coverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_PairPos1( GPOS_Instance* gpi,\r
+ HB_PairPosFormat1* ppf1,\r
+ HB_Buffer buffer,\r
+ HB_UInt first_pos,\r
+ HB_UShort index,\r
+ HB_UShort format1,\r
+ HB_UShort format2 )\r
+{\r
+ HB_Error error;\r
+ HB_UShort numpvr, glyph2;\r
+\r
+ HB_PairValueRecord* pvr;\r
+\r
+\r
+ if ( index >= ppf1->PairSetCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ pvr = ppf1->PairSet[index].PairValueRecord;\r
+ if ( !pvr )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ glyph2 = IN_CURGLYPH();\r
+\r
+ for ( numpvr = ppf1->PairSet[index].PairValueCount;\r
+ numpvr;\r
+ numpvr--, pvr++ )\r
+ {\r
+ if ( glyph2 == pvr->SecondGlyph )\r
+ {\r
+ error = Get_ValueRecord( gpi, &pvr->Value1, format1,\r
+ POSITION( first_pos ) );\r
+ if ( error )\r
+ return error;\r
+ return Get_ValueRecord( gpi, &pvr->Value2, format2,\r
+ POSITION( buffer->in_pos ) );\r
+ }\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+static HB_Error Lookup_PairPos2( GPOS_Instance* gpi,\r
+ HB_PairPosFormat2* ppf2,\r
+ HB_Buffer buffer,\r
+ HB_UInt first_pos,\r
+ HB_UShort format1,\r
+ HB_UShort format2 )\r
+{\r
+ HB_Error error;\r
+ HB_UShort cl1 = 0, cl2 = 0; /* shut compiler up */\r
+\r
+ HB_Class1Record* c1r;\r
+ HB_Class2Record* c2r;\r
+\r
+\r
+ error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),\r
+ &cl1, NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+ error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),\r
+ &cl2, NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ c1r = &ppf2->Class1Record[cl1];\r
+ if ( !c1r )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+ c2r = &c1r->Class2Record[cl2];\r
+\r
+ error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );\r
+ if ( error )\r
+ return error;\r
+ return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );\r
+}\r
+\r
+\r
+static HB_Error Lookup_PairPos( GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_Error error;\r
+ HB_UShort index, property;\r
+ HB_UInt first_pos;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_PairPos* pp = &st->pair;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( buffer->in_pos >= buffer->in_length - 1 )\r
+ return HB_Err_Not_Covered; /* Not enough glyphs in stream */\r
+\r
+ if ( context_length != 0xFFFF && context_length < 2 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ /* second glyph */\r
+\r
+ first_pos = buffer->in_pos;\r
+ (buffer->in_pos)++;\r
+\r
+ while ( CHECK_Property( gpos->gdef, IN_CURITEM(),\r
+ flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( buffer->in_pos == buffer->in_length )\r
+ {\r
+ buffer->in_pos = first_pos;\r
+ return HB_Err_Not_Covered;\r
+ }\r
+ (buffer->in_pos)++;\r
+\r
+ }\r
+\r
+ switch ( pp->PosFormat )\r
+ {\r
+ case 1:\r
+ error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,\r
+ first_pos, index,\r
+ pp->ValueFormat1, pp->ValueFormat2 );\r
+ break;\r
+\r
+ case 2:\r
+ error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,\r
+ pp->ValueFormat1, pp->ValueFormat2 );\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ /* if we don't have coverage for the second glyph don't skip it for\r
+ further lookups but reset in_pos back to the first_glyph and let\r
+ the caller in Do_String_Lookup increment in_pos */\r
+ if ( error == HB_Err_Not_Covered )\r
+ buffer->in_pos = first_pos;\r
+\r
+ /* adjusting the `next' glyph */\r
+\r
+ if ( pp->ValueFormat2 )\r
+ (buffer->in_pos)++;\r
+\r
+ return error;\r
+}\r
+\r
+\r
+/* LookupType 3 */\r
+\r
+/* CursivePosFormat1 */\r
+\r
+static HB_Error Load_CursivePos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_CursivePos* cp = &st->cursive;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_EntryExitRecord* eer;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ cp->PosFormat = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = cp->EntryExitCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cp->EntryExitRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) )\r
+ goto Fail2;\r
+\r
+ eer = cp->EntryExitRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ HB_UInt entry_offset;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ entry_offset = new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Anchor( &eer[n].EntryAnchor,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ eer[n].EntryAnchor.PosFormat = 0;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Anchor( &eer[n].ExitAnchor,\r
+ stream ) ) != HB_Err_Ok )\r
+ {\r
+ if ( entry_offset )\r
+ Free_Anchor( &eer[n].EntryAnchor );\r
+ goto Fail1;\r
+ }\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ eer[n].ExitAnchor.PosFormat = 0;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ {\r
+ Free_Anchor( &eer[m].EntryAnchor );\r
+ Free_Anchor( &eer[m].ExitAnchor );\r
+ }\r
+\r
+ FREE( eer );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &cp->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_CursivePos( HB_GPOS_SubTable* st )\r
+{\r
+ HB_UShort n, count;\r
+ HB_CursivePos* cp = &st->cursive;\r
+\r
+ HB_EntryExitRecord* eer;\r
+\r
+\r
+ if ( cp->EntryExitRecord )\r
+ {\r
+ count = cp->EntryExitCount;\r
+ eer = cp->EntryExitRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ Free_Anchor( &eer[n].EntryAnchor );\r
+ Free_Anchor( &eer[n].ExitAnchor );\r
+ }\r
+\r
+ FREE( eer );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &cp->Coverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_CursivePos( GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_CursivePos* cp = &st->cursive;\r
+\r
+ HB_EntryExitRecord* eer;\r
+ HB_Fixed entry_x, entry_y;\r
+ HB_Fixed exit_x, exit_y;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ {\r
+ gpi->last = 0xFFFF;\r
+ return HB_Err_Not_Covered;\r
+ }\r
+\r
+ /* Glyphs not having the right GDEF properties will be ignored, i.e.,\r
+ gpi->last won't be reset (contrary to user defined properties). */\r
+\r
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ /* We don't handle mark glyphs here. According to Andrei, this isn't\r
+ possible, but who knows... */\r
+\r
+ if ( property == HB_GDEF_MARK )\r
+ {\r
+ gpi->last = 0xFFFF;\r
+ return HB_Err_Not_Covered;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ {\r
+ gpi->last = 0xFFFF;\r
+ return error;\r
+ }\r
+\r
+ if ( index >= cp->EntryExitCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ eer = &cp->EntryExitRecord[index];\r
+\r
+ /* Now comes the messiest part of the whole OpenType\r
+ specification. At first glance, cursive connections seem easy\r
+ to understand, but there are pitfalls! The reason is that\r
+ the specs don't mention how to compute the advance values\r
+ resp. glyph offsets. I was told it would be an omission, to\r
+ be fixed in the next OpenType version... Again many thanks to\r
+ Andrei Burago <andreib@microsoft.com> for clarifications.\r
+\r
+ Consider the following example:\r
+\r
+ | xadv1 |\r
+ +---------+\r
+ | |\r
+ +-----+--+ 1 |\r
+ | | .| |\r
+ | 0+--+------+\r
+ | 2 |\r
+ | |\r
+ 0+--------+\r
+ | xadv2 |\r
+\r
+ glyph1: advance width = 12\r
+ anchor point = (3,1)\r
+\r
+ glyph2: advance width = 11\r
+ anchor point = (9,4)\r
+\r
+ LSB is 1 for both glyphs (so the boxes drawn above are glyph\r
+ bboxes). Writing direction is R2L; `0' denotes the glyph's\r
+ coordinate origin.\r
+\r
+ Now the surprising part: The advance width of the *left* glyph\r
+ (resp. of the *bottom* glyph) will be modified, no matter\r
+ whether the writing direction is L2R or R2L (resp. T2B or\r
+ B2T)! This assymetry is caused by the fact that the glyph's\r
+ coordinate origin is always the lower left corner for all\r
+ writing directions.\r
+\r
+ Continuing the above example, we can compute the new\r
+ (horizontal) advance width of glyph2 as\r
+\r
+ 9 - 3 = 6 ,\r
+\r
+ and the new vertical offset of glyph2 as\r
+\r
+ 1 - 4 = -3 .\r
+\r
+\r
+ Vertical writing direction is far more complicated:\r
+\r
+ a) Assuming that we recompute the advance height of the lower glyph:\r
+\r
+ --\r
+ +---------+\r
+ -- | |\r
+ +-----+--+ 1 | yadv1\r
+ | | .| |\r
+ yadv2 | 0+--+------+ -- BSB1 --\r
+ | 2 | -- -- y_offset\r
+ | |\r
+ BSB2 -- 0+--------+ --\r
+ -- --\r
+\r
+ glyph1: advance height = 6\r
+ anchor point = (3,1)\r
+\r
+ glyph2: advance height = 7\r
+ anchor point = (9,4)\r
+\r
+ TSB is 1 for both glyphs; writing direction is T2B.\r
+\r
+\r
+ BSB1 = yadv1 - (TSB1 + ymax1)\r
+ BSB2 = yadv2 - (TSB2 + ymax2)\r
+ y_offset = y2 - y1\r
+\r
+ vertical advance width of glyph2\r
+ = y_offset + BSB2 - BSB1\r
+ = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))\r
+ = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)\r
+ = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1\r
+\r
+\r
+ b) Assuming that we recompute the advance height of the upper glyph:\r
+\r
+ -- --\r
+ +---------+ -- TSB1\r
+ -- -- | |\r
+ TSB2 -- +-----+--+ 1 | yadv1 ymax1\r
+ | | .| |\r
+ yadv2 | 0+--+------+ -- --\r
+ ymax2 | 2 | -- y_offset\r
+ | |\r
+ -- 0+--------+ --\r
+ --\r
+\r
+ glyph1: advance height = 6\r
+ anchor point = (3,1)\r
+\r
+ glyph2: advance height = 7\r
+ anchor point = (9,4)\r
+\r
+ TSB is 1 for both glyphs; writing direction is T2B.\r
+\r
+ y_offset = y2 - y1\r
+\r
+ vertical advance width of glyph2\r
+ = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)\r
+ = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2\r
+\r
+\r
+ Comparing a) with b) shows that b) is easier to compute. I'll wait\r
+ for a reply from Andrei to see what should really be implemented...\r
+\r
+ Since horizontal advance widths or vertical advance heights\r
+ can be used alone but not together, no ambiguity occurs. */\r
+\r
+ if ( gpi->last == 0xFFFF )\r
+ goto end;\r
+\r
+ /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor\r
+ table. */\r
+\r
+ error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),\r
+ &entry_x, &entry_y );\r
+ if ( error == HB_Err_Not_Covered )\r
+ goto end;\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( gpi->r2l )\r
+ {\r
+ POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;\r
+ POSITION( buffer->in_pos )->new_advance = TRUE;\r
+ }\r
+ else\r
+ {\r
+ POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;\r
+ POSITION( gpi->last )->new_advance = TRUE;\r
+ }\r
+\r
+ if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )\r
+ {\r
+ POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;\r
+ POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;\r
+ }\r
+ else\r
+ {\r
+ POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;\r
+ POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;\r
+ }\r
+\r
+end:\r
+ error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),\r
+ &exit_x, &exit_y );\r
+ if ( error == HB_Err_Not_Covered )\r
+ gpi->last = 0xFFFF;\r
+ else\r
+ {\r
+ gpi->last = buffer->in_pos;\r
+ gpi->anchor_x = exit_x;\r
+ gpi->anchor_y = exit_y;\r
+ }\r
+ if ( error )\r
+ return error;\r
+\r
+ (buffer->in_pos)++;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 4 */\r
+\r
+/* BaseArray */\r
+\r
+static HB_Error Load_BaseArray( HB_BaseArray* ba,\r
+ HB_UShort num_classes,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort m, n, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_BaseRecord *br;\r
+ HB_Anchor *ban, *bans;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = ba->BaseCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ba->BaseRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) )\r
+ return error;\r
+\r
+ br = ba->BaseRecord;\r
+\r
+ bans = NULL;\r
+\r
+ if ( ALLOC_ARRAY( bans, count * num_classes, HB_Anchor ) )\r
+ goto Fail;\r
+\r
+ for ( m = 0; m < count; m++ )\r
+ {\r
+ br[m].BaseAnchor = NULL;\r
+\r
+ ban = br[m].BaseAnchor = bans + m * num_classes;\r
+\r
+ for ( n = 0; n < num_classes; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if (new_offset == base_offset) {\r
+ /* XXX\r
+ * Doulos SIL Regular is buggy and has zero offsets here.\r
+ * Skip it\r
+ */\r
+ ban[n].PosFormat = 0;\r
+ continue;\r
+ }\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Anchor( &ban[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ FREE( bans );\r
+ FREE( br );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_BaseArray( HB_BaseArray* ba,\r
+ HB_UShort num_classes )\r
+{\r
+ HB_BaseRecord *br;\r
+ HB_Anchor *bans;\r
+\r
+ if ( ba->BaseRecord )\r
+ {\r
+ br = ba->BaseRecord;\r
+\r
+ if ( ba->BaseCount )\r
+ {\r
+ HB_UShort i, count;\r
+ count = num_classes * ba->BaseCount;\r
+ bans = br[0].BaseAnchor;\r
+ for (i = 0; i < count; i++)\r
+ Free_Anchor (&bans[i]);\r
+ FREE( bans );\r
+ }\r
+\r
+ FREE( br );\r
+ }\r
+}\r
+\r
+\r
+/* MarkBasePosFormat1 */\r
+\r
+static HB_Error Load_MarkBasePos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_MarkBasePos* mbp = &st->markbase;\r
+\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ mbp->PosFormat = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if (mbp->PosFormat != 1)\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ goto Fail2;\r
+\r
+ mbp->ClassCount = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ Free_MarkArray( &mbp->MarkArray );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_MarkBasePos( HB_GPOS_SubTable* st )\r
+{\r
+ HB_MarkBasePos* mbp = &st->markbase;\r
+\r
+ Free_BaseArray( &mbp->BaseArray, mbp->ClassCount );\r
+ Free_MarkArray( &mbp->MarkArray );\r
+ _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );\r
+ _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort i, j, mark_index, base_index, property, klass;\r
+ HB_Fixed x_mark_value, y_mark_value, x_base_value, y_base_value;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_MarkBasePos* mbp = &st->markbase;\r
+\r
+ HB_MarkArray* ma;\r
+ HB_BaseArray* ba;\r
+ HB_BaseRecord* br;\r
+ HB_Anchor* mark_anchor;\r
+ HB_Anchor* base_anchor;\r
+\r
+ HB_Position o;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(),\r
+ flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),\r
+ &mark_index );\r
+ if ( error )\r
+ return error;\r
+\r
+ /* now we search backwards for a non-mark glyph */\r
+\r
+ i = 1;\r
+ j = buffer->in_pos - 1;\r
+\r
+ while ( i <= buffer->in_pos )\r
+ {\r
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),\r
+ &property );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )\r
+ break;\r
+\r
+ i++;\r
+ j--;\r
+ }\r
+\r
+ /* The following assertion is too strong -- at least for mangal.ttf. */\r
+#if 0\r
+ if ( property != HB_GDEF_BASE_GLYPH )\r
+ return HB_Err_Not_Covered;\r
+#endif\r
+\r
+ if ( i > buffer->in_pos )\r
+ return HB_Err_Not_Covered;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),\r
+ &base_index );\r
+ if ( error )\r
+ return error;\r
+\r
+ ma = &mbp->MarkArray;\r
+\r
+ if ( mark_index >= ma->MarkCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ klass = ma->MarkRecord[mark_index].Class;\r
+ mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;\r
+\r
+ if ( klass >= mbp->ClassCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ ba = &mbp->BaseArray;\r
+\r
+ if ( base_index >= ba->BaseCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ br = &ba->BaseRecord[base_index];\r
+ base_anchor = &br->BaseAnchor[klass];\r
+\r
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),\r
+ &x_mark_value, &y_mark_value );\r
+ if ( error )\r
+ return error;\r
+\r
+ error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),\r
+ &x_base_value, &y_base_value );\r
+ if ( error )\r
+ return error;\r
+\r
+ /* anchor points are not cumulative */\r
+\r
+ o = POSITION( buffer->in_pos );\r
+\r
+ o->x_pos = x_base_value - x_mark_value;\r
+ o->y_pos = y_base_value - y_mark_value;\r
+ o->x_advance = 0;\r
+ o->y_advance = 0;\r
+ o->back = i;\r
+\r
+ (buffer->in_pos)++;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 5 */\r
+\r
+/* LigatureAttach */\r
+\r
+static HB_Error Load_LigatureAttach( HB_LigatureAttach* lat,\r
+ HB_UShort num_classes,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort m, n, k, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ComponentRecord* cr;\r
+ HB_Anchor* lan;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = lat->ComponentCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ lat->ComponentRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) )\r
+ return error;\r
+\r
+ cr = lat->ComponentRecord;\r
+\r
+ for ( m = 0; m < count; m++ )\r
+ {\r
+ cr[m].LigatureAnchor = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) )\r
+ goto Fail;\r
+\r
+ lan = cr[m].LigatureAnchor;\r
+\r
+ for ( n = 0; n < num_classes; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail0;\r
+\r
+ new_offset = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset )\r
+ {\r
+ new_offset += base_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Anchor( &lan[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail0;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ lan[n].PosFormat = 0;\r
+ }\r
+\r
+ continue;\r
+ Fail0:\r
+ for ( k = 0; k < n; k++ )\r
+ Free_Anchor( &lan[k] );\r
+ goto Fail;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( k = 0; k < m; k++ )\r
+ {\r
+ lan = cr[k].LigatureAnchor;\r
+\r
+ for ( n = 0; n < num_classes; n++ )\r
+ Free_Anchor( &lan[n] );\r
+\r
+ FREE( lan );\r
+ }\r
+\r
+ FREE( cr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_LigatureAttach( HB_LigatureAttach* lat,\r
+ HB_UShort num_classes )\r
+{\r
+ HB_UShort m, n, count;\r
+\r
+ HB_ComponentRecord* cr;\r
+ HB_Anchor* lan;\r
+\r
+\r
+ if ( lat->ComponentRecord )\r
+ {\r
+ count = lat->ComponentCount;\r
+ cr = lat->ComponentRecord;\r
+\r
+ for ( m = 0; m < count; m++ )\r
+ {\r
+ lan = cr[m].LigatureAnchor;\r
+\r
+ for ( n = 0; n < num_classes; n++ )\r
+ Free_Anchor( &lan[n] );\r
+\r
+ FREE( lan );\r
+ }\r
+\r
+ FREE( cr );\r
+ }\r
+}\r
+\r
+\r
+/* LigatureArray */\r
+\r
+static HB_Error Load_LigatureArray( HB_LigatureArray* la,\r
+ HB_UShort num_classes,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_LigatureAttach* lat;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = la->LigatureCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ la->LigatureAttach = NULL;\r
+\r
+ if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) )\r
+ return error;\r
+\r
+ lat = la->LigatureAttach;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_LigatureAttach( &lat[n], num_classes,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_LigatureAttach( &lat[m], num_classes );\r
+\r
+ FREE( lat );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_LigatureArray( HB_LigatureArray* la,\r
+ HB_UShort num_classes )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_LigatureAttach* lat;\r
+\r
+\r
+ if ( la->LigatureAttach )\r
+ {\r
+ count = la->LigatureCount;\r
+ lat = la->LigatureAttach;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_LigatureAttach( &lat[n], num_classes );\r
+\r
+ FREE( lat );\r
+ }\r
+}\r
+\r
+\r
+/* MarkLigPosFormat1 */\r
+\r
+static HB_Error Load_MarkLigPos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_MarkLigPos* mlp = &st->marklig;\r
+\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ mlp->PosFormat = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ goto Fail2;\r
+\r
+ mlp->ClassCount = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ Free_MarkArray( &mlp->MarkArray );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_MarkLigPos( HB_GPOS_SubTable* st)\r
+{\r
+ HB_MarkLigPos* mlp = &st->marklig;\r
+\r
+ Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount );\r
+ Free_MarkArray( &mlp->MarkArray );\r
+ _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );\r
+ _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort i, j, mark_index, lig_index, property, klass;\r
+ HB_UShort mark_glyph;\r
+ HB_Fixed x_mark_value, y_mark_value, x_lig_value, y_lig_value;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_MarkLigPos* mlp = &st->marklig;\r
+\r
+ HB_MarkArray* ma;\r
+ HB_LigatureArray* la;\r
+ HB_LigatureAttach* lat;\r
+ HB_ComponentRecord* cr;\r
+ HB_UShort comp_index;\r
+ HB_Anchor* mark_anchor;\r
+ HB_Anchor* lig_anchor;\r
+\r
+ HB_Position o;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES )\r
+ return HB_Err_Not_Covered;\r
+\r
+ mark_glyph = IN_CURGLYPH();\r
+\r
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );\r
+ if ( error )\r
+ return error;\r
+\r
+ /* now we search backwards for a non-mark glyph */\r
+\r
+ i = 1;\r
+ j = buffer->in_pos - 1;\r
+\r
+ while ( i <= buffer->in_pos )\r
+ {\r
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),\r
+ &property );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )\r
+ break;\r
+\r
+ i++;\r
+ j--;\r
+ }\r
+\r
+ /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is\r
+ too strong, thus it is commented out. */\r
+#if 0\r
+ if ( property != HB_GDEF_LIGATURE )\r
+ return HB_Err_Not_Covered;\r
+#endif\r
+\r
+ if ( i > buffer->in_pos )\r
+ return HB_Err_Not_Covered;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),\r
+ &lig_index );\r
+ if ( error )\r
+ return error;\r
+\r
+ ma = &mlp->MarkArray;\r
+\r
+ if ( mark_index >= ma->MarkCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ klass = ma->MarkRecord[mark_index].Class;\r
+ mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;\r
+\r
+ if ( klass >= mlp->ClassCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ la = &mlp->LigatureArray;\r
+\r
+ if ( lig_index >= la->LigatureCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ lat = &la->LigatureAttach[lig_index];\r
+\r
+ /* We must now check whether the ligature ID of the current mark glyph\r
+ is identical to the ligature ID of the found ligature. If yes, we\r
+ can directly use the component index. If not, we attach the mark\r
+ glyph to the last component of the ligature. */\r
+\r
+ if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )\r
+ {\r
+ comp_index = IN_COMPONENT( buffer->in_pos );\r
+ if ( comp_index >= lat->ComponentCount )\r
+ return HB_Err_Not_Covered;\r
+ }\r
+ else\r
+ comp_index = lat->ComponentCount - 1;\r
+\r
+ cr = &lat->ComponentRecord[comp_index];\r
+ lig_anchor = &cr->LigatureAnchor[klass];\r
+\r
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),\r
+ &x_mark_value, &y_mark_value );\r
+ if ( error )\r
+ return error;\r
+ error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),\r
+ &x_lig_value, &y_lig_value );\r
+ if ( error )\r
+ return error;\r
+\r
+ /* anchor points are not cumulative */\r
+\r
+ o = POSITION( buffer->in_pos );\r
+\r
+ o->x_pos = x_lig_value - x_mark_value;\r
+ o->y_pos = y_lig_value - y_mark_value;\r
+ o->x_advance = 0;\r
+ o->y_advance = 0;\r
+ o->back = i;\r
+\r
+ (buffer->in_pos)++;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 6 */\r
+\r
+/* Mark2Array */\r
+\r
+static HB_Error Load_Mark2Array( HB_Mark2Array* m2a,\r
+ HB_UShort num_classes,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort m, n, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Mark2Record *m2r;\r
+ HB_Anchor *m2an, *m2ans;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = m2a->Mark2Count = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ m2a->Mark2Record = NULL;\r
+\r
+ if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) )\r
+ return error;\r
+\r
+ m2r = m2a->Mark2Record;\r
+\r
+ m2ans = NULL;\r
+\r
+ if ( ALLOC_ARRAY( m2ans, count * num_classes, HB_Anchor ) )\r
+ goto Fail;\r
+\r
+ for ( m = 0; m < count; m++ )\r
+ {\r
+ m2an = m2r[m].Mark2Anchor = m2ans + m * num_classes;\r
+\r
+ for ( n = 0; n < num_classes; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if (new_offset == base_offset) {\r
+ /* Anchor table not provided. Skip loading.\r
+ * Some versions of FreeSans hit this. */\r
+ m2an[n].PosFormat = 0;\r
+ continue;\r
+ }\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Anchor( &m2an[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ FREE( m2ans );\r
+ FREE( m2r );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_Mark2Array( HB_Mark2Array* m2a,\r
+ HB_UShort num_classes )\r
+{\r
+ HB_Mark2Record *m2r;\r
+ HB_Anchor *m2ans;\r
+\r
+ HB_UNUSED(num_classes);\r
+\r
+ if ( m2a->Mark2Record )\r
+ {\r
+ m2r = m2a->Mark2Record;\r
+\r
+ if ( m2a->Mark2Count )\r
+ {\r
+ m2ans = m2r[0].Mark2Anchor;\r
+ FREE( m2ans );\r
+ }\r
+\r
+ FREE( m2r );\r
+ }\r
+}\r
+\r
+\r
+/* MarkMarkPosFormat1 */\r
+\r
+static HB_Error Load_MarkMarkPos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_MarkMarkPos* mmp = &st->markmark;\r
+\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ mmp->PosFormat = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage,\r
+ stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ goto Fail2;\r
+\r
+ mmp->ClassCount = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ Free_MarkArray( &mmp->Mark1Array );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_MarkMarkPos( HB_GPOS_SubTable* st)\r
+{\r
+ HB_MarkMarkPos* mmp = &st->markmark;\r
+\r
+ Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount );\r
+ Free_MarkArray( &mmp->Mark1Array );\r
+ _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );\r
+ _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort i, j, mark1_index, mark2_index, property, klass;\r
+ HB_Fixed x_mark1_value, y_mark1_value,\r
+ x_mark2_value, y_mark2_value;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_MarkMarkPos* mmp = &st->markmark;\r
+\r
+ HB_MarkArray* ma1;\r
+ HB_Mark2Array* ma2;\r
+ HB_Mark2Record* m2r;\r
+ HB_Anchor* mark1_anchor;\r
+ HB_Anchor* mark2_anchor;\r
+\r
+ HB_Position o;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(),\r
+ flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),\r
+ &mark1_index );\r
+ if ( error )\r
+ return error;\r
+\r
+ /* now we search backwards for a suitable mark glyph until a non-mark\r
+ glyph */\r
+\r
+ if ( buffer->in_pos == 0 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ i = 1;\r
+ j = buffer->in_pos - 1;\r
+ while ( i <= buffer->in_pos )\r
+ {\r
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),\r
+ &property );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )\r
+ {\r
+ if ( property == (flags & 0xFF00) )\r
+ break;\r
+ }\r
+ else\r
+ break;\r
+\r
+ i++;\r
+ j--;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),\r
+ &mark2_index );\r
+ if ( error )\r
+ return error;\r
+\r
+ ma1 = &mmp->Mark1Array;\r
+\r
+ if ( mark1_index >= ma1->MarkCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ klass = ma1->MarkRecord[mark1_index].Class;\r
+ mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;\r
+\r
+ if ( klass >= mmp->ClassCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ ma2 = &mmp->Mark2Array;\r
+\r
+ if ( mark2_index >= ma2->Mark2Count )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ m2r = &ma2->Mark2Record[mark2_index];\r
+ mark2_anchor = &m2r->Mark2Anchor[klass];\r
+\r
+ error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),\r
+ &x_mark1_value, &y_mark1_value );\r
+ if ( error )\r
+ return error;\r
+ error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),\r
+ &x_mark2_value, &y_mark2_value );\r
+ if ( error )\r
+ return error;\r
+\r
+ /* anchor points are not cumulative */\r
+\r
+ o = POSITION( buffer->in_pos );\r
+\r
+ o->x_pos = x_mark2_value - x_mark1_value;\r
+ o->y_pos = y_mark2_value - y_mark1_value;\r
+ o->x_advance = 0;\r
+ o->y_advance = 0;\r
+ o->back = 1;\r
+\r
+ (buffer->in_pos)++;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* Do the actual positioning for a context positioning (either format\r
+ 7 or 8). This is only called after we've determined that the stream\r
+ matches the subrule. */\r
+\r
+static HB_Error Do_ContextPos( GPOS_Instance* gpi,\r
+ HB_UShort GlyphCount,\r
+ HB_UShort PosCount,\r
+ HB_PosLookupRecord* pos,\r
+ HB_Buffer buffer,\r
+ int nesting_level )\r
+{\r
+ HB_Error error;\r
+ HB_UInt i, old_pos;\r
+\r
+\r
+ i = 0;\r
+\r
+ while ( i < GlyphCount )\r
+ {\r
+ if ( PosCount && i == pos->SequenceIndex )\r
+ {\r
+ old_pos = buffer->in_pos;\r
+\r
+ /* Do a positioning */\r
+\r
+ error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,\r
+ GlyphCount, nesting_level );\r
+\r
+ if ( error )\r
+ return error;\r
+\r
+ pos++;\r
+ PosCount--;\r
+ i += buffer->in_pos - old_pos;\r
+ }\r
+ else\r
+ {\r
+ i++;\r
+ (buffer->in_pos)++;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 7 */\r
+\r
+/* PosRule */\r
+\r
+static HB_Error Load_PosRule( HB_PosRule* pr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* i;\r
+\r
+ HB_PosLookupRecord* plr;\r
+\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ pr->GlyphCount = GET_UShort();\r
+ pr->PosCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ pr->Input = NULL;\r
+\r
+ count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( pr->Input, count, HB_UShort ) )\r
+ return error;\r
+\r
+ i = pr->Input;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ i[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ pr->PosLookupRecord = NULL;\r
+\r
+ count = pr->PosCount;\r
+\r
+ if ( ALLOC_ARRAY( pr->PosLookupRecord, count, HB_PosLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ plr = pr->PosLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ plr[n].SequenceIndex = GET_UShort();\r
+ plr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( plr );\r
+\r
+Fail2:\r
+ FREE( i );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PosRule( HB_PosRule* pr )\r
+{\r
+ FREE( pr->PosLookupRecord );\r
+ FREE( pr->Input );\r
+}\r
+\r
+\r
+/* PosRuleSet */\r
+\r
+static HB_Error Load_PosRuleSet( HB_PosRuleSet* prs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_PosRule* pr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = prs->PosRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ prs->PosRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( prs->PosRule, count, HB_PosRule ) )\r
+ return error;\r
+\r
+ pr = prs->PosRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_PosRule( &pr[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_PosRule( &pr[m] );\r
+\r
+ FREE( pr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PosRuleSet( HB_PosRuleSet* prs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_PosRule* pr;\r
+\r
+\r
+ if ( prs->PosRule )\r
+ {\r
+ count = prs->PosRuleCount;\r
+ pr = prs->PosRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_PosRule( &pr[n] );\r
+\r
+ FREE( pr );\r
+ }\r
+}\r
+\r
+\r
+/* ContextPosFormat1 */\r
+\r
+static HB_Error Load_ContextPos1( HB_ContextPosFormat1* cpf1,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_PosRuleSet* prs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = cpf1->PosRuleSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpf1->PosRuleSet = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, HB_PosRuleSet ) )\r
+ goto Fail2;\r
+\r
+ prs = cpf1->PosRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_PosRuleSet( &prs[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_PosRuleSet( &prs[m] );\r
+\r
+ FREE( prs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &cpf1->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ContextPos1( HB_ContextPosFormat1* cpf1 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_PosRuleSet* prs;\r
+\r
+\r
+ if ( cpf1->PosRuleSet )\r
+ {\r
+ count = cpf1->PosRuleSetCount;\r
+ prs = cpf1->PosRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_PosRuleSet( &prs[n] );\r
+\r
+ FREE( prs );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &cpf1->Coverage );\r
+}\r
+\r
+\r
+/* PosClassRule */\r
+\r
+static HB_Error Load_PosClassRule( HB_ContextPosFormat2* cpf2,\r
+ HB_PosClassRule* pcr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* c;\r
+ HB_PosLookupRecord* plr;\r
+\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ pcr->GlyphCount = GET_UShort();\r
+ pcr->PosCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( pcr->GlyphCount > cpf2->MaxContextLength )\r
+ cpf2->MaxContextLength = pcr->GlyphCount;\r
+\r
+ pcr->Class = NULL;\r
+\r
+ count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( pcr->Class, count, HB_UShort ) )\r
+ return error;\r
+\r
+ c = pcr->Class;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ c[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ pcr->PosLookupRecord = NULL;\r
+\r
+ count = pcr->PosCount;\r
+\r
+ if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_PosLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ plr = pcr->PosLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ plr[n].SequenceIndex = GET_UShort();\r
+ plr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( plr );\r
+\r
+Fail2:\r
+ FREE( c );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PosClassRule( HB_PosClassRule* pcr )\r
+{\r
+ FREE( pcr->PosLookupRecord );\r
+ FREE( pcr->Class );\r
+}\r
+\r
+\r
+/* PosClassSet */\r
+\r
+static HB_Error Load_PosClassSet( HB_ContextPosFormat2* cpf2,\r
+ HB_PosClassSet* pcs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_PosClassRule* pcr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = pcs->PosClassRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ pcs->PosClassRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( pcs->PosClassRule, count, HB_PosClassRule ) )\r
+ return error;\r
+\r
+ pcr = pcs->PosClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_PosClassRule( cpf2, &pcr[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_PosClassRule( &pcr[m] );\r
+\r
+ FREE( pcr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_PosClassSet( HB_PosClassSet* pcs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_PosClassRule* pcr;\r
+\r
+\r
+ if ( pcs->PosClassRule )\r
+ {\r
+ count = pcs->PosClassRuleCount;\r
+ pcr = pcs->PosClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_PosClassRule( &pcr[n] );\r
+\r
+ FREE( pcr );\r
+ }\r
+}\r
+\r
+\r
+/* ContextPosFormat2 */\r
+\r
+static HB_Error Load_ContextPos2( HB_ContextPosFormat2* cpf2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_PosClassSet* pcs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ /* `PosClassSetCount' is the upper limit for klass values, thus we\r
+ read it now to make an additional safety check. */\r
+\r
+ count = cpf2->PosClassSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ cpf2->PosClassSet = NULL;\r
+ cpf2->MaxContextLength = 0;\r
+\r
+ if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_PosClassSet ) )\r
+ goto Fail2;\r
+\r
+ pcs = cpf2->PosClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset != base_offset ) /* not a NULL offset */\r
+ {\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_PosClassSet( cpf2, &pcs[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ {\r
+ /* we create a PosClassSet table with no entries */\r
+\r
+ cpf2->PosClassSet[n].PosClassRuleCount = 0;\r
+ cpf2->PosClassSet[n].PosClassRule = NULL;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; n++ )\r
+ Free_PosClassSet( &pcs[m] );\r
+\r
+ FREE( pcs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_Coverage( &cpf2->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ContextPos2( HB_ContextPosFormat2* cpf2 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_PosClassSet* pcs;\r
+\r
+\r
+ if ( cpf2->PosClassSet )\r
+ {\r
+ count = cpf2->PosClassSetCount;\r
+ pcs = cpf2->PosClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_PosClassSet( &pcs[n] );\r
+\r
+ FREE( pcs );\r
+ }\r
+\r
+ _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );\r
+ _HB_OPEN_Free_Coverage( &cpf2->Coverage );\r
+}\r
+\r
+\r
+/* ContextPosFormat3 */\r
+\r
+static HB_Error Load_ContextPos3( HB_ContextPosFormat3* cpf3,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Coverage* c;\r
+ HB_PosLookupRecord* plr;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ cpf3->GlyphCount = GET_UShort();\r
+ cpf3->PosCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpf3->Coverage = NULL;\r
+\r
+ count = cpf3->GlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( cpf3->Coverage, count, HB_Coverage ) )\r
+ return error;\r
+\r
+ c = cpf3->Coverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ cpf3->PosLookupRecord = NULL;\r
+\r
+ count = cpf3->PosCount;\r
+\r
+ if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_PosLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ plr = cpf3->PosLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ plr[n].SequenceIndex = GET_UShort();\r
+ plr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( plr );\r
+\r
+Fail2:\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ContextPos3( HB_ContextPosFormat3* cpf3 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_Coverage* c;\r
+\r
+\r
+ FREE( cpf3->PosLookupRecord );\r
+\r
+ if ( cpf3->Coverage )\r
+ {\r
+ count = cpf3->GlyphCount;\r
+ c = cpf3->Coverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+}\r
+\r
+\r
+/* ContextPos */\r
+\r
+static HB_Error Load_ContextPos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_ContextPos* cp = &st->context;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cp->PosFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( cp->PosFormat )\r
+ {\r
+ case 1:\r
+ return Load_ContextPos1( &cp->cpf.cpf1, stream );\r
+\r
+ case 2:\r
+ return Load_ContextPos2( &cp->cpf.cpf2, stream );\r
+\r
+ case 3:\r
+ return Load_ContextPos3( &cp->cpf.cpf3, stream );\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+static void Free_ContextPos( HB_GPOS_SubTable* st )\r
+{\r
+ HB_ContextPos* cp = &st->context;\r
+\r
+ switch ( cp->PosFormat )\r
+ {\r
+ case 1: Free_ContextPos1( &cp->cpf.cpf1 ); break;\r
+ case 2: Free_ContextPos2( &cp->cpf.cpf2 ); break;\r
+ case 3: Free_ContextPos3( &cp->cpf.cpf3 ); break;\r
+ default: break;\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextPos1( GPOS_Instance* gpi,\r
+ HB_ContextPosFormat1* cpf1,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_UShort i, j, k, numpr;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_PosRule* pr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gpos->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ pr = cpf1->PosRuleSet[index].PosRule;\r
+ numpr = cpf1->PosRuleSet[index].PosRuleCount;\r
+\r
+ for ( k = 0; k < numpr; k++ )\r
+ {\r
+ if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )\r
+ goto next_posrule;\r
+\r
+ if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )\r
+ goto next_posrule; /* context is too long */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + pr[k].GlyphCount - i == (HB_Int)buffer->in_length )\r
+ goto next_posrule;\r
+ j++;\r
+ }\r
+\r
+ if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )\r
+ goto next_posrule;\r
+ }\r
+\r
+ return Do_ContextPos( gpi, pr[k].GlyphCount,\r
+ pr[k].PosCount, pr[k].PosLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+\r
+ next_posrule:\r
+ ;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi,\r
+ HB_ContextPosFormat2* cpf2,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_Error error;\r
+ HB_UShort i, j, k, known_classes;\r
+\r
+ HB_UShort* classes;\r
+ HB_UShort* cl;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_PosClassSet* pcs;\r
+ HB_PosClassRule* pr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gpos->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ /* Note: The coverage table in format 2 doesn't give an index into\r
+ anything. It just lets us know whether or not we need to\r
+ do any lookup at all. */\r
+\r
+ error = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ if (cpf2->MaxContextLength < 1)\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, HB_UShort ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),\r
+ &classes[0], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End;\r
+ known_classes = 0;\r
+\r
+ pcs = &cpf2->PosClassSet[classes[0]];\r
+ if ( !pcs )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_SubTable);\r
+ goto End;\r
+ }\r
+\r
+ for ( k = 0; k < pcs->PosClassRuleCount; k++ )\r
+ {\r
+ pr = &pcs->PosClassRule[k];\r
+\r
+ if ( context_length != 0xFFFF && context_length < pr->GlyphCount )\r
+ goto next_posclassrule;\r
+\r
+ if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )\r
+ goto next_posclassrule; /* context is too long */\r
+\r
+ cl = pr->Class;\r
+\r
+ /* Start at 1 because [0] is implied */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End;\r
+\r
+ if ( j + pr->GlyphCount - i == (HB_Int)buffer->in_length )\r
+ goto next_posclassrule;\r
+ j++;\r
+ }\r
+\r
+ if ( i > known_classes )\r
+ {\r
+ /* Keeps us from having to do this for each rule */\r
+\r
+ error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End;\r
+ known_classes = i;\r
+ }\r
+\r
+ if ( cl[i - 1] != classes[i] )\r
+ goto next_posclassrule;\r
+ }\r
+\r
+ error = Do_ContextPos( gpi, pr->GlyphCount,\r
+ pr->PosCount, pr->PosLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+ goto End;\r
+\r
+ next_posclassrule:\r
+ ;\r
+ }\r
+\r
+ error = HB_Err_Not_Covered;\r
+\r
+End:\r
+ FREE( classes );\r
+ return error;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextPos3( GPOS_Instance* gpi,\r
+ HB_ContextPosFormat3* cpf3,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_Error error;\r
+ HB_UShort index, i, j, property;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_Coverage* c;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gpos->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )\r
+ return HB_Err_Not_Covered; /* context is too long */\r
+\r
+ c = cpf3->Coverage;\r
+\r
+ for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + cpf3->GlyphCount - i == (HB_Int)buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+ j++;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ return Do_ContextPos( gpi, cpf3->GlyphCount,\r
+ cpf3->PosCount, cpf3->PosLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextPos( GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_ContextPos* cp = &st->context;\r
+\r
+ switch ( cp->PosFormat )\r
+ {\r
+ case 1:\r
+ return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,\r
+ flags, context_length, nesting_level );\r
+\r
+ case 2:\r
+ return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,\r
+ flags, context_length, nesting_level );\r
+\r
+ case 3:\r
+ return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,\r
+ flags, context_length, nesting_level );\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+/* LookupType 8 */\r
+\r
+/* ChainPosRule */\r
+\r
+static HB_Error Load_ChainPosRule( HB_ChainPosRule* cpr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* b;\r
+ HB_UShort* i;\r
+ HB_UShort* l;\r
+\r
+ HB_PosLookupRecord* plr;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cpr->BacktrackGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpr->Backtrack = NULL;\r
+\r
+ count = cpr->BacktrackGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( cpr->Backtrack, count, HB_UShort ) )\r
+ return error;\r
+\r
+ b = cpr->Backtrack;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail4;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ b[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ cpr->InputGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpr->Input = NULL;\r
+\r
+ count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( cpr->Input, count, HB_UShort ) )\r
+ goto Fail4;\r
+\r
+ i = cpr->Input;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail3;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ i[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ cpr->LookaheadGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpr->Lookahead = NULL;\r
+\r
+ count = cpr->LookaheadGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( cpr->Lookahead, count, HB_UShort ) )\r
+ goto Fail3;\r
+\r
+ l = cpr->Lookahead;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ l[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ cpr->PosCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpr->PosLookupRecord = NULL;\r
+\r
+ count = cpr->PosCount;\r
+\r
+ if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, HB_PosLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ plr = cpr->PosLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ plr[n].SequenceIndex = GET_UShort();\r
+ plr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( plr );\r
+\r
+Fail2:\r
+ FREE( l );\r
+\r
+Fail3:\r
+ FREE( i );\r
+\r
+Fail4:\r
+ FREE( b );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainPosRule( HB_ChainPosRule* cpr )\r
+{\r
+ FREE( cpr->PosLookupRecord );\r
+ FREE( cpr->Lookahead );\r
+ FREE( cpr->Input );\r
+ FREE( cpr->Backtrack );\r
+}\r
+\r
+\r
+/* ChainPosRuleSet */\r
+\r
+static HB_Error Load_ChainPosRuleSet( HB_ChainPosRuleSet* cprs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ChainPosRule* cpr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = cprs->ChainPosRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cprs->ChainPosRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cprs->ChainPosRule, count, HB_ChainPosRule ) )\r
+ return error;\r
+\r
+ cpr = cprs->ChainPosRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainPosRule( &cpr[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainPosRule( &cpr[m] );\r
+\r
+ FREE( cpr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainPosRuleSet( HB_ChainPosRuleSet* cprs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainPosRule* cpr;\r
+\r
+\r
+ if ( cprs->ChainPosRule )\r
+ {\r
+ count = cprs->ChainPosRuleCount;\r
+ cpr = cprs->ChainPosRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainPosRule( &cpr[n] );\r
+\r
+ FREE( cpr );\r
+ }\r
+}\r
+\r
+\r
+/* ChainContextPosFormat1 */\r
+\r
+static HB_Error Load_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ChainPosRuleSet* cprs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = ccpf1->ChainPosRuleSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccpf1->ChainPosRuleSet = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, HB_ChainPosRuleSet ) )\r
+ goto Fail2;\r
+\r
+ cprs = ccpf1->ChainPosRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainPosRuleSet( &cprs[m] );\r
+\r
+ FREE( cprs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &ccpf1->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainPosRuleSet* cprs;\r
+\r
+\r
+ if ( ccpf1->ChainPosRuleSet )\r
+ {\r
+ count = ccpf1->ChainPosRuleSetCount;\r
+ cprs = ccpf1->ChainPosRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainPosRuleSet( &cprs[n] );\r
+\r
+ FREE( cprs );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &ccpf1->Coverage );\r
+}\r
+\r
+\r
+/* ChainPosClassRule */\r
+\r
+static HB_Error Load_ChainPosClassRule(\r
+ HB_ChainContextPosFormat2* ccpf2,\r
+ HB_ChainPosClassRule* cpcr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* b;\r
+ HB_UShort* i;\r
+ HB_UShort* l;\r
+ HB_PosLookupRecord* plr;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cpcr->BacktrackGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength )\r
+ ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount;\r
+\r
+ cpcr->Backtrack = NULL;\r
+\r
+ count = cpcr->BacktrackGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( cpcr->Backtrack, count, HB_UShort ) )\r
+ return error;\r
+\r
+ b = cpcr->Backtrack;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail4;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ b[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ cpcr->InputGlyphCount = GET_UShort();\r
+\r
+ if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength )\r
+ ccpf2->MaxInputLength = cpcr->InputGlyphCount;\r
+\r
+ FORGET_Frame();\r
+\r
+ cpcr->Input = NULL;\r
+\r
+ count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( cpcr->Input, count, HB_UShort ) )\r
+ goto Fail4;\r
+\r
+ i = cpcr->Input;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail3;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ i[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ cpcr->LookaheadGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength )\r
+ ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount;\r
+\r
+ cpcr->Lookahead = NULL;\r
+\r
+ count = cpcr->LookaheadGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( cpcr->Lookahead, count, HB_UShort ) )\r
+ goto Fail3;\r
+\r
+ l = cpcr->Lookahead;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ l[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ cpcr->PosCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpcr->PosLookupRecord = NULL;\r
+\r
+ count = cpcr->PosCount;\r
+\r
+ if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_PosLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ plr = cpcr->PosLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ plr[n].SequenceIndex = GET_UShort();\r
+ plr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( plr );\r
+\r
+Fail2:\r
+ FREE( l );\r
+\r
+Fail3:\r
+ FREE( i );\r
+\r
+Fail4:\r
+ FREE( b );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainPosClassRule( HB_ChainPosClassRule* cpcr )\r
+{\r
+ FREE( cpcr->PosLookupRecord );\r
+ FREE( cpcr->Lookahead );\r
+ FREE( cpcr->Input );\r
+ FREE( cpcr->Backtrack );\r
+}\r
+\r
+\r
+/* PosClassSet */\r
+\r
+static HB_Error Load_ChainPosClassSet(\r
+ HB_ChainContextPosFormat2* ccpf2,\r
+ HB_ChainPosClassSet* cpcs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ChainPosClassRule* cpcr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = cpcs->ChainPosClassRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cpcs->ChainPosClassRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count,\r
+ HB_ChainPosClassRule ) )\r
+ return error;\r
+\r
+ cpcr = cpcs->ChainPosClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainPosClassRule( &cpcr[m] );\r
+\r
+ FREE( cpcr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainPosClassSet( HB_ChainPosClassSet* cpcs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainPosClassRule* cpcr;\r
+\r
+\r
+ if ( cpcs->ChainPosClassRule )\r
+ {\r
+ count = cpcs->ChainPosClassRuleCount;\r
+ cpcr = cpcs->ChainPosClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainPosClassRule( &cpcr[n] );\r
+\r
+ FREE( cpcr );\r
+ }\r
+}\r
+\r
+\r
+/* ChainContextPosFormat2 */\r
+\r
+static HB_Error Load_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+ HB_UInt backtrack_offset, input_offset, lookahead_offset;\r
+\r
+ HB_ChainPosClassSet* cpcs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 8L ) )\r
+ goto Fail5;\r
+\r
+ backtrack_offset = GET_UShort();\r
+ input_offset = GET_UShort();\r
+ lookahead_offset = GET_UShort();\r
+\r
+ /* `ChainPosClassSetCount' is the upper limit for input klass values,\r
+ thus we read it now to make an additional safety check. No limit\r
+ is known or needed for the other two klass definitions */\r
+\r
+ count = ccpf2->ChainPosClassSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,\r
+ backtrack_offset, base_offset,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail5;\r
+ if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,\r
+ input_offset, base_offset,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail4;\r
+ if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,\r
+ lookahead_offset, base_offset,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+\r
+ ccpf2->ChainPosClassSet = NULL;\r
+ ccpf2->MaxBacktrackLength = 0;\r
+ ccpf2->MaxInputLength = 0;\r
+ ccpf2->MaxLookaheadLength = 0;\r
+\r
+ if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_ChainPosClassSet ) )\r
+ goto Fail2;\r
+\r
+ cpcs = ccpf2->ChainPosClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset != base_offset ) /* not a NULL offset */\r
+ {\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ {\r
+ /* we create a ChainPosClassSet table with no entries */\r
+\r
+ ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0;\r
+ ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainPosClassSet( &cpcs[m] );\r
+\r
+ FREE( cpcs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );\r
+\r
+Fail4:\r
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );\r
+\r
+Fail5:\r
+ _HB_OPEN_Free_Coverage( &ccpf2->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainPosClassSet* cpcs;\r
+\r
+\r
+ if ( ccpf2->ChainPosClassSet )\r
+ {\r
+ count = ccpf2->ChainPosClassSetCount;\r
+ cpcs = ccpf2->ChainPosClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainPosClassSet( &cpcs[n] );\r
+\r
+ FREE( cpcs );\r
+ }\r
+\r
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );\r
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );\r
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );\r
+\r
+ _HB_OPEN_Free_Coverage( &ccpf2->Coverage );\r
+}\r
+\r
+\r
+/* ChainContextPosFormat3 */\r
+\r
+static HB_Error Load_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, nb, ni, nl, m, count;\r
+ HB_UShort backtrack_count, input_count, lookahead_count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Coverage* b;\r
+ HB_Coverage* i;\r
+ HB_Coverage* l;\r
+ HB_PosLookupRecord* plr;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ ccpf3->BacktrackGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccpf3->BacktrackCoverage = NULL;\r
+\r
+ backtrack_count = ccpf3->BacktrackGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count,\r
+ HB_Coverage ) )\r
+ return error;\r
+\r
+ b = ccpf3->BacktrackCoverage;\r
+\r
+ for ( nb = 0; nb < backtrack_count; nb++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )\r
+ goto Fail4;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ ccpf3->InputGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccpf3->InputCoverage = NULL;\r
+\r
+ input_count = ccpf3->InputGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, HB_Coverage ) )\r
+ goto Fail4;\r
+\r
+ i = ccpf3->InputCoverage;\r
+\r
+ for ( ni = 0; ni < input_count; ni++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ ccpf3->LookaheadGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccpf3->LookaheadCoverage = NULL;\r
+\r
+ lookahead_count = ccpf3->LookaheadGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count,\r
+ HB_Coverage ) )\r
+ goto Fail3;\r
+\r
+ l = ccpf3->LookaheadCoverage;\r
+\r
+ for ( nl = 0; nl < lookahead_count; nl++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ ccpf3->PosCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccpf3->PosLookupRecord = NULL;\r
+\r
+ count = ccpf3->PosCount;\r
+\r
+ if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, HB_PosLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ plr = ccpf3->PosLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ plr[n].SequenceIndex = GET_UShort();\r
+ plr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( plr );\r
+\r
+Fail2:\r
+ for ( m = 0; m < nl; m++ )\r
+ _HB_OPEN_Free_Coverage( &l[m] );\r
+\r
+ FREE( l );\r
+\r
+Fail3:\r
+ for ( m = 0; m < ni; m++ )\r
+ _HB_OPEN_Free_Coverage( &i[m] );\r
+\r
+ FREE( i );\r
+\r
+Fail4:\r
+ for ( m = 0; m < nb; m++ )\r
+ _HB_OPEN_Free_Coverage( &b[m] );\r
+\r
+ FREE( b );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_Coverage* c;\r
+\r
+\r
+ FREE( ccpf3->PosLookupRecord );\r
+\r
+ if ( ccpf3->LookaheadCoverage )\r
+ {\r
+ count = ccpf3->LookaheadGlyphCount;\r
+ c = ccpf3->LookaheadCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+\r
+ if ( ccpf3->InputCoverage )\r
+ {\r
+ count = ccpf3->InputGlyphCount;\r
+ c = ccpf3->InputCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+\r
+ if ( ccpf3->BacktrackCoverage )\r
+ {\r
+ count = ccpf3->BacktrackGlyphCount;\r
+ c = ccpf3->BacktrackCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+}\r
+\r
+\r
+/* ChainContextPos */\r
+\r
+static HB_Error Load_ChainContextPos( HB_GPOS_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_ChainContextPos* ccp = &st->chain;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ ccp->PosFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( ccp->PosFormat )\r
+ {\r
+ case 1:\r
+ return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );\r
+\r
+ case 2:\r
+ return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );\r
+\r
+ case 3:\r
+ return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+static void Free_ChainContextPos( HB_GPOS_SubTable* st )\r
+{\r
+ HB_ChainContextPos* ccp = &st->chain;\r
+\r
+ switch ( ccp->PosFormat )\r
+ {\r
+ case 1: Free_ChainContextPos1( &ccp->ccpf.ccpf1 ); break;\r
+ case 2: Free_ChainContextPos2( &ccp->ccpf.ccpf2 ); break;\r
+ case 3: Free_ChainContextPos3( &ccp->ccpf.ccpf3 ); break;\r
+ default: break;\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextPos1(\r
+ GPOS_Instance* gpi,\r
+ HB_ChainContextPosFormat1* ccpf1,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_UShort i, j, k, num_cpr;\r
+ HB_UShort bgc, igc, lgc;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_ChainPosRule* cpr;\r
+ HB_ChainPosRule curr_cpr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gpos->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule;\r
+ num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount;\r
+\r
+ for ( k = 0; k < num_cpr; k++ )\r
+ {\r
+ curr_cpr = cpr[k];\r
+ bgc = curr_cpr.BacktrackGlyphCount;\r
+ igc = curr_cpr.InputGlyphCount;\r
+ lgc = curr_cpr.LookaheadGlyphCount;\r
+\r
+ if ( context_length != 0xFFFF && context_length < igc )\r
+ goto next_chainposrule;\r
+\r
+ /* check whether context is too long; it is a first guess only */\r
+\r
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )\r
+ goto next_chainposrule;\r
+\r
+ if ( bgc )\r
+ {\r
+ /* Since we don't know in advance the number of glyphs to inspect,\r
+ we search backwards for matches in the backtrack glyph array */\r
+\r
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + 1 == bgc - i )\r
+ goto next_chainposrule;\r
+ j--;\r
+ }\r
+\r
+ /* In OpenType 1.3, it is undefined whether the offsets of\r
+ backtrack glyphs is in logical order or not. Version 1.4\r
+ will clarify this:\r
+\r
+ Logical order - a b c d e f g h i j\r
+ i\r
+ Input offsets - 0 1\r
+ Backtrack offsets - 3 2 1 0\r
+ Lookahead offsets - 0 1 2 3 */\r
+\r
+ if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )\r
+ goto next_chainposrule;\r
+ }\r
+ }\r
+\r
+ /* Start at 1 because [0] is implied */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + igc - i + lgc == (HB_Int)buffer->in_length )\r
+ goto next_chainposrule;\r
+ j++;\r
+ }\r
+\r
+ if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )\r
+ goto next_chainposrule;\r
+ }\r
+\r
+ /* we are starting to check for lookahead glyphs right after the\r
+ last context glyph */\r
+\r
+ for ( i = 0; i < lgc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + lgc - i == (HB_Int)buffer->in_length )\r
+ goto next_chainposrule;\r
+ j++;\r
+ }\r
+\r
+ if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )\r
+ goto next_chainposrule;\r
+ }\r
+\r
+ return Do_ContextPos( gpi, igc,\r
+ curr_cpr.PosCount,\r
+ curr_cpr.PosLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+\r
+ next_chainposrule:\r
+ ;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextPos2(\r
+ GPOS_Instance* gpi,\r
+ HB_ChainContextPosFormat2* ccpf2,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_Error error;\r
+ HB_UShort i, j, k;\r
+ HB_UShort bgc, igc, lgc;\r
+ HB_UShort known_backtrack_classes,\r
+ known_input_classes,\r
+ known_lookahead_classes;\r
+\r
+ HB_UShort* backtrack_classes;\r
+ HB_UShort* input_classes;\r
+ HB_UShort* lookahead_classes;\r
+\r
+ HB_UShort* bc;\r
+ HB_UShort* ic;\r
+ HB_UShort* lc;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_ChainPosClassSet* cpcs;\r
+ HB_ChainPosClassRule cpcr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gpos->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ /* Note: The coverage table in format 2 doesn't give an index into\r
+ anything. It just lets us know whether or not we need to\r
+ do any lookup at all. */\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, HB_UShort ) )\r
+ return error;\r
+ known_backtrack_classes = 0;\r
+\r
+ if (ccpf2->MaxInputLength < 1)\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, HB_UShort ) )\r
+ goto End3;\r
+ known_input_classes = 1;\r
+\r
+ if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, HB_UShort ) )\r
+ goto End2;\r
+ known_lookahead_classes = 0;\r
+\r
+ error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),\r
+ &input_classes[0], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];\r
+ if ( !cpcs )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_SubTable);\r
+ goto End1;\r
+ }\r
+\r
+ for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ )\r
+ {\r
+ cpcr = cpcs->ChainPosClassRule[k];\r
+ bgc = cpcr.BacktrackGlyphCount;\r
+ igc = cpcr.InputGlyphCount;\r
+ lgc = cpcr.LookaheadGlyphCount;\r
+\r
+ if ( context_length != 0xFFFF && context_length < igc )\r
+ goto next_chainposclassrule;\r
+\r
+ /* check whether context is too long; it is a first guess only */\r
+\r
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )\r
+ goto next_chainposclassrule;\r
+\r
+ if ( bgc )\r
+ {\r
+ /* Since we don't know in advance the number of glyphs to inspect,\r
+ we search backwards for matches in the backtrack glyph array.\r
+ Note that `known_backtrack_classes' starts at index 0. */\r
+\r
+ bc = cpcr.Backtrack;\r
+\r
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ if ( j + 1 == bgc - i )\r
+ goto next_chainposclassrule;\r
+ j++;\r
+ }\r
+\r
+ if ( i >= known_backtrack_classes )\r
+ {\r
+ /* Keeps us from having to do this for each rule */\r
+\r
+ error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),\r
+ &backtrack_classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+ known_backtrack_classes = i;\r
+ }\r
+\r
+ if ( bc[i] != backtrack_classes[i] )\r
+ goto next_chainposclassrule;\r
+ }\r
+ }\r
+\r
+ ic = cpcr.Input;\r
+\r
+ /* Start at 1 because [0] is implied */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ if ( j + igc - i + lgc == (HB_Int)buffer->in_length )\r
+ goto next_chainposclassrule;\r
+ j++;\r
+ }\r
+\r
+ if ( i >= known_input_classes )\r
+ {\r
+ error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),\r
+ &input_classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+ known_input_classes = i;\r
+ }\r
+\r
+ if ( ic[i - 1] != input_classes[i] )\r
+ goto next_chainposclassrule;\r
+ }\r
+\r
+ /* we are starting to check for lookahead glyphs right after the\r
+ last context glyph */\r
+\r
+ lc = cpcr.Lookahead;\r
+\r
+ for ( i = 0; i < lgc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ if ( j + lgc - i == (HB_Int)buffer->in_length )\r
+ goto next_chainposclassrule;\r
+ j++;\r
+ }\r
+\r
+ if ( i >= known_lookahead_classes )\r
+ {\r
+ error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),\r
+ &lookahead_classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+ known_lookahead_classes = i;\r
+ }\r
+\r
+ if ( lc[i] != lookahead_classes[i] )\r
+ goto next_chainposclassrule;\r
+ }\r
+\r
+ error = Do_ContextPos( gpi, igc,\r
+ cpcr.PosCount,\r
+ cpcr.PosLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+ goto End1;\r
+\r
+ next_chainposclassrule:\r
+ ;\r
+ }\r
+\r
+ error = HB_Err_Not_Covered;\r
+\r
+End1:\r
+ FREE( lookahead_classes );\r
+\r
+End2:\r
+ FREE( input_classes );\r
+\r
+End3:\r
+ FREE( backtrack_classes );\r
+ return error;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextPos3(\r
+ GPOS_Instance* gpi,\r
+ HB_ChainContextPosFormat3* ccpf3,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, i, j, property;\r
+ HB_UShort bgc, igc, lgc;\r
+ HB_Error error;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_Coverage* bc;\r
+ HB_Coverage* ic;\r
+ HB_Coverage* lc;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gpos->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ bgc = ccpf3->BacktrackGlyphCount;\r
+ igc = ccpf3->InputGlyphCount;\r
+ lgc = ccpf3->LookaheadGlyphCount;\r
+\r
+ if ( context_length != 0xFFFF && context_length < igc )\r
+ return HB_Err_Not_Covered;\r
+\r
+ /* check whether context is too long; it is a first guess only */\r
+\r
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( bgc )\r
+ {\r
+ /* Since we don't know in advance the number of glyphs to inspect,\r
+ we search backwards for matches in the backtrack glyph array */\r
+\r
+ bc = ccpf3->BacktrackCoverage;\r
+\r
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + 1 == bgc - i )\r
+ return HB_Err_Not_Covered;\r
+ j--;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+ }\r
+\r
+ ic = ccpf3->InputCoverage;\r
+\r
+ for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )\r
+ {\r
+ /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */\r
+ while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + igc - i + lgc == (HB_Int)buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+ j++;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ /* we are starting to check for lookahead glyphs right after the\r
+ last context glyph */\r
+\r
+ lc = ccpf3->LookaheadCoverage;\r
+\r
+ for ( i = 0; i < lgc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + lgc - i == (HB_Int)buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+ j++;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ return Do_ContextPos( gpi, igc,\r
+ ccpf3->PosCount,\r
+ ccpf3->PosLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextPos(\r
+ GPOS_Instance* gpi,\r
+ HB_GPOS_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_ChainContextPos* ccp = &st->chain;\r
+\r
+ switch ( ccp->PosFormat )\r
+ {\r
+ case 1:\r
+ return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,\r
+ flags, context_length,\r
+ nesting_level );\r
+\r
+ case 2:\r
+ return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,\r
+ flags, context_length,\r
+ nesting_level );\r
+\r
+ case 3:\r
+ return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,\r
+ flags, context_length,\r
+ nesting_level );\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+\r
+/***********\r
+ * GPOS API\r
+ ***********/\r
+\r
+\r
+\r
+HB_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,\r
+ HB_UInt script_tag,\r
+ HB_UShort* script_index )\r
+{\r
+ HB_UShort n;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+\r
+\r
+ if ( !gpos || !script_index )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gpos->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ for ( n = 0; n < sl->ScriptCount; n++ )\r
+ if ( script_tag == sr[n].ScriptTag )\r
+ {\r
+ *script_index = n;\r
+\r
+ return HB_Err_Ok;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,\r
+ HB_UInt language_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort* language_index,\r
+ HB_UShort* req_feature_index )\r
+{\r
+ HB_UShort n;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+\r
+\r
+ if ( !gpos || !language_index || !req_feature_index )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gpos->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ for ( n = 0; n < s->LangSysCount; n++ )\r
+ if ( language_tag == lsr[n].LangSysTag )\r
+ {\r
+ *language_index = n;\r
+ *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;\r
+\r
+ return HB_Err_Ok;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+/* selecting 0xFFFF for language_index asks for the values of the\r
+ default language (DefaultLangSys) */\r
+\r
+\r
+HB_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,\r
+ HB_UInt feature_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UShort* feature_index )\r
+{\r
+ HB_UShort n;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+ HB_LangSys* ls;\r
+ HB_UShort* fi;\r
+\r
+ HB_FeatureList* fl;\r
+ HB_FeatureRecord* fr;\r
+\r
+\r
+ if ( !gpos || !feature_index )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gpos->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ fl = &gpos->FeatureList;\r
+ fr = fl->FeatureRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ if ( language_index == 0xFFFF )\r
+ ls = &s->DefaultLangSys;\r
+ else\r
+ {\r
+ if ( language_index >= s->LangSysCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ ls = &lsr[language_index].LangSys;\r
+ }\r
+\r
+ fi = ls->FeatureIndex;\r
+\r
+ for ( n = 0; n < ls->FeatureCount; n++ )\r
+ {\r
+ if ( fi[n] >= fl->FeatureCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+\r
+ if ( feature_tag == fr[fi[n]].FeatureTag )\r
+ {\r
+ *feature_index = fi[n];\r
+\r
+ return HB_Err_Ok;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+/* The next three functions return a null-terminated list */\r
+\r
+\r
+HB_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,\r
+ HB_UInt** script_tag_list )\r
+{\r
+ HB_Error error;\r
+ HB_UShort n;\r
+ HB_UInt* stl;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+\r
+\r
+ if ( !gpos || !script_tag_list )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gpos->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )\r
+ return error;\r
+\r
+ for ( n = 0; n < sl->ScriptCount; n++ )\r
+ stl[n] = sr[n].ScriptTag;\r
+ stl[n] = 0;\r
+\r
+ *script_tag_list = stl;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,\r
+ HB_UShort script_index,\r
+ HB_UInt** language_tag_list )\r
+{\r
+ HB_Error error;\r
+ HB_UShort n;\r
+ HB_UInt* ltl;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+\r
+\r
+ if ( !gpos || !language_tag_list )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gpos->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )\r
+ return error;\r
+\r
+ for ( n = 0; n < s->LangSysCount; n++ )\r
+ ltl[n] = lsr[n].LangSysTag;\r
+ ltl[n] = 0;\r
+\r
+ *language_tag_list = ltl;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* selecting 0xFFFF for language_index asks for the values of the\r
+ default language (DefaultLangSys) */\r
+\r
+\r
+HB_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UInt** feature_tag_list )\r
+{\r
+ HB_UShort n;\r
+ HB_Error error;\r
+ HB_UInt* ftl;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+ HB_LangSys* ls;\r
+ HB_UShort* fi;\r
+\r
+ HB_FeatureList* fl;\r
+ HB_FeatureRecord* fr;\r
+\r
+\r
+ if ( !gpos || !feature_tag_list )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gpos->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ fl = &gpos->FeatureList;\r
+ fr = fl->FeatureRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ if ( language_index == 0xFFFF )\r
+ ls = &s->DefaultLangSys;\r
+ else\r
+ {\r
+ if ( language_index >= s->LangSysCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ ls = &lsr[language_index].LangSys;\r
+ }\r
+\r
+ fi = ls->FeatureIndex;\r
+\r
+ if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )\r
+ return error;\r
+\r
+ for ( n = 0; n < ls->FeatureCount; n++ )\r
+ {\r
+ if ( fi[n] >= fl->FeatureCount )\r
+ {\r
+ FREE( ftl );\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+ ftl[n] = fr[fi[n]].FeatureTag;\r
+ }\r
+ ftl[n] = 0;\r
+\r
+ *feature_tag_list = ftl;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* Do an individual subtable lookup. Returns HB_Err_Ok if positioning\r
+ has been done, or HB_Err_Not_Covered if not. */\r
+static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,\r
+ HB_UShort lookup_index,\r
+ HB_Buffer buffer,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_Error error = HB_Err_Not_Covered;\r
+ HB_UShort i, flags, lookup_count;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+ HB_Lookup* lo;\r
+ int lookup_type;\r
+\r
+\r
+ nesting_level++;\r
+\r
+ if ( nesting_level > HB_MAX_NESTING_LEVEL )\r
+ return ERR_HB(HB_Err_Not_Covered); /* ERR_HB() call intended */\r
+\r
+ lookup_count = gpos->LookupList.LookupCount;\r
+ if (lookup_index >= lookup_count)\r
+ return error;\r
+\r
+ lo = &gpos->LookupList.Lookup[lookup_index];\r
+ flags = lo->LookupFlag;\r
+ lookup_type = lo->LookupType;\r
+\r
+ for ( i = 0; i < lo->SubTableCount; i++ )\r
+ {\r
+ HB_GPOS_SubTable *st = &lo->SubTable[i].st.gpos;\r
+\r
+ switch (lookup_type) {\r
+ case HB_GPOS_LOOKUP_SINGLE:\r
+ error = Lookup_SinglePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GPOS_LOOKUP_PAIR:\r
+ error = Lookup_PairPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GPOS_LOOKUP_CURSIVE:\r
+ error = Lookup_CursivePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GPOS_LOOKUP_MARKBASE:\r
+ error = Lookup_MarkBasePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GPOS_LOOKUP_MARKLIG:\r
+ error = Lookup_MarkLigPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GPOS_LOOKUP_MARKMARK:\r
+ error = Lookup_MarkMarkPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GPOS_LOOKUP_CONTEXT:\r
+ error = Lookup_ContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GPOS_LOOKUP_CHAIN:\r
+ error = Lookup_ChainContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;\r
+ /*case HB_GPOS_LOOKUP_EXTENSION:\r
+ error = Lookup_ExtensionPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;*/\r
+ default:\r
+ error = HB_Err_Not_Covered;\r
+ }\r
+\r
+ /* Check whether we have a successful positioning or an error other\r
+ than HB_Err_Not_Covered */\r
+ if ( error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,\r
+ HB_Stream stream,\r
+ HB_UShort lookup_type )\r
+{\r
+ switch ( lookup_type ) {\r
+ case HB_GPOS_LOOKUP_SINGLE: return Load_SinglePos ( st, stream );\r
+ case HB_GPOS_LOOKUP_PAIR: return Load_PairPos ( st, stream );\r
+ case HB_GPOS_LOOKUP_CURSIVE: return Load_CursivePos ( st, stream );\r
+ case HB_GPOS_LOOKUP_MARKBASE: return Load_MarkBasePos ( st, stream );\r
+ case HB_GPOS_LOOKUP_MARKLIG: return Load_MarkLigPos ( st, stream );\r
+ case HB_GPOS_LOOKUP_MARKMARK: return Load_MarkMarkPos ( st, stream );\r
+ case HB_GPOS_LOOKUP_CONTEXT: return Load_ContextPos ( st, stream );\r
+ case HB_GPOS_LOOKUP_CHAIN: return Load_ChainContextPos ( st, stream );\r
+ /*case HB_GPOS_LOOKUP_EXTENSION: return Load_ExtensionPos ( st, stream );*/\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,\r
+ HB_UShort lookup_type )\r
+{\r
+ switch ( lookup_type ) {\r
+ case HB_GPOS_LOOKUP_SINGLE: Free_SinglePos ( st ); return;\r
+ case HB_GPOS_LOOKUP_PAIR: Free_PairPos ( st ); return;\r
+ case HB_GPOS_LOOKUP_CURSIVE: Free_CursivePos ( st ); return;\r
+ case HB_GPOS_LOOKUP_MARKBASE: Free_MarkBasePos ( st ); return;\r
+ case HB_GPOS_LOOKUP_MARKLIG: Free_MarkLigPos ( st ); return;\r
+ case HB_GPOS_LOOKUP_MARKMARK: Free_MarkMarkPos ( st ); return;\r
+ case HB_GPOS_LOOKUP_CONTEXT: Free_ContextPos ( st ); return;\r
+ case HB_GPOS_LOOKUP_CHAIN: Free_ChainContextPos ( st ); return;\r
+ /*case HB_GPOS_LOOKUP_EXTENSION: Free_ExtensionPos ( st ); return;*/\r
+ default: return;\r
+ }\r
+}\r
+\r
+\r
+/* apply one lookup to the input string object */\r
+\r
+static HB_Error GPOS_Do_String_Lookup( GPOS_Instance* gpi,\r
+ HB_UShort lookup_index,\r
+ HB_Buffer buffer )\r
+{\r
+ HB_Error error, retError = HB_Err_Not_Covered;\r
+ HB_GPOSHeader* gpos = gpi->gpos;\r
+\r
+ HB_UInt* properties = gpos->LookupList.Properties;\r
+\r
+ const int nesting_level = 0;\r
+ /* 0xFFFF indicates that we don't have a context length yet */\r
+ const HB_UShort context_length = 0xFFFF;\r
+\r
+\r
+ gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */\r
+\r
+ buffer->in_pos = 0;\r
+ while ( buffer->in_pos < buffer->in_length )\r
+ {\r
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )\r
+ {\r
+ /* Note that the connection between mark and base glyphs hold\r
+ exactly one (string) lookup. For example, it would be possible\r
+ that in the first lookup, mark glyph X is attached to base\r
+ glyph A, and in the next lookup it is attached to base glyph B.\r
+ It is up to the font designer to provide meaningful lookups and\r
+ lookup order. */\r
+\r
+ error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer, context_length, nesting_level );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+ else\r
+ {\r
+ /* Contrary to properties defined in GDEF, user-defined properties\r
+ will always stop a possible cursive positioning. */\r
+ gpi->last = 0xFFFF;\r
+\r
+ error = HB_Err_Not_Covered;\r
+ }\r
+\r
+ if ( error == HB_Err_Not_Covered )\r
+ (buffer->in_pos)++;\r
+ else\r
+ retError = error;\r
+ }\r
+\r
+ return retError;\r
+}\r
+\r
+\r
+static HB_Error Position_CursiveChain ( HB_Buffer buffer )\r
+{\r
+ HB_UInt i, j;\r
+ HB_Position positions = buffer->positions;\r
+\r
+ /* First handle all left-to-right connections */\r
+ for (j = 0; j < buffer->in_length; j++)\r
+ {\r
+ if (positions[j].cursive_chain > 0)\r
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;\r
+ }\r
+\r
+ /* Then handle all right-to-left connections */\r
+ for (i = buffer->in_length; i > 0; i--)\r
+ {\r
+ j = i - 1;\r
+\r
+ if (positions[j].cursive_chain < 0)\r
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+HB_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,\r
+ HB_UShort feature_index,\r
+ HB_UInt property )\r
+{\r
+ HB_UShort i;\r
+\r
+ HB_Feature feature;\r
+ HB_UInt* properties;\r
+ HB_UShort* index;\r
+ HB_UShort lookup_count;\r
+\r
+ /* Each feature can only be added once */\r
+\r
+ if ( !gpos ||\r
+ feature_index >= gpos->FeatureList.FeatureCount ||\r
+ gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;\r
+\r
+ properties = gpos->LookupList.Properties;\r
+\r
+ feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;\r
+ index = feature.LookupListIndex;\r
+ lookup_count = gpos->LookupList.LookupCount;\r
+\r
+ for ( i = 0; i < feature.LookupListCount; i++ )\r
+ {\r
+ HB_UShort lookup_index = index[i];\r
+ if (lookup_index < lookup_count)\r
+ properties[lookup_index] |= property;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos )\r
+{\r
+ HB_UShort i;\r
+\r
+ HB_UInt* properties;\r
+\r
+\r
+ if ( !gpos )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ gpos->FeatureList.ApplyCount = 0;\r
+\r
+ properties = gpos->LookupList.Properties;\r
+\r
+ for ( i = 0; i < gpos->LookupList.LookupCount; i++ )\r
+ properties[i] = 0;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,\r
+ HB_MMFunction mmfunc,\r
+ void* data )\r
+{\r
+ if ( !gpos )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ gpos->mmfunc = mmfunc;\r
+ gpos->data = data;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+/* If `dvi' is TRUE, glyph contour points for anchor points and device\r
+ tables are ignored -- you will get device independent values. */\r
+\r
+\r
+HB_Error HB_GPOS_Apply_String( HB_Font font,\r
+ HB_GPOSHeader* gpos,\r
+ HB_UShort load_flags,\r
+ HB_Buffer buffer,\r
+ HB_Bool dvi,\r
+ HB_Bool r2l )\r
+{\r
+ HB_Error error, retError = HB_Err_Not_Covered;\r
+ GPOS_Instance gpi;\r
+ int i, j, lookup_count, num_features;\r
+\r
+ if ( !font || !gpos || !buffer )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ if ( buffer->in_length == 0 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ gpi.font = font;\r
+ gpi.gpos = gpos;\r
+ gpi.load_flags = load_flags;\r
+ gpi.r2l = r2l;\r
+ gpi.dvi = dvi;\r
+\r
+ lookup_count = gpos->LookupList.LookupCount;\r
+ num_features = gpos->FeatureList.ApplyCount;\r
+\r
+ if ( num_features )\r
+ {\r
+ error = _hb_buffer_clear_positions( buffer );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ for ( i = 0; i < num_features; i++ )\r
+ {\r
+ HB_UShort feature_index = gpos->FeatureList.ApplyOrder[i];\r
+ HB_Feature feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;\r
+\r
+ for ( j = 0; j < feature.LookupListCount; j++ )\r
+ {\r
+ HB_UShort lookup_index = feature.LookupListIndex[j];\r
+\r
+ /* Skip nonexistant lookups */\r
+ if (lookup_index >= lookup_count)\r
+ continue;\r
+\r
+ error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer );\r
+ if ( error )\r
+ {\r
+ if ( error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+ else\r
+ retError = error;\r
+ }\r
+ }\r
+\r
+ if ( num_features )\r
+ {\r
+ error = Position_CursiveChain ( buffer );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ return retError;\r
+}\r
+\r
+/* END */\r
--- /dev/null
+/*\r
+ * Copyright (C) 1998-2004 David Turner and Werner Lemberg\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ * Copyright (C) 2007 Red Hat, Inc.\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Behdad Esfahbod\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-gsub-private.h"\r
+#include "harfbuzz-open-private.h"\r
+#include "harfbuzz-gdef-private.h"\r
+\r
+static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,\r
+ HB_UShort lookup_index,\r
+ HB_Buffer buffer,\r
+ HB_UShort context_length,\r
+ int nesting_level );\r
+\r
+\r
+\r
+/**********************\r
+ * Auxiliary functions\r
+ **********************/\r
+\r
+\r
+\r
+HB_Error HB_Load_GSUB_Table( HB_Stream stream,\r
+ HB_GSUBHeader** retptr,\r
+ HB_GDEFHeader* gdef,\r
+ HB_Stream gdefStream )\r
+{\r
+ HB_Error error;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_GSUBHeader* gsub;\r
+\r
+ if ( !retptr )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ if ( GOTO_Table( TTAG_GSUB ) )\r
+ return error;\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ALLOC ( gsub, sizeof( *gsub ), HB_GSUBHeader* ) ) \r
+ return error;\r
+ \r
+\r
+ /* skip version */\r
+\r
+ if ( FILE_Seek( base_offset + 4L ) ||\r
+ ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail4;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList,\r
+ stream, HB_Type_GSUB ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+\r
+ gsub->gdef = gdef; /* can be NULL */\r
+\r
+ if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,\r
+ gsub->LookupList.Lookup,\r
+ gsub->LookupList.LookupCount ) ) )\r
+ goto Fail1;\r
+\r
+ *retptr = gsub;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_FeatureList( &gsub->FeatureList );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_ScriptList( &gsub->ScriptList );\r
+\r
+Fail4:\r
+ FREE ( gsub );\r
+\r
+\r
+ return error;\r
+}\r
+\r
+\r
+HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub )\r
+{\r
+ _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );\r
+ _HB_OPEN_Free_FeatureList( &gsub->FeatureList );\r
+ _HB_OPEN_Free_ScriptList( &gsub->ScriptList );\r
+\r
+ FREE( gsub );\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+/*****************************\r
+ * SubTable related functions\r
+ *****************************/\r
+\r
+\r
+/* LookupType 1 */\r
+\r
+/* SingleSubstFormat1 */\r
+/* SingleSubstFormat2 */\r
+\r
+static HB_Error Load_SingleSubst( HB_GSUB_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_SingleSubst* ss = &st->single;\r
+\r
+ HB_UShort n, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_UShort* s;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ ss->SubstFormat = GET_UShort();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ switch ( ss->SubstFormat )\r
+ {\r
+ case 1:\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ ss->ssf.ssf1.DeltaGlyphID = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ break;\r
+\r
+ case 2:\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = ss->ssf.ssf2.GlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ss->ssf.ssf2.Substitute = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, HB_UShort ) )\r
+ goto Fail2;\r
+\r
+ s = ss->ssf.ssf2.Substitute;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ s[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( s );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &ss->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_SingleSubst( HB_GSUB_SubTable* st )\r
+{\r
+ HB_SingleSubst* ss = &st->single;\r
+\r
+ switch ( ss->SubstFormat )\r
+ {\r
+ case 1:\r
+ break;\r
+\r
+ case 2:\r
+ FREE( ss->ssf.ssf2.Substitute );\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &ss->Coverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_SingleSubst( HB_GSUBHeader* gsub,\r
+ HB_GSUB_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, value, property;\r
+ HB_Error error;\r
+ HB_SingleSubst* ss = &st->single;\r
+ HB_GDEFHeader* gdef = gsub->gdef;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ switch ( ss->SubstFormat )\r
+ {\r
+ case 1:\r
+ value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;\r
+ if ( REPLACE_Glyph( buffer, value, nesting_level ) )\r
+ return error;\r
+ break;\r
+\r
+ case 2:\r
+ if ( index >= ss->ssf.ssf2.GlyphCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+ value = ss->ssf.ssf2.Substitute[index];\r
+ if ( REPLACE_Glyph( buffer, value, nesting_level ) )\r
+ return error;\r
+ break;\r
+\r
+ default:\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+ }\r
+\r
+ if ( gdef && gdef->NewGlyphClasses )\r
+ {\r
+ /* we inherit the old glyph class to the substituted glyph */\r
+\r
+ error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 2 */\r
+\r
+/* Sequence */\r
+\r
+static HB_Error Load_Sequence( HB_Sequence* s,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* sub;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = s->GlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ s->Substitute = NULL;\r
+\r
+ if ( count )\r
+ {\r
+ if ( ALLOC_ARRAY( s->Substitute, count, HB_UShort ) )\r
+ return error;\r
+\r
+ sub = s->Substitute;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( sub );\r
+ return error;\r
+ }\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ sub[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_Sequence( HB_Sequence* s )\r
+{\r
+ FREE( s->Substitute );\r
+}\r
+\r
+\r
+/* MultipleSubstFormat1 */\r
+\r
+static HB_Error Load_MultipleSubst( HB_GSUB_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_MultipleSubst* ms = &st->multiple;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Sequence* s;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ ms->SubstFormat = GET_UShort(); /* should be 1 */\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = ms->SequenceCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ms->Sequence = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) )\r
+ goto Fail2;\r
+\r
+ s = ms->Sequence;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Sequence( &s[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_Sequence( &s[m] );\r
+\r
+ FREE( s );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &ms->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_MultipleSubst( HB_GSUB_SubTable* st )\r
+{\r
+ HB_UShort n, count;\r
+ HB_MultipleSubst* ms = &st->multiple;\r
+\r
+ HB_Sequence* s;\r
+\r
+\r
+ if ( ms->Sequence )\r
+ {\r
+ count = ms->SequenceCount;\r
+ s = ms->Sequence;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_Sequence( &s[n] );\r
+\r
+ FREE( s );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &ms->Coverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub,\r
+ HB_GSUB_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_Error error;\r
+ HB_UShort index, property, n, count;\r
+ HB_UShort*s;\r
+ HB_MultipleSubst* ms = &st->multiple;\r
+ HB_GDEFHeader* gdef = gsub->gdef;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( index >= ms->SequenceCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ count = ms->Sequence[index].GlyphCount;\r
+ s = ms->Sequence[index].Substitute;\r
+\r
+ if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )\r
+ return error;\r
+\r
+ if ( gdef && gdef->NewGlyphClasses )\r
+ {\r
+ /* this is a guess only ... */\r
+\r
+ if ( property == HB_GDEF_LIGATURE )\r
+ property = HB_GDEF_BASE_GLYPH;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 3 */\r
+\r
+/* AlternateSet */\r
+\r
+static HB_Error Load_AlternateSet( HB_AlternateSet* as,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* a;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = as->GlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ as->Alternate = NULL;\r
+\r
+ if ( ALLOC_ARRAY( as->Alternate, count, HB_UShort ) )\r
+ return error;\r
+\r
+ a = as->Alternate;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( a );\r
+ return error;\r
+ }\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ a[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_AlternateSet( HB_AlternateSet* as )\r
+{\r
+ FREE( as->Alternate );\r
+}\r
+\r
+\r
+/* AlternateSubstFormat1 */\r
+\r
+static HB_Error Load_AlternateSubst( HB_GSUB_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_AlternateSubst* as = &st->alternate;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_AlternateSet* aset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ as->SubstFormat = GET_UShort(); /* should be 1 */\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = as->AlternateSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ as->AlternateSet = NULL;\r
+\r
+ if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) )\r
+ goto Fail2;\r
+\r
+ aset = as->AlternateSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_AlternateSet( &aset[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_AlternateSet( &aset[m] );\r
+\r
+ FREE( aset );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &as->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_AlternateSubst( HB_GSUB_SubTable* st )\r
+{\r
+ HB_UShort n, count;\r
+ HB_AlternateSubst* as = &st->alternate;\r
+\r
+ HB_AlternateSet* aset;\r
+\r
+\r
+ if ( as->AlternateSet )\r
+ {\r
+ count = as->AlternateSetCount;\r
+ aset = as->AlternateSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_AlternateSet( &aset[n] );\r
+\r
+ FREE( aset );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &as->Coverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,\r
+ HB_GSUB_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_Error error;\r
+ HB_UShort index, value, alt_index, property;\r
+ HB_AlternateSubst* as = &st->alternate;\r
+ HB_GDEFHeader* gdef = gsub->gdef;\r
+ HB_AlternateSet aset;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( context_length != 0xFFFF && context_length < 1 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ aset = as->AlternateSet[index];\r
+\r
+ /* we use a user-defined callback function to get the alternate index */\r
+\r
+ if ( gsub->altfunc )\r
+ alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(),\r
+ aset.GlyphCount, aset.Alternate,\r
+ gsub->data );\r
+ else\r
+ alt_index = 0;\r
+\r
+ value = aset.Alternate[alt_index];\r
+ if ( REPLACE_Glyph( buffer, value, nesting_level ) )\r
+ return error;\r
+\r
+ if ( gdef && gdef->NewGlyphClasses )\r
+ {\r
+ /* we inherit the old glyph class to the substituted glyph */\r
+\r
+ error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 4 */\r
+\r
+/* Ligature */\r
+\r
+static HB_Error Load_Ligature( HB_Ligature* l,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* c;\r
+\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ l->LigGlyph = GET_UShort();\r
+ l->ComponentCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ l->Component = NULL;\r
+\r
+ count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( l->Component, count, HB_UShort ) )\r
+ return error;\r
+\r
+ c = l->Component;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( c );\r
+ return error;\r
+ }\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ c[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_Ligature( HB_Ligature* l )\r
+{\r
+ FREE( l->Component );\r
+}\r
+\r
+\r
+/* LigatureSet */\r
+\r
+static HB_Error Load_LigatureSet( HB_LigatureSet* ls,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Ligature* l;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = ls->LigatureCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ls->Ligature = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) )\r
+ return error;\r
+\r
+ l = ls->Ligature;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Ligature( &l[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_Ligature( &l[m] );\r
+\r
+ FREE( l );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_LigatureSet( HB_LigatureSet* ls )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_Ligature* l;\r
+\r
+\r
+ if ( ls->Ligature )\r
+ {\r
+ count = ls->LigatureCount;\r
+ l = ls->Ligature;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_Ligature( &l[n] );\r
+\r
+ FREE( l );\r
+ }\r
+}\r
+\r
+\r
+/* LigatureSubstFormat1 */\r
+\r
+static HB_Error Load_LigatureSubst( HB_GSUB_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_LigatureSubst* ls = &st->ligature;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_LigatureSet* lset;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ ls->SubstFormat = GET_UShort(); /* should be 1 */\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = ls->LigatureSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ls->LigatureSet = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) )\r
+ goto Fail2;\r
+\r
+ lset = ls->LigatureSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_LigatureSet( &lset[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_LigatureSet( &lset[m] );\r
+\r
+ FREE( lset );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &ls->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_LigatureSubst( HB_GSUB_SubTable* st )\r
+{\r
+ HB_UShort n, count;\r
+ HB_LigatureSubst* ls = &st->ligature;\r
+\r
+ HB_LigatureSet* lset;\r
+\r
+\r
+ if ( ls->LigatureSet )\r
+ {\r
+ count = ls->LigatureSetCount;\r
+ lset = ls->LigatureSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_LigatureSet( &lset[n] );\r
+\r
+ FREE( lset );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &ls->Coverage );\r
+}\r
+\r
+\r
+static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,\r
+ HB_GSUB_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_Error error;\r
+ HB_UShort numlig, i, j, is_mark, first_is_mark = FALSE;\r
+ HB_UShort* c;\r
+ HB_LigatureSubst* ls = &st->ligature;\r
+ HB_GDEFHeader* gdef = gsub->gdef;\r
+\r
+ HB_Ligature* lig;\r
+\r
+ HB_UNUSED(nesting_level);\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )\r
+ first_is_mark = TRUE;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( index >= ls->LigatureSetCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ lig = ls->LigatureSet[index].Ligature;\r
+\r
+ for ( numlig = ls->LigatureSet[index].LigatureCount;\r
+ numlig;\r
+ numlig--, lig++ )\r
+ {\r
+ if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )\r
+ goto next_ligature; /* Not enough glyphs in input */\r
+\r
+ c = lig->Component;\r
+\r
+ is_mark = first_is_mark;\r
+\r
+ if ( context_length != 0xFFFF && context_length < lig->ComponentCount )\r
+ break;\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + lig->ComponentCount - i == (HB_Int)buffer->in_length )\r
+ goto next_ligature;\r
+ j++;\r
+ }\r
+\r
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )\r
+ is_mark = FALSE;\r
+\r
+ if ( IN_GLYPH( j ) != c[i - 1] )\r
+ goto next_ligature;\r
+ }\r
+\r
+ if ( gdef && gdef->NewGlyphClasses )\r
+ {\r
+ /* this is just a guess ... */\r
+\r
+ error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph,\r
+ is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+\r
+ if ( j == buffer->in_pos + i ) /* No input glyphs skipped */\r
+ {\r
+ /* We don't use a new ligature ID if there are no skipped\r
+ glyphs and the ligature already has an ID. */\r
+\r
+ if ( IN_LIGID( buffer->in_pos ) )\r
+ {\r
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,\r
+ 0xFFFF, 0xFFFF ) )\r
+ return error;\r
+ }\r
+ else\r
+ {\r
+ HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );\r
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,\r
+ 0xFFFF, ligID ) )\r
+ return error;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );\r
+ if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) )\r
+ return error;\r
+\r
+ /* Now we must do a second loop to copy the skipped glyphs to\r
+ `out' and assign component values to it. We start with the\r
+ glyph after the first component. Glyphs between component\r
+ i and i+1 belong to component i. Together with the ligID\r
+ value it is later possible to check whether a specific\r
+ component value really belongs to a given ligature. */\r
+\r
+ for ( i = 0; i < lig->ComponentCount - 1; i++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_CURITEM(),\r
+ flags, &property ) )\r
+ if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )\r
+ return error;\r
+\r
+ (buffer->in_pos)++;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+ next_ligature:\r
+ ;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+/* Do the actual substitution for a context substitution (either format\r
+ 5 or 6). This is only called after we've determined that the input\r
+ matches the subrule. */\r
+\r
+static HB_Error Do_ContextSubst( HB_GSUBHeader* gsub,\r
+ HB_UShort GlyphCount,\r
+ HB_UShort SubstCount,\r
+ HB_SubstLookupRecord* subst,\r
+ HB_Buffer buffer,\r
+ int nesting_level )\r
+{\r
+ HB_Error error;\r
+ HB_UInt i, old_pos;\r
+\r
+\r
+ i = 0;\r
+\r
+ while ( i < GlyphCount )\r
+ {\r
+ if ( SubstCount && i == subst->SequenceIndex )\r
+ {\r
+ old_pos = buffer->in_pos;\r
+\r
+ /* Do a substitution */\r
+\r
+ error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,\r
+ GlyphCount, nesting_level );\r
+\r
+ subst++;\r
+ SubstCount--;\r
+ i += buffer->in_pos - old_pos;\r
+\r
+ if ( error == HB_Err_Not_Covered )\r
+ {\r
+ if ( COPY_Glyph( buffer ) )\r
+ return error;\r
+ i++;\r
+ }\r
+ else if ( error )\r
+ return error;\r
+ }\r
+ else\r
+ {\r
+ /* No substitution for this index */\r
+\r
+ if ( COPY_Glyph( buffer ) )\r
+ return error;\r
+ i++;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* LookupType 5 */\r
+\r
+/* SubRule */\r
+\r
+static HB_Error Load_SubRule( HB_SubRule* sr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* i;\r
+\r
+ HB_SubstLookupRecord* slr;\r
+\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ sr->GlyphCount = GET_UShort();\r
+ sr->SubstCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ sr->Input = NULL;\r
+\r
+ count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( sr->Input, count, HB_UShort ) )\r
+ return error;\r
+\r
+ i = sr->Input;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ i[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ sr->SubstLookupRecord = NULL;\r
+\r
+ count = sr->SubstCount;\r
+\r
+ if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ slr = sr->SubstLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ slr[n].SequenceIndex = GET_UShort();\r
+ slr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( slr );\r
+\r
+Fail2:\r
+ FREE( i );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_SubRule( HB_SubRule* sr )\r
+{\r
+ FREE( sr->SubstLookupRecord );\r
+ FREE( sr->Input );\r
+}\r
+\r
+\r
+/* SubRuleSet */\r
+\r
+static HB_Error Load_SubRuleSet( HB_SubRuleSet* srs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_SubRule* sr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = srs->SubRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ srs->SubRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) )\r
+ return error;\r
+\r
+ sr = srs->SubRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_SubRule( &sr[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_SubRule( &sr[m] );\r
+\r
+ FREE( sr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_SubRuleSet( HB_SubRuleSet* srs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_SubRule* sr;\r
+\r
+\r
+ if ( srs->SubRule )\r
+ {\r
+ count = srs->SubRuleCount;\r
+ sr = srs->SubRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_SubRule( &sr[n] );\r
+\r
+ FREE( sr );\r
+ }\r
+}\r
+\r
+\r
+/* ContextSubstFormat1 */\r
+\r
+static HB_Error Load_ContextSubst1( HB_ContextSubstFormat1* csf1,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_SubRuleSet* srs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = csf1->SubRuleSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ csf1->SubRuleSet = NULL;\r
+\r
+ if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) )\r
+ goto Fail2;\r
+\r
+ srs = csf1->SubRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_SubRuleSet( &srs[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_SubRuleSet( &srs[m] );\r
+\r
+ FREE( srs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &csf1->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ContextSubst1( HB_ContextSubstFormat1* csf1 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_SubRuleSet* srs;\r
+\r
+\r
+ if ( csf1->SubRuleSet )\r
+ {\r
+ count = csf1->SubRuleSetCount;\r
+ srs = csf1->SubRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_SubRuleSet( &srs[n] );\r
+\r
+ FREE( srs );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &csf1->Coverage );\r
+}\r
+\r
+\r
+/* SubClassRule */\r
+\r
+static HB_Error Load_SubClassRule( HB_ContextSubstFormat2* csf2,\r
+ HB_SubClassRule* scr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* c;\r
+ HB_SubstLookupRecord* slr;\r
+\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ scr->GlyphCount = GET_UShort();\r
+ scr->SubstCount = GET_UShort();\r
+\r
+ if ( scr->GlyphCount > csf2->MaxContextLength )\r
+ csf2->MaxContextLength = scr->GlyphCount;\r
+\r
+ FORGET_Frame();\r
+\r
+ scr->Class = NULL;\r
+\r
+ count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) )\r
+ return error;\r
+\r
+ c = scr->Class;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ c[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ scr->SubstLookupRecord = NULL;\r
+\r
+ count = scr->SubstCount;\r
+\r
+ if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ slr = scr->SubstLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ slr[n].SequenceIndex = GET_UShort();\r
+ slr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( slr );\r
+\r
+Fail2:\r
+ FREE( c );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_SubClassRule( HB_SubClassRule* scr )\r
+{\r
+ FREE( scr->SubstLookupRecord );\r
+ FREE( scr->Class );\r
+}\r
+\r
+\r
+/* SubClassSet */\r
+\r
+static HB_Error Load_SubClassSet( HB_ContextSubstFormat2* csf2,\r
+ HB_SubClassSet* scs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_SubClassRule* scr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = scs->SubClassRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ scs->SubClassRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) )\r
+ return error;\r
+\r
+ scr = scs->SubClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_SubClassRule( csf2, &scr[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_SubClassRule( &scr[m] );\r
+\r
+ FREE( scr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_SubClassSet( HB_SubClassSet* scs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_SubClassRule* scr;\r
+\r
+\r
+ if ( scs->SubClassRule )\r
+ {\r
+ count = scs->SubClassRuleCount;\r
+ scr = scs->SubClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_SubClassRule( &scr[n] );\r
+\r
+ FREE( scr );\r
+ }\r
+}\r
+\r
+\r
+/* ContextSubstFormat2 */\r
+\r
+static HB_Error Load_ContextSubst2( HB_ContextSubstFormat2* csf2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_SubClassSet* scs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ /* `SubClassSetCount' is the upper limit for class values, thus we\r
+ read it now to make an additional safety check. */\r
+\r
+ count = csf2->SubClassSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ csf2->SubClassSet = NULL;\r
+ csf2->MaxContextLength = 0;\r
+\r
+ if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) )\r
+ goto Fail2;\r
+\r
+ scs = csf2->SubClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset != base_offset ) /* not a NULL offset */\r
+ {\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_SubClassSet( csf2, &scs[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ {\r
+ /* we create a SubClassSet table with no entries */\r
+\r
+ csf2->SubClassSet[n].SubClassRuleCount = 0;\r
+ csf2->SubClassSet[n].SubClassRule = NULL;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_SubClassSet( &scs[m] );\r
+\r
+ FREE( scs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_Coverage( &csf2->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ContextSubst2( HB_ContextSubstFormat2* csf2 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_SubClassSet* scs;\r
+\r
+\r
+ if ( csf2->SubClassSet )\r
+ {\r
+ count = csf2->SubClassSetCount;\r
+ scs = csf2->SubClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_SubClassSet( &scs[n] );\r
+\r
+ FREE( scs );\r
+ }\r
+\r
+ _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );\r
+ _HB_OPEN_Free_Coverage( &csf2->Coverage );\r
+}\r
+\r
+\r
+/* ContextSubstFormat3 */\r
+\r
+static HB_Error Load_ContextSubst3( HB_ContextSubstFormat3* csf3,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Coverage* c;\r
+ HB_SubstLookupRecord* slr;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ csf3->GlyphCount = GET_UShort();\r
+ csf3->SubstCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ csf3->Coverage = NULL;\r
+\r
+ count = csf3->GlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) )\r
+ return error;\r
+\r
+ c = csf3->Coverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ csf3->SubstLookupRecord = NULL;\r
+\r
+ count = csf3->SubstCount;\r
+\r
+ if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,\r
+ HB_SubstLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ slr = csf3->SubstLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ slr[n].SequenceIndex = GET_UShort();\r
+ slr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( slr );\r
+\r
+Fail2:\r
+ for ( m = 0; m < n; m++ )\r
+ _HB_OPEN_Free_Coverage( &c[m] );\r
+\r
+ FREE( c );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ContextSubst3( HB_ContextSubstFormat3* csf3 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_Coverage* c;\r
+\r
+\r
+ FREE( csf3->SubstLookupRecord );\r
+\r
+ if ( csf3->Coverage )\r
+ {\r
+ count = csf3->GlyphCount;\r
+ c = csf3->Coverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+}\r
+\r
+\r
+/* ContextSubst */\r
+\r
+static HB_Error Load_ContextSubst( HB_GSUB_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_ContextSubst* cs = &st->context;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cs->SubstFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( cs->SubstFormat )\r
+ {\r
+ case 1: return Load_ContextSubst1( &cs->csf.csf1, stream );\r
+ case 2: return Load_ContextSubst2( &cs->csf.csf2, stream );\r
+ case 3: return Load_ContextSubst3( &cs->csf.csf3, stream );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+static void Free_ContextSubst( HB_GSUB_SubTable* st )\r
+{\r
+ HB_ContextSubst* cs = &st->context;\r
+\r
+ switch ( cs->SubstFormat )\r
+ {\r
+ case 1: Free_ContextSubst1( &cs->csf.csf1 ); break;\r
+ case 2: Free_ContextSubst2( &cs->csf.csf2 ); break;\r
+ case 3: Free_ContextSubst3( &cs->csf.csf3 ); break;\r
+ default: break;\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,\r
+ HB_ContextSubstFormat1* csf1,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_UShort i, j, k, numsr;\r
+ HB_Error error;\r
+\r
+ HB_SubRule* sr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gsub->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ sr = csf1->SubRuleSet[index].SubRule;\r
+ numsr = csf1->SubRuleSet[index].SubRuleCount;\r
+\r
+ for ( k = 0; k < numsr; k++ )\r
+ {\r
+ if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )\r
+ goto next_subrule;\r
+\r
+ if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )\r
+ goto next_subrule; /* context is too long */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + sr[k].GlyphCount - i == (HB_Int)buffer->in_length )\r
+ goto next_subrule;\r
+ j++;\r
+ }\r
+\r
+ if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )\r
+ goto next_subrule;\r
+ }\r
+\r
+ return Do_ContextSubst( gsub, sr[k].GlyphCount,\r
+ sr[k].SubstCount, sr[k].SubstLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+ next_subrule:\r
+ ;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,\r
+ HB_ContextSubstFormat2* csf2,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_Error error;\r
+ HB_UShort i, j, k, known_classes;\r
+\r
+ HB_UShort* classes;\r
+ HB_UShort* cl;\r
+\r
+ HB_SubClassSet* scs;\r
+ HB_SubClassRule* sr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gsub->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ /* Note: The coverage table in format 2 doesn't give an index into\r
+ anything. It just lets us know whether or not we need to\r
+ do any lookup at all. */\r
+\r
+ error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ if (csf2->MaxContextLength < 1)\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(),\r
+ &classes[0], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End;\r
+ known_classes = 0;\r
+\r
+ scs = &csf2->SubClassSet[classes[0]];\r
+ if ( !scs )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_SubTable);\r
+ goto End;\r
+ }\r
+\r
+ for ( k = 0; k < scs->SubClassRuleCount; k++ )\r
+ {\r
+ sr = &scs->SubClassRule[k];\r
+\r
+ if ( context_length != 0xFFFF && context_length < sr->GlyphCount )\r
+ goto next_subclassrule;\r
+\r
+ if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )\r
+ goto next_subclassrule; /* context is too long */\r
+\r
+ cl = sr->Class;\r
+\r
+ /* Start at 1 because [0] is implied */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End;\r
+\r
+ if ( j + sr->GlyphCount - i < (HB_Int)buffer->in_length )\r
+ goto next_subclassrule;\r
+ j++;\r
+ }\r
+\r
+ if ( i > known_classes )\r
+ {\r
+ /* Keeps us from having to do this for each rule */\r
+\r
+ error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End;\r
+ known_classes = i;\r
+ }\r
+\r
+ if ( cl[i - 1] != classes[i] )\r
+ goto next_subclassrule;\r
+ }\r
+\r
+ error = Do_ContextSubst( gsub, sr->GlyphCount,\r
+ sr->SubstCount, sr->SubstLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+ goto End;\r
+\r
+ next_subclassrule:\r
+ ;\r
+ }\r
+\r
+ error = HB_Err_Not_Covered;\r
+\r
+End:\r
+ FREE( classes );\r
+ return error;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,\r
+ HB_ContextSubstFormat3* csf3,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_Error error;\r
+ HB_UShort index, i, j, property;\r
+\r
+ HB_Coverage* c;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gsub->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )\r
+ return HB_Err_Not_Covered; /* context is too long */\r
+\r
+ c = csf3->Coverage;\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + csf3->GlyphCount - i == (HB_Int)buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+ j++;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ return Do_ContextSubst( gsub, csf3->GlyphCount,\r
+ csf3->SubstCount, csf3->SubstLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+}\r
+\r
+\r
+static HB_Error Lookup_ContextSubst( HB_GSUBHeader* gsub,\r
+ HB_GSUB_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_ContextSubst* cs = &st->context;\r
+\r
+ switch ( cs->SubstFormat )\r
+ {\r
+ case 1: return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level );\r
+ case 2: return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level );\r
+ case 3: return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+/* LookupType 6 */\r
+\r
+/* ChainSubRule */\r
+\r
+static HB_Error Load_ChainSubRule( HB_ChainSubRule* csr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+ HB_UShort* b;\r
+ HB_UShort* i;\r
+ HB_UShort* l;\r
+\r
+ HB_SubstLookupRecord* slr;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ csr->BacktrackGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ csr->Backtrack = NULL;\r
+\r
+ count = csr->BacktrackGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( csr->Backtrack, count, HB_UShort ) )\r
+ return error;\r
+\r
+ b = csr->Backtrack;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail4;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ b[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ csr->InputGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ csr->Input = NULL;\r
+\r
+ count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( csr->Input, count, HB_UShort ) )\r
+ goto Fail4;\r
+\r
+ i = csr->Input;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail3;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ i[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ csr->LookaheadGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ csr->Lookahead = NULL;\r
+\r
+ count = csr->LookaheadGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( csr->Lookahead, count, HB_UShort ) )\r
+ goto Fail3;\r
+\r
+ l = csr->Lookahead;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ l[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ csr->SubstCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ csr->SubstLookupRecord = NULL;\r
+\r
+ count = csr->SubstCount;\r
+\r
+ if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ slr = csr->SubstLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ slr[n].SequenceIndex = GET_UShort();\r
+ slr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( slr );\r
+\r
+Fail2:\r
+ FREE( l );\r
+\r
+Fail3:\r
+ FREE( i );\r
+\r
+Fail4:\r
+ FREE( b );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainSubRule( HB_ChainSubRule* csr )\r
+{\r
+ FREE( csr->SubstLookupRecord );\r
+ FREE( csr->Lookahead );\r
+ FREE( csr->Input );\r
+ FREE( csr->Backtrack );\r
+}\r
+\r
+\r
+/* ChainSubRuleSet */\r
+\r
+static HB_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ChainSubRule* csr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = csrs->ChainSubRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ csrs->ChainSubRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) )\r
+ return error;\r
+\r
+ csr = csrs->ChainSubRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainSubRule( &csr[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainSubRule( &csr[m] );\r
+\r
+ FREE( csr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainSubRule* csr;\r
+\r
+\r
+ if ( csrs->ChainSubRule )\r
+ {\r
+ count = csrs->ChainSubRuleCount;\r
+ csr = csrs->ChainSubRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainSubRule( &csr[n] );\r
+\r
+ FREE( csr );\r
+ }\r
+}\r
+\r
+\r
+/* ChainContextSubstFormat1 */\r
+\r
+static HB_Error Load_ChainContextSubst1(\r
+ HB_ChainContextSubstFormat1* ccsf1,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ChainSubRuleSet* csrs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = ccsf1->ChainSubRuleSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccsf1->ChainSubRuleSet = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) )\r
+ goto Fail2;\r
+\r
+ csrs = ccsf1->ChainSubRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainSubRuleSet( &csrs[m] );\r
+\r
+ FREE( csrs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_Coverage( &ccsf1->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainSubRuleSet* csrs;\r
+\r
+\r
+ if ( ccsf1->ChainSubRuleSet )\r
+ {\r
+ count = ccsf1->ChainSubRuleSetCount;\r
+ csrs = ccsf1->ChainSubRuleSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainSubRuleSet( &csrs[n] );\r
+\r
+ FREE( csrs );\r
+ }\r
+\r
+ _HB_OPEN_Free_Coverage( &ccsf1->Coverage );\r
+}\r
+\r
+\r
+/* ChainSubClassRule */\r
+\r
+static HB_Error Load_ChainSubClassRule(\r
+ HB_ChainContextSubstFormat2* ccsf2,\r
+ HB_ChainSubClassRule* cscr,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* b;\r
+ HB_UShort* i;\r
+ HB_UShort* l;\r
+ HB_SubstLookupRecord* slr;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cscr->BacktrackGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )\r
+ ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;\r
+\r
+ cscr->Backtrack = NULL;\r
+\r
+ count = cscr->BacktrackGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) )\r
+ return error;\r
+\r
+ b = cscr->Backtrack;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail4;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ b[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ cscr->InputGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )\r
+ ccsf2->MaxInputLength = cscr->InputGlyphCount;\r
+\r
+ cscr->Input = NULL;\r
+\r
+ count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */\r
+\r
+ if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) )\r
+ goto Fail4;\r
+\r
+ i = cscr->Input;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail3;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ i[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ cscr->LookaheadGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )\r
+ ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;\r
+\r
+ cscr->Lookahead = NULL;\r
+\r
+ count = cscr->LookaheadGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( cscr->Lookahead, count, HB_UShort ) )\r
+ goto Fail3;\r
+\r
+ l = cscr->Lookahead;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail2;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ l[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ cscr->SubstCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cscr->SubstLookupRecord = NULL;\r
+\r
+ count = cscr->SubstCount;\r
+\r
+ if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,\r
+ HB_SubstLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ slr = cscr->SubstLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ slr[n].SequenceIndex = GET_UShort();\r
+ slr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( slr );\r
+\r
+Fail2:\r
+ FREE( l );\r
+\r
+Fail3:\r
+ FREE( i );\r
+\r
+Fail4:\r
+ FREE( b );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr )\r
+{\r
+ FREE( cscr->SubstLookupRecord );\r
+ FREE( cscr->Lookahead );\r
+ FREE( cscr->Input );\r
+ FREE( cscr->Backtrack );\r
+}\r
+\r
+\r
+/* SubClassSet */\r
+\r
+static HB_Error Load_ChainSubClassSet(\r
+ HB_ChainContextSubstFormat2* ccsf2,\r
+ HB_ChainSubClassSet* cscs,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ChainSubClassRule* cscr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = cscs->ChainSubClassRuleCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cscs->ChainSubClassRule = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,\r
+ HB_ChainSubClassRule ) )\r
+ return error;\r
+\r
+ cscr = cscs->ChainSubClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainSubClassRule( &cscr[m] );\r
+\r
+ FREE( cscr );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainSubClassRule* cscr;\r
+\r
+\r
+ if ( cscs->ChainSubClassRule )\r
+ {\r
+ count = cscs->ChainSubClassRuleCount;\r
+ cscr = cscs->ChainSubClassRule;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainSubClassRule( &cscr[n] );\r
+\r
+ FREE( cscr );\r
+ }\r
+}\r
+\r
+\r
+/* ChainContextSubstFormat2 */\r
+\r
+static HB_Error Load_ChainContextSubst2(\r
+ HB_ChainContextSubstFormat2* ccsf2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n = 0, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+ HB_UInt backtrack_offset, input_offset, lookahead_offset;\r
+\r
+ HB_ChainSubClassSet* cscs;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+ if ( ACCESS_Frame( 8L ) )\r
+ goto Fail5;\r
+\r
+ backtrack_offset = GET_UShort();\r
+ input_offset = GET_UShort();\r
+ lookahead_offset = GET_UShort();\r
+\r
+ /* `ChainSubClassSetCount' is the upper limit for input class values,\r
+ thus we read it now to make an additional safety check. No limit\r
+ is known or needed for the other two class definitions */\r
+\r
+ count = ccsf2->ChainSubClassSetCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,\r
+ backtrack_offset, base_offset,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail5;\r
+\r
+ if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,\r
+ input_offset, base_offset,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail4;\r
+ if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,\r
+ lookahead_offset, base_offset,\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+\r
+ ccsf2->ChainSubClassSet = NULL;\r
+ ccsf2->MaxBacktrackLength = 0;\r
+ ccsf2->MaxInputLength = 0;\r
+ ccsf2->MaxLookaheadLength = 0;\r
+\r
+ if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) )\r
+ goto Fail2;\r
+\r
+ cscs = ccsf2->ChainSubClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset != base_offset ) /* not a NULL offset */\r
+ {\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],\r
+ stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ {\r
+ /* we create a ChainSubClassSet table with no entries */\r
+\r
+ ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;\r
+ ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_ChainSubClassSet( &cscs[m] );\r
+\r
+ FREE( cscs );\r
+\r
+Fail2:\r
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );\r
+\r
+Fail3:\r
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );\r
+\r
+Fail4:\r
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );\r
+\r
+Fail5:\r
+ _HB_OPEN_Free_Coverage( &ccsf2->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ChainSubClassSet* cscs;\r
+\r
+\r
+ if ( ccsf2->ChainSubClassSet )\r
+ {\r
+ count = ccsf2->ChainSubClassSetCount;\r
+ cscs = ccsf2->ChainSubClassSet;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_ChainSubClassSet( &cscs[n] );\r
+\r
+ FREE( cscs );\r
+ }\r
+\r
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );\r
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );\r
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );\r
+\r
+ _HB_OPEN_Free_Coverage( &ccsf2->Coverage );\r
+}\r
+\r
+\r
+/* ChainContextSubstFormat3 */\r
+\r
+static HB_Error Load_ChainContextSubst3(\r
+ HB_ChainContextSubstFormat3* ccsf3,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, nb = 0, ni =0, nl = 0, m, count;\r
+ HB_UShort backtrack_count, input_count, lookahead_count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Coverage* b;\r
+ HB_Coverage* i;\r
+ HB_Coverage* l;\r
+ HB_SubstLookupRecord* slr;\r
+\r
+\r
+ base_offset = FILE_Pos() - 2L;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ ccsf3->BacktrackGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccsf3->BacktrackCoverage = NULL;\r
+\r
+ backtrack_count = ccsf3->BacktrackGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,\r
+ HB_Coverage ) )\r
+ return error;\r
+\r
+ b = ccsf3->BacktrackCoverage;\r
+\r
+ for ( nb = 0; nb < backtrack_count; nb++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )\r
+ goto Fail4;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ ccsf3->InputGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccsf3->InputCoverage = NULL;\r
+\r
+ input_count = ccsf3->InputGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) )\r
+ goto Fail4;\r
+\r
+ i = ccsf3->InputCoverage;\r
+\r
+ for ( ni = 0; ni < input_count; ni++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ ccsf3->LookaheadGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccsf3->LookaheadCoverage = NULL;\r
+\r
+ lookahead_count = ccsf3->LookaheadGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,\r
+ HB_Coverage ) )\r
+ goto Fail3;\r
+\r
+ l = ccsf3->LookaheadCoverage;\r
+\r
+ for ( nl = 0; nl < lookahead_count; nl++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ ccsf3->SubstCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ccsf3->SubstLookupRecord = NULL;\r
+\r
+ count = ccsf3->SubstCount;\r
+\r
+ if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,\r
+ HB_SubstLookupRecord ) )\r
+ goto Fail2;\r
+\r
+ slr = ccsf3->SubstLookupRecord;\r
+\r
+ if ( ACCESS_Frame( count * 4L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ slr[n].SequenceIndex = GET_UShort();\r
+ slr[n].LookupListIndex = GET_UShort();\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( slr );\r
+\r
+Fail2:\r
+ for ( m = 0; m < nl; m++ )\r
+ _HB_OPEN_Free_Coverage( &l[m] );\r
+\r
+ FREE( l );\r
+\r
+Fail3:\r
+ for ( m = 0; m < ni; m++ )\r
+ _HB_OPEN_Free_Coverage( &i[m] );\r
+\r
+ FREE( i );\r
+\r
+Fail4:\r
+ for ( m = 0; m < nb; m++ )\r
+ _HB_OPEN_Free_Coverage( &b[m] );\r
+\r
+ FREE( b );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3 )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_Coverage* c;\r
+\r
+\r
+ FREE( ccsf3->SubstLookupRecord );\r
+\r
+ if ( ccsf3->LookaheadCoverage )\r
+ {\r
+ count = ccsf3->LookaheadGlyphCount;\r
+ c = ccsf3->LookaheadCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+\r
+ if ( ccsf3->InputCoverage )\r
+ {\r
+ count = ccsf3->InputGlyphCount;\r
+ c = ccsf3->InputCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+\r
+ if ( ccsf3->BacktrackCoverage )\r
+ {\r
+ count = ccsf3->BacktrackGlyphCount;\r
+ c = ccsf3->BacktrackCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+}\r
+\r
+\r
+/* ChainContextSubst */\r
+\r
+static HB_Error Load_ChainContextSubst( HB_GSUB_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_ChainContextSubst* ccs = &st->chain;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ ccs->SubstFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( ccs->SubstFormat ) {\r
+ case 1: return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );\r
+ case 2: return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );\r
+ case 3: return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+static void Free_ChainContextSubst( HB_GSUB_SubTable* st )\r
+{\r
+ HB_ChainContextSubst* ccs = &st->chain;\r
+\r
+ switch ( ccs->SubstFormat ) {\r
+ case 1: Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break;\r
+ case 2: Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break;\r
+ case 3: Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break;\r
+ default: break;\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,\r
+ HB_ChainContextSubstFormat1* ccsf1,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_UShort i, j, k, num_csr;\r
+ HB_UShort bgc, igc, lgc;\r
+ HB_Error error;\r
+\r
+ HB_ChainSubRule* csr;\r
+ HB_ChainSubRule curr_csr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gsub->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ csr = ccsf1->ChainSubRuleSet[index].ChainSubRule;\r
+ num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;\r
+\r
+ for ( k = 0; k < num_csr; k++ )\r
+ {\r
+ curr_csr = csr[k];\r
+ bgc = curr_csr.BacktrackGlyphCount;\r
+ igc = curr_csr.InputGlyphCount;\r
+ lgc = curr_csr.LookaheadGlyphCount;\r
+\r
+ if ( context_length != 0xFFFF && context_length < igc )\r
+ goto next_chainsubrule;\r
+\r
+ /* check whether context is too long; it is a first guess only */\r
+\r
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )\r
+ goto next_chainsubrule;\r
+\r
+ if ( bgc )\r
+ {\r
+ /* since we don't know in advance the number of glyphs to inspect,\r
+ we search backwards for matches in the backtrack glyph array */\r
+\r
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )\r
+ {\r
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + 1 == bgc - i )\r
+ goto next_chainsubrule;\r
+ j--;\r
+ }\r
+\r
+ /* In OpenType 1.3, it is undefined whether the offsets of\r
+ backtrack glyphs is in logical order or not. Version 1.4\r
+ will clarify this:\r
+\r
+ Logical order - a b c d e f g h i j\r
+ i\r
+ Input offsets - 0 1\r
+ Backtrack offsets - 3 2 1 0\r
+ Lookahead offsets - 0 1 2 3 */\r
+\r
+ if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )\r
+ goto next_chainsubrule;\r
+ }\r
+ }\r
+\r
+ /* Start at 1 because [0] is implied */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + igc - i + lgc == (HB_Int)buffer->in_length )\r
+ goto next_chainsubrule;\r
+ j++;\r
+ }\r
+\r
+ if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )\r
+ goto next_chainsubrule;\r
+ }\r
+\r
+ /* we are starting to check for lookahead glyphs right after the\r
+ last context glyph */\r
+\r
+ for ( i = 0; i < lgc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + lgc - i == (HB_Int)buffer->in_length )\r
+ goto next_chainsubrule;\r
+ j++;\r
+ }\r
+\r
+ if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )\r
+ goto next_chainsubrule;\r
+ }\r
+\r
+ return Do_ContextSubst( gsub, igc,\r
+ curr_csr.SubstCount,\r
+ curr_csr.SubstLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+\r
+ next_chainsubrule:\r
+ ;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,\r
+ HB_ChainContextSubstFormat2* ccsf2,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, property;\r
+ HB_Error error;\r
+ HB_UShort i, j, k;\r
+ HB_UShort bgc, igc, lgc;\r
+ HB_UShort known_backtrack_classes,\r
+ known_input_classes,\r
+ known_lookahead_classes;\r
+\r
+ HB_UShort* backtrack_classes;\r
+ HB_UShort* input_classes;\r
+ HB_UShort* lookahead_classes;\r
+\r
+ HB_UShort* bc;\r
+ HB_UShort* ic;\r
+ HB_UShort* lc;\r
+\r
+ HB_ChainSubClassSet* cscs;\r
+ HB_ChainSubClassRule ccsr;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gsub->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ /* Note: The coverage table in format 2 doesn't give an index into\r
+ anything. It just lets us know whether or not we need to\r
+ do any lookup at all. */\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index );\r
+ if ( error )\r
+ return error;\r
+\r
+ if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, HB_UShort ) )\r
+ return error;\r
+ known_backtrack_classes = 0;\r
+\r
+ if (ccsf2->MaxInputLength < 1)\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, HB_UShort ) )\r
+ goto End3;\r
+ known_input_classes = 1;\r
+\r
+ if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, HB_UShort ) )\r
+ goto End2;\r
+ known_lookahead_classes = 0;\r
+\r
+ error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(),\r
+ &input_classes[0], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ cscs = &ccsf2->ChainSubClassSet[input_classes[0]];\r
+ if ( !cscs )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_SubTable);\r
+ goto End1;\r
+ }\r
+\r
+ for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ )\r
+ {\r
+ ccsr = cscs->ChainSubClassRule[k];\r
+ bgc = ccsr.BacktrackGlyphCount;\r
+ igc = ccsr.InputGlyphCount;\r
+ lgc = ccsr.LookaheadGlyphCount;\r
+\r
+ if ( context_length != 0xFFFF && context_length < igc )\r
+ goto next_chainsubclassrule;\r
+\r
+ /* check whether context is too long; it is a first guess only */\r
+\r
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )\r
+ goto next_chainsubclassrule;\r
+\r
+ if ( bgc )\r
+ {\r
+ /* Since we don't know in advance the number of glyphs to inspect,\r
+ we search backwards for matches in the backtrack glyph array.\r
+ Note that `known_backtrack_classes' starts at index 0. */\r
+\r
+ bc = ccsr.Backtrack;\r
+\r
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )\r
+ {\r
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ if ( j + 1 == bgc - i )\r
+ goto next_chainsubclassrule;\r
+ j--;\r
+ }\r
+\r
+ if ( i >= known_backtrack_classes )\r
+ {\r
+ /* Keeps us from having to do this for each rule */\r
+\r
+ error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ),\r
+ &backtrack_classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+ known_backtrack_classes = i;\r
+ }\r
+\r
+ if ( bc[i] != backtrack_classes[i] )\r
+ goto next_chainsubclassrule;\r
+ }\r
+ }\r
+\r
+ ic = ccsr.Input;\r
+\r
+ /* Start at 1 because [0] is implied */\r
+\r
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ if ( j + igc - i + lgc == (HB_Int)buffer->in_length )\r
+ goto next_chainsubclassrule;\r
+ j++;\r
+ }\r
+\r
+ if ( i >= known_input_classes )\r
+ {\r
+ error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),\r
+ &input_classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+ known_input_classes = i;\r
+ }\r
+\r
+ if ( ic[i - 1] != input_classes[i] )\r
+ goto next_chainsubclassrule;\r
+ }\r
+\r
+ /* we are starting to check for lookahead glyphs right after the\r
+ last context glyph */\r
+\r
+ lc = ccsr.Lookahead;\r
+\r
+ for ( i = 0; i < lgc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+\r
+ if ( j + lgc - i == (HB_Int)buffer->in_length )\r
+ goto next_chainsubclassrule;\r
+ j++;\r
+ }\r
+\r
+ if ( i >= known_lookahead_classes )\r
+ {\r
+ error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),\r
+ &lookahead_classes[i], NULL );\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ goto End1;\r
+ known_lookahead_classes = i;\r
+ }\r
+\r
+ if ( lc[i] != lookahead_classes[i] )\r
+ goto next_chainsubclassrule;\r
+ }\r
+\r
+ error = Do_ContextSubst( gsub, igc,\r
+ ccsr.SubstCount,\r
+ ccsr.SubstLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+ goto End1;\r
+\r
+ next_chainsubclassrule:\r
+ ;\r
+ }\r
+\r
+ error = HB_Err_Not_Covered;\r
+\r
+End1:\r
+ FREE( lookahead_classes );\r
+\r
+End2:\r
+ FREE( input_classes );\r
+\r
+End3:\r
+ FREE( backtrack_classes );\r
+ return error;\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,\r
+ HB_ChainContextSubstFormat3* ccsf3,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, i, j, property;\r
+ HB_UShort bgc, igc, lgc;\r
+ HB_Error error;\r
+\r
+ HB_Coverage* bc;\r
+ HB_Coverage* ic;\r
+ HB_Coverage* lc;\r
+ HB_GDEFHeader* gdef;\r
+\r
+\r
+ gdef = gsub->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ bgc = ccsf3->BacktrackGlyphCount;\r
+ igc = ccsf3->InputGlyphCount;\r
+ lgc = ccsf3->LookaheadGlyphCount;\r
+\r
+ if ( context_length != 0xFFFF && context_length < igc )\r
+ return HB_Err_Not_Covered;\r
+\r
+ /* check whether context is too long; it is a first guess only */\r
+\r
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( bgc )\r
+ {\r
+ /* Since we don't know in advance the number of glyphs to inspect,\r
+ we search backwards for matches in the backtrack glyph array */\r
+\r
+ bc = ccsf3->BacktrackCoverage;\r
+\r
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )\r
+ {\r
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + 1 == bgc - i )\r
+ return HB_Err_Not_Covered;\r
+ j--;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+ }\r
+\r
+ ic = ccsf3->InputCoverage;\r
+\r
+ for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )\r
+ {\r
+ /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */\r
+ while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + igc - i + lgc == (HB_Int)buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+ j++;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ /* we are starting for lookahead glyphs right after the last context\r
+ glyph */\r
+\r
+ lc = ccsf3->LookaheadCoverage;\r
+\r
+ for ( i = 0; i < lgc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + lgc - i == (HB_Int)buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+ j++;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ return Do_ContextSubst( gsub, igc,\r
+ ccsf3->SubstCount,\r
+ ccsf3->SubstLookupRecord,\r
+ buffer,\r
+ nesting_level );\r
+}\r
+\r
+\r
+static HB_Error Lookup_ChainContextSubst( HB_GSUBHeader* gsub,\r
+ HB_GSUB_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_ChainContextSubst* ccs = &st->chain;\r
+\r
+ switch ( ccs->SubstFormat ) {\r
+ case 1: return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer, flags, context_length, nesting_level );\r
+ case 2: return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer, flags, context_length, nesting_level );\r
+ case 3: return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer, flags, context_length, nesting_level );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Load_ReverseChainContextSubst( HB_GSUB_SubTable* st,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_ReverseChainContextSubst* rccs = &st->reverse;\r
+\r
+ HB_UShort m, count;\r
+\r
+ HB_UShort nb = 0, nl = 0, n;\r
+ HB_UShort backtrack_count, lookahead_count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Coverage* b;\r
+ HB_Coverage* l;\r
+ HB_UShort* sub;\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ rccs->SubstFormat = GET_UShort();\r
+\r
+ if ( rccs->SubstFormat != 1 )\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail4;\r
+\r
+ rccs->BacktrackGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ rccs->BacktrackCoverage = NULL;\r
+\r
+ backtrack_count = rccs->BacktrackGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count,\r
+ HB_Coverage ) )\r
+ goto Fail4;\r
+\r
+ b = rccs->BacktrackCoverage;\r
+\r
+ for ( nb = 0; nb < backtrack_count; nb++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )\r
+ goto Fail3;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail3;\r
+\r
+ rccs->LookaheadGlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ rccs->LookaheadCoverage = NULL;\r
+\r
+ lookahead_count = rccs->LookaheadGlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count,\r
+ HB_Coverage ) )\r
+ goto Fail3;\r
+\r
+ l = rccs->LookaheadCoverage;\r
+\r
+ for ( nl = 0; nl < lookahead_count; nl++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )\r
+ goto Fail2;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ rccs->GlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ rccs->Substitute = NULL;\r
+\r
+ count = rccs->GlyphCount;\r
+\r
+ if ( ALLOC_ARRAY( rccs->Substitute, count,\r
+ HB_UShort ) )\r
+ goto Fail2;\r
+\r
+ sub = rccs->Substitute;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail1;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ sub[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( sub );\r
+\r
+Fail2:\r
+ for ( m = 0; m < nl; m++ )\r
+ _HB_OPEN_Free_Coverage( &l[m] );\r
+\r
+ FREE( l );\r
+\r
+Fail3:\r
+ for ( m = 0; m < nb; m++ )\r
+ _HB_OPEN_Free_Coverage( &b[m] );\r
+\r
+ FREE( b );\r
+\r
+Fail4:\r
+ _HB_OPEN_Free_Coverage( &rccs->Coverage );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ReverseChainContextSubst( HB_GSUB_SubTable* st )\r
+{\r
+ HB_UShort n, count;\r
+ HB_ReverseChainContextSubst* rccs = &st->reverse;\r
+\r
+ HB_Coverage* c;\r
+\r
+ _HB_OPEN_Free_Coverage( &rccs->Coverage );\r
+\r
+ if ( rccs->LookaheadCoverage )\r
+ {\r
+ count = rccs->LookaheadGlyphCount;\r
+ c = rccs->LookaheadCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+\r
+ if ( rccs->BacktrackCoverage )\r
+ {\r
+ count = rccs->BacktrackGlyphCount;\r
+ c = rccs->BacktrackCoverage;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ _HB_OPEN_Free_Coverage( &c[n] );\r
+\r
+ FREE( c );\r
+ }\r
+\r
+ FREE ( rccs->Substitute );\r
+}\r
+\r
+\r
+static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,\r
+ HB_GSUB_SubTable* st,\r
+ HB_Buffer buffer,\r
+ HB_UShort flags,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_UShort index, input_index, i, j, property;\r
+ HB_UShort bgc, lgc;\r
+ HB_Error error;\r
+\r
+ HB_ReverseChainContextSubst* rccs = &st->reverse;\r
+ HB_Coverage* bc;\r
+ HB_Coverage* lc;\r
+ HB_GDEFHeader* gdef;\r
+\r
+ if ( nesting_level != 1 || context_length != 0xFFFF )\r
+ return HB_Err_Not_Covered;\r
+\r
+ gdef = gsub->gdef;\r
+\r
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )\r
+ return error;\r
+\r
+ bgc = rccs->BacktrackGlyphCount;\r
+ lgc = rccs->LookaheadGlyphCount;\r
+\r
+ /* check whether context is too long; it is a first guess only */\r
+\r
+ if ( bgc > buffer->in_pos || buffer->in_pos + 1 + lgc > buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+\r
+ if ( bgc )\r
+ {\r
+ /* Since we don't know in advance the number of glyphs to inspect,\r
+ we search backwards for matches in the backtrack glyph array */\r
+\r
+ bc = rccs->BacktrackCoverage;\r
+\r
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + 1 == bgc - i )\r
+ return HB_Err_Not_Covered;\r
+ j--;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+ }\r
+\r
+ j = buffer->in_pos;\r
+\r
+ error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );\r
+ if ( error )\r
+ return error;\r
+\r
+ lc = rccs->LookaheadCoverage;\r
+\r
+ for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ )\r
+ {\r
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )\r
+ {\r
+ if ( error && error != HB_Err_Not_Covered )\r
+ return error;\r
+\r
+ if ( j + lgc - i == (HB_Int)buffer->in_length )\r
+ return HB_Err_Not_Covered;\r
+ j++;\r
+ }\r
+\r
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );\r
+ if ( error )\r
+ return error;\r
+ }\r
+\r
+ IN_CURGLYPH() = rccs->Substitute[input_index];\r
+ buffer->in_pos--; /* Reverse! */\r
+\r
+ return error;\r
+}\r
+\r
+\r
+\r
+/***********\r
+ * GSUB API\r
+ ***********/\r
+\r
+\r
+\r
+HB_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,\r
+ HB_UInt script_tag,\r
+ HB_UShort* script_index )\r
+{\r
+ HB_UShort n;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+\r
+\r
+ if ( !gsub || !script_index )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gsub->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ for ( n = 0; n < sl->ScriptCount; n++ )\r
+ if ( script_tag == sr[n].ScriptTag )\r
+ {\r
+ *script_index = n;\r
+\r
+ return HB_Err_Ok;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,\r
+ HB_UInt language_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort* language_index,\r
+ HB_UShort* req_feature_index )\r
+{\r
+ HB_UShort n;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+\r
+\r
+ if ( !gsub || !language_index || !req_feature_index )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gsub->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ for ( n = 0; n < s->LangSysCount; n++ )\r
+ if ( language_tag == lsr[n].LangSysTag )\r
+ {\r
+ *language_index = n;\r
+ *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;\r
+\r
+ return HB_Err_Ok;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+/* selecting 0xFFFF for language_index asks for the values of the\r
+ default language (DefaultLangSys) */\r
+\r
+\r
+HB_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,\r
+ HB_UInt feature_tag,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UShort* feature_index )\r
+{\r
+ HB_UShort n;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+ HB_LangSys* ls;\r
+ HB_UShort* fi;\r
+\r
+ HB_FeatureList* fl;\r
+ HB_FeatureRecord* fr;\r
+\r
+\r
+ if ( !gsub || !feature_index )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gsub->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ fl = &gsub->FeatureList;\r
+ fr = fl->FeatureRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ if ( language_index == 0xFFFF )\r
+ ls = &s->DefaultLangSys;\r
+ else\r
+ {\r
+ if ( language_index >= s->LangSysCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ ls = &lsr[language_index].LangSys;\r
+ }\r
+\r
+ fi = ls->FeatureIndex;\r
+\r
+ for ( n = 0; n < ls->FeatureCount; n++ )\r
+ {\r
+ if ( fi[n] >= fl->FeatureCount )\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+\r
+ if ( feature_tag == fr[fi[n]].FeatureTag )\r
+ {\r
+ *feature_index = fi[n];\r
+\r
+ return HB_Err_Ok;\r
+ }\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+/* The next three functions return a null-terminated list */\r
+\r
+\r
+HB_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,\r
+ HB_UInt** script_tag_list )\r
+{\r
+ HB_UShort n;\r
+ HB_Error error;\r
+ HB_UInt* stl;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+\r
+\r
+ if ( !gsub || !script_tag_list )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gsub->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )\r
+ return error;\r
+\r
+ for ( n = 0; n < sl->ScriptCount; n++ )\r
+ stl[n] = sr[n].ScriptTag;\r
+ stl[n] = 0;\r
+\r
+ *script_tag_list = stl;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,\r
+ HB_UShort script_index,\r
+ HB_UInt** language_tag_list )\r
+{\r
+ HB_UShort n;\r
+ HB_Error error;\r
+ HB_UInt* ltl;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+\r
+\r
+ if ( !gsub || !language_tag_list )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gsub->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )\r
+ return error;\r
+\r
+ for ( n = 0; n < s->LangSysCount; n++ )\r
+ ltl[n] = lsr[n].LangSysTag;\r
+ ltl[n] = 0;\r
+\r
+ *language_tag_list = ltl;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* selecting 0xFFFF for language_index asks for the values of the\r
+ default language (DefaultLangSys) */\r
+\r
+\r
+HB_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,\r
+ HB_UShort script_index,\r
+ HB_UShort language_index,\r
+ HB_UInt** feature_tag_list )\r
+{\r
+ HB_UShort n;\r
+ HB_Error error;\r
+ HB_UInt* ftl;\r
+\r
+ HB_ScriptList* sl;\r
+ HB_ScriptRecord* sr;\r
+ HB_ScriptTable* s;\r
+ HB_LangSysRecord* lsr;\r
+ HB_LangSys* ls;\r
+ HB_UShort* fi;\r
+\r
+ HB_FeatureList* fl;\r
+ HB_FeatureRecord* fr;\r
+\r
+\r
+ if ( !gsub || !feature_tag_list )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ sl = &gsub->ScriptList;\r
+ sr = sl->ScriptRecord;\r
+\r
+ fl = &gsub->FeatureList;\r
+ fr = fl->FeatureRecord;\r
+\r
+ if ( script_index >= sl->ScriptCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ s = &sr[script_index].Script;\r
+ lsr = s->LangSysRecord;\r
+\r
+ if ( language_index == 0xFFFF )\r
+ ls = &s->DefaultLangSys;\r
+ else\r
+ {\r
+ if ( language_index >= s->LangSysCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ ls = &lsr[language_index].LangSys;\r
+ }\r
+\r
+ fi = ls->FeatureIndex;\r
+\r
+ if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )\r
+ return error;\r
+\r
+ for ( n = 0; n < ls->FeatureCount; n++ )\r
+ {\r
+ if ( fi[n] >= fl->FeatureCount )\r
+ {\r
+ FREE( ftl );\r
+ return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+ ftl[n] = fr[fi[n]].FeatureTag;\r
+ }\r
+ ftl[n] = 0;\r
+\r
+ *feature_tag_list = ftl;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+/* Do an individual subtable lookup. Returns HB_Err_Ok if substitution\r
+ has been done, or HB_Err_Not_Covered if not. */\r
+static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,\r
+ HB_UShort lookup_index,\r
+ HB_Buffer buffer,\r
+ HB_UShort context_length,\r
+ int nesting_level )\r
+{\r
+ HB_Error error = HB_Err_Not_Covered;\r
+ HB_UShort i, flags, lookup_count;\r
+ HB_Lookup* lo;\r
+ int lookup_type;\r
+\r
+ nesting_level++;\r
+\r
+ if ( nesting_level > HB_MAX_NESTING_LEVEL )\r
+ return ERR_HB(HB_Err_Not_Covered); /* ERR_HB() call intended */\r
+\r
+ lookup_count = gsub->LookupList.LookupCount;\r
+ if (lookup_index >= lookup_count)\r
+ return error;\r
+\r
+ lo = &gsub->LookupList.Lookup[lookup_index];\r
+ flags = lo->LookupFlag;\r
+ lookup_type = lo->LookupType;\r
+\r
+ for ( i = 0; i < lo->SubTableCount; i++ )\r
+ {\r
+ HB_GSUB_SubTable *st = &lo->SubTable[i].st.gsub;\r
+\r
+ switch (lookup_type) {\r
+ case HB_GSUB_LOOKUP_SINGLE:\r
+ error = Lookup_SingleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GSUB_LOOKUP_MULTIPLE:\r
+ error = Lookup_MultipleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GSUB_LOOKUP_ALTERNATE:\r
+ error = Lookup_AlternateSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GSUB_LOOKUP_LIGATURE:\r
+ error = Lookup_LigatureSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GSUB_LOOKUP_CONTEXT:\r
+ error = Lookup_ContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;\r
+ case HB_GSUB_LOOKUP_CHAIN:\r
+ error = Lookup_ChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;\r
+ /*case HB_GSUB_LOOKUP_EXTENSION:\r
+ error = Lookup_ExtensionSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;*/\r
+ case HB_GSUB_LOOKUP_REVERSE_CHAIN:\r
+ error = Lookup_ReverseChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;\r
+ default:\r
+ error = HB_Err_Not_Covered;\r
+ };\r
+\r
+ /* Check whether we have a successful substitution or an error other\r
+ than HB_Err_Not_Covered */\r
+ if ( error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,\r
+ HB_Stream stream,\r
+ HB_UShort lookup_type )\r
+{\r
+ switch (lookup_type) {\r
+ case HB_GSUB_LOOKUP_SINGLE: return Load_SingleSubst ( st, stream );\r
+ case HB_GSUB_LOOKUP_MULTIPLE: return Load_MultipleSubst ( st, stream );\r
+ case HB_GSUB_LOOKUP_ALTERNATE: return Load_AlternateSubst ( st, stream );\r
+ case HB_GSUB_LOOKUP_LIGATURE: return Load_LigatureSubst ( st, stream );\r
+ case HB_GSUB_LOOKUP_CONTEXT: return Load_ContextSubst ( st, stream );\r
+ case HB_GSUB_LOOKUP_CHAIN: return Load_ChainContextSubst ( st, stream );\r
+ /*case HB_GSUB_LOOKUP_EXTENSION: return Load_ExtensionSubst ( st, stream );*/\r
+ case HB_GSUB_LOOKUP_REVERSE_CHAIN: return Load_ReverseChainContextSubst ( st, stream );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ };\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,\r
+ HB_UShort lookup_type )\r
+{\r
+ switch ( lookup_type ) {\r
+ case HB_GSUB_LOOKUP_SINGLE: Free_SingleSubst ( st ); return;\r
+ case HB_GSUB_LOOKUP_MULTIPLE: Free_MultipleSubst ( st ); return;\r
+ case HB_GSUB_LOOKUP_ALTERNATE: Free_AlternateSubst ( st ); return;\r
+ case HB_GSUB_LOOKUP_LIGATURE: Free_LigatureSubst ( st ); return;\r
+ case HB_GSUB_LOOKUP_CONTEXT: Free_ContextSubst ( st ); return;\r
+ case HB_GSUB_LOOKUP_CHAIN: Free_ChainContextSubst ( st ); return;\r
+ /*case HB_GSUB_LOOKUP_EXTENSION: Free_ExtensionSubst ( st ); return;*/\r
+ case HB_GSUB_LOOKUP_REVERSE_CHAIN: Free_ReverseChainContextSubst ( st ); return;\r
+ default: return;\r
+ };\r
+}\r
+\r
+\r
+\r
+/* apply one lookup to the input string object */\r
+\r
+static HB_Error GSUB_Do_String_Lookup( HB_GSUBHeader* gsub,\r
+ HB_UShort lookup_index,\r
+ HB_Buffer buffer )\r
+{\r
+ HB_Error error, retError = HB_Err_Not_Covered;\r
+\r
+ HB_UInt* properties = gsub->LookupList.Properties;\r
+ int lookup_type = gsub->LookupList.Lookup[lookup_index].LookupType;\r
+\r
+ const int nesting_level = 0;\r
+ /* 0xFFFF indicates that we don't have a context length yet */\r
+ const HB_UShort context_length = 0xFFFF;\r
+\r
+ switch (lookup_type) {\r
+\r
+ case HB_GSUB_LOOKUP_SINGLE:\r
+ case HB_GSUB_LOOKUP_MULTIPLE:\r
+ case HB_GSUB_LOOKUP_ALTERNATE:\r
+ case HB_GSUB_LOOKUP_LIGATURE:\r
+ case HB_GSUB_LOOKUP_CONTEXT:\r
+ case HB_GSUB_LOOKUP_CHAIN:\r
+ /* in/out forward substitution (implemented lazy) */\r
+\r
+ _hb_buffer_clear_output ( buffer );\r
+ buffer->in_pos = 0;\r
+ while ( buffer->in_pos < buffer->in_length )\r
+ {\r
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )\r
+ {\r
+ error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );\r
+ if ( error )\r
+ {\r
+ if ( error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+ else\r
+ retError = error;\r
+ }\r
+ else\r
+ error = HB_Err_Not_Covered;\r
+\r
+ if ( error == HB_Err_Not_Covered )\r
+ if ( COPY_Glyph ( buffer ) )\r
+ return error;\r
+ }\r
+ /* we shouldn't swap if error occurred.\r
+ *\r
+ * also don't swap if nothing changed (ie HB_Err_Not_Covered).\r
+ * shouldn't matter in that case though.\r
+ */\r
+ if ( retError == HB_Err_Ok )\r
+ _hb_buffer_swap( buffer );\r
+\r
+ return retError;\r
+\r
+ case HB_GSUB_LOOKUP_REVERSE_CHAIN:\r
+ /* in-place backward substitution */\r
+\r
+ buffer->in_pos = buffer->in_length - 1;\r
+ do\r
+ {\r
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )\r
+ {\r
+ error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );\r
+ if ( error )\r
+ {\r
+ if ( error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+ else\r
+ retError = error;\r
+ }\r
+ else\r
+ error = HB_Err_Not_Covered;\r
+\r
+ if ( error == HB_Err_Not_Covered )\r
+ buffer->in_pos--;\r
+ }\r
+ while ((HB_Int) buffer->in_pos >= 0);\r
+\r
+ return retError;\r
+\r
+ /*case HB_GSUB_LOOKUP_EXTENSION:*/\r
+ default:\r
+ return retError;\r
+ };\r
+}\r
+\r
+\r
+HB_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,\r
+ HB_UShort feature_index,\r
+ HB_UInt property )\r
+{\r
+ HB_UShort i;\r
+\r
+ HB_Feature feature;\r
+ HB_UInt* properties;\r
+ HB_UShort* index;\r
+ HB_UShort lookup_count;\r
+\r
+ /* Each feature can only be added once */\r
+\r
+ if ( !gsub ||\r
+ feature_index >= gsub->FeatureList.FeatureCount ||\r
+ gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;\r
+\r
+ properties = gsub->LookupList.Properties;\r
+\r
+ feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;\r
+ index = feature.LookupListIndex;\r
+ lookup_count = gsub->LookupList.LookupCount;\r
+\r
+ for ( i = 0; i < feature.LookupListCount; i++ )\r
+ {\r
+ HB_UShort lookup_index = index[i];\r
+ if (lookup_index < lookup_count)\r
+ properties[lookup_index] |= property;\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub )\r
+{\r
+ HB_UShort i;\r
+\r
+ HB_UInt* properties;\r
+\r
+\r
+ if ( !gsub )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ gsub->FeatureList.ApplyCount = 0;\r
+\r
+ properties = gsub->LookupList.Properties;\r
+\r
+ for ( i = 0; i < gsub->LookupList.LookupCount; i++ )\r
+ properties[i] = 0;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+\r
+HB_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,\r
+ HB_AltFunction altfunc,\r
+ void* data )\r
+{\r
+ if ( !gsub )\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ gsub->altfunc = altfunc;\r
+ gsub->data = data;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+/* returns error if one happened, otherwise returns HB_Err_Not_Covered if no\r
+ * feature were applied, or HB_Err_Ok otherwise.\r
+ */\r
+HB_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,\r
+ HB_Buffer buffer )\r
+{\r
+ HB_Error error, retError = HB_Err_Not_Covered;\r
+ int i, j, lookup_count, num_features;\r
+\r
+ if ( !gsub ||\r
+ !buffer)\r
+ return ERR_HB(HB_Err_Invalid_Argument);\r
+\r
+ if ( buffer->in_length == 0 )\r
+ return retError;\r
+\r
+ lookup_count = gsub->LookupList.LookupCount;\r
+ num_features = gsub->FeatureList.ApplyCount;\r
+\r
+ for ( i = 0; i < num_features; i++)\r
+ {\r
+ HB_UShort feature_index = gsub->FeatureList.ApplyOrder[i];\r
+ HB_Feature feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;\r
+\r
+ for ( j = 0; j < feature.LookupListCount; j++ )\r
+ {\r
+ HB_UShort lookup_index = feature.LookupListIndex[j];\r
+\r
+ /* Skip nonexistant lookups */\r
+ if (lookup_index >= lookup_count)\r
+ continue;\r
+\r
+ error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer );\r
+ if ( error )\r
+ {\r
+ if ( error != HB_Err_Not_Covered )\r
+ return error;\r
+ }\r
+ else\r
+ retError = error;\r
+ }\r
+ }\r
+\r
+ error = retError;\r
+\r
+ return error;\r
+}\r
+\r
+\r
+/* END */\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+#include <assert.h>\r
+\r
+/*\r
+// Hangul is a syllable based script. Unicode reserves a large range\r
+// for precomposed hangul, where syllables are already precomposed to\r
+// their final glyph shape. In addition, a so called jamo range is\r
+// defined, that can be used to express old Hangul. Modern hangul\r
+// syllables can also be expressed as jamo, and should be composed\r
+// into syllables. The operation is rather simple and mathematical.\r
+\r
+// Every hangul jamo is classified as being either a Leading consonant\r
+// (L), and intermediat Vowel (V) or a trailing consonant (T). Modern\r
+// hangul syllables (the ones in the precomposed area can be of type\r
+// LV or LVT.\r
+//\r
+// Syllable breaks do _not_ occur between:\r
+//\r
+// L L, V or precomposed\r
+// V, LV V, T\r
+// LVT, T T\r
+//\r
+// A standard syllable is of the form L+V+T*. The above rules allow\r
+// nonstandard syllables L*V*T*. To transform them into standard\r
+// syllables fill characters L_f and V_f can be inserted.\r
+*/\r
+\r
+enum {\r
+ Hangul_SBase = 0xac00,\r
+ Hangul_LBase = 0x1100,\r
+ Hangul_VBase = 0x1161,\r
+ Hangul_TBase = 0x11a7,\r
+ Hangul_SCount = 11172,\r
+ Hangul_LCount = 19,\r
+ Hangul_VCount = 21,\r
+ Hangul_TCount = 28,\r
+ Hangul_NCount = 21*28\r
+};\r
+\r
+#define hangul_isPrecomposed(uc) \\r
+ (uc >= Hangul_SBase && uc < Hangul_SBase + Hangul_SCount)\r
+\r
+#define hangul_isLV(uc) \\r
+ ((uc - Hangul_SBase) % Hangul_TCount == 0)\r
+\r
+typedef enum {\r
+ L,\r
+ V,\r
+ T,\r
+ LV,\r
+ LVT,\r
+ X\r
+} HangulType;\r
+\r
+static HangulType hangul_type(unsigned short uc) {\r
+ if (uc > Hangul_SBase && uc < Hangul_SBase + Hangul_SCount)\r
+ return hangul_isLV(uc) ? LV : LVT;\r
+ if (uc < Hangul_LBase || uc > 0x11ff)\r
+ return X;\r
+ if (uc < Hangul_VBase)\r
+ return L;\r
+ if (uc < Hangul_TBase)\r
+ return V;\r
+ return T;\r
+}\r
+\r
+static int hangul_nextSyllableBoundary(const HB_UChar16 *s, int start, int end)\r
+{\r
+ const HB_UChar16 *uc = s + start;\r
+\r
+ HangulType state = hangul_type(*uc);\r
+ int pos = 1;\r
+\r
+ while (pos < end - start) {\r
+ HangulType newState = hangul_type(uc[pos]);\r
+ switch(newState) {\r
+ case X:\r
+ goto finish;\r
+ case L:\r
+ case V:\r
+ case T:\r
+ if (state > newState)\r
+ goto finish;\r
+ state = newState;\r
+ break;\r
+ case LV:\r
+ if (state > L)\r
+ goto finish;\r
+ state = V;\r
+ break;\r
+ case LVT:\r
+ if (state > L)\r
+ goto finish;\r
+ state = T;\r
+ }\r
+ ++pos;\r
+ }\r
+\r
+ finish:\r
+ return start+pos;\r
+}\r
+\r
+#ifndef NO_OPENTYPE\r
+static const HB_OpenTypeFeature hangul_features [] = {\r
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },\r
+ { HB_MAKE_TAG('l', 'j', 'm', 'o'), CcmpProperty },\r
+ { HB_MAKE_TAG('j', 'j', 'm', 'o'), CcmpProperty },\r
+ { HB_MAKE_TAG('t', 'j', 'm', 'o'), CcmpProperty },\r
+ { 0, 0 }\r
+};\r
+#endif\r
+\r
+static HB_Bool hangul_shape_syllable(HB_ShaperItem *item, HB_Bool openType)\r
+{\r
+ const HB_UChar16 *ch = item->string + item->item.pos;\r
+ int len = item->item.length;\r
+#ifndef NO_OPENTYPE\r
+ const int availableGlyphs = item->num_glyphs;\r
+#endif\r
+\r
+ int i;\r
+ HB_UChar16 composed = 0;\r
+ /* see if we can compose the syllable into a modern hangul */\r
+ if (item->item.length == 2) {\r
+ int LIndex = ch[0] - Hangul_LBase;\r
+ int VIndex = ch[1] - Hangul_VBase;\r
+ if (LIndex >= 0 && LIndex < Hangul_LCount &&\r
+ VIndex >= 0 && VIndex < Hangul_VCount)\r
+ composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + Hangul_SBase;\r
+ } else if (item->item.length == 3) {\r
+ int LIndex = ch[0] - Hangul_LBase;\r
+ int VIndex = ch[1] - Hangul_VBase;\r
+ int TIndex = ch[2] - Hangul_TBase;\r
+ if (LIndex >= 0 && LIndex < Hangul_LCount &&\r
+ VIndex >= 0 && VIndex < Hangul_VCount &&\r
+ TIndex >= 0 && TIndex < Hangul_TCount)\r
+ composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + TIndex + Hangul_SBase;\r
+ }\r
+\r
+\r
+\r
+ /* if we have a modern hangul use the composed form */\r
+ if (composed) {\r
+ ch = &composed;\r
+ len = 1;\r
+ }\r
+\r
+ if (!item->font->klass->convertStringToGlyphIndices(item->font,\r
+ ch, len,\r
+ item->glyphs, &item->num_glyphs,\r
+ item->item.bidiLevel % 2))\r
+ return FALSE;\r
+ for (i = 0; i < len; i++) {\r
+ item->attributes[i].mark = FALSE;\r
+ item->attributes[i].clusterStart = FALSE;\r
+ item->attributes[i].justification = 0;\r
+ item->attributes[i].zeroWidth = FALSE;\r
+ /*IDEBUG(" %d: %4x", i, ch[i].unicode()); */\r
+ }\r
+\r
+#ifndef NO_OPENTYPE\r
+ if (!composed && openType) {\r
+ HB_Bool positioned;\r
+\r
+ HB_STACKARRAY(unsigned short, logClusters, len);\r
+ for (i = 0; i < len; ++i)\r
+ logClusters[i] = i;\r
+ item->log_clusters = logClusters;\r
+\r
+ HB_OpenTypeShape(item, /*properties*/0);\r
+\r
+ positioned = HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE);\r
+\r
+ HB_FREE_STACKARRAY(logClusters);\r
+\r
+ if (!positioned)\r
+ return FALSE;\r
+ } else {\r
+ HB_HeuristicPosition(item);\r
+ }\r
+#endif\r
+\r
+ item->attributes[0].clusterStart = TRUE;\r
+ return TRUE;\r
+}\r
+\r
+HB_Bool HB_HangulShape(HB_ShaperItem *item)\r
+{\r
+ const HB_UChar16 *uc = item->string + item->item.pos;\r
+ HB_Bool allPrecomposed = TRUE;\r
+ int i;\r
+\r
+ assert(item->item.script == HB_Script_Hangul);\r
+\r
+ for (i = 0; i < (int)item->item.length; ++i) {\r
+ if (!hangul_isPrecomposed(uc[i])) {\r
+ allPrecomposed = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!allPrecomposed) {\r
+ HB_Bool openType = FALSE;\r
+ unsigned short *logClusters = item->log_clusters;\r
+ HB_ShaperItem syllable;\r
+ int first_glyph = 0;\r
+ int sstart = item->item.pos;\r
+ int end = sstart + item->item.length;\r
+\r
+#ifndef NO_OPENTYPE\r
+ openType = HB_SelectScript(item, hangul_features);\r
+#endif\r
+ syllable = *item;\r
+\r
+ while (sstart < end) {\r
+ int send = hangul_nextSyllableBoundary(item->string, sstart, end);\r
+\r
+ syllable.item.pos = sstart;\r
+ syllable.item.length = send-sstart;\r
+ syllable.glyphs = item->glyphs + first_glyph;\r
+ syllable.attributes = item->attributes + first_glyph;\r
+ syllable.offsets = item->offsets + first_glyph;\r
+ syllable.advances = item->advances + first_glyph;\r
+ syllable.num_glyphs = item->num_glyphs - first_glyph;\r
+ if (!hangul_shape_syllable(&syllable, openType)) {\r
+ item->num_glyphs += syllable.num_glyphs;\r
+ return FALSE;\r
+ }\r
+ /* fix logcluster array */\r
+ for (i = sstart; i < send; ++i)\r
+ logClusters[i-item->item.pos] = first_glyph;\r
+ sstart = send;\r
+ first_glyph += syllable.num_glyphs;\r
+ }\r
+ item->num_glyphs = first_glyph;\r
+ return TRUE;\r
+ }\r
+\r
+ return HB_BasicShape(item);\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+#include <assert.h>\r
+\r
+/*\r
+// Uniscribe also defines dlig for Hebrew, but we leave this out for now, as it's mostly\r
+// ligatures one does not want in modern Hebrew (as lam-alef ligatures).\r
+*/\r
+#ifndef NO_OPENTYPE\r
+static const HB_OpenTypeFeature hebrew_features[] = {\r
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },\r
+ {0, 0}\r
+};\r
+#endif\r
+\r
+/* Hebrew shaping. In the non opentype case we try to use the\r
+ presentation forms specified for Hebrew. Especially for the\r
+ ligatures with Dagesh this gives much better results than we could\r
+ achieve manually.\r
+*/\r
+HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item)\r
+{\r
+ enum {\r
+ Dagesh = 0x5bc,\r
+ ShinDot = 0x5c1,\r
+ SinDot = 0x5c2,\r
+ Patah = 0x5b7,\r
+ Qamats = 0x5b8,\r
+ Holam = 0x5b9,\r
+ Rafe = 0x5bf\r
+ };\r
+\r
+ assert(shaper_item->item.script == HB_Script_Hebrew);\r
+\r
+ HB_HeuristicSetGlyphAttributes(shaper_item);\r
+\r
+#ifndef NO_OPENTYPE\r
+ if (HB_SelectScript(shaper_item, hebrew_features)) {\r
+\r
+ const int availableGlyphs = shaper_item->num_glyphs;\r
+ if (!HB_ConvertStringToGlyphIndices(shaper_item))\r
+ return FALSE;\r
+\r
+\r
+ HB_OpenTypeShape(shaper_item, /*properties*/0);\r
+ return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE);\r
+ }\r
+#endif\r
+\r
+ {\r
+ const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos;\r
+ unsigned short *logClusters = shaper_item->log_clusters;\r
+ HB_GlyphAttributes *attributes = shaper_item->attributes;\r
+\r
+ HB_Bool haveGlyphs;\r
+ int slen = 1;\r
+ int cluster_start = 0;\r
+ hb_uint32 i;\r
+\r
+ HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length);\r
+ *shapedChars = *uc;\r
+ logClusters[0] = 0;\r
+\r
+ for (i = 1; i < shaper_item->item.length; ++i) {\r
+ hb_uint16 base = shapedChars[slen-1];\r
+ hb_uint16 shaped = 0;\r
+ HB_Bool invalid = FALSE;\r
+ if (uc[i] == Dagesh) {\r
+ if (base >= 0x5d0\r
+ && base <= 0x5ea\r
+ && base != 0x5d7\r
+ && base != 0x5dd\r
+ && base != 0x5df\r
+ && base != 0x5e2\r
+ && base != 0x5e5) {\r
+ shaped = base - 0x5d0 + 0xfb30;\r
+ } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) {\r
+ shaped = base + 2;\r
+ } else {\r
+ invalid = TRUE;\r
+ }\r
+ } else if (uc[i] == ShinDot) {\r
+ if (base == 0x05e9)\r
+ shaped = 0xfb2a;\r
+ else if (base == 0xfb49)\r
+ shaped = 0xfb2c;\r
+ else\r
+ invalid = TRUE;\r
+ } else if (uc[i] == SinDot) {\r
+ if (base == 0x05e9)\r
+ shaped = 0xfb2b;\r
+ else if (base == 0xfb49)\r
+ shaped = 0xfb2d;\r
+ else\r
+ invalid = TRUE;\r
+ } else if (uc[i] == Patah) {\r
+ if (base == 0x5d0)\r
+ shaped = 0xfb2e;\r
+ } else if (uc[i] == Qamats) {\r
+ if (base == 0x5d0)\r
+ shaped = 0xfb2f;\r
+ } else if (uc[i] == Holam) {\r
+ if (base == 0x5d5)\r
+ shaped = 0xfb4b;\r
+ } else if (uc[i] == Rafe) {\r
+ if (base == 0x5d1)\r
+ shaped = 0xfb4c;\r
+ else if (base == 0x5db)\r
+ shaped = 0xfb4d;\r
+ else if (base == 0x5e4)\r
+ shaped = 0xfb4e;\r
+ }\r
+\r
+ if (invalid) {\r
+ shapedChars[slen] = 0x25cc;\r
+ attributes[slen].clusterStart = TRUE;\r
+ attributes[slen].mark = FALSE;\r
+ attributes[slen].combiningClass = 0;\r
+ cluster_start = slen;\r
+ ++slen;\r
+ }\r
+ if (shaped) {\r
+ if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) {\r
+ shapedChars[slen-1] = shaped;\r
+ } else\r
+ shaped = 0;\r
+ }\r
+ if (!shaped) {\r
+ HB_CharCategory category;\r
+ int cmb;\r
+ shapedChars[slen] = uc[i];\r
+ HB_GetUnicodeCharProperties(uc[i], &category, &cmb);\r
+ if (category != HB_Mark_NonSpacing) {\r
+ attributes[slen].clusterStart = TRUE;\r
+ attributes[slen].mark = FALSE;\r
+ attributes[slen].combiningClass = 0;\r
+ attributes[slen].dontPrint = HB_IsControlChar(uc[i]);\r
+ cluster_start = slen;\r
+ } else {\r
+ attributes[slen].clusterStart = FALSE;\r
+ attributes[slen].mark = TRUE;\r
+ attributes[slen].combiningClass = cmb;\r
+ }\r
+ ++slen;\r
+ }\r
+ logClusters[i] = cluster_start;\r
+ }\r
+\r
+ haveGlyphs = shaper_item->font->klass\r
+ ->convertStringToGlyphIndices(shaper_item->font,\r
+ shapedChars, slen,\r
+ shaper_item->glyphs, &shaper_item->num_glyphs,\r
+ shaper_item->item.bidiLevel % 2);\r
+\r
+ HB_FREE_STACKARRAY(shapedChars);\r
+\r
+ if (!haveGlyphs)\r
+ return FALSE;\r
+\r
+ HB_HeuristicPosition(shaper_item);\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Behdad Esfahbod\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+\r
+\r
+//HB_INTERNAL \r
+HB_Pointer\r
+_hb_alloc(size_t size,\r
+ HB_Error *perror )\r
+{\r
+ HB_Error error = (HB_Error)0;\r
+ HB_Pointer block = NULL;\r
+\r
+ if ( size > 0 )\r
+ {\r
+ block = calloc( 1, size );\r
+ if ( !block )\r
+ error = ERR_HB(HB_Err_Out_Of_Memory);\r
+ }\r
+\r
+ *perror = error;\r
+ return block;\r
+}\r
+\r
+\r
+//HB_INTERNAL \r
+ HB_Pointer\r
+_hb_realloc(HB_Pointer block,\r
+ size_t new_size,\r
+ HB_Error *perror )\r
+{\r
+ HB_Pointer block2 = NULL;\r
+ HB_Error error = (HB_Error)0;\r
+\r
+ block2 = realloc( block, new_size );\r
+ if ( block2 == NULL && new_size != 0 )\r
+ error = ERR_HB(HB_Err_Out_Of_Memory);\r
+\r
+ if ( !error )\r
+ block = block2;\r
+\r
+ *perror = error;\r
+ return block;\r
+}\r
+\r
+\r
+//HB_INTERNAL \r
+ void\r
+_hb_free( HB_Pointer block )\r
+{\r
+ if ( block )\r
+ free( block );\r
+}\r
+\r
+\r
+/* helper func to set a breakpoint on */\r
+//HB_INTERNAL \r
+HB_Error\r
+_hb_err(HB_Error code)\r
+{\r
+ return code;\r
+}\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+#include <assert.h>\r
+#include <stdio.h>\r
+\r
+#define FLAG(x) (1 << (x))\r
+\r
+static HB_Bool isLetter(HB_UChar16 ucs)\r
+{\r
+ const int test = FLAG(HB_Letter_Uppercase) |\r
+ FLAG(HB_Letter_Lowercase) |\r
+ FLAG(HB_Letter_Titlecase) |\r
+ FLAG(HB_Letter_Modifier) |\r
+ FLAG(HB_Letter_Other);\r
+ return FLAG(HB_GetUnicodeCharCategory(ucs)) & test;\r
+}\r
+\r
+static HB_Bool isMark(HB_UChar16 ucs)\r
+{\r
+ const int test = FLAG(HB_Mark_NonSpacing) |\r
+ FLAG(HB_Mark_SpacingCombining) |\r
+ FLAG(HB_Mark_Enclosing);\r
+ return FLAG(HB_GetUnicodeCharCategory(ucs)) & test;\r
+}\r
+\r
+typedef enum _Form {\r
+ Invalid = 0x0,\r
+ UnknownForm = Invalid,\r
+ Consonant,\r
+ Nukta,\r
+ Halant,\r
+ Matra,\r
+ VowelMark,\r
+ StressMark,\r
+ IndependentVowel,\r
+ LengthMark,\r
+ Control,\r
+ Other\r
+}Form;\r
+\r
+static const unsigned char indicForms[0xe00-0x900] = {\r
+ // Devangari\r
+ Invalid, VowelMark, VowelMark, VowelMark,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Nukta, Other, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Halant, UnknownForm, UnknownForm,\r
+\r
+ Other, StressMark, StressMark, StressMark,\r
+ StressMark, UnknownForm, UnknownForm, UnknownForm,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ IndependentVowel, IndependentVowel, VowelMark, VowelMark,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Consonant,\r
+ Consonant, Consonant /* ??? */, Consonant, Consonant,\r
+\r
+ // Bengali\r
+ Invalid, VowelMark, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Invalid, Invalid, IndependentVowel,\r
+\r
+ IndependentVowel, Invalid, Invalid, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Invalid, Consonant, Invalid,\r
+ Invalid, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Nukta, Other, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Invalid, Invalid, Matra,\r
+ Matra, Invalid, Invalid, Matra,\r
+ Matra, Halant, Consonant, UnknownForm,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, VowelMark,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Consonant, Consonant, Invalid, Consonant,\r
+\r
+ IndependentVowel, IndependentVowel, VowelMark, VowelMark,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Consonant, Consonant, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ // Gurmukhi\r
+ Invalid, VowelMark, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, Invalid,\r
+ Invalid, Invalid, Invalid, IndependentVowel,\r
+\r
+ IndependentVowel, Invalid, Invalid, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Invalid, Consonant, Consonant, Invalid,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Nukta, Other, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Invalid,\r
+ Invalid, Invalid, Invalid, Matra,\r
+ Matra, Invalid, Invalid, Matra,\r
+ Matra, Halant, UnknownForm, UnknownForm,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, UnknownForm, UnknownForm, UnknownForm,\r
+ Invalid, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Invalid,\r
+\r
+ Other, Other, Invalid, Invalid,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ StressMark, StressMark, Consonant, Consonant,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ // Gujarati\r
+ Invalid, VowelMark, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, Invalid, IndependentVowel,\r
+\r
+ IndependentVowel, IndependentVowel, Invalid, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Invalid, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Nukta, Other, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Matra, Invalid, Matra,\r
+ Matra, Matra, Invalid, Matra,\r
+ Matra, Halant, UnknownForm, UnknownForm,\r
+\r
+ Other, UnknownForm, UnknownForm, UnknownForm,\r
+ UnknownForm, UnknownForm, UnknownForm, UnknownForm,\r
+ UnknownForm, UnknownForm, UnknownForm, UnknownForm,\r
+ UnknownForm, UnknownForm, UnknownForm, UnknownForm,\r
+\r
+ IndependentVowel, IndependentVowel, VowelMark, VowelMark,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ // Oriya\r
+ Invalid, VowelMark, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Invalid, Invalid, IndependentVowel,\r
+\r
+ IndependentVowel, Invalid, Invalid, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Invalid, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Nukta, Other, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Invalid, Invalid, Invalid, Matra,\r
+ Matra, Invalid, Invalid, Matra,\r
+ Matra, Halant, UnknownForm, UnknownForm,\r
+\r
+ Other, Invalid, Invalid, Invalid,\r
+ Invalid, UnknownForm, LengthMark, LengthMark,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Consonant, Consonant, Invalid, Consonant,\r
+\r
+ IndependentVowel, IndependentVowel, Invalid, Invalid,\r
+ Invalid, Invalid, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Other, Consonant, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ //Tamil\r
+ Invalid, Invalid, VowelMark, Other,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, Invalid,\r
+ Invalid, Invalid, IndependentVowel, IndependentVowel,\r
+\r
+ IndependentVowel, Invalid, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Consonant, Invalid, Invalid,\r
+ Invalid, Consonant, Consonant, Invalid,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+\r
+ Invalid, Invalid, Invalid, Consonant,\r
+ Consonant, Invalid, Invalid, Invalid,\r
+ Consonant, Consonant, Consonant, Invalid,\r
+ Invalid, Invalid, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Invalid, Invalid, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Invalid,\r
+ Invalid, Invalid, Matra, Matra,\r
+ Matra, Invalid, Matra, Matra,\r
+ Matra, Halant, Invalid, Invalid,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, LengthMark,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ // Telugu\r
+ Invalid, VowelMark, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Invalid, IndependentVowel, IndependentVowel,\r
+\r
+ IndependentVowel, Invalid, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Invalid, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Invalid, Invalid, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Invalid, Matra, Matra,\r
+ Matra, Invalid, Matra, Matra,\r
+ Matra, Halant, Invalid, Invalid,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, LengthMark, Matra, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+\r
+ IndependentVowel, IndependentVowel, Invalid, Invalid,\r
+ Invalid, Invalid, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ // Kannada\r
+ Invalid, Invalid, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Invalid, IndependentVowel, IndependentVowel,\r
+\r
+ IndependentVowel, Invalid, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Invalid, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Nukta, Other, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Invalid, Matra, Matra,\r
+ Matra, Invalid, Matra, Matra,\r
+ Matra, Halant, Invalid, Invalid,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, LengthMark, LengthMark, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Consonant, Invalid,\r
+\r
+ IndependentVowel, IndependentVowel, VowelMark, VowelMark,\r
+ Invalid, Invalid, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ // Malayalam\r
+ Invalid, Invalid, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Invalid, IndependentVowel, IndependentVowel,\r
+\r
+ IndependentVowel, Invalid, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, UnknownForm, UnknownForm,\r
+ Invalid, Invalid, Matra, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Invalid, Invalid, Matra, Matra,\r
+ Matra, Invalid, Matra, Matra,\r
+ Matra, Halant, Invalid, Invalid,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, Matra,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+\r
+ IndependentVowel, IndependentVowel, Invalid, Invalid,\r
+ Invalid, Invalid, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+\r
+ // Sinhala\r
+ Invalid, Invalid, VowelMark, VowelMark,\r
+ Invalid, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+\r
+ IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,\r
+ IndependentVowel, IndependentVowel, IndependentVowel, Invalid,\r
+ Invalid, Invalid, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+\r
+ Consonant, Consonant, Invalid, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Invalid, Consonant, Invalid, Invalid,\r
+\r
+ Consonant, Consonant, Consonant, Consonant,\r
+ Consonant, Consonant, Consonant, Invalid,\r
+ Invalid, Invalid, Halant, Invalid,\r
+ Invalid, Invalid, Invalid, Matra,\r
+\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Invalid, Matra, Invalid,\r
+ Matra, Matra, Matra, Matra,\r
+ Matra, Matra, Matra, Matra,\r
+\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+ Invalid, Invalid, Invalid, Invalid,\r
+\r
+ Invalid, Invalid, Matra, Matra,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+ Other, Other, Other, Other,\r
+};\r
+\r
+typedef enum _Position {\r
+ None,\r
+ Pre,\r
+ Above,\r
+ Below,\r
+ Post,\r
+ Split,\r
+ Base,\r
+ Reph,\r
+ Vattu,\r
+ Inherit\r
+}Position;\r
+\r
+static const unsigned char indicPosition[0xe00-0x900] = {\r
+ // Devanagari\r
+ None, Above, Above, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ Below, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, Post, Pre,\r
+\r
+ Post, Below, Below, Below,\r
+ Below, Above, Above, Above,\r
+ Above, Post, Post, Post,\r
+ Post, None, None, None,\r
+\r
+ None, Above, Below, Above,\r
+ Above, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, Below, Below,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Bengali\r
+ None, Above, Post, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ Below, None, None, Post,\r
+\r
+ Below, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ Below, None, Post, Pre,\r
+\r
+ Post, Below, Below, Below,\r
+ Below, None, None, Pre,\r
+ Pre, None, None, Split,\r
+ Split, Below, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, Below, Below,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ Below, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Gurmukhi\r
+ None, Above, Above, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, Post,\r
+\r
+ Below, None, None, None,\r
+ None, Below, None, None,\r
+ None, Below, None, None,\r
+ Below, None, Post, Pre,\r
+\r
+ Post, Below, Below, None,\r
+ None, None, None, Above,\r
+ Above, None, None, Above,\r
+ Above, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ Above, Above, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Gujarati\r
+ None, Above, Above, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ Below, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, Post, Pre,\r
+\r
+ Post, Below, Below, Below,\r
+ Below, Above, None, Above,\r
+ Above, Post, None, Post,\r
+ Post, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, Below, Below,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Oriya\r
+ None, Above, Post, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ Below, None, None, None,\r
+ Below, None, None, None,\r
+ Below, Below, Below, Post,\r
+\r
+ Below, None, Below, Below,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, Post, Above,\r
+\r
+ Post, Below, Below, Below,\r
+ None, None, None, Pre,\r
+ Split, None, None, Split,\r
+ Split, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, Above, Post,\r
+ None, None, None, None,\r
+ None, None, None, Post,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, Below, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Tamil\r
+ None, None, Above, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, Post, Post,\r
+\r
+ Above, Below, Below, None,\r
+ None, None, Pre, Pre,\r
+ Pre, None, Split, Split,\r
+ Split, Halant, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Telugu\r
+ None, Post, Post, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+\r
+ Below, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+ Below, None, Below, Below,\r
+ Below, Below, Below, Below,\r
+\r
+ Below, None, Below, Below,\r
+ None, Below, Below, Below,\r
+ Below, Below, None, None,\r
+ None, None, Post, Above,\r
+\r
+ Above, Post, Post, Post,\r
+ Post, None, Above, Above,\r
+ Split, None, Post, Above,\r
+ Above, Halant, None, None,\r
+\r
+ None, None, None, None,\r
+ None, Above, Below, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Kannada\r
+ None, None, Post, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+\r
+ Below, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+ Below, Below, Below, Below,\r
+\r
+ Below, None, Below, Below,\r
+ None, Below, Below, Below,\r
+ Below, Below, None, None,\r
+ None, None, Post, Above,\r
+\r
+ Split, Post, Post, Post,\r
+ Post, None, Above, Split,\r
+ Split, None, Split, Split,\r
+ Above, Halant, None, None,\r
+\r
+ None, None, None, None,\r
+ None, Post, Post, None,\r
+ None, None, None, None,\r
+ None, None, Below, None,\r
+\r
+ None, None, Below, Below,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Malayalam\r
+ None, None, Post, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, Post,\r
+\r
+ Post, None, Below, None,\r
+ None, Post, None, None,\r
+ None, None, None, None,\r
+ None, None, Post, Post,\r
+\r
+ Post, Post, Post, Post,\r
+ None, None, Pre, Pre,\r
+ Pre, None, Split, Split,\r
+ Split, Halant, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ // Sinhala\r
+ None, None, Post, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, Post,\r
+\r
+ Post, Post, Above, Above,\r
+ Below, None, Below, None,\r
+ Post, Pre, Split, Pre,\r
+ Split, Split, Split, Post,\r
+\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+\r
+ None, None, Post, Post,\r
+ None, None, None, None,\r
+ None, None, None, None,\r
+ None, None, None, None\r
+};\r
+\r
+static Form form(unsigned short uc) {\r
+ if (uc < 0x900 || uc > 0xdff) {\r
+ if (uc == 0x25cc)\r
+ return Consonant;\r
+ if (uc == 0x200c || uc == 0x200d)\r
+ return Control;\r
+ return Other;\r
+ }\r
+ return (Form)indicForms[uc-0x900];\r
+}\r
+\r
+static Position indic_position(unsigned short uc) {\r
+ if (uc < 0x900 || uc > 0xdff)\r
+ return None;\r
+ return (Position) indicPosition[uc-0x900];\r
+}\r
+\r
+\r
+enum IndicScriptProperties {\r
+ HasReph = 0x01,\r
+ HasSplit = 0x02\r
+};\r
+\r
+const hb_uint8 scriptProperties[10] = {\r
+ // Devanagari,\r
+ HasReph,\r
+ // Bengali,\r
+ HasReph|HasSplit,\r
+ // Gurmukhi,\r
+ 0,\r
+ // Gujarati,\r
+ HasReph,\r
+ // Oriya,\r
+ HasReph|HasSplit,\r
+ // Tamil,\r
+ HasSplit,\r
+ // Telugu,\r
+ HasSplit,\r
+ // Kannada,\r
+ HasSplit|HasReph,\r
+ // Malayalam,\r
+ HasSplit,\r
+ // Sinhala,\r
+ HasSplit\r
+};\r
+\r
+typedef struct _IndicOrdering {\r
+ Form form;\r
+ Position position;\r
+}IndicOrdering;\r
+\r
+static const IndicOrdering devanagari_order [] = {\r
+ { Consonant, Below },\r
+ { Matra, Below },\r
+ { VowelMark, Below },\r
+ { StressMark, Below },\r
+ { Matra, Above },\r
+ { Matra, Post },\r
+ { Consonant, Reph },\r
+ { VowelMark, Above },\r
+ { StressMark, Above },\r
+ { VowelMark, Post },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering bengali_order [] = {\r
+ { Consonant, Below },\r
+ { Matra, Below },\r
+ { Matra, Above },\r
+ { Consonant, Reph },\r
+ { VowelMark, Above },\r
+ { Consonant, Post },\r
+ { Matra, Post },\r
+ { VowelMark, Post },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering gurmukhi_order [] = {\r
+ { Consonant, Below },\r
+ { Matra, Below },\r
+ { Matra, Above },\r
+ { Consonant, Post },\r
+ { Matra, Post },\r
+ { VowelMark, Above },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering tamil_order [] = {\r
+ { Matra, Above },\r
+ { Matra, Post },\r
+ { VowelMark, Post },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering telugu_order [] = {\r
+ { Matra, Above },\r
+ { Matra, Below },\r
+ { Matra, Post },\r
+ { Consonant, Below },\r
+ { Consonant, Post },\r
+ { VowelMark, Post },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering kannada_order [] = {\r
+ { Matra, Above },\r
+ { Matra, Post },\r
+ { Consonant, Below },\r
+ { Consonant, Post },\r
+ { LengthMark, Post },\r
+ { Consonant, Reph },\r
+ { VowelMark, Post },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering malayalam_order [] = {\r
+ { Consonant, Below },\r
+ { Matra, Below },\r
+ { Consonant, Reph },\r
+ { Consonant, Post },\r
+ { Matra, Post },\r
+ { VowelMark, Post },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering sinhala_order [] = {\r
+ { Matra, Below },\r
+ { Matra, Above },\r
+ { Matra, Post },\r
+ { VowelMark, Post },\r
+ { (Form)0, None }\r
+};\r
+\r
+static const IndicOrdering * const indic_order[] = {\r
+ devanagari_order, // Devanagari\r
+ bengali_order, // Bengali\r
+ gurmukhi_order, // Gurmukhi\r
+ devanagari_order, // Gujarati\r
+ bengali_order, // Oriya\r
+ tamil_order, // Tamil\r
+ telugu_order, // Telugu\r
+ kannada_order, // Kannada\r
+ malayalam_order, // Malayalam\r
+ sinhala_order // Sinhala\r
+};\r
+\r
+\r
+\r
+// vowel matras that have to be split into two parts.\r
+static const unsigned short split_matras[] = {\r
+ // matra, split1, split2, split3\r
+\r
+ // bengalis\r
+ 0x9cb, 0x9c7, 0x9be, 0x0,\r
+ 0x9cc, 0x9c7, 0x9d7, 0x0,\r
+ // oriya\r
+ 0xb48, 0xb47, 0xb56, 0x0,\r
+ 0xb4b, 0xb47, 0xb3e, 0x0,\r
+ 0xb4c, 0xb47, 0xb57, 0x0,\r
+ // tamil\r
+ 0xbca, 0xbc6, 0xbbe, 0x0,\r
+ 0xbcb, 0xbc7, 0xbbe, 0x0,\r
+ 0xbcc, 0xbc6, 0xbd7, 0x0,\r
+ // telugu\r
+ 0xc48, 0xc46, 0xc56, 0x0,\r
+ // kannada\r
+ 0xcc0, 0xcbf, 0xcd5, 0x0,\r
+ 0xcc7, 0xcc6, 0xcd5, 0x0,\r
+ 0xcc8, 0xcc6, 0xcd6, 0x0,\r
+ 0xcca, 0xcc6, 0xcc2, 0x0,\r
+ 0xccb, 0xcc6, 0xcc2, 0xcd5,\r
+ // malayalam\r
+ 0xd4a, 0xd46, 0xd3e, 0x0,\r
+ 0xd4b, 0xd47, 0xd3e, 0x0,\r
+ 0xd4c, 0xd46, 0xd57, 0x0,\r
+ // sinhala\r
+ 0xdda, 0xdd9, 0xdca, 0x0,\r
+ 0xddc, 0xdd9, 0xdcf, 0x0,\r
+ 0xddd, 0xdd9, 0xdcf, 0xdca,\r
+ 0xdde, 0xdd9, 0xddf, 0x0,\r
+ 0xffff\r
+};\r
+\r
+static void splitMatra(unsigned short *reordered, int matra, int *len)\r
+{\r
+ unsigned short matra_uc = reordered[matra];\r
+ //qDebug("matra=%d, reordered[matra]=%x", matra, reordered[matra]);\r
+\r
+ const unsigned short *split = split_matras;\r
+ while (split[0] < matra_uc)\r
+ split += 4;\r
+\r
+ assert(*split == matra_uc);\r
+ ++split;\r
+\r
+ int added_chars = split[2] == 0x0 ? 1 : 2;\r
+\r
+ memmove(reordered + matra + added_chars, reordered + matra, (*len-matra)*sizeof(unsigned short));\r
+ reordered[matra] = split[0];\r
+ reordered[matra+1] = split[1];\r
+ if(added_chars == 2)\r
+ reordered[matra+2] = split[2];\r
+ *len += added_chars;\r
+}\r
+\r
+#ifndef NO_OPENTYPE\r
+static const HB_OpenTypeFeature indic_features[] = {\r
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },\r
+ { HB_MAKE_TAG('i', 'n', 'i', 't'), InitProperty },\r
+ { HB_MAKE_TAG('n', 'u', 'k', 't'), NuktaProperty },\r
+ { HB_MAKE_TAG('a', 'k', 'h', 'n'), AkhantProperty },\r
+ { HB_MAKE_TAG('r', 'p', 'h', 'f'), RephProperty },\r
+ { HB_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty },\r
+ { HB_MAKE_TAG('h', 'a', 'l', 'f'), HalfFormProperty },\r
+ { HB_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty },\r
+ { HB_MAKE_TAG('v', 'a', 't', 'u'), VattuProperty },\r
+ { HB_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty },\r
+ { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },\r
+ { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },\r
+ { HB_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty },\r
+ { HB_MAKE_TAG('h', 'a', 'l', 'n'), HalantProperty },\r
+ { 0, 0 }\r
+};\r
+#endif\r
+\r
+// #define INDIC_DEBUG\r
+#ifdef INDIC_DEBUG\r
+#define IDEBUG hb_debug\r
+#include <stdarg.h>\r
+\r
+static void hb_debug(const char *msg, ...)\r
+{\r
+ va_list ap;\r
+ va_start(ap, msg); // use variable arg list\r
+ vfprintf(stderr, msg, ap);\r
+ va_end(ap);\r
+ fprintf(stderr, "\n");\r
+}\r
+\r
+#else\r
+#define IDEBUG if(0) printf\r
+#endif\r
+\r
+#if 0 //def INDIC_DEBUG\r
+static QString propertiesToString(int properties)\r
+{\r
+ QString res;\r
+ properties = ~properties;\r
+ if (properties & CcmpProperty)\r
+ res += "Ccmp ";\r
+ if (properties & InitProperty)\r
+ res += "Init ";\r
+ if (properties & NuktaProperty)\r
+ res += "Nukta ";\r
+ if (properties & AkhantProperty)\r
+ res += "Akhant ";\r
+ if (properties & RephProperty)\r
+ res += "Reph ";\r
+ if (properties & PreFormProperty)\r
+ res += "PreForm ";\r
+ if (properties & BelowFormProperty)\r
+ res += "BelowForm ";\r
+ if (properties & AboveFormProperty)\r
+ res += "AboveForm ";\r
+ if (properties & HalfFormProperty)\r
+ res += "HalfForm ";\r
+ if (properties & PostFormProperty)\r
+ res += "PostForm ";\r
+ if (properties & VattuProperty)\r
+ res += "Vattu ";\r
+ if (properties & PreSubstProperty)\r
+ res += "PreSubst ";\r
+ if (properties & BelowSubstProperty)\r
+ res += "BelowSubst ";\r
+ if (properties & AboveSubstProperty)\r
+ res += "AboveSubst ";\r
+ if (properties & PostSubstProperty)\r
+ res += "PostSubst ";\r
+ if (properties & HalantProperty)\r
+ res += "Halant ";\r
+ if (properties & CligProperty)\r
+ res += "Clig ";\r
+ return res;\r
+}\r
+#endif\r
+\r
+static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool invalid)\r
+{\r
+ HB_Script script = item->item.script;\r
+ assert(script >= HB_Script_Devanagari && script <= HB_Script_Sinhala);\r
+ const unsigned short script_base = 0x0900 + 0x80*(script-HB_Script_Devanagari);\r
+ const unsigned short ra = script_base + 0x30;\r
+ const unsigned short halant = script_base + 0x4d;\r
+ const unsigned short nukta = script_base + 0x3c;\r
+ bool control = false;\r
+\r
+ int len = (int)item->item.length;\r
+ IDEBUG(">>>>> indic shape: from=%d, len=%d invalid=%d", item->item.pos, item->item.length, invalid);\r
+\r
+ if ((int)item->num_glyphs < len+4) {\r
+ item->num_glyphs = len+4;\r
+ return false;\r
+ }\r
+\r
+ HB_STACKARRAY(HB_UChar16, reordered, len + 4);\r
+ HB_STACKARRAY(hb_uint8, position, len + 4);\r
+\r
+ unsigned char properties = scriptProperties[script-HB_Script_Devanagari];\r
+\r
+ if (invalid) {\r
+ *reordered = 0x25cc;\r
+ memcpy(reordered+1, item->string + item->item.pos, len*sizeof(HB_UChar16));\r
+ len++;\r
+ } else {\r
+ memcpy(reordered, item->string + item->item.pos, len*sizeof(HB_UChar16));\r
+ }\r
+ if (reordered[len-1] == 0x200c) // zero width non joiner\r
+ len--;\r
+\r
+ int i;\r
+ int base = 0;\r
+ int reph = -1;\r
+\r
+#ifdef INDIC_DEBUG\r
+ IDEBUG("original:");\r
+ for (i = 0; i < len; i++) {\r
+ IDEBUG(" %d: %4x", i, reordered[i]);\r
+ }\r
+#endif\r
+\r
+ if (len != 1) {\r
+ HB_UChar16 *uc = reordered;\r
+ bool beginsWithRa = false;\r
+\r
+ // Rule 1: find base consonant\r
+ //\r
+ // The shaping engine finds the base consonant of the\r
+ // syllable, using the following algorithm: starting from the\r
+ // end of the syllable, move backwards until a consonant is\r
+ // found that does not have a below-base or post-base form\r
+ // (post-base forms have to follow below-base forms), or\r
+ // arrive at the first consonant. The consonant stopped at\r
+ // will be the base.\r
+ //\r
+ // * If the syllable starts with Ra + H (in a script that has\r
+ // 'Reph'), Ra is excluded from candidates for base\r
+ // consonants.\r
+ //\r
+ // * In Kannada and Telugu, the base consonant cannot be\r
+ // farther than 3 consonants from the end of the syllable.\r
+ // #### replace the HasReph property by testing if the feature exists in the font!\r
+ if (form(*uc) == Consonant || (script == HB_Script_Bengali && form(*uc) == IndependentVowel)) {\r
+ if ((properties & HasReph) && (len > 2) &&\r
+ (*uc == ra || *uc == 0x9f0) && *(uc+1) == halant)\r
+ beginsWithRa = true;\r
+\r
+ if (beginsWithRa && form(*(uc+2)) == Control)\r
+ beginsWithRa = false;\r
+\r
+ base = (beginsWithRa ? 2 : 0);\r
+ IDEBUG(" length = %d, beginsWithRa = %d, base=%d", len, beginsWithRa, base);\r
+\r
+ int lastConsonant = 0;\r
+ int matra = -1;\r
+ // we remember:\r
+ // * the last consonant since we need it for rule 2\r
+ // * the matras position for rule 3 and 4\r
+\r
+ // figure out possible base glyphs\r
+ memset(position, 0, len);\r
+ if (script == HB_Script_Devanagari || script == HB_Script_Gujarati) {\r
+ bool vattu = false;\r
+ for (i = base; i < len; ++i) {\r
+ position[i] = form(uc[i]);\r
+ if (position[i] == Consonant) {\r
+ lastConsonant = i;\r
+ vattu = (!vattu && uc[i] == ra);\r
+ if (vattu) {\r
+ IDEBUG("excluding vattu glyph at %d from base candidates", i);\r
+ position[i] = Vattu;\r
+ }\r
+ } else if (position[i] == Matra) {\r
+ matra = i;\r
+ }\r
+ }\r
+ } else {\r
+ for (i = base; i < len; ++i) {\r
+ position[i] = form(uc[i]);\r
+ if (position[i] == Consonant)\r
+ lastConsonant = i;\r
+ else if (matra < 0 && position[i] == Matra)\r
+ matra = i;\r
+ }\r
+ }\r
+ int skipped = 0;\r
+ Position pos = Post;\r
+ for (i = len-1; i > base; i--) {\r
+ if (position[i] != Consonant && (position[i] != Control || script == HB_Script_Kannada))\r
+ continue;\r
+\r
+ Position charPosition = indic_position(uc[i]);\r
+ if (pos == Post && charPosition == Post) {\r
+ pos = Post;\r
+ } else if ((pos == Post || pos == Below) && charPosition == Below) {\r
+ if (script == HB_Script_Devanagari || script == HB_Script_Gujarati)\r
+ base = i;\r
+ pos = Below;\r
+ } else {\r
+ base = i;\r
+ break;\r
+ }\r
+ if (skipped == 2 && (script == HB_Script_Kannada || script == HB_Script_Telugu)) {\r
+ base = i;\r
+ break;\r
+ }\r
+ ++skipped;\r
+ }\r
+\r
+ IDEBUG(" base consonant at %d skipped=%d, lastConsonant=%d", base, skipped, lastConsonant);\r
+\r
+ // Rule 2:\r
+ //\r
+ // If the base consonant is not the last one, Uniscribe\r
+ // moves the halant from the base consonant to the last\r
+ // one.\r
+ if (lastConsonant > base) {\r
+ int halantPos = 0;\r
+ if (uc[base+1] == halant)\r
+ halantPos = base + 1;\r
+ else if (uc[base+1] == nukta && uc[base+2] == halant)\r
+ halantPos = base + 2;\r
+ if (halantPos > 0) {\r
+ IDEBUG(" moving halant from %d to %d!", base+1, lastConsonant);\r
+ for (i = halantPos; i < lastConsonant; i++)\r
+ uc[i] = uc[i+1];\r
+ uc[lastConsonant] = halant;\r
+ }\r
+ }\r
+\r
+ // Rule 3:\r
+ //\r
+ // If the syllable starts with Ra + H, Uniscribe moves\r
+ // this combination so that it follows either:\r
+\r
+ // * the post-base 'matra' (if any) or the base consonant\r
+ // (in scripts that show similarity to Devanagari, i.e.,\r
+ // Devanagari, Gujarati, Bengali)\r
+ // * the base consonant (other scripts)\r
+ // * the end of the syllable (Kannada)\r
+\r
+ Position matra_position = None;\r
+ if (matra > 0)\r
+ matra_position = indic_position(uc[matra]);\r
+ IDEBUG(" matra at %d with form %d, base=%d", matra, matra_position, base);\r
+\r
+ if (beginsWithRa && base != 0) {\r
+ int toPos = base+1;\r
+ if (toPos < len && uc[toPos] == nukta)\r
+ toPos++;\r
+ if (toPos < len && uc[toPos] == halant)\r
+ toPos++;\r
+ if (toPos < len && uc[toPos] == 0x200d)\r
+ toPos++;\r
+ if (toPos < len-1 && uc[toPos] == ra && uc[toPos+1] == halant)\r
+ toPos += 2;\r
+ if (script == HB_Script_Devanagari || script == HB_Script_Gujarati || script == HB_Script_Bengali) {\r
+ if (matra_position == Post || matra_position == Split) {\r
+ toPos = matra+1;\r
+ matra -= 2;\r
+ }\r
+ } else if (script == HB_Script_Kannada) {\r
+ toPos = len;\r
+ matra -= 2;\r
+ }\r
+\r
+ IDEBUG("moving leading ra+halant to position %d", toPos);\r
+ for (i = 2; i < toPos; i++)\r
+ uc[i-2] = uc[i];\r
+ uc[toPos-2] = ra;\r
+ uc[toPos-1] = halant;\r
+ base -= 2;\r
+ if (properties & HasReph)\r
+ reph = toPos-2;\r
+ }\r
+\r
+ // Rule 4:\r
+\r
+ // Uniscribe splits two- or three-part matras into their\r
+ // parts. This splitting is a character-to-character\r
+ // operation).\r
+ //\r
+ // Uniscribe describes some moving operations for these\r
+ // matras here. For shaping however all pre matras need\r
+ // to be at the beginning of the syllable, so we just move\r
+ // them there now.\r
+ if (matra_position == Split) {\r
+ splitMatra(uc, matra, &len);\r
+ // Handle three-part matras (0xccb in Kannada)\r
+ matra_position = indic_position(uc[matra]);\r
+ }\r
+\r
+ if (matra_position == Pre) {\r
+ unsigned short m = uc[matra];\r
+ while (matra--)\r
+ uc[matra+1] = uc[matra];\r
+ uc[0] = m;\r
+ base++;\r
+ }\r
+ }\r
+\r
+ // Rule 5:\r
+ //\r
+ // Uniscribe classifies consonants and 'matra' parts as\r
+ // pre-base, above-base (Reph), below-base or post-base. This\r
+ // classification exists on the character code level and is\r
+ // language-dependent, not font-dependent.\r
+ for (i = 0; i < base; ++i)\r
+ position[i] = Pre;\r
+ position[base] = Base;\r
+ for (i = base+1; i < len; ++i) {\r
+ position[i] = indic_position(uc[i]);\r
+ // #### replace by adjusting table\r
+ if (uc[i] == nukta || uc[i] == halant)\r
+ position[i] = Inherit;\r
+ }\r
+ if (reph > 0) {\r
+ // recalculate reph, it might have changed.\r
+ for (i = base+1; i < len; ++i)\r
+ if (uc[i] == ra)\r
+ reph = i;\r
+ position[reph] = Reph;\r
+ position[reph+1] = Inherit;\r
+ }\r
+\r
+ // all reordering happens now to the chars after the base\r
+ int fixed = base+1;\r
+ if (fixed < len && uc[fixed] == nukta)\r
+ fixed++;\r
+ if (fixed < len && uc[fixed] == halant)\r
+ fixed++;\r
+ if (fixed < len && uc[fixed] == 0x200d)\r
+ fixed++;\r
+\r
+#ifdef INDIC_DEBUG\r
+ for (i = fixed; i < len; ++i)\r
+ IDEBUG("position[%d] = %d, form=%d uc=%x", i, position[i], form(uc[i]), uc[i]);\r
+#endif\r
+ // we continuosly position the matras and vowel marks and increase the fixed\r
+ // until we reached the end.\r
+ const IndicOrdering *finalOrder = indic_order[script-HB_Script_Devanagari];\r
+\r
+ IDEBUG(" reordering pass:");\r
+ IDEBUG(" base=%d fixed=%d", base, fixed);\r
+ int toMove = 0;\r
+ while (finalOrder[toMove].form && fixed < len-1) {\r
+ IDEBUG(" fixed = %d, toMove=%d, moving form %d with pos %d", fixed, toMove, finalOrder[toMove].form, finalOrder[toMove].position);\r
+ for (i = fixed; i < len; i++) {\r
+// IDEBUG() << " i=" << i << "uc=" << hex << uc[i] << "form=" << form(uc[i])\r
+// << "position=" << position[i];\r
+ if (form(uc[i]) == finalOrder[toMove].form &&\r
+ position[i] == finalOrder[toMove].position) {\r
+ int j=0;\r
+ // need to move this glyph\r
+ int to = fixed;\r
+ if (i < len-1 && position[i+1] == Inherit) {\r
+ IDEBUG(" moving two chars from %d to %d", i, to);\r
+ unsigned short ch = uc[i];\r
+ unsigned short ch2 = uc[i+1];\r
+ unsigned char pos = position[i];\r
+ for (j = i+1; j > to+1; j--) {\r
+ uc[j] = uc[j-2];\r
+ position[j] = position[j-2];\r
+ }\r
+ uc[to] = ch;\r
+ uc[to+1] = ch2;\r
+ position[to] = pos;\r
+ position[to+1] = pos;\r
+ fixed += 2;\r
+ } else {\r
+ IDEBUG(" moving one char from %d to %d", i, to);\r
+ unsigned short ch = uc[i];\r
+ unsigned char pos = position[i];\r
+ for (j = i; j > to; j--) {\r
+ uc[j] = uc[j-1];\r
+ position[j] = position[j-1];\r
+ }\r
+ uc[to] = ch;\r
+ position[to] = pos;\r
+ fixed++;\r
+ }\r
+ }\r
+ }\r
+ toMove++;\r
+ }\r
+\r
+ }\r
+\r
+ if (reph > 0) {\r
+ // recalculate reph, it might have changed.\r
+ for (i = base+1; i < len; ++i)\r
+ if (reordered[i] == ra)\r
+ reph = i;\r
+ }\r
+\r
+#ifndef NO_OPENTYPE\r
+ const int availableGlyphs = item->num_glyphs;\r
+#endif\r
+ if (!item->font->klass->convertStringToGlyphIndices(item->font,\r
+ reordered, len,\r
+ item->glyphs, &item->num_glyphs,\r
+ item->item.bidiLevel % 2))\r
+ goto error;\r
+\r
+\r
+ IDEBUG(" base=%d, reph=%d", base, reph);\r
+ IDEBUG("reordered:");\r
+ for (i = 0; i < len; i++) {\r
+ item->attributes[i].mark = false;\r
+ item->attributes[i].clusterStart = false;\r
+ item->attributes[i].justification = 0;\r
+ item->attributes[i].zeroWidth = false;\r
+ IDEBUG(" %d: %4x", i, reordered[i]);\r
+ }\r
+\r
+ // now we have the syllable in the right order, and can start running it through open type.\r
+\r
+ for (i = 0; i < len; ++i)\r
+ control |= (form(reordered[i]) == Control);\r
+\r
+#ifndef NO_OPENTYPE\r
+ if (openType) {\r
+\r
+ // we need to keep track of where the base glyph is for some\r
+ // scripts and use the cluster feature for this. This\r
+ // also means we have to correct the logCluster output from\r
+ // the open type engine manually afterwards. for indic this\r
+ // is rather simple, as all chars just point to the first\r
+ // glyph in the syllable.\r
+ HB_STACKARRAY(unsigned short, clusters, len);\r
+ HB_STACKARRAY(unsigned int, properties, len);\r
+\r
+ for (i = 0; i < len; ++i)\r
+ clusters[i] = i;\r
+\r
+ // features we should always apply\r
+ for (i = 0; i < len; ++i)\r
+ properties[i] = ~(CcmpProperty\r
+ | NuktaProperty\r
+ | VattuProperty\r
+ | PreSubstProperty\r
+ | BelowSubstProperty\r
+ | AboveSubstProperty\r
+ | HalantProperty\r
+ | PositioningProperties);\r
+\r
+ // Ccmp always applies\r
+ // Init\r
+ if (item->item.pos == 0\r
+ || !(isLetter(item->string[item->item.pos-1]) || isMark(item->string[item->item.pos-1])))\r
+ properties[0] &= ~InitProperty;\r
+\r
+ // Nukta always applies\r
+ // Akhant\r
+ for (i = 0; i <= base; ++i)\r
+ properties[i] &= ~AkhantProperty;\r
+ // Reph\r
+ if (reph >= 0) {\r
+ properties[reph] &= ~RephProperty;\r
+ properties[reph+1] &= ~RephProperty;\r
+ }\r
+ // BelowForm\r
+ for (i = base+1; i < len; ++i)\r
+ properties[i] &= ~BelowFormProperty;\r
+\r
+ if (script == HB_Script_Devanagari || script == HB_Script_Gujarati) {\r
+ // vattu glyphs need this aswell\r
+ bool vattu = false;\r
+ for (i = base-2; i > 1; --i) {\r
+ if (form(reordered[i]) == Consonant) {\r
+ vattu = (!vattu && reordered[i] == ra);\r
+ if (vattu) {\r
+ IDEBUG("forming vattu ligature at %d", i);\r
+ properties[i] &= ~BelowFormProperty;\r
+ properties[i+1] &= ~BelowFormProperty;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ // HalfFormProperty\r
+ for (i = 0; i < base; ++i)\r
+ properties[i] &= ~HalfFormProperty;\r
+ if (control) {\r
+ for (i = 2; i < len; ++i) {\r
+ if (reordered[i] == 0x200d /* ZWJ */) {\r
+ properties[i-1] &= ~HalfFormProperty;\r
+ properties[i-2] &= ~HalfFormProperty;\r
+ } else if (reordered[i] == 0x200c /* ZWNJ */) {\r
+ properties[i-1] &= ~HalfFormProperty;\r
+ properties[i-2] &= ~HalfFormProperty;\r
+ }\r
+ }\r
+ }\r
+ // PostFormProperty\r
+ for (i = base+1; i < len; ++i)\r
+ properties[i] &= ~PostFormProperty;\r
+ // vattu always applies\r
+ // pres always applies\r
+ // blws always applies\r
+ // abvs always applies\r
+\r
+ // psts\r
+ // ### this looks slightly different from before, but I believe it's correct\r
+ if (reordered[len-1] != halant || base != len-2)\r
+ properties[base] &= ~PostSubstProperty;\r
+ for (i = base+1; i < len; ++i)\r
+ properties[i] &= ~PostSubstProperty;\r
+\r
+ // halant always applies\r
+\r
+#ifdef INDIC_DEBUG\r
+// {\r
+// IDEBUG("OT properties:");\r
+// for (int i = 0; i < len; ++i)\r
+// qDebug(" i: %s", ::propertiesToString(properties[i]).toLatin1().data());\r
+// }\r
+#endif\r
+\r
+ // initialize\r
+ item->log_clusters = clusters;\r
+ HB_OpenTypeShape(item, properties);\r
+\r
+ int newLen = item->face->buffer->in_length;\r
+ HB_GlyphItem otl_glyphs = item->face->buffer->in_string;\r
+\r
+ // move the left matra back to its correct position in malayalam and tamil\r
+ if ((script == HB_Script_Malayalam || script == HB_Script_Tamil) && (form(reordered[0]) == Matra)) {\r
+// qDebug("reordering matra, len=%d", newLen);\r
+ // need to find the base in the shaped string and move the matra there\r
+ int basePos = 0;\r
+ while (basePos < newLen && (int)otl_glyphs[basePos].cluster <= base)\r
+ basePos++;\r
+ --basePos;\r
+ if (basePos < newLen && basePos > 1) {\r
+// qDebug("moving prebase matra to position %d in syllable newlen=%d", basePos, newLen);\r
+ HB_GlyphItemRec m = otl_glyphs[0];\r
+ --basePos;\r
+ for (i = 0; i < basePos; ++i)\r
+ otl_glyphs[i] = otl_glyphs[i+1];\r
+ otl_glyphs[basePos] = m;\r
+ }\r
+ }\r
+\r
+ HB_Bool positioned = HB_OpenTypePosition(item, availableGlyphs, false);\r
+\r
+ HB_FREE_STACKARRAY(clusters);\r
+ HB_FREE_STACKARRAY(properties);\r
+\r
+ if (!positioned)\r
+ goto error;\r
+\r
+ if (control) {\r
+ IDEBUG("found a control char in the syllable");\r
+ hb_uint32 i = 0, j = 0;\r
+ while (i < item->num_glyphs) {\r
+ if (form(reordered[otl_glyphs[i].cluster]) == Control) {\r
+ ++i;\r
+ if (i >= item->num_glyphs)\r
+ break;\r
+ }\r
+ item->glyphs[j] = item->glyphs[i];\r
+ item->attributes[j] = item->attributes[i];\r
+ ++i;\r
+ ++j;\r
+ }\r
+ item->num_glyphs = j;\r
+ }\r
+\r
+ } else {\r
+ HB_HeuristicPosition(item);\r
+ }\r
+#endif // NO_OPENTYPE\r
+ item->attributes[0].clusterStart = true;\r
+\r
+ HB_FREE_STACKARRAY(reordered);\r
+ HB_FREE_STACKARRAY(position);\r
+\r
+ IDEBUG("<<<<<<");\r
+ return true;\r
+\r
+error:\r
+ HB_FREE_STACKARRAY(reordered);\r
+ HB_FREE_STACKARRAY(position);\r
+ return false;\r
+}\r
+\r
+/* syllables are of the form:\r
+\r
+ (Consonant Nukta? Halant)* Consonant Matra? VowelMark? StressMark?\r
+ (Consonant Nukta? Halant)* Consonant Halant\r
+ IndependentVowel VowelMark? StressMark?\r
+\r
+ We return syllable boundaries on invalid combinations aswell\r
+*/\r
+/* SAMSUNG - Kaja Changes -Start */\r
+int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+//static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+/* SAMSUNG - Kaja Changes -End */\r
+{\r
+ *invalid = false;\r
+ IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end);\r
+ const HB_UChar16 *uc = s+start ;\r
+\r
+ int pos = 0;\r
+ Form state = form(uc[pos]);\r
+ IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);\r
+ pos++;\r
+\r
+ if (state != Consonant && state != IndependentVowel) {\r
+ if (state != Other)\r
+ *invalid = true;\r
+ goto finish;\r
+ }\r
+\r
+ while (pos < end - start) {\r
+ Form newState = form(uc[pos]);\r
+ IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos]);\r
+ switch(newState) {\r
+ case Control:\r
+ newState = state;\r
+ if (state == Halant && uc[pos] == 0x200d /* ZWJ */)\r
+ break;\r
+ // the control character should be the last char in the item\r
+ ++pos;\r
+ goto finish;\r
+ case Consonant:\r
+ if (state == Halant && (script != HB_Script_Sinhala || uc[pos-1] == 0x200d /* ZWJ */))\r
+ break;\r
+ goto finish;\r
+ case Halant:\r
+ if (state == Nukta || state == Consonant)\r
+ break;\r
+ // Bengali has a special exception allowing the combination Vowel_A/E + Halant + Ya\r
+ if (script == HB_Script_Bengali && pos == 1 &&\r
+ (uc[0] == 0x0985 || uc[0] == 0x098f))\r
+ break;\r
+ // Sinhala uses the Halant as a component of certain matras. Allow these, but keep the state on Matra.\r
+ if (script == HB_Script_Sinhala && state == Matra) {\r
+ ++pos;\r
+ continue;\r
+ }\r
+ if (script == HB_Script_Malayalam && state == Matra && uc[pos-1] == 0x0d41) {\r
+ ++pos;\r
+ continue;\r
+ }\r
+ goto finish;\r
+ case Nukta:\r
+ if (state == Consonant)\r
+ break;\r
+ goto finish;\r
+ case StressMark:\r
+ if (state == VowelMark)\r
+ break;\r
+ // fall through\r
+ case VowelMark:\r
+ if (state == Matra || state == LengthMark || state == IndependentVowel)\r
+ break;\r
+ // fall through\r
+ case Matra:\r
+ if (state == Consonant || state == Nukta)\r
+ break;\r
+ if (state == Matra) {\r
+ // ### needs proper testing for correct two/three part matras\r
+ break;\r
+ }\r
+ // ### not sure if this is correct. If it is, does it apply only to Bengali or should\r
+ // it work for all Indic languages?\r
+ // the combination Independent_A + Vowel Sign AA is allowed.\r
+ if (script == HB_Script_Bengali && uc[pos] == 0x9be && uc[pos-1] == 0x985)\r
+ break;\r
+ if (script == HB_Script_Tamil && state == Matra) {\r
+ if (uc[pos-1] == 0x0bc6 &&\r
+ (uc[pos] == 0xbbe || uc[pos] == 0xbd7))\r
+ break;\r
+ if (uc[pos-1] == 0x0bc7 && uc[pos] == 0xbbe)\r
+ break;\r
+ }\r
+ goto finish;\r
+\r
+ case LengthMark:\r
+ if (state == Matra) {\r
+ // ### needs proper testing for correct two/three part matras\r
+ break;\r
+ }\r
+ case IndependentVowel:\r
+ case Invalid:\r
+ case Other:\r
+ goto finish;\r
+ }\r
+ state = newState;\r
+ pos++;\r
+ }\r
+ finish:\r
+ return pos+start;\r
+}\r
+\r
+HB_Bool HB_IndicShape(HB_ShaperItem *item)\r
+{\r
+ assert(item->item.script >= HB_Script_Devanagari && item->item.script <= HB_Script_Sinhala);\r
+\r
+ HB_Bool openType = false;\r
+#ifndef NO_OPENTYPE\r
+ openType = HB_SelectScript(item, indic_features);\r
+#endif\r
+ unsigned short *logClusters = item->log_clusters;\r
+\r
+ HB_ShaperItem syllable = *item;\r
+ int first_glyph = 0;\r
+\r
+ int sstart = item->item.pos;\r
+ int end = sstart + item->item.length;\r
+ IDEBUG("indic_shape: from %d length %d", item->item.pos, item->item.length);\r
+ while (sstart < end) {\r
+ HB_Bool invalid;\r
+ int send = indic_nextSyllableBoundary(item->item.script, item->string, sstart, end, &invalid);\r
+ IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,\r
+ invalid ? "true" : "false");\r
+ syllable.item.pos = sstart;\r
+ syllable.item.length = send-sstart;\r
+ syllable.glyphs = item->glyphs + first_glyph;\r
+ syllable.attributes = item->attributes + first_glyph;\r
+ syllable.offsets = item->offsets + first_glyph;\r
+ syllable.advances = item->advances + first_glyph;\r
+ syllable.num_glyphs = item->num_glyphs - first_glyph;\r
+ if (!indic_shape_syllable(openType, &syllable, invalid)) {\r
+ IDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);\r
+ item->num_glyphs += syllable.num_glyphs;\r
+ return false;\r
+ }\r
+ // fix logcluster array\r
+ IDEBUG("syllable:");\r
+ hb_uint32 g;\r
+ for (g = first_glyph; g < first_glyph + syllable.num_glyphs; ++g)\r
+ IDEBUG(" %d -> glyph %x", g, item->glyphs[g]);\r
+ IDEBUG(" logclusters:");\r
+ int i;\r
+ for (i = sstart; i < send; ++i) {\r
+ IDEBUG(" %d -> glyph %d", i, first_glyph);\r
+ logClusters[i-item->item.pos] = first_glyph;\r
+ }\r
+ sstart = send;\r
+ first_glyph += syllable.num_glyphs;\r
+ }\r
+ item->num_glyphs = first_glyph;\r
+ return true;\r
+}\r
+\r
+void HB_IndicAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)\r
+{\r
+ int end = from + len;\r
+ const HB_UChar16 *uc = text + from;\r
+ attributes += from;\r
+ hb_uint32 i = 0;\r
+ while (i < len) {\r
+ HB_Bool invalid;\r
+ hb_uint32 boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from;\r
+ attributes[i].charStop = true;\r
+\r
+ if (boundary > len-1) boundary = len;\r
+ i++;\r
+ while (i < boundary) {\r
+ attributes[i].charStop = false;\r
+ ++uc;\r
+ ++i;\r
+ }\r
+ assert(i == boundary);\r
+ }\r
+\r
+\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+#include <assert.h>\r
+#include <stdio.h>\r
+\r
+/*\r
+// Vocabulary\r
+// Base -> A consonant or an independent vowel in its full (not subscript) form. It is the\r
+// center of the syllable, it can be surrounded by coeng (subscript) consonants, vowels,\r
+// split vowels, signs... but there is only one base in a syllable, it has to be coded as\r
+// the first character of the syllable.\r
+// split vowel --> vowel that has two parts placed separately (e.g. Before and after the consonant).\r
+// Khmer language has five of them. Khmer split vowels either have one part before the\r
+// base and one after the base or they have a part before the base and a part above the base.\r
+// The first part of all Khmer split vowels is the same character, identical to\r
+// the glyph of Khmer dependent vowel SRA EI\r
+// coeng --> modifier used in Khmer to construct coeng (subscript) consonants\r
+// Differently than indian languages, the coeng modifies the consonant that follows it,\r
+// not the one preceding it Each consonant has two forms, the base form and the subscript form\r
+// the base form is the normal one (using the consonants code-point), the subscript form is\r
+// displayed when the combination coeng + consonant is encountered.\r
+// Consonant of type 1 -> A consonant which has subscript for that only occupies space under a base consonant\r
+// Consonant of type 2.-> Its subscript form occupies space under and before the base (only one, RO)\r
+// Consonant of Type 3 -> Its subscript form occupies space under and after the base (KHO, CHHO, THHO, BA, YO, SA)\r
+// Consonant shifter -> Khmer has to series of consonants. The same dependent vowel has different sounds\r
+// if it is attached to a consonant of the first series or a consonant of the second series\r
+// Most consonants have an equivalent in the other series, but some of theme exist only in\r
+// one series (for example SA). If we want to use the consonant SA with a vowel sound that\r
+// can only be done with a vowel sound that corresponds to a vowel accompanying a consonant\r
+// of the other series, then we need to use a consonant shifter: TRIISAP or MUSIKATOAN\r
+// x17C9 y x17CA. TRIISAP changes a first series consonant to second series sound and\r
+// MUSIKATOAN a second series consonant to have a first series vowel sound.\r
+// Consonant shifter are both normally supercript marks, but, when they are followed by a\r
+// superscript, they change shape and take the form of subscript dependent vowel SRA U.\r
+// If they are in the same syllable as a coeng consonant, Unicode 3.0 says that they\r
+// should be typed before the coeng. Unicode 4.0 breaks the standard and says that it should\r
+// be placed after the coeng consonant.\r
+// Dependent vowel -> In khmer dependent vowels can be placed above, below, before or after the base\r
+// Each vowel has its own position. Only one vowel per syllable is allowed.\r
+// Signs -> Khmer has above signs and post signs. Only one above sign and/or one post sign are\r
+// Allowed in a syllable.\r
+//\r
+//\r
+// order is important here! This order must be the same that is found in each horizontal\r
+// line in the statetable for Khmer (see khmerStateTable) .\r
+*/\r
+enum KhmerCharClassValues {\r
+ CC_RESERVED = 0,\r
+ CC_CONSONANT = 1, /* Consonant of type 1 or independent vowel */\r
+ CC_CONSONANT2 = 2, /* Consonant of type 2 */\r
+ CC_CONSONANT3 = 3, /* Consonant of type 3 */\r
+ CC_ZERO_WIDTH_NJ_MARK = 4, /* Zero Width non joiner character (0x200C) */\r
+ CC_CONSONANT_SHIFTER = 5,\r
+ CC_ROBAT = 6, /* Khmer special diacritic accent -treated differently in state table */\r
+ CC_COENG = 7, /* Subscript consonant combining character */\r
+ CC_DEPENDENT_VOWEL = 8,\r
+ CC_SIGN_ABOVE = 9,\r
+ CC_SIGN_AFTER = 10,\r
+ CC_ZERO_WIDTH_J_MARK = 11, /* Zero width joiner character */\r
+ CC_COUNT = 12 /* This is the number of character classes */\r
+};\r
+\r
+\r
+enum KhmerCharClassFlags {\r
+ CF_CLASS_MASK = 0x0000FFFF,\r
+\r
+ CF_CONSONANT = 0x01000000, /* flag to speed up comparing */\r
+ CF_SPLIT_VOWEL = 0x02000000, /* flag for a split vowel -> the first part is added in front of the syllable */\r
+ CF_DOTTED_CIRCLE = 0x04000000, /* add a dotted circle if a character with this flag is the first in a syllable */\r
+ CF_COENG = 0x08000000, /* flag to speed up comparing */\r
+ CF_SHIFTER = 0x10000000, /* flag to speed up comparing */\r
+ CF_ABOVE_VOWEL = 0x20000000, /* flag to speed up comparing */\r
+\r
+ /* position flags */\r
+ CF_POS_BEFORE = 0x00080000,\r
+ CF_POS_BELOW = 0x00040000,\r
+ CF_POS_ABOVE = 0x00020000,\r
+ CF_POS_AFTER = 0x00010000,\r
+ CF_POS_MASK = 0x000f0000\r
+};\r
+\r
+\r
+/* Characters that get referred to by name */\r
+enum KhmerChar {\r
+ C_SIGN_ZWNJ = 0x200C,\r
+ C_SIGN_ZWJ = 0x200D,\r
+ C_RO = 0x179A,\r
+ C_VOWEL_AA = 0x17B6,\r
+ C_SIGN_NIKAHIT = 0x17C6,\r
+ C_VOWEL_E = 0x17C1,\r
+ C_COENG = 0x17D2\r
+};\r
+\r
+\r
+/*\r
+// simple classes, they are used in the statetable (in this file) to control the length of a syllable\r
+// they are also used to know where a character should be placed (location in reference to the base character)\r
+// and also to know if a character, when independently displayed, should be displayed with a dotted-circle to\r
+// indicate error in syllable construction\r
+*/\r
+enum {\r
+ _xx = CC_RESERVED,\r
+ _sa = CC_SIGN_ABOVE | CF_DOTTED_CIRCLE | CF_POS_ABOVE,\r
+ _sp = CC_SIGN_AFTER | CF_DOTTED_CIRCLE| CF_POS_AFTER,\r
+ _c1 = CC_CONSONANT | CF_CONSONANT,\r
+ _c2 = CC_CONSONANT2 | CF_CONSONANT,\r
+ _c3 = CC_CONSONANT3 | CF_CONSONANT,\r
+ _rb = CC_ROBAT | CF_POS_ABOVE | CF_DOTTED_CIRCLE,\r
+ _cs = CC_CONSONANT_SHIFTER | CF_DOTTED_CIRCLE | CF_SHIFTER,\r
+ _dl = CC_DEPENDENT_VOWEL | CF_POS_BEFORE | CF_DOTTED_CIRCLE,\r
+ _db = CC_DEPENDENT_VOWEL | CF_POS_BELOW | CF_DOTTED_CIRCLE,\r
+ _da = CC_DEPENDENT_VOWEL | CF_POS_ABOVE | CF_DOTTED_CIRCLE | CF_ABOVE_VOWEL,\r
+ _dr = CC_DEPENDENT_VOWEL | CF_POS_AFTER | CF_DOTTED_CIRCLE,\r
+ _co = CC_COENG | CF_COENG | CF_DOTTED_CIRCLE,\r
+\r
+ /* split vowel */\r
+ _va = _da | CF_SPLIT_VOWEL,\r
+ _vr = _dr | CF_SPLIT_VOWEL\r
+};\r
+\r
+\r
+/*\r
+// Character class: a character class value\r
+// ORed with character class flags.\r
+*/\r
+typedef unsigned long KhmerCharClass;\r
+\r
+\r
+/*\r
+// Character class tables\r
+// _xx character does not combine into syllable, such as numbers, puntuation marks, non-Khmer signs...\r
+// _sa Sign placed above the base\r
+// _sp Sign placed after the base\r
+// _c1 Consonant of type 1 or independent vowel (independent vowels behave as type 1 consonants)\r
+// _c2 Consonant of type 2 (only RO)\r
+// _c3 Consonant of type 3\r
+// _rb Khmer sign robat u17CC. combining mark for subscript consonants\r
+// _cd Consonant-shifter\r
+// _dl Dependent vowel placed before the base (left of the base)\r
+// _db Dependent vowel placed below the base\r
+// _da Dependent vowel placed above the base\r
+// _dr Dependent vowel placed behind the base (right of the base)\r
+// _co Khmer combining mark COENG u17D2, combines with the consonant or independent vowel following\r
+// it to create a subscript consonant or independent vowel\r
+// _va Khmer split vowel in which the first part is before the base and the second one above the base\r
+// _vr Khmer split vowel in which the first part is before the base and the second one behind (right of) the base\r
+*/\r
+static const KhmerCharClass khmerCharClasses[] = {\r
+ _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, /* 1780 - 178F */\r
+ _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c2, _c1, _c1, _c1, _c3, _c3, /* 1790 - 179F */\r
+ _c1, _c3, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, /* 17A0 - 17AF */\r
+ _c1, _c1, _c1, _c1, _dr, _dr, _dr, _da, _da, _da, _da, _db, _db, _db, _va, _vr, /* 17B0 - 17BF */\r
+ _vr, _dl, _dl, _dl, _vr, _vr, _sa, _sp, _sp, _cs, _cs, _sa, _rb, _sa, _sa, _sa, /* 17C0 - 17CF */\r
+ _sa, _sa, _co, _sa, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _sa, _xx, _xx /* 17D0 - 17DF */\r
+};\r
+\r
+/* this enum must reflect the range of khmerCharClasses */\r
+enum KhmerCharClassesRange {\r
+ KhmerFirstChar = 0x1780,\r
+ KhmerLastChar = 0x17df\r
+};\r
+\r
+/*\r
+// Below we define how a character in the input string is either in the khmerCharClasses table\r
+// (in which case we get its type back), a ZWJ or ZWNJ (two characters that may appear\r
+// within the syllable, but are not in the table) we also get their type back, or an unknown object\r
+// in which case we get _xx (CC_RESERVED) back\r
+*/\r
+static KhmerCharClass getKhmerCharClass(HB_UChar16 uc)\r
+{\r
+ if (uc == C_SIGN_ZWJ) {\r
+ return CC_ZERO_WIDTH_J_MARK;\r
+ }\r
+\r
+ if (uc == C_SIGN_ZWNJ) {\r
+ return CC_ZERO_WIDTH_NJ_MARK;\r
+ }\r
+\r
+ if (uc < KhmerFirstChar || uc > KhmerLastChar) {\r
+ return CC_RESERVED;\r
+ }\r
+\r
+ return khmerCharClasses[uc - KhmerFirstChar];\r
+}\r
+\r
+\r
+/*\r
+// The stateTable is used to calculate the end (the length) of a well\r
+// formed Khmer Syllable.\r
+//\r
+// Each horizontal line is ordered exactly the same way as the values in KhmerClassTable\r
+// CharClassValues. This coincidence of values allows the follow up of the table.\r
+//\r
+// Each line corresponds to a state, which does not necessarily need to be a type\r
+// of component... for example, state 2 is a base, with is always a first character\r
+// in the syllable, but the state could be produced a consonant of any type when\r
+// it is the first character that is analysed (in ground state).\r
+//\r
+// Differentiating 3 types of consonants is necessary in order to\r
+// forbid the use of certain combinations, such as having a second\r
+// coeng after a coeng RO,\r
+// The inexistent possibility of having a type 3 after another type 3 is permitted,\r
+// eliminating it would very much complicate the table, and it does not create typing\r
+// problems, as the case above.\r
+//\r
+// The table is quite complex, in order to limit the number of coeng consonants\r
+// to 2 (by means of the table).\r
+//\r
+// There a peculiarity, as far as Unicode is concerned:\r
+// - The consonant-shifter is considered in two possible different\r
+// locations, the one considered in Unicode 3.0 and the one considered in\r
+// Unicode 4.0. (there is a backwards compatibility problem in this standard).\r
+//\r
+//\r
+// xx independent character, such as a number, punctuation sign or non-khmer char\r
+//\r
+// c1 Khmer consonant of type 1 or an independent vowel\r
+// that is, a letter in which the subscript for is only under the\r
+// base, not taking any space to the right or to the left\r
+//\r
+// c2 Khmer consonant of type 2, the coeng form takes space under\r
+// and to the left of the base (only RO is of this type)\r
+//\r
+// c3 Khmer consonant of type 3. Its subscript form takes space under\r
+// and to the right of the base.\r
+//\r
+// cs Khmer consonant shifter\r
+//\r
+// rb Khmer robat\r
+//\r
+// co coeng character (u17D2)\r
+//\r
+// dv dependent vowel (including split vowels, they are treated in the same way).\r
+// even if dv is not defined above, the component that is really tested for is\r
+// KhmerClassTable::CC_DEPENDENT_VOWEL, which is common to all dependent vowels\r
+//\r
+// zwj Zero Width joiner\r
+//\r
+// zwnj Zero width non joiner\r
+//\r
+// sa above sign\r
+//\r
+// sp post sign\r
+//\r
+// there are lines with equal content but for an easier understanding\r
+// (and maybe change in the future) we did not join them\r
+*/\r
+static const signed char khmerStateTable[][CC_COUNT] =\r
+{\r
+ /* xx c1 c2 c3 zwnj cs rb co dv sa sp zwj */\r
+ { 1, 2, 2, 2, 1, 1, 1, 6, 1, 1, 1, 2}, /* 0 - ground state */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 1 - exit state (or sign to the right of the syllable) */\r
+ {-1, -1, -1, -1, 3, 4, 5, 6, 16, 17, 1, -1}, /* 2 - Base consonant */\r
+ {-1, -1, -1, -1, -1, 4, -1, -1, 16, -1, -1, -1}, /* 3 - First ZWNJ before a register shifter It can only be followed by a shifter or a vowel */\r
+ {-1, -1, -1, -1, 15, -1, -1, 6, 16, 17, 1, 14}, /* 4 - First register shifter */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, 20, -1, 1, -1}, /* 5 - Robat */\r
+ {-1, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1}, /* 6 - First Coeng */\r
+ {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, /* 7 - First consonant of type 1 after coeng */\r
+ {-1, -1, -1, -1, 12, 13, -1, -1, 16, 17, 1, 14}, /* 8 - First consonant of type 2 after coeng */\r
+ {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, /* 9 - First consonant or type 3 after ceong */\r
+ {-1, 11, 11, 11, -1, -1, -1, -1, -1, -1, -1, -1}, /* 10 - Second Coeng (no register shifter before) */\r
+ {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, /* 11 - Second coeng consonant (or ind. vowel) no register shifter before */\r
+ {-1, -1, -1, -1, -1, 13, -1, -1, 16, -1, -1, -1}, /* 12 - Second ZWNJ before a register shifter */\r
+ {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, /* 13 - Second register shifter */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, /* 14 - ZWJ before vowel */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, /* 15 - ZWNJ before vowel */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 1, 18}, /* 16 - dependent vowel */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 18}, /* 17 - sign above */\r
+ {-1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1}, /* 18 - ZWJ after vowel */\r
+ {-1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 19 - Third coeng */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, /* 20 - dependent vowel after a Robat */\r
+};\r
+\r
+\r
+/* #define KHMER_DEBUG */\r
+#ifdef KHMER_DEBUG\r
+#define KHDEBUG qDebug\r
+#else\r
+#define KHDEBUG if(0) printf\r
+#endif\r
+\r
+/*\r
+// Given an input string of characters and a location in which to start looking\r
+// calculate, using the state table, which one is the last character of the syllable\r
+// that starts in the starting position.\r
+*/\r
+/* SAMSUNG - Kaja Changes -Start */\r
+//static int khmer_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+int khmer_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+/* SAMSUNG - Kaja Changes -End */\r
+{\r
+ const HB_UChar16 *uc = s + start;\r
+ int state = 0;\r
+ int pos = start;\r
+ *invalid = FALSE;\r
+\r
+ while (pos < end) {\r
+ KhmerCharClass charClass = getKhmerCharClass(*uc);\r
+ if (pos == start) {\r
+ *invalid = (charClass > 0) && ! (charClass & CF_CONSONANT);\r
+ }\r
+ state = khmerStateTable[state][charClass & CF_CLASS_MASK];\r
+\r
+ KHDEBUG("state[%d]=%d class=%8lx (uc=%4x)", pos - start, state,\r
+ charClass, *uc );\r
+\r
+ if (state < 0) {\r
+ break;\r
+ }\r
+ ++uc;\r
+ ++pos;\r
+ }\r
+ return pos;\r
+}\r
+\r
+#ifndef NO_OPENTYPE\r
+static const HB_OpenTypeFeature khmer_features[] = {\r
+ { HB_MAKE_TAG( 'p', 'r', 'e', 'f' ), PreFormProperty },\r
+ { HB_MAKE_TAG( 'b', 'l', 'w', 'f' ), BelowFormProperty },\r
+ { HB_MAKE_TAG( 'a', 'b', 'v', 'f' ), AboveFormProperty },\r
+ { HB_MAKE_TAG( 'p', 's', 't', 'f' ), PostFormProperty },\r
+ { HB_MAKE_TAG( 'p', 'r', 'e', 's' ), PreSubstProperty },\r
+ { HB_MAKE_TAG( 'b', 'l', 'w', 's' ), BelowSubstProperty },\r
+ { HB_MAKE_TAG( 'a', 'b', 'v', 's' ), AboveSubstProperty },\r
+ { HB_MAKE_TAG( 'p', 's', 't', 's' ), PostSubstProperty },\r
+ { HB_MAKE_TAG( 'c', 'l', 'i', 'g' ), CligProperty },\r
+ { 0, 0 }\r
+};\r
+#endif\r
+\r
+\r
+static HB_Bool khmer_shape_syllable(HB_Bool openType, HB_ShaperItem *item)\r
+{\r
+/* KHDEBUG("syllable from %d len %d, str='%s'", item->from, item->length,\r
+ item->string->mid(item->from, item->length).toUtf8().data()); */\r
+\r
+ int len = 0;\r
+ int syllableEnd = item->item.pos + item->item.length;\r
+ unsigned short reordered[16];\r
+ unsigned char properties[16];\r
+ enum {\r
+ AboveForm = 0x01,\r
+ PreForm = 0x02,\r
+ PostForm = 0x04,\r
+ BelowForm = 0x08\r
+ };\r
+#ifndef NO_OPENTYPE\r
+ const int availableGlyphs = item->num_glyphs;\r
+#endif\r
+ int coengRo;\r
+ int i;\r
+\r
+ /* according to the specs this is the max length one can get\r
+ ### the real value should be smaller */\r
+ assert(item->item.length < 13);\r
+\r
+ memset(properties, 0, 16*sizeof(unsigned char));\r
+\r
+#ifdef KHMER_DEBUG\r
+ qDebug("original:");\r
+ for (int i = from; i < syllableEnd; i++) {\r
+ qDebug(" %d: %4x", i, string[i]);\r
+ }\r
+#endif\r
+\r
+ /*\r
+ // write a pre vowel or the pre part of a split vowel first\r
+ // and look out for coeng + ro. RO is the only vowel of type 2, and\r
+ // therefore the only one that requires saving space before the base.\r
+ */\r
+ coengRo = -1; /* There is no Coeng Ro, if found this value will change */\r
+ for (i = item->item.pos; i < syllableEnd; i += 1) {\r
+ KhmerCharClass charClass = getKhmerCharClass(item->string[i]);\r
+\r
+ /* if a split vowel, write the pre part. In Khmer the pre part\r
+ is the same for all split vowels, same glyph as pre vowel C_VOWEL_E */\r
+ if (charClass & CF_SPLIT_VOWEL) {\r
+ reordered[len] = C_VOWEL_E;\r
+ properties[len] = PreForm;\r
+ ++len;\r
+ break; /* there can be only one vowel */\r
+ }\r
+ /* if a vowel with pos before write it out */\r
+ if (charClass & CF_POS_BEFORE) {\r
+ reordered[len] = item->string[i];\r
+ properties[len] = PreForm;\r
+ ++len;\r
+ break; /* there can be only one vowel */\r
+ }\r
+ /* look for coeng + ro and remember position\r
+ works because coeng + ro is always in front of a vowel (if there is a vowel)\r
+ and because CC_CONSONANT2 is enough to identify it, as it is the only consonant\r
+ with this flag */\r
+ if ( (charClass & CF_COENG) && (i + 1 < syllableEnd) &&\r
+ ( (getKhmerCharClass(item->string[i+1]) & CF_CLASS_MASK) == CC_CONSONANT2) ) {\r
+ coengRo = i;\r
+ }\r
+ }\r
+\r
+ /* write coeng + ro if found */\r
+ if (coengRo > -1) {\r
+ reordered[len] = C_COENG;\r
+ properties[len] = PreForm;\r
+ ++len;\r
+ reordered[len] = C_RO;\r
+ properties[len] = PreForm;\r
+ ++len;\r
+ }\r
+\r
+ /*\r
+ shall we add a dotted circle?\r
+ If in the position in which the base should be (first char in the string) there is\r
+ a character that has the Dotted circle flag (a character that cannot be a base)\r
+ then write a dotted circle */\r
+ if (getKhmerCharClass(item->string[item->item.pos]) & CF_DOTTED_CIRCLE) {\r
+ reordered[len] = C_DOTTED_CIRCLE;\r
+ ++len;\r
+ }\r
+\r
+ /* copy what is left to the output, skipping before vowels and\r
+ coeng Ro if they are present */\r
+ for (i = item->item.pos; i < syllableEnd; i += 1) {\r
+ HB_UChar16 uc = item->string[i];\r
+ KhmerCharClass charClass = getKhmerCharClass(uc);\r
+\r
+ /* skip a before vowel, it was already processed */\r
+ if (charClass & CF_POS_BEFORE) {\r
+ continue;\r
+ }\r
+\r
+ /* skip coeng + ro, it was already processed */\r
+ if (i == coengRo) {\r
+ i += 1;\r
+ continue;\r
+ }\r
+\r
+ switch (charClass & CF_POS_MASK)\r
+ {\r
+ case CF_POS_ABOVE :\r
+ reordered[len] = uc;\r
+ properties[len] = AboveForm;\r
+ ++len;\r
+ break;\r
+\r
+ case CF_POS_AFTER :\r
+ reordered[len] = uc;\r
+ properties[len] = PostForm;\r
+ ++len;\r
+ break;\r
+\r
+ case CF_POS_BELOW :\r
+ reordered[len] = uc;\r
+ properties[len] = BelowForm;\r
+ ++len;\r
+ break;\r
+\r
+ default:\r
+ /* assign the correct flags to a coeng consonant\r
+ Consonants of type 3 are taged as Post forms and those type 1 as below forms */\r
+ if ( (charClass & CF_COENG) && i + 1 < syllableEnd ) {\r
+ unsigned char property = (getKhmerCharClass(item->string[i+1]) & CF_CLASS_MASK) == CC_CONSONANT3 ?\r
+ PostForm : BelowForm;\r
+ reordered[len] = uc;\r
+ properties[len] = property;\r
+ ++len;\r
+ i += 1;\r
+ reordered[len] = item->string[i];\r
+ properties[len] = property;\r
+ ++len;\r
+ break;\r
+ }\r
+\r
+ /* if a shifter is followed by an above vowel change the shifter to below form,\r
+ an above vowel can have two possible positions i + 1 or i + 3\r
+ (position i+1 corresponds to unicode 3, position i+3 to Unicode 4)\r
+ and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two\r
+ different positions, right after the shifter or after a vowel (Unicode 4) */\r
+ if ( (charClass & CF_SHIFTER) && (i + 1 < syllableEnd) ) {\r
+ if (getKhmerCharClass(item->string[i+1]) & CF_ABOVE_VOWEL ) {\r
+ reordered[len] = uc;\r
+ properties[len] = BelowForm;\r
+ ++len;\r
+ break;\r
+ }\r
+ if (i + 2 < syllableEnd &&\r
+ (item->string[i+1] == C_VOWEL_AA) &&\r
+ (item->string[i+2] == C_SIGN_NIKAHIT) )\r
+ {\r
+ reordered[len] = uc;\r
+ properties[len] = BelowForm;\r
+ ++len;\r
+ break;\r
+ }\r
+ if (i + 3 < syllableEnd && (getKhmerCharClass(item->string[i+3]) & CF_ABOVE_VOWEL) ) {\r
+ reordered[len] = uc;\r
+ properties[len] = BelowForm;\r
+ ++len;\r
+ break;\r
+ }\r
+ if (i + 4 < syllableEnd &&\r
+ (item->string[i+3] == C_VOWEL_AA) &&\r
+ (item->string[i+4] == C_SIGN_NIKAHIT) )\r
+ {\r
+ reordered[len] = uc;\r
+ properties[len] = BelowForm;\r
+ ++len;\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* default - any other characters */\r
+ reordered[len] = uc;\r
+ ++len;\r
+ break;\r
+ } /* switch */\r
+ } /* for */\r
+\r
+ if (!item->font->klass->convertStringToGlyphIndices(item->font,\r
+ reordered, len,\r
+ item->glyphs, &item->num_glyphs,\r
+ item->item.bidiLevel % 2))\r
+ return FALSE;\r
+\r
+\r
+ KHDEBUG("after shaping: len=%d", len);\r
+ for (i = 0; i < len; i++) {\r
+ item->attributes[i].mark = FALSE;\r
+ item->attributes[i].clusterStart = FALSE;\r
+ item->attributes[i].justification = 0;\r
+ item->attributes[i].zeroWidth = FALSE;\r
+ KHDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]);\r
+ }\r
+\r
+ /* now we have the syllable in the right order, and can start running it through open type. */\r
+\r
+#ifndef NO_OPENTYPE\r
+ if (openType) {\r
+ hb_uint32 where[16];\r
+ for (i = 0; i < len; ++i) {\r
+ where[i] = ~(PreSubstProperty\r
+ | BelowSubstProperty\r
+ | AboveSubstProperty\r
+ | PostSubstProperty\r
+ | CligProperty\r
+ | PositioningProperties);\r
+ if (properties[i] == PreForm)\r
+ where[i] &= ~PreFormProperty;\r
+ else if (properties[i] == BelowForm)\r
+ where[i] &= ~BelowFormProperty;\r
+ else if (properties[i] == AboveForm)\r
+ where[i] &= ~AboveFormProperty;\r
+ else if (properties[i] == PostForm)\r
+ where[i] &= ~PostFormProperty;\r
+ }\r
+\r
+ HB_OpenTypeShape(item, where);\r
+ if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))\r
+ return FALSE;\r
+ } else\r
+#endif\r
+ {\r
+ KHDEBUG("Not using openType");\r
+ HB_HeuristicPosition(item);\r
+ }\r
+\r
+ item->attributes[0].clusterStart = TRUE;\r
+ return TRUE;\r
+}\r
+\r
+HB_Bool HB_KhmerShape(HB_ShaperItem *item)\r
+{\r
+ HB_Bool openType = FALSE;\r
+ unsigned short *logClusters = item->log_clusters;\r
+ int i;\r
+\r
+ HB_ShaperItem syllable = *item;\r
+ int first_glyph = 0;\r
+\r
+ int sstart = item->item.pos;\r
+ int end = sstart + item->item.length;\r
+\r
+ assert(item->item.script == HB_Script_Khmer);\r
+\r
+#ifndef NO_OPENTYPE\r
+ openType = HB_SelectScript(item, khmer_features);\r
+#endif\r
+\r
+ KHDEBUG("khmer_shape: from %d length %d", item->item.pos, item->item.length);\r
+ while (sstart < end) {\r
+ HB_Bool invalid;\r
+ int send = khmer_nextSyllableBoundary(item->string, sstart, end, &invalid);\r
+ KHDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,\r
+ invalid ? "TRUE" : "FALSE");\r
+ syllable.item.pos = sstart;\r
+ syllable.item.length = send-sstart;\r
+ syllable.glyphs = item->glyphs + first_glyph;\r
+ syllable.attributes = item->attributes + first_glyph;\r
+ syllable.offsets = item->offsets + first_glyph;\r
+ syllable.advances = item->advances + first_glyph;\r
+ syllable.num_glyphs = item->num_glyphs - first_glyph;\r
+ if (!khmer_shape_syllable(openType, &syllable)) {\r
+ KHDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);\r
+ item->num_glyphs += syllable.num_glyphs;\r
+ return FALSE;\r
+ }\r
+ /* fix logcluster array */\r
+ KHDEBUG("syllable:");\r
+ for (i = first_glyph; i < first_glyph + (int)syllable.num_glyphs; ++i)\r
+ KHDEBUG(" %d -> glyph %x", i, item->glyphs[i]);\r
+ KHDEBUG(" logclusters:");\r
+ for (i = sstart; i < send; ++i) {\r
+ KHDEBUG(" %d -> glyph %d", i, first_glyph);\r
+ logClusters[i-item->item.pos] = first_glyph;\r
+ }\r
+ sstart = send;\r
+ first_glyph += syllable.num_glyphs;\r
+ }\r
+ item->num_glyphs = first_glyph;\r
+ return TRUE;\r
+}\r
+\r
+void HB_KhmerAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)\r
+{\r
+ int end = from + len;\r
+ const HB_UChar16 *uc = text + from;\r
+ hb_uint32 i = 0;\r
+ HB_UNUSED(script);\r
+ attributes += from;\r
+ while ( i < len ) {\r
+ HB_Bool invalid;\r
+ hb_uint32 boundary = khmer_nextSyllableBoundary( text, from+i, end, &invalid ) - from;\r
+\r
+ attributes[i].charStop = TRUE;\r
+\r
+ if ( boundary > len-1 ) boundary = len;\r
+ i++;\r
+ while ( i < boundary ) {\r
+ attributes[i].charStop = FALSE;\r
+ ++uc;\r
+ ++i;\r
+ }\r
+ assert( i == boundary );\r
+ }\r
+}\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+#include <assert.h>\r
+#include <stdio.h>\r
+\r
+enum MymrCharClassValues\r
+{\r
+ Mymr_CC_RESERVED = 0,\r
+ Mymr_CC_CONSONANT = 1, /* Consonant of type 1, that has subscript form */\r
+ Mymr_CC_CONSONANT2 = 2, /* Consonant of type 2, that has no subscript form */\r
+ Mymr_CC_NGA = 3, /* Consonant NGA */\r
+ Mymr_CC_YA = 4, /* Consonant YA */\r
+ Mymr_CC_RA = 5, /* Consonant RA */\r
+ Mymr_CC_WA = 6, /* Consonant WA */\r
+ Mymr_CC_HA = 7, /* Consonant HA */\r
+ Mymr_CC_IND_VOWEL = 8, /* Independent vowel */\r
+ Mymr_CC_ZERO_WIDTH_NJ_MARK = 9, /* Zero Width non joiner character (0x200C) */\r
+ Mymr_CC_VIRAMA = 10, /* Subscript consonant combining character */\r
+ Mymr_CC_PRE_VOWEL = 11, /* Dependent vowel, prebase (Vowel e) */\r
+ Mymr_CC_BELOW_VOWEL = 12, /* Dependent vowel, prebase (Vowel u, uu) */\r
+ Mymr_CC_ABOVE_VOWEL = 13, /* Dependent vowel, prebase (Vowel i, ii, ai) */\r
+ Mymr_CC_POST_VOWEL = 14, /* Dependent vowel, prebase (Vowel aa) */\r
+ Mymr_CC_SIGN_ABOVE = 15,\r
+ Mymr_CC_SIGN_BELOW = 16,\r
+ Mymr_CC_SIGN_AFTER = 17,\r
+ Mymr_CC_ZERO_WIDTH_J_MARK = 18, /* Zero width joiner character */\r
+ Mymr_CC_COUNT = 19 /* This is the number of character classes */\r
+};\r
+\r
+enum MymrCharClassFlags\r
+{\r
+ Mymr_CF_CLASS_MASK = 0x0000FFFF,\r
+\r
+ Mymr_CF_CONSONANT = 0x01000000, /* flag to speed up comparing */\r
+ Mymr_CF_MEDIAL = 0x02000000, /* flag to speed up comparing */\r
+ Mymr_CF_IND_VOWEL = 0x04000000, /* flag to speed up comparing */\r
+ Mymr_CF_DEP_VOWEL = 0x08000000, /* flag to speed up comparing */\r
+ Mymr_CF_DOTTED_CIRCLE = 0x10000000, /* add a dotted circle if a character with this flag is the first in a syllable */\r
+ Mymr_CF_VIRAMA = 0x20000000, /* flag to speed up comparing */\r
+\r
+ /* position flags */\r
+ Mymr_CF_POS_BEFORE = 0x00080000,\r
+ Mymr_CF_POS_BELOW = 0x00040000,\r
+ Mymr_CF_POS_ABOVE = 0x00020000,\r
+ Mymr_CF_POS_AFTER = 0x00010000,\r
+ Mymr_CF_POS_MASK = 0x000f0000,\r
+\r
+ Mymr_CF_AFTER_KINZI = 0x00100000\r
+};\r
+\r
+/* Characters that get refrered to by name */\r
+enum MymrChar\r
+{\r
+ Mymr_C_SIGN_ZWNJ = 0x200C,\r
+ Mymr_C_SIGN_ZWJ = 0x200D,\r
+ Mymr_C_DOTTED_CIRCLE = 0x25CC,\r
+ Mymr_C_RA = 0x101B,\r
+ Mymr_C_YA = 0x101A,\r
+ Mymr_C_NGA = 0x1004,\r
+ Mymr_C_VOWEL_E = 0x1031,\r
+ Mymr_C_VIRAMA = 0x1039\r
+};\r
+\r
+enum\r
+{\r
+ Mymr_xx = Mymr_CC_RESERVED,\r
+ Mymr_c1 = Mymr_CC_CONSONANT | Mymr_CF_CONSONANT | Mymr_CF_POS_BELOW,\r
+ Mymr_c2 = Mymr_CC_CONSONANT2 | Mymr_CF_CONSONANT,\r
+ Mymr_ng = Mymr_CC_NGA | Mymr_CF_CONSONANT | Mymr_CF_POS_ABOVE,\r
+ Mymr_ya = Mymr_CC_YA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_AFTER | Mymr_CF_AFTER_KINZI,\r
+ Mymr_ra = Mymr_CC_RA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BEFORE,\r
+ Mymr_wa = Mymr_CC_WA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW,\r
+ Mymr_ha = Mymr_CC_HA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW,\r
+ Mymr_id = Mymr_CC_IND_VOWEL | Mymr_CF_IND_VOWEL,\r
+ Mymr_vi = Mymr_CC_VIRAMA | Mymr_CF_VIRAMA | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE,\r
+ Mymr_dl = Mymr_CC_PRE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BEFORE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,\r
+ Mymr_db = Mymr_CC_BELOW_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,\r
+ Mymr_da = Mymr_CC_ABOVE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,\r
+ Mymr_dr = Mymr_CC_POST_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI,\r
+ Mymr_sa = Mymr_CC_SIGN_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_ABOVE | Mymr_CF_AFTER_KINZI,\r
+ Mymr_sb = Mymr_CC_SIGN_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_BELOW | Mymr_CF_AFTER_KINZI,\r
+ Mymr_sp = Mymr_CC_SIGN_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI\r
+};\r
+\r
+\r
+typedef int MymrCharClass;\r
+\r
+\r
+static const MymrCharClass mymrCharClasses[] =\r
+{\r
+ Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_ng, Mymr_c1, Mymr_c1, Mymr_c1,\r
+ Mymr_c1, Mymr_c1, Mymr_c2, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, /* 1000 - 100F */\r
+ Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1,\r
+ Mymr_c1, Mymr_c1, Mymr_ya, Mymr_ra, Mymr_c1, Mymr_wa, Mymr_c1, Mymr_ha, /* 1010 - 101F */\r
+ Mymr_c2, Mymr_c2, Mymr_xx, Mymr_id, Mymr_id, Mymr_id, Mymr_id, Mymr_id,\r
+ Mymr_xx, Mymr_id, Mymr_id, Mymr_xx, Mymr_dr, Mymr_da, Mymr_da, Mymr_db, /* 1020 - 102F */\r
+ Mymr_db, Mymr_dl, Mymr_da, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_sa, Mymr_sb,\r
+ Mymr_sp, Mymr_vi, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1030 - 103F */\r
+ Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx,\r
+ Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1040 - 104F */\r
+ Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx,\r
+ Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1050 - 105F */\r
+};\r
+\r
+static MymrCharClass\r
+getMyanmarCharClass (HB_UChar16 ch)\r
+{\r
+ if (ch == Mymr_C_SIGN_ZWJ)\r
+ return Mymr_CC_ZERO_WIDTH_J_MARK;\r
+\r
+ if (ch == Mymr_C_SIGN_ZWNJ)\r
+ return Mymr_CC_ZERO_WIDTH_NJ_MARK;\r
+\r
+ if (ch < 0x1000 || ch > 0x105f)\r
+ return Mymr_CC_RESERVED;\r
+\r
+ return mymrCharClasses[ch - 0x1000];\r
+}\r
+\r
+static const signed char mymrStateTable[][Mymr_CC_COUNT] =\r
+{\r
+/* xx c1, c2 ng ya ra wa ha id zwnj vi dl db da dr sa sb sp zwj */\r
+ { 1, 4, 4, 2, 4, 4, 4, 4, 24, 1, 27, 17, 18, 19, 20, 21, 1, 1, 4}, /* 0 - ground state */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 1 - exit state (or sp to the right of the syllable) */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 17, 18, 19, 20, 21, -1, -1, 4}, /* 2 - NGA */\r
+ {-1, 4, 4, 4, 4, 4, 4, 4, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 3 - Virama after NGA */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 17, 18, 19, 20, 21, 1, 1, -1}, /* 4 - Base consonant */\r
+ {-2, 6, -2, -2, 7, 8, 9, 10, -2, 23, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 5 - First virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 17, 18, 19, 20, 21, -1, -1, -1}, /* 6 - c1 after virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 7 - ya after virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 8 - ra after virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 9 - wa after virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 10 - ha after virama */\r
+ {-1, -1, -1, -1, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 11 - Virama after NGA+zwj */\r
+ {-2, -2, -2, -2, -2, -2, 13, 14, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 12 - Second virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 17, 18, 19, 20, 21, -1, -1, -1}, /* 13 - wa after virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 14 - ha after virama */\r
+ {-2, -2, -2, -2, -2, -2, -2, 16, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 15 - Third virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 16 - ha after virama */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, 1, 1, -1}, /* 17 - dl, Dependent vowel e */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, 21, 1, 1, -1}, /* 18 - db, Dependent vowel u,uu */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1}, /* 19 - da, Dependent vowel i,ii,ai */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, 1, 1, -1}, /* 20 - dr, Dependent vowel aa */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, /* 21 - sa, Sign anusvara */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 22 - atha */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, /* 23 - zwnj for atha */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, /* 24 - Independent vowel */\r
+ {-2, -2, -2, -2, 26, 26, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 25 - Virama after subscript consonant */\r
+ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, 1, -1}, /* 26 - ra/ya after subscript consonant + virama */\r
+ {-1, 6, -1, -1, 7, 8, 9, 10, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 - Virama after ground state */\r
+/* exit state -2 is for invalid order of medials and combination of invalids\r
+ with virama where virama should treat as start of next syllable\r
+ */\r
+};\r
+\r
+\r
+\r
+/*#define MYANMAR_DEBUG */\r
+#ifdef MYANMAR_DEBUG\r
+#define MMDEBUG qDebug\r
+#else\r
+#define MMDEBUG if(0) printf\r
+#endif\r
+\r
+/*\r
+// Given an input string of characters and a location in which to start looking\r
+// calculate, using the state table, which one is the last character of the syllable\r
+// that starts in the starting position.\r
+*/\r
+/* SAMSUNG - Kaja Changes -Start */\r
+//static int myanmar_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+int myanmar_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+/* SAMSUNG - Kaja Changes -End */\r
+{\r
+ const HB_UChar16 *uc = s + start;\r
+ int state = 0;\r
+ int pos = start;\r
+ *invalid = FALSE;\r
+\r
+ while (pos < end) {\r
+ MymrCharClass charClass = getMyanmarCharClass(*uc);\r
+ state = mymrStateTable[state][charClass & Mymr_CF_CLASS_MASK];\r
+ if (pos == start)\r
+ *invalid = (HB_Bool)(charClass & Mymr_CF_DOTTED_CIRCLE);\r
+\r
+ MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos - start, state, charClass, *uc);\r
+\r
+ if (state < 0) {\r
+ if (state < -1)\r
+ --pos;\r
+ break;\r
+ }\r
+ ++uc;\r
+ ++pos;\r
+ }\r
+ return pos;\r
+}\r
+\r
+#ifndef NO_OPENTYPE\r
+/* ###### might have to change order of above and below forms and substitutions,\r
+ but according to Unicode below comes before above */\r
+static const HB_OpenTypeFeature myanmar_features[] = {\r
+ { HB_MAKE_TAG('p', 'r', 'e', 'f'), PreFormProperty },\r
+ { HB_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty },\r
+ { HB_MAKE_TAG('a', 'b', 'v', 'f'), AboveFormProperty },\r
+ { HB_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty },\r
+ { HB_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty },\r
+ { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },\r
+ { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },\r
+ { HB_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty },\r
+ { HB_MAKE_TAG('r', 'l', 'i', 'g'), CligProperty }, /* Myanmar1 uses this instead of the other features */\r
+ { 0, 0 }\r
+};\r
+#endif\r
+\r
+\r
+/*\r
+// Visual order before shaping should be:\r
+//\r
+// [Vowel Mark E]\r
+// [Virama + Medial Ra]\r
+// [Base]\r
+// [Virama + Consonant]\r
+// [Nga + Virama] (Kinzi) ### should probably come before post forms (medial ya)\r
+// [Vowels]\r
+// [Marks]\r
+//\r
+// This means that we can keep the logical order apart from having to\r
+// move the pre vowel, medial ra and kinzi\r
+*/\r
+\r
+static HB_Bool myanmar_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_Bool invalid)\r
+{\r
+ /*\r
+// MMDEBUG("\nsyllable from %d len %d, str='%s'", item->item.pos, item->item.length,\r
+// item->string->mid(item->from, item->length).toUtf8().data());\r
+ */\r
+\r
+#ifndef NO_OPENTYPE\r
+ const int availableGlyphs = item->num_glyphs;\r
+#endif\r
+ const HB_UChar16 *uc = item->string + item->item.pos;\r
+ int vowel_e = -1;\r
+ int kinzi = -1;\r
+ int medial_ra = -1;\r
+ int base = -1;\r
+ int i;\r
+ int len = 0;\r
+ unsigned short reordered[32];\r
+ unsigned char properties[32];\r
+ enum {\r
+ AboveForm = 0x01,\r
+ PreForm = 0x02,\r
+ PostForm = 0x04,\r
+ BelowForm = 0x08\r
+ };\r
+ HB_Bool lastWasVirama = FALSE;\r
+ int basePos = -1;\r
+\r
+ memset(properties, 0, 32*sizeof(unsigned char));\r
+\r
+ /* according to the table the max length of a syllable should be around 14 chars */\r
+ assert(item->item.length < 32);\r
+\r
+#ifdef MYANMAR_DEBUG\r
+ printf("original:");\r
+ for (i = 0; i < (int)item->item.length; i++) {\r
+ printf(" %d: %4x", i, uc[i]);\r
+ }\r
+#endif\r
+ for (i = 0; i < (int)item->item.length; ++i) {\r
+ HB_UChar16 chr = uc[i];\r
+\r
+ if (chr == Mymr_C_VOWEL_E) {\r
+ vowel_e = i;\r
+ continue;\r
+ }\r
+ if (i == 0\r
+ && chr == Mymr_C_NGA\r
+ && i + 2 < (int)item->item.length\r
+ && uc[i+1] == Mymr_C_VIRAMA) {\r
+ int mc = getMyanmarCharClass(uc[i+2]);\r
+ /*MMDEBUG("maybe kinzi: mc=%x", mc);*/\r
+ if ((mc & Mymr_CF_CONSONANT) == Mymr_CF_CONSONANT) {\r
+ kinzi = i;\r
+ continue;\r
+ }\r
+ }\r
+ if (base >= 0\r
+ && chr == Mymr_C_VIRAMA\r
+ && i + 1 < (int)item->item.length\r
+ && uc[i+1] == Mymr_C_RA) {\r
+ medial_ra = i;\r
+ continue;\r
+ }\r
+ if (base < 0)\r
+ base = i;\r
+ }\r
+\r
+ MMDEBUG("\n base=%d, vowel_e=%d, kinzi=%d, medial_ra=%d", base, vowel_e, kinzi, medial_ra);\r
+ /* write vowel_e if found */\r
+ if (vowel_e >= 0) {\r
+ reordered[0] = Mymr_C_VOWEL_E;\r
+ len = 1;\r
+ }\r
+ /* write medial_ra */\r
+ if (medial_ra >= 0) {\r
+ reordered[len] = Mymr_C_VIRAMA;\r
+ reordered[len+1] = Mymr_C_RA;\r
+ properties[len] = PreForm;\r
+ properties[len+1] = PreForm;\r
+ len += 2;\r
+ }\r
+\r
+ /* shall we add a dotted circle?\r
+ If in the position in which the base should be (first char in the string) there is\r
+ a character that has the Dotted circle flag (a character that cannot be a base)\r
+ then write a dotted circle */\r
+ if (invalid) {\r
+ reordered[len] = C_DOTTED_CIRCLE;\r
+ ++len;\r
+ }\r
+\r
+ /* copy the rest of the syllable to the output, inserting the kinzi\r
+ at the correct place */\r
+ for (i = 0; i < (int)item->item.length; ++i) {\r
+ hb_uint16 chr = uc[i];\r
+ MymrCharClass cc;\r
+ if (i == vowel_e)\r
+ continue;\r
+ if (i == medial_ra || i == kinzi) {\r
+ ++i;\r
+ continue;\r
+ }\r
+\r
+ cc = getMyanmarCharClass(uc[i]);\r
+ if (kinzi >= 0 && i > base && (cc & Mymr_CF_AFTER_KINZI)) {\r
+ reordered[len] = Mymr_C_NGA;\r
+ reordered[len+1] = Mymr_C_VIRAMA;\r
+ properties[len-1] = AboveForm;\r
+ properties[len] = AboveForm;\r
+ len += 2;\r
+ kinzi = -1;\r
+ }\r
+\r
+ if (lastWasVirama) {\r
+ int prop = 0;\r
+ switch(cc & Mymr_CF_POS_MASK) {\r
+ case Mymr_CF_POS_BEFORE:\r
+ prop = PreForm;\r
+ break;\r
+ case Mymr_CF_POS_BELOW:\r
+ prop = BelowForm;\r
+ break;\r
+ case Mymr_CF_POS_ABOVE:\r
+ prop = AboveForm;\r
+ break;\r
+ case Mymr_CF_POS_AFTER:\r
+ prop = PostForm;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ properties[len-1] = prop;\r
+ properties[len] = prop;\r
+ if(basePos >= 0 && basePos == len-2)\r
+ properties[len-2] = prop;\r
+ }\r
+ lastWasVirama = (chr == Mymr_C_VIRAMA);\r
+ if(i == base)\r
+ basePos = len;\r
+\r
+ if ((chr != Mymr_C_SIGN_ZWNJ && chr != Mymr_C_SIGN_ZWJ) || !len) {\r
+ reordered[len] = chr;\r
+ ++len;\r
+ }\r
+ }\r
+ if (kinzi >= 0) {\r
+ reordered[len] = Mymr_C_NGA;\r
+ reordered[len+1] = Mymr_C_VIRAMA;\r
+ properties[len] = AboveForm;\r
+ properties[len+1] = AboveForm;\r
+ len += 2;\r
+ }\r
+\r
+ if (!item->font->klass->convertStringToGlyphIndices(item->font,\r
+ reordered, len,\r
+ item->glyphs, &item->num_glyphs,\r
+ item->item.bidiLevel % 2))\r
+ return FALSE;\r
+\r
+ MMDEBUG("after shaping: len=%d", len);\r
+ for (i = 0; i < len; i++) {\r
+ item->attributes[i].mark = FALSE;\r
+ item->attributes[i].clusterStart = FALSE;\r
+ item->attributes[i].justification = 0;\r
+ item->attributes[i].zeroWidth = FALSE;\r
+ MMDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]);\r
+ }\r
+\r
+ /* now we have the syllable in the right order, and can start running it through open type. */\r
+\r
+#ifndef NO_OPENTYPE\r
+ if (openType) {\r
+ unsigned short logClusters[32];\r
+ hb_uint32 where[32];\r
+\r
+ for (i = 0; i < len; ++i)\r
+ logClusters[i] = i;\r
+\r
+ for (i = 0; i < len; ++i) {\r
+ where[i] = ~(PreSubstProperty\r
+ | BelowSubstProperty\r
+ | AboveSubstProperty\r
+ | PostSubstProperty\r
+ | CligProperty\r
+ | PositioningProperties);\r
+ if (properties[i] & PreForm)\r
+ where[i] &= ~PreFormProperty;\r
+ if (properties[i] & BelowForm)\r
+ where[i] &= ~BelowFormProperty;\r
+ if (properties[i] & AboveForm)\r
+ where[i] &= ~AboveFormProperty;\r
+ if (properties[i] & PostForm)\r
+ where[i] &= ~PostFormProperty;\r
+ }\r
+\r
+ HB_OpenTypeShape(item, where);\r
+ if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))\r
+ return FALSE;\r
+ } else\r
+#endif\r
+ {\r
+ MMDEBUG("Not using openType");\r
+ HB_HeuristicPosition(item);\r
+ }\r
+\r
+ item->attributes[0].clusterStart = TRUE;\r
+ return TRUE;\r
+}\r
+\r
+HB_Bool HB_MyanmarShape(HB_ShaperItem *item)\r
+{\r
+ HB_Bool openType = FALSE;\r
+ unsigned short *logClusters = item->log_clusters;\r
+\r
+ HB_ShaperItem syllable = *item;\r
+ int first_glyph = 0;\r
+\r
+ int sstart = item->item.pos;\r
+ int end = sstart + item->item.length;\r
+ int i = 0;\r
+\r
+ assert(item->item.script == HB_Script_Myanmar);\r
+#ifndef NO_OPENTYPE\r
+ openType = HB_SelectScript(item, myanmar_features);\r
+#endif\r
+\r
+ MMDEBUG("myanmar_shape: from %d length %d", item->item.pos, item->item.length);\r
+ while (sstart < end) {\r
+ HB_Bool invalid;\r
+ int send = myanmar_nextSyllableBoundary(item->string, sstart, end, &invalid);\r
+ MMDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,\r
+ invalid ? "TRUE" : "FALSE");\r
+ syllable.item.pos = sstart;\r
+ syllable.item.length = send-sstart;\r
+ syllable.glyphs = item->glyphs + first_glyph;\r
+ syllable.attributes = item->attributes + first_glyph;\r
+ syllable.advances = item->advances + first_glyph;\r
+ syllable.offsets = item->offsets + first_glyph;\r
+ syllable.num_glyphs = item->num_glyphs - first_glyph;\r
+ if (!myanmar_shape_syllable(openType, &syllable, invalid)) {\r
+ MMDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);\r
+ item->num_glyphs += syllable.num_glyphs;\r
+ return FALSE;\r
+ }\r
+\r
+ /* fix logcluster array */\r
+ MMDEBUG("syllable:");\r
+ for (i = first_glyph; i < first_glyph + (int)syllable.num_glyphs; ++i)\r
+ MMDEBUG(" %d -> glyph %x", i, item->glyphs[i]);\r
+ MMDEBUG(" logclusters:");\r
+ for (i = sstart; i < send; ++i) {\r
+ MMDEBUG(" %d -> glyph %d", i, first_glyph);\r
+ logClusters[i-item->item.pos] = first_glyph;\r
+ }\r
+ sstart = send;\r
+ first_glyph += syllable.num_glyphs;\r
+ }\r
+ item->num_glyphs = first_glyph;\r
+ return TRUE;\r
+}\r
+\r
+void HB_MyanmarAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)\r
+{\r
+ int end = from + len;\r
+ const HB_UChar16 *uc = text + from;\r
+ hb_uint32 i = 0;\r
+ HB_UNUSED(script);\r
+ attributes += from;\r
+ while (i < len) {\r
+ HB_Bool invalid;\r
+ hb_uint32 boundary = myanmar_nextSyllableBoundary(text, from+i, end, &invalid) - from;\r
+\r
+ attributes[i].charStop = TRUE;\r
+ if (i)\r
+ attributes[i-1].lineBreakType = HB_Break;\r
+\r
+ if (boundary > len-1)\r
+ boundary = len;\r
+ i++;\r
+ while (i < boundary) {\r
+ attributes[i].charStop = FALSE;\r
+ ++uc;\r
+ ++i;\r
+ }\r
+ assert(i == boundary);\r
+ }\r
+}\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-open-private.h"\r
+\r
+\r
+/***************************\r
+ * Script related functions\r
+ ***************************/\r
+\r
+\r
+/* LangSys */\r
+\r
+static HB_Error Load_LangSys( HB_LangSys* ls,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_UShort n, count;\r
+ HB_UShort* fi;\r
+\r
+\r
+ if ( ACCESS_Frame( 6L ) )\r
+ return error;\r
+\r
+ ls->LookupOrderOffset = GET_UShort(); /* should be 0 */\r
+ ls->ReqFeatureIndex = GET_UShort();\r
+ count = ls->FeatureCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ls->FeatureIndex = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) )\r
+ return error;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( ls->FeatureIndex );\r
+ return error;\r
+ }\r
+\r
+ fi = ls->FeatureIndex;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ fi[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_LangSys( HB_LangSys* ls )\r
+{\r
+ FREE( ls->FeatureIndex );\r
+}\r
+\r
+\r
+/* Script */\r
+\r
+static HB_Error Load_Script( HB_ScriptTable* s,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_LangSysRecord* lsr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ if ( new_offset != base_offset ) /* not a NULL offset */\r
+ {\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_LangSys( &s->DefaultLangSys,\r
+ stream ) ) != HB_Err_Ok )\r
+ return error;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+ else\r
+ {\r
+ /* we create a DefaultLangSys table with no entries */\r
+\r
+ s->DefaultLangSys.LookupOrderOffset = 0;\r
+ s->DefaultLangSys.ReqFeatureIndex = 0xFFFF;\r
+ s->DefaultLangSys.FeatureCount = 0;\r
+ s->DefaultLangSys.FeatureIndex = NULL;\r
+ }\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail2;\r
+\r
+ count = s->LangSysCount = GET_UShort();\r
+\r
+ /* safety check; otherwise the official handling of TrueType Open\r
+ fonts won't work */\r
+\r
+ if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )\r
+ {\r
+ error = HB_Err_Not_Covered;\r
+ goto Fail2;\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ s->LangSysRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) )\r
+ goto Fail2;\r
+\r
+ lsr = s->LangSysRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 6L ) )\r
+ goto Fail1;\r
+\r
+ lsr[n].LangSysTag = GET_ULong();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_LangSys( &lsr[m].LangSys );\r
+\r
+ FREE( s->LangSysRecord );\r
+\r
+Fail2:\r
+ Free_LangSys( &s->DefaultLangSys );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_Script( HB_ScriptTable* s )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_LangSysRecord* lsr;\r
+\r
+\r
+ Free_LangSys( &s->DefaultLangSys );\r
+\r
+ if ( s->LangSysRecord )\r
+ {\r
+ count = s->LangSysCount;\r
+ lsr = s->LangSysRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_LangSys( &lsr[n].LangSys );\r
+\r
+ FREE( lsr );\r
+ }\r
+}\r
+\r
+\r
+/* ScriptList */\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_ScriptList( HB_ScriptList* sl,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, script_count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_ScriptRecord* sr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ script_count = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ sl->ScriptRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) )\r
+ return error;\r
+\r
+ sr = sl->ScriptRecord;\r
+\r
+ sl->ScriptCount= 0;\r
+ for ( n = 0; n < script_count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 6L ) )\r
+ goto Fail;\r
+\r
+ sr[sl->ScriptCount].ScriptTag = GET_ULong();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+\r
+ if ( FILE_Seek( new_offset ) )\r
+ goto Fail;\r
+\r
+ error = Load_Script( &sr[sl->ScriptCount].Script, stream );\r
+ if ( error == HB_Err_Ok )\r
+ sl->ScriptCount += 1;\r
+ else if ( error != HB_Err_Not_Covered )\r
+ goto Fail;\r
+\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ /* Empty tables are harmless and generated by fontforge.\r
+ * See http://bugzilla.gnome.org/show_bug.cgi?id=347073\r
+ */\r
+#if 0\r
+ if ( sl->ScriptCount == 0 )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_SubTable);\r
+ goto Fail;\r
+ }\r
+#endif\r
+ \r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( n = 0; n < sl->ScriptCount; n++ )\r
+ Free_Script( &sr[n].Script );\r
+\r
+ FREE( sl->ScriptRecord );\r
+ return error;\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_HB_OPEN_Free_ScriptList( HB_ScriptList* sl )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_ScriptRecord* sr;\r
+\r
+\r
+ if ( sl->ScriptRecord )\r
+ {\r
+ count = sl->ScriptCount;\r
+ sr = sl->ScriptRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_Script( &sr[n].Script );\r
+\r
+ FREE( sr );\r
+ }\r
+}\r
+\r
+\r
+\r
+/*********************************\r
+ * Feature List related functions\r
+ *********************************/\r
+\r
+\r
+/* Feature */\r
+\r
+static HB_Error Load_Feature( HB_Feature* f,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* lli;\r
+\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ f->FeatureParams = GET_UShort(); /* should be 0 */\r
+ count = f->LookupListCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ f->LookupListIndex = NULL;\r
+\r
+ if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) )\r
+ return error;\r
+\r
+ lli = f->LookupListIndex;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( f->LookupListIndex );\r
+ return error;\r
+ }\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ lli[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_Feature( HB_Feature* f )\r
+{\r
+ FREE( f->LookupListIndex );\r
+}\r
+\r
+\r
+/* FeatureList */\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_FeatureList( HB_FeatureList* fl,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_FeatureRecord* fr;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = fl->FeatureCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ fl->FeatureRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) )\r
+ return error;\r
+ if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) )\r
+ goto Fail2;\r
+ \r
+ fl->ApplyCount = 0;\r
+\r
+ fr = fl->FeatureRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 6L ) )\r
+ goto Fail1;\r
+\r
+ fr[n].FeatureTag = GET_ULong();\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_Feature( &fr[m].Feature );\r
+\r
+ FREE( fl->ApplyOrder );\r
+\r
+Fail2:\r
+ FREE( fl->FeatureRecord );\r
+\r
+ return error;\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_HB_OPEN_Free_FeatureList( HB_FeatureList* fl )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_FeatureRecord* fr;\r
+\r
+\r
+ if ( fl->FeatureRecord )\r
+ {\r
+ count = fl->FeatureCount;\r
+ fr = fl->FeatureRecord;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_Feature( &fr[n].Feature );\r
+\r
+ FREE( fr );\r
+ }\r
+ \r
+ FREE( fl->ApplyOrder );\r
+}\r
+\r
+\r
+\r
+/********************************\r
+ * Lookup List related functions\r
+ ********************************/\r
+\r
+/* the subroutines of the following two functions are defined in\r
+ ftxgsub.c and ftxgpos.c respectively */\r
+\r
+\r
+/* SubTable */\r
+\r
+static HB_Error Load_SubTable( HB_SubTable* st,\r
+ HB_Stream stream,\r
+ HB_Type table_type,\r
+ HB_UShort lookup_type )\r
+{\r
+ if ( table_type == HB_Type_GSUB )\r
+ return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type );\r
+ else\r
+ return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type );\r
+}\r
+\r
+\r
+static void Free_SubTable( HB_SubTable* st,\r
+ HB_Type table_type,\r
+ HB_UShort lookup_type )\r
+{\r
+ if ( table_type == HB_Type_GSUB )\r
+ _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type );\r
+ else\r
+ _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type );\r
+}\r
+\r
+\r
+/* Lookup */\r
+\r
+static HB_Error Load_Lookup( HB_Lookup* l,\r
+ HB_Stream stream,\r
+ HB_Type type )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_SubTable* st;\r
+\r
+ HB_Bool is_extension = FALSE;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 6L ) )\r
+ return error;\r
+\r
+ l->LookupType = GET_UShort();\r
+ l->LookupFlag = GET_UShort();\r
+ count = l->SubTableCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ l->SubTable = NULL;\r
+\r
+ if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) )\r
+ return error;\r
+\r
+ st = l->SubTable;\r
+\r
+ if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) ||\r
+ ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) )\r
+ is_extension = TRUE;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+\r
+ if ( is_extension )\r
+ {\r
+ if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) )\r
+ goto Fail;\r
+\r
+ if (GET_UShort() != 1) /* format should be 1 */\r
+ goto Fail;\r
+\r
+ l->LookupType = GET_UShort();\r
+ new_offset += GET_ULong();\r
+\r
+ FORGET_Frame();\r
+ }\r
+\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_SubTable( &st[n], stream,\r
+ type, l->LookupType ) ) != HB_Err_Ok )\r
+ goto Fail;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ for ( m = 0; m < n; m++ )\r
+ Free_SubTable( &st[m], type, l->LookupType );\r
+\r
+ FREE( l->SubTable );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_Lookup( HB_Lookup* l,\r
+ HB_Type type)\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_SubTable* st;\r
+\r
+\r
+ if ( l->SubTable )\r
+ {\r
+ count = l->SubTableCount;\r
+ st = l->SubTable;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_SubTable( &st[n], type, l->LookupType );\r
+\r
+ FREE( st );\r
+ }\r
+}\r
+\r
+\r
+/* LookupList */\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_LookupList( HB_LookupList* ll,\r
+ HB_Stream stream,\r
+ HB_Type type )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, m, count;\r
+ HB_UInt cur_offset, new_offset, base_offset;\r
+\r
+ HB_Lookup* l;\r
+\r
+\r
+ base_offset = FILE_Pos();\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = ll->LookupCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ ll->Lookup = NULL;\r
+\r
+ if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) )\r
+ return error;\r
+ if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) )\r
+ goto Fail2;\r
+\r
+ l = ll->Lookup;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ if ( ACCESS_Frame( 2L ) )\r
+ goto Fail1;\r
+\r
+ new_offset = GET_UShort() + base_offset;\r
+\r
+ FORGET_Frame();\r
+\r
+ cur_offset = FILE_Pos();\r
+ if ( FILE_Seek( new_offset ) ||\r
+ ( error = Load_Lookup( &l[n], stream, type ) ) != HB_Err_Ok )\r
+ goto Fail1;\r
+ (void)FILE_Seek( cur_offset );\r
+ }\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail1:\r
+ FREE( ll->Properties );\r
+\r
+ for ( m = 0; m < n; m++ )\r
+ Free_Lookup( &l[m], type );\r
+\r
+Fail2:\r
+ FREE( ll->Lookup );\r
+ return error;\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_HB_OPEN_Free_LookupList( HB_LookupList* ll,\r
+ HB_Type type )\r
+{\r
+ HB_UShort n, count;\r
+\r
+ HB_Lookup* l;\r
+\r
+\r
+ FREE( ll->Properties );\r
+\r
+ if ( ll->Lookup )\r
+ {\r
+ count = ll->LookupCount;\r
+ l = ll->Lookup;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ Free_Lookup( &l[n], type );\r
+\r
+ FREE( l );\r
+ }\r
+}\r
+\r
+\r
+\r
+/*****************************\r
+ * Coverage related functions\r
+ *****************************/\r
+\r
+\r
+/* CoverageFormat1 */\r
+\r
+static HB_Error Load_Coverage1( HB_CoverageFormat1* cf1,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* ga;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = cf1->GlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cf1->GlyphArray = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) )\r
+ return error;\r
+\r
+ ga = cf1->GlyphArray;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( cf1->GlyphArray );\r
+ return error;\r
+ }\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ ga[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static void Free_Coverage1( HB_CoverageFormat1* cf1)\r
+{\r
+ FREE( cf1->GlyphArray );\r
+}\r
+\r
+\r
+/* CoverageFormat2 */\r
+\r
+static HB_Error Load_Coverage2( HB_CoverageFormat2* cf2,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_RangeRecord* rr;\r
+\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = cf2->RangeCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ cf2->RangeRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) )\r
+ return error;\r
+\r
+ rr = cf2->RangeRecord;\r
+\r
+ if ( ACCESS_Frame( count * 6L ) )\r
+ goto Fail;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ rr[n].Start = GET_UShort();\r
+ rr[n].End = GET_UShort();\r
+ rr[n].StartCoverageIndex = GET_UShort();\r
+\r
+ /* sanity check; we are limited to 16bit integers */\r
+ if ( rr[n].Start > rr[n].End ||\r
+ ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=\r
+ 0x10000L )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_SubTable);\r
+ goto Fail;\r
+ }\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ FREE( cf2->RangeRecord );\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_Coverage2( HB_CoverageFormat2* cf2 )\r
+{\r
+ FREE( cf2->RangeRecord );\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_Coverage( HB_Coverage* c,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ c->CoverageFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( c->CoverageFormat )\r
+ {\r
+ case 1: return Load_Coverage1( &c->cf.cf1, stream );\r
+ case 2: return Load_Coverage2( &c->cf.cf2, stream );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_HB_OPEN_Free_Coverage( HB_Coverage* c )\r
+{\r
+ switch ( c->CoverageFormat )\r
+ {\r
+ case 1: Free_Coverage1( &c->cf.cf1 ); break;\r
+ case 2: Free_Coverage2( &c->cf.cf2 ); break;\r
+ default: break;\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Coverage_Index1( HB_CoverageFormat1* cf1,\r
+ HB_UShort glyphID,\r
+ HB_UShort* index )\r
+{\r
+ HB_UShort min, max, new_min, new_max, middle;\r
+\r
+ HB_UShort* array = cf1->GlyphArray;\r
+\r
+\r
+ /* binary search */\r
+\r
+ if ( cf1->GlyphCount == 0 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ new_min = 0;\r
+ new_max = cf1->GlyphCount - 1;\r
+\r
+ do\r
+ {\r
+ min = new_min;\r
+ max = new_max;\r
+\r
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid\r
+ overflow and rounding errors */\r
+\r
+ middle = max - ( ( max - min ) >> 1 );\r
+\r
+ if ( glyphID == array[middle] )\r
+ {\r
+ *index = middle;\r
+ return HB_Err_Ok;\r
+ }\r
+ else if ( glyphID < array[middle] )\r
+ {\r
+ if ( middle == min )\r
+ break;\r
+ new_max = middle - 1;\r
+ }\r
+ else\r
+ {\r
+ if ( middle == max )\r
+ break;\r
+ new_min = middle + 1;\r
+ }\r
+ } while ( min < max );\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+static HB_Error Coverage_Index2( HB_CoverageFormat2* cf2,\r
+ HB_UShort glyphID,\r
+ HB_UShort* index )\r
+{\r
+ HB_UShort min, max, new_min, new_max, middle;\r
+\r
+ HB_RangeRecord* rr = cf2->RangeRecord;\r
+\r
+\r
+ /* binary search */\r
+\r
+ if ( cf2->RangeCount == 0 )\r
+ return HB_Err_Not_Covered;\r
+\r
+ new_min = 0;\r
+ new_max = cf2->RangeCount - 1;\r
+\r
+ do\r
+ {\r
+ min = new_min;\r
+ max = new_max;\r
+\r
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid\r
+ overflow and rounding errors */\r
+\r
+ middle = max - ( ( max - min ) >> 1 );\r
+\r
+ if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End )\r
+ {\r
+ *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start;\r
+ return HB_Err_Ok;\r
+ }\r
+ else if ( glyphID < rr[middle].Start )\r
+ {\r
+ if ( middle == min )\r
+ break;\r
+ new_max = middle - 1;\r
+ }\r
+ else\r
+ {\r
+ if ( middle == max )\r
+ break;\r
+ new_min = middle + 1;\r
+ }\r
+ } while ( min < max );\r
+\r
+ return HB_Err_Not_Covered;\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Coverage_Index( HB_Coverage* c,\r
+ HB_UShort glyphID,\r
+ HB_UShort* index )\r
+{\r
+ switch ( c->CoverageFormat )\r
+ {\r
+ case 1: return Coverage_Index1( &c->cf.cf1, glyphID, index );\r
+ case 2: return Coverage_Index2( &c->cf.cf2, glyphID, index );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+\r
+/*************************************\r
+ * Class Definition related functions\r
+ *************************************/\r
+\r
+\r
+/* ClassDefFormat1 */\r
+\r
+static HB_Error Load_ClassDef1( HB_ClassDefinition* cd,\r
+ HB_UShort limit,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* cva;\r
+\r
+ HB_ClassDefFormat1* cdf1;\r
+\r
+\r
+ cdf1 = &cd->cd.cd1;\r
+\r
+ if ( ACCESS_Frame( 4L ) )\r
+ return error;\r
+\r
+ cdf1->StartGlyph = GET_UShort();\r
+ count = cdf1->GlyphCount = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ /* sanity check; we are limited to 16bit integers */\r
+\r
+ if ( cdf1->StartGlyph + (long)count >= 0x10000L )\r
+ return ERR_HB(HB_Err_Invalid_SubTable);\r
+\r
+ cdf1->ClassValueArray = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, HB_UShort ) )\r
+ return error;\r
+\r
+ cva = cdf1->ClassValueArray;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ goto Fail;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ cva[n] = GET_UShort();\r
+ if ( cva[n] >= limit )\r
+ {\r
+ error = ERR_HB(HB_Err_Invalid_SubTable);\r
+ goto Fail;\r
+ }\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ FREE( cva );\r
+\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ClassDef1( HB_ClassDefFormat1* cdf1 )\r
+{\r
+ FREE( cdf1->ClassValueArray );\r
+}\r
+\r
+\r
+/* ClassDefFormat2 */\r
+\r
+static HB_Error Load_ClassDef2( HB_ClassDefinition* cd,\r
+ HB_UShort limit,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_ClassRangeRecord* crr;\r
+\r
+ HB_ClassDefFormat2* cdf2;\r
+\r
+\r
+ cdf2 = &cd->cd.cd2;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ count = GET_UShort();\r
+ cdf2->ClassRangeCount = 0; /* zero for now. we fill with the number of good entries later */\r
+\r
+ FORGET_Frame();\r
+\r
+ cdf2->ClassRangeRecord = NULL;\r
+\r
+ if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) )\r
+ return error;\r
+\r
+ crr = cdf2->ClassRangeRecord;\r
+\r
+ if ( ACCESS_Frame( count * 6L ) )\r
+ goto Fail;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ {\r
+ crr[n].Start = GET_UShort();\r
+ crr[n].End = GET_UShort();\r
+ crr[n].Class = GET_UShort();\r
+\r
+ /* sanity check */\r
+\r
+ if ( crr[n].Start > crr[n].End ||\r
+ crr[n].Class >= limit )\r
+ {\r
+ /* XXX\r
+ * Corrupt entry. Skip it.\r
+ * This is hit by Nafees Nastaliq font for example\r
+ */\r
+ n--;\r
+ count--;\r
+ }\r
+ }\r
+\r
+ FORGET_Frame();\r
+\r
+ cdf2->ClassRangeCount = count;\r
+\r
+ return HB_Err_Ok;\r
+\r
+Fail:\r
+ FREE( crr );\r
+\r
+ return error;\r
+}\r
+\r
+\r
+static void Free_ClassDef2( HB_ClassDefFormat2* cdf2 )\r
+{\r
+ FREE( cdf2->ClassRangeRecord );\r
+}\r
+\r
+\r
+/* ClassDefinition */\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,\r
+ HB_UShort limit,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ if ( ACCESS_Frame( 2L ) )\r
+ return error;\r
+\r
+ cd->ClassFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ switch ( cd->ClassFormat )\r
+ {\r
+ case 1: error = Load_ClassDef1( cd, limit, stream ); break;\r
+ case 2: error = Load_ClassDef2( cd, limit, stream ); break;\r
+ default: error = ERR_HB(HB_Err_Invalid_SubTable_Format); break;\r
+ }\r
+\r
+ if ( error )\r
+ return error;\r
+\r
+ cd->loaded = TRUE;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+static HB_Error\r
+_HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd )\r
+{\r
+ HB_Error error;\r
+\r
+ cd->ClassFormat = 1; /* Meaningless */\r
+\r
+ if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, HB_UShort ) )\r
+ return error;\r
+\r
+ cd->loaded = TRUE;\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,\r
+ HB_UShort limit,\r
+ HB_UInt class_offset,\r
+ HB_UInt base_offset,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+ HB_UInt cur_offset;\r
+\r
+ cur_offset = FILE_Pos();\r
+\r
+ if ( class_offset )\r
+ {\r
+ if ( !FILE_Seek( class_offset + base_offset ) )\r
+ error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );\r
+ }\r
+ else\r
+ error = _HB_OPEN_Load_EmptyClassDefinition ( cd );\r
+\r
+ if (error == HB_Err_Ok)\r
+ (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */\r
+\r
+ return error;\r
+}\r
+\r
+HB_INTERNAL void\r
+_HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd )\r
+{\r
+ if ( !cd->loaded )\r
+ return;\r
+\r
+ switch ( cd->ClassFormat )\r
+ {\r
+ case 1: Free_ClassDef1( &cd->cd.cd1 ); break;\r
+ case 2: Free_ClassDef2( &cd->cd.cd2 ); break;\r
+ default: break;\r
+ }\r
+}\r
+\r
+\r
+static HB_Error Get_Class1( HB_ClassDefFormat1* cdf1,\r
+ HB_UShort glyphID,\r
+ HB_UShort* klass,\r
+ HB_UShort* index )\r
+{\r
+ HB_UShort* cva = cdf1->ClassValueArray;\r
+\r
+\r
+ if ( index )\r
+ *index = 0;\r
+\r
+ if ( glyphID >= cdf1->StartGlyph &&\r
+ glyphID < cdf1->StartGlyph + cdf1->GlyphCount )\r
+ {\r
+ *klass = cva[glyphID - cdf1->StartGlyph];\r
+ return HB_Err_Ok;\r
+ }\r
+ else\r
+ {\r
+ *klass = 0;\r
+ return HB_Err_Not_Covered;\r
+ }\r
+}\r
+\r
+\r
+/* we need the index value of the last searched class range record\r
+ in case of failure for constructed GDEF tables */\r
+\r
+static HB_Error Get_Class2( HB_ClassDefFormat2* cdf2,\r
+ HB_UShort glyphID,\r
+ HB_UShort* klass,\r
+ HB_UShort* index )\r
+{\r
+ HB_Error error = HB_Err_Ok;\r
+ HB_UShort min, max, new_min, new_max, middle;\r
+\r
+ HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord;\r
+\r
+\r
+ /* binary search */\r
+\r
+ if ( cdf2->ClassRangeCount == 0 )\r
+ {\r
+ *klass = 0;\r
+ if ( index )\r
+ *index = 0;\r
+ \r
+ return HB_Err_Not_Covered;\r
+ }\r
+\r
+ new_min = 0;\r
+ new_max = cdf2->ClassRangeCount - 1;\r
+\r
+ do\r
+ {\r
+ min = new_min;\r
+ max = new_max;\r
+\r
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid\r
+ overflow and rounding errors */\r
+\r
+ middle = max - ( ( max - min ) >> 1 );\r
+\r
+ if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )\r
+ {\r
+ *klass = crr[middle].Class;\r
+ error = HB_Err_Ok;\r
+ break;\r
+ }\r
+ else if ( glyphID < crr[middle].Start )\r
+ {\r
+ if ( middle == min )\r
+ {\r
+ *klass = 0;\r
+ error = HB_Err_Not_Covered;\r
+ break;\r
+ }\r
+ new_max = middle - 1;\r
+ }\r
+ else\r
+ {\r
+ if ( middle == max )\r
+ {\r
+ *klass = 0;\r
+ error = HB_Err_Not_Covered;\r
+ break;\r
+ }\r
+ new_min = middle + 1;\r
+ }\r
+ } while ( min < max );\r
+\r
+ if ( index )\r
+ *index = middle;\r
+\r
+ return error;\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Get_Class( HB_ClassDefinition* cd,\r
+ HB_UShort glyphID,\r
+ HB_UShort* klass,\r
+ HB_UShort* index )\r
+{\r
+ switch ( cd->ClassFormat )\r
+ {\r
+ case 1: return Get_Class1( &cd->cd.cd1, glyphID, klass, index );\r
+ case 2: return Get_Class2( &cd->cd.cd2, glyphID, klass, index );\r
+ default: return ERR_HB(HB_Err_Invalid_SubTable_Format);\r
+ }\r
+\r
+ return HB_Err_Ok; /* never reached */\r
+}\r
+\r
+\r
+\r
+/***************************\r
+ * Device related functions\r
+ ***************************/\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Load_Device( HB_Device* d,\r
+ HB_Stream stream )\r
+{\r
+ HB_Error error;\r
+\r
+ HB_UShort n, count;\r
+\r
+ HB_UShort* dv;\r
+\r
+\r
+ if ( ACCESS_Frame( 6L ) )\r
+ return error;\r
+\r
+ d->StartSize = GET_UShort();\r
+ d->EndSize = GET_UShort();\r
+ d->DeltaFormat = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ d->DeltaValue = NULL;\r
+\r
+ if ( d->StartSize > d->EndSize ||\r
+ d->DeltaFormat == 0 || d->DeltaFormat > 3 )\r
+ {\r
+ /* XXX\r
+ * I've seen fontforge generate DeltaFormat == 0.\r
+ * Just return Ok and let the NULL DeltaValue disable\r
+ * this table.\r
+ */\r
+ return HB_Err_Ok;\r
+ }\r
+\r
+ count = ( ( d->EndSize - d->StartSize + 1 ) >>\r
+ ( 4 - d->DeltaFormat ) ) + 1;\r
+\r
+ if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) )\r
+ return error;\r
+\r
+ if ( ACCESS_Frame( count * 2L ) )\r
+ {\r
+ FREE( d->DeltaValue );\r
+ return error;\r
+ }\r
+\r
+ dv = d->DeltaValue;\r
+\r
+ for ( n = 0; n < count; n++ )\r
+ dv[n] = GET_UShort();\r
+\r
+ FORGET_Frame();\r
+\r
+ return HB_Err_Ok;\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_HB_OPEN_Free_Device( HB_Device* d )\r
+{\r
+ FREE( d->DeltaValue );\r
+}\r
+\r
+\r
+/* Since we have the delta values stored in compressed form, we must\r
+ uncompress it now. To simplify the interface, the function always\r
+ returns a meaningful value in `value'; the error is just for\r
+ information.\r
+ | |\r
+ format = 1: 0011223344556677|8899101112131415|...\r
+ | |\r
+ byte 1 byte 2\r
+\r
+ 00: (byte >> 14) & mask\r
+ 11: (byte >> 12) & mask\r
+ ...\r
+\r
+ mask = 0x0003\r
+ | |\r
+ format = 2: 0000111122223333|4444555566667777|...\r
+ | |\r
+ byte 1 byte 2\r
+\r
+ 0000: (byte >> 12) & mask\r
+ 1111: (byte >> 8) & mask\r
+ ...\r
+\r
+ mask = 0x000F\r
+ | |\r
+ format = 3: 0000000011111111|2222222233333333|...\r
+ | |\r
+ byte 1 byte 2\r
+\r
+ 00000000: (byte >> 8) & mask\r
+ 11111111: (byte >> 0) & mask\r
+ ....\r
+\r
+ mask = 0x00FF */\r
+\r
+HB_INTERNAL HB_Error\r
+_HB_OPEN_Get_Device( HB_Device* d,\r
+ HB_UShort size,\r
+ HB_Short* value )\r
+{\r
+ HB_UShort byte, bits, mask, f, s;\r
+\r
+\r
+ f = d->DeltaFormat;\r
+\r
+ if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize )\r
+ {\r
+ s = size - d->StartSize;\r
+ byte = d->DeltaValue[s >> ( 4 - f )];\r
+ bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );\r
+ mask = 0xFFFF >> ( 16 - ( 1 << f ) );\r
+\r
+ *value = (HB_Short)( bits & mask );\r
+\r
+ /* conversion to a signed value */\r
+\r
+ if ( *value >= ( ( mask + 1 ) >> 1 ) )\r
+ *value -= mask + 1;\r
+\r
+ return HB_Err_Ok;\r
+ }\r
+ else\r
+ {\r
+ *value = 0;\r
+ return HB_Err_Not_Covered;\r
+ }\r
+}\r
+\r
+\r
+/* END */\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.c"\r
+#include "harfbuzz-indic.c"\r
+\r
+#include "harfbuzz-tibetan.c"\r
+#include "harfbuzz-khmer.c"\r
+#include "harfbuzz-hebrew.c"\r
+#include "harfbuzz-arabic.c"\r
+#include "harfbuzz-hangul.c"\r
+#include "harfbuzz-myanmar.c"\r
+#include "harfbuzz-thai.c"\r
+\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+#include "harfbuzz-stream-private.h"\r
+#include <assert.h>\r
+#include <stdio.h>\r
+\r
+#define HB_MIN(a, b) ((a) < (b) ? (a) : (b))\r
+#define HB_MAX(a, b) ((a) > (b) ? (a) : (b))\r
+\r
+// -----------------------------------------------------------------------------------------------------\r
+//\r
+// The line break algorithm. See http://www.unicode.org/reports/tr14/tr14-13.html\r
+//\r
+// -----------------------------------------------------------------------------------------------------\r
+\r
+/* The Unicode algorithm does in our opinion allow line breaks at some\r
+ places they shouldn't be allowed. The following changes were thus\r
+ made in comparison to the Unicode reference:\r
+\r
+ EX->AL from DB to IB\r
+ SY->AL from DB to IB\r
+ SY->PO from DB to IB\r
+ SY->PR from DB to IB\r
+ SY->OP from DB to IB\r
+ AL->PR from DB to IB\r
+ AL->PO from DB to IB\r
+ PR->PR from DB to IB\r
+ PO->PO from DB to IB\r
+ PR->PO from DB to IB\r
+ PO->PR from DB to IB\r
+ HY->PO from DB to IB\r
+ HY->PR from DB to IB\r
+ HY->OP from DB to IB\r
+ NU->EX from PB to IB\r
+ EX->PO from DB to IB\r
+*/\r
+\r
+// The following line break classes are not treated by the table:\r
+// AI, BK, CB, CR, LF, NL, SA, SG, SP, XX\r
+\r
+enum break_class {\r
+ // the first 4 values have to agree with the enum in QCharAttributes\r
+ ProhibitedBreak, // PB in table\r
+ DirectBreak, // DB in table\r
+ IndirectBreak, // IB in table\r
+ CombiningIndirectBreak, // CI in table\r
+ CombiningProhibitedBreak // CP in table\r
+};\r
+#define DB DirectBreak\r
+#define IB IndirectBreak\r
+#define CI CombiningIndirectBreak\r
+#define CP CombiningProhibitedBreak\r
+#define PB ProhibitedBreak\r
+\r
+static const hb_uint8 breakTable[HB_LineBreak_JT+1][HB_LineBreak_JT+1] =\r
+{\r
+/* OP CL QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT */\r
+/* OP */ { PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, CP, PB, PB, PB, PB, PB, PB },\r
+/* CL */ { DB, PB, IB, IB, PB, PB, PB, PB, IB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* QU */ { PB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB },\r
+/* GL */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB },\r
+/* NS */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* EX */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* SY */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* IS */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* PR */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, DB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, IB },\r
+/* PO */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* NU */ { IB, PB, IB, IB, IB, IB, PB, PB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* AL */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* ID */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* IN */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* HY */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* BA */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* BB */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB },\r
+/* B2 */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, DB, DB, DB, DB, IB, IB, DB, PB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* ZW */ { DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, PB, DB, DB, DB, DB, DB, DB, DB },\r
+/* CM */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, DB, IB, IB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, DB },\r
+/* WJ */ { IB, PB, IB, IB, IB, PB, PB, PB, IB, IB, IB, IB, IB, IB, IB, IB, IB, IB, PB, CI, PB, IB, IB, IB, IB, IB },\r
+/* H2 */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB },\r
+/* H3 */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB },\r
+/* JL */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, IB, IB, IB, IB, DB },\r
+/* JV */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, IB, IB },\r
+/* JT */ { DB, PB, IB, IB, IB, PB, PB, PB, DB, IB, DB, DB, DB, IB, IB, IB, DB, DB, PB, CI, PB, DB, DB, DB, DB, IB }\r
+};\r
+#undef DB\r
+#undef IB\r
+#undef CI\r
+#undef CP\r
+#undef PB\r
+\r
+static const hb_uint8 graphemeTable[HB_Grapheme_LVT + 1][HB_Grapheme_LVT + 1] =\r
+{\r
+// Other, CR, LF, Control,Extend,L, V, T, LV, LVT\r
+ { true , true , true , true , true , true , true , true , true , true }, // Other, \r
+ { true , true , true , true , true , true , true , true , true , true }, // CR,\r
+ { true , false, true , true , true , true , true , true , true , true }, // LF,\r
+ { true , true , true , true , true , true , true , true , true , true }, // Control,\r
+ { false, true , true , true , false, false, false, false, false, false }, // Extend,\r
+ { true , true , true , true , true , false, true , true , true , true }, // L, \r
+ { true , true , true , true , true , false, false, true , false, true }, // V, \r
+ { true , true , true , true , true , true , false, false, false, false }, // T, \r
+ { true , true , true , true , true , false, true , true , true , true }, // LV, \r
+ { true , true , true , true , true , false, true , true , true , true }, // LVT\r
+};\r
+ \r
+static void calcLineBreaks(const HB_UChar16 *uc, hb_uint32 len, HB_CharAttributes *charAttributes)\r
+{\r
+ hb_uint32 i ;\r
+ \r
+ if (!len)\r
+ return;\r
+\r
+ // ##### can this fail if the first char is a surrogate?\r
+ HB_LineBreakClass cls;\r
+ HB_GraphemeClass grapheme;\r
+ HB_GetGraphemeAndLineBreakClass(*uc, &grapheme, &cls);\r
+ // handle case where input starts with an LF\r
+ if (cls == HB_LineBreak_LF)\r
+ cls = HB_LineBreak_BK;\r
+\r
+ charAttributes[0].whiteSpace = (cls == HB_LineBreak_SP || cls == HB_LineBreak_BK);\r
+ charAttributes[0].charStop = true;\r
+\r
+ int lcls = cls;\r
+ for (i = 1; i < len; ++i) {\r
+ HB_UChar32 code = uc[i];\r
+ HB_GraphemeClass ngrapheme;\r
+ HB_LineBreakClass ncls;\r
+ \r
+ charAttributes[i].whiteSpace = false;\r
+ charAttributes[i].charStop = true;\r
+ \r
+ HB_GetGraphemeAndLineBreakClass(code, &ngrapheme, &ncls);\r
+ charAttributes[i].charStop = graphemeTable[ngrapheme][grapheme];\r
+ // handle surrogates\r
+ if (ncls == HB_LineBreak_SG) {\r
+ if (HB_IsHighSurrogate(uc[i]) && i < len - 1 && HB_IsLowSurrogate(uc[i+1])) {\r
+ continue;\r
+ } else if (HB_IsLowSurrogate(uc[i]) && HB_IsHighSurrogate(uc[i-1])) {\r
+ code = HB_SurrogateToUcs4(uc[i-1], uc[i]);\r
+ HB_GetGraphemeAndLineBreakClass(code, &ngrapheme, &ncls);\r
+ charAttributes[i].charStop = false;\r
+ } else {\r
+ ncls = HB_LineBreak_AL;\r
+ }\r
+ }\r
+\r
+ // set white space and char stop flag\r
+ if (ncls >= HB_LineBreak_SP)\r
+ charAttributes[i].whiteSpace = true;\r
+\r
+ HB_LineBreakType lineBreakType = HB_NoBreak;\r
+ if (cls >= HB_LineBreak_LF) {\r
+ lineBreakType = HB_ForcedBreak;\r
+ } else if(cls == HB_LineBreak_CR) {\r
+ lineBreakType = (ncls == HB_LineBreak_LF) ? HB_NoBreak : HB_ForcedBreak;\r
+ }\r
+\r
+ if (ncls == HB_LineBreak_SP)\r
+ goto next_no_cls_update;\r
+ if (ncls >= HB_LineBreak_CR)\r
+ goto next;\r
+\r
+ // two complex chars (thai or lao), thai_attributes might override, but here we do a best guess\r
+ if (cls == HB_LineBreak_SA && ncls == HB_LineBreak_SA) {\r
+ lineBreakType = HB_Break;\r
+ goto next;\r
+ }\r
+\r
+ {\r
+ int tcls = ncls;\r
+ if (tcls >= HB_LineBreak_SA)\r
+ tcls = HB_LineBreak_ID;\r
+ if (cls >= HB_LineBreak_SA)\r
+ cls = HB_LineBreak_ID;\r
+\r
+ int brk = breakTable[cls][tcls];\r
+ switch (brk) {\r
+ case DirectBreak:\r
+ lineBreakType = HB_Break;\r
+ if (uc[i-1] == 0xad) // soft hyphen\r
+ lineBreakType = HB_SoftHyphen;\r
+ break;\r
+ case IndirectBreak:\r
+ lineBreakType = (lcls == HB_LineBreak_SP) ? HB_Break : HB_NoBreak;\r
+ break;\r
+ case CombiningIndirectBreak:\r
+ lineBreakType = HB_NoBreak;\r
+ if (lcls == HB_LineBreak_SP){\r
+ if (i > 1)\r
+ charAttributes[i-2].lineBreakType = HB_Break;\r
+ } else {\r
+ goto next_no_cls_update;\r
+ }\r
+ break;\r
+ case CombiningProhibitedBreak:\r
+ lineBreakType = HB_NoBreak;\r
+ if (lcls != HB_LineBreak_SP)\r
+ goto next_no_cls_update;\r
+ case ProhibitedBreak:\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ next:\r
+ cls = ncls;\r
+ next_no_cls_update:\r
+ lcls = ncls;\r
+ grapheme = ngrapheme;\r
+ charAttributes[i-1].lineBreakType = lineBreakType;\r
+ }\r
+ charAttributes[len-1].lineBreakType = HB_ForcedBreak;\r
+}\r
+\r
+// --------------------------------------------------------------------------------------------------------------------------------------------\r
+//\r
+// Basic processing\r
+//\r
+// --------------------------------------------------------------------------------------------------------------------------------------------\r
+\r
+static inline void positionCluster(HB_ShaperItem *item, int gfrom, int glast)\r
+{\r
+ int nmarks = glast - gfrom;\r
+ HB_Bool rightToLeft = item->item.bidiLevel % 2;\r
+ int i;\r
+ unsigned char lastCmb = 0;\r
+ HB_GlyphMetrics attachmentRect;\r
+ \r
+ assert(nmarks > 0);\r
+\r
+ HB_Glyph *glyphs = item->glyphs;\r
+ HB_GlyphAttributes *attributes = item->attributes;\r
+\r
+ HB_GlyphMetrics baseMetrics;\r
+ item->font->klass->getGlyphMetrics(item->font, glyphs[gfrom], &baseMetrics);\r
+\r
+ if (item->item.script == HB_Script_Hebrew\r
+ && (-baseMetrics.y) > baseMetrics.height)\r
+ // we need to attach below the baseline, because of the hebrew iud.\r
+ baseMetrics.height = -baseMetrics.y;\r
+\r
+// qDebug("---> positionCluster: cluster from %d to %d", gfrom, glast);\r
+// qDebug("baseInfo: %f/%f (%f/%f) off=%f/%f", baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height, baseInfo.xoff, baseInfo.yoff);\r
+\r
+ HB_Fixed size = item->font->klass->getFontMetric(item->font, HB_FontAscent) / 10;\r
+ HB_Fixed offsetBase = HB_FIXED_CONSTANT(1) + (size - HB_FIXED_CONSTANT(4)) / 4;\r
+ if (size > HB_FIXED_CONSTANT(4))\r
+ offsetBase += HB_FIXED_CONSTANT(4);\r
+ else\r
+ offsetBase += size;\r
+ //qreal offsetBase = (size - 4) / 4 + qMin<qreal>(size, 4) + 1;\r
+// qDebug("offset = %f", offsetBase);\r
+\r
+ memset(&attachmentRect, 0, sizeof(attachmentRect));\r
+\r
+ for(i = 1; i <= nmarks; i++) {\r
+ HB_Glyph mark = glyphs[gfrom+i];\r
+ HB_GlyphMetrics markMetrics;\r
+ HB_GlyphMetrics unitedAttachmentRect = attachmentRect;\r
+ \r
+ item->font->klass->getGlyphMetrics(item->font, mark, &markMetrics);\r
+ HB_FixedPoint p;\r
+ p.x = p.y = 0;\r
+// qDebug("markInfo: %f/%f (%f/%f) off=%f/%f", markInfo.x, markInfo.y, markInfo.width, markInfo.height, markInfo.xoff, markInfo.yoff);\r
+\r
+ HB_Fixed offset = offsetBase;\r
+ unsigned char cmb = attributes[gfrom+i].combiningClass;\r
+\r
+ // ### maybe the whole position determination should move down to heuristicSetGlyphAttributes. Would save some\r
+ // bits in the glyphAttributes structure.\r
+ if (cmb < 200) {\r
+ // fixed position classes. We approximate by mapping to one of the others.\r
+ // currently I added only the ones for arabic, hebrew, lao and thai.\r
+\r
+ // for Lao and Thai marks with class 0, see below (heuristicSetGlyphAttributes)\r
+\r
+ // add a bit more offset to arabic, a bit hacky\r
+ if (cmb >= 27 && cmb <= 36 && offset < 3)\r
+ offset +=1;\r
+ // below\r
+ if ((cmb >= 10 && cmb <= 18) ||\r
+ cmb == 20 || cmb == 22 ||\r
+ cmb == 29 || cmb == 32)\r
+ cmb = HB_Combining_Below;\r
+ // above\r
+ else if (cmb == 23 || cmb == 27 || cmb == 28 ||\r
+ cmb == 30 || cmb == 31 || (cmb >= 33 && cmb <= 36))\r
+ cmb = HB_Combining_Above;\r
+ //below-right\r
+ else if (cmb == 9 || cmb == 103 || cmb == 118)\r
+ cmb = HB_Combining_BelowRight;\r
+ // above-right\r
+ else if (cmb == 24 || cmb == 107 || cmb == 122)\r
+ cmb = HB_Combining_AboveRight;\r
+ else if (cmb == 25)\r
+ cmb = HB_Combining_AboveLeft;\r
+ // fixed:\r
+ // 19 21\r
+\r
+ }\r
+\r
+ // combining marks of different class don't interact. Reset the rectangle.\r
+ if (cmb != lastCmb) {\r
+ //qDebug("resetting rect");\r
+ attachmentRect = baseMetrics;\r
+ }\r
+\r
+ switch(cmb) {\r
+ case HB_Combining_DoubleBelow:\r
+ // ### wrong in rtl context!\r
+ case HB_Combining_BelowLeft:\r
+ p.y += offset;\r
+ case HB_Combining_BelowLeftAttached:\r
+ p.x += attachmentRect.x - markMetrics.x;\r
+ p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y;\r
+ break;\r
+ case HB_Combining_Below:\r
+ p.y += offset;\r
+ case HB_Combining_BelowAttached:\r
+ p.x += attachmentRect.x - markMetrics.x;\r
+ p.y += (attachmentRect.y + attachmentRect.height) - markMetrics.y;\r
+\r
+ p.x += (attachmentRect.width - markMetrics.width) / 2;\r
+ break;\r
+ case HB_Combining_BelowRight:\r
+ p.y += offset;\r
+ case HB_Combining_BelowRightAttached:\r
+ p.x += attachmentRect.x + attachmentRect.width - markMetrics.width - markMetrics.x;\r
+ p.y += attachmentRect.y + attachmentRect.height - markMetrics.y;\r
+ break;\r
+ case HB_Combining_Left:\r
+ p.x -= offset;\r
+ case HB_Combining_LeftAttached:\r
+ break;\r
+ case HB_Combining_Right:\r
+ p.x += offset;\r
+ case HB_Combining_RightAttached:\r
+ break;\r
+ case HB_Combining_DoubleAbove:\r
+ // ### wrong in RTL context!\r
+ case HB_Combining_AboveLeft:\r
+ p.y -= offset;\r
+ case HB_Combining_AboveLeftAttached:\r
+ p.x += attachmentRect.x - markMetrics.x;\r
+ p.y += attachmentRect.y - markMetrics.y - markMetrics.height;\r
+ break;\r
+ case HB_Combining_Above:\r
+ p.y -= offset;\r
+ case HB_Combining_AboveAttached:\r
+ p.x += attachmentRect.x - markMetrics.x;\r
+ p.y += attachmentRect.y - markMetrics.y - markMetrics.height;\r
+\r
+ p.x += (attachmentRect.width - markMetrics.width) / 2;\r
+ break;\r
+ case HB_Combining_AboveRight:\r
+ p.y -= offset;\r
+ case HB_Combining_AboveRightAttached:\r
+ p.x += attachmentRect.x + attachmentRect.width - markMetrics.x - markMetrics.width;\r
+ p.y += attachmentRect.y - markMetrics.y - markMetrics.height;\r
+ break;\r
+\r
+ case HB_Combining_IotaSubscript:\r
+ default:\r
+ break;\r
+ }\r
+// qDebug("char=%x combiningClass = %d offset=%f/%f", mark, cmb, p.x(), p.y());\r
+ markMetrics.x += p.x;\r
+ markMetrics.y += p.y;\r
+\r
+ unitedAttachmentRect.x = HB_MIN(attachmentRect.x, markMetrics.x);\r
+ unitedAttachmentRect.y = HB_MIN(attachmentRect.y, markMetrics.y);\r
+ unitedAttachmentRect.width = HB_MAX(attachmentRect.x + attachmentRect.width, markMetrics.x + markMetrics.width) - unitedAttachmentRect.x;\r
+ unitedAttachmentRect.height = HB_MAX(attachmentRect.y + attachmentRect.height, markMetrics.y + markMetrics.height) - unitedAttachmentRect.y;\r
+ attachmentRect = unitedAttachmentRect;\r
+\r
+ lastCmb = cmb;\r
+ if (rightToLeft) {\r
+ item->offsets[gfrom+i].x = p.x;\r
+ item->offsets[gfrom+i].y = p.y;\r
+ } else {\r
+ item->offsets[gfrom+i].x = p.x - baseMetrics.xOffset;\r
+ item->offsets[gfrom+i].y = p.y - baseMetrics.yOffset;\r
+ }\r
+ item->advances[gfrom+i] = 0;\r
+ }\r
+}\r
+\r
+void HB_HeuristicPosition(HB_ShaperItem *item)\r
+{\r
+ HB_GetGlyphAdvances(item);\r
+ HB_GlyphAttributes *attributes = item->attributes;\r
+\r
+ int cEnd = -1;\r
+ int i = item->num_glyphs;\r
+ while (i--) {\r
+ if (cEnd == -1 && attributes[i].mark) {\r
+ cEnd = i;\r
+ } else if (cEnd != -1 && !attributes[i].mark) {\r
+ positionCluster(item, i, cEnd);\r
+ cEnd = -1;\r
+ }\r
+ }\r
+}\r
+\r
+// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs\r
+// and no reordering.\r
+// also computes logClusters heuristically\r
+void HB_HeuristicSetGlyphAttributes(HB_ShaperItem *item)\r
+{\r
+ const HB_UChar16 *uc = item->string + item->item.pos;\r
+ hb_uint32 length = item->item.length;\r
+\r
+ // ### zeroWidth and justification are missing here!!!!!\r
+\r
+ assert(item->num_glyphs <= length);\r
+\r
+// qDebug("QScriptEngine::heuristicSetGlyphAttributes, num_glyphs=%d", item->num_glyphs);\r
+ HB_GlyphAttributes *attributes = item->attributes;\r
+ unsigned short *logClusters = item->log_clusters;\r
+\r
+ hb_uint32 glyph_pos = 0;\r
+ hb_uint32 i;\r
+ int cStart = 0;\r
+ const bool symbolFont = item->face->isSymbolFont;\r
+ \r
+ for (i = 0; i < length; i++) {\r
+ if (HB_IsHighSurrogate(uc[i]) && i < length - 1\r
+ && HB_IsLowSurrogate(uc[i + 1])) {\r
+ logClusters[i] = glyph_pos;\r
+ logClusters[++i] = glyph_pos;\r
+ } else {\r
+ logClusters[i] = glyph_pos;\r
+ }\r
+ ++glyph_pos;\r
+ }\r
+ assert(glyph_pos == item->num_glyphs);\r
+\r
+ // first char in a run is never (treated as) a mark\r
+ attributes[0].mark = false;\r
+ attributes[0].clusterStart = true;\r
+ attributes[0].dontPrint = (!symbolFont && uc[0] == 0x00ad) || HB_IsControlChar(uc[0]);\r
+\r
+ int pos = 0;\r
+ HB_CharCategory lastCat;\r
+ int dummy;\r
+ HB_GetUnicodeCharProperties(uc[0], &lastCat, &dummy);\r
+ for (i = 1; i < length; ++i) {\r
+ if (logClusters[i] == pos)\r
+ // same glyph\r
+ continue;\r
+ ++pos;\r
+ while (pos < logClusters[i]) {\r
+ attributes[pos] = attributes[pos-1];\r
+ ++pos;\r
+ }\r
+ // hide soft-hyphens by default\r
+ if ((!symbolFont && uc[i] == 0x00ad) || HB_IsControlChar(uc[i]))\r
+ attributes[pos].dontPrint = true;\r
+ HB_CharCategory cat;\r
+ int cmb;\r
+ HB_GetUnicodeCharProperties(uc[i], &cat, &cmb);\r
+ if (cat != HB_Mark_NonSpacing) {\r
+ attributes[pos].mark = false;\r
+ attributes[pos].clusterStart = true;\r
+ attributes[pos].combiningClass = 0;\r
+ cStart = logClusters[i];\r
+ } else {\r
+ if (cmb == 0) {\r
+ // Fix 0 combining classes\r
+ if ((uc[pos] & 0xff00) == 0x0e00) {\r
+ // thai or lao\r
+ if (uc[pos] == 0xe31 ||\r
+ uc[pos] == 0xe34 ||\r
+ uc[pos] == 0xe35 ||\r
+ uc[pos] == 0xe36 ||\r
+ uc[pos] == 0xe37 ||\r
+ uc[pos] == 0xe47 ||\r
+ uc[pos] == 0xe4c ||\r
+ uc[pos] == 0xe4d ||\r
+ uc[pos] == 0xe4e) {\r
+ cmb = HB_Combining_AboveRight;\r
+ } else if (uc[pos] == 0xeb1 ||\r
+ uc[pos] == 0xeb4 ||\r
+ uc[pos] == 0xeb5 ||\r
+ uc[pos] == 0xeb6 ||\r
+ uc[pos] == 0xeb7 ||\r
+ uc[pos] == 0xebb ||\r
+ uc[pos] == 0xecc ||\r
+ uc[pos] == 0xecd) {\r
+ cmb = HB_Combining_Above;\r
+ } else if (uc[pos] == 0xebc) {\r
+ cmb = HB_Combining_Below;\r
+ }\r
+ }\r
+ }\r
+\r
+ attributes[pos].mark = true;\r
+ attributes[pos].clusterStart = false;\r
+ attributes[pos].combiningClass = cmb;\r
+ logClusters[i] = cStart;\r
+ }\r
+ // one gets an inter character justification point if the current char is not a non spacing mark.\r
+ // as then the current char belongs to the last one and one gets a space justification point\r
+ // after the space char.\r
+ if (lastCat == HB_Separator_Space)\r
+ attributes[pos-1].justification = HB_Space;\r
+ else if (cat != HB_Mark_NonSpacing)\r
+ attributes[pos-1].justification = HB_Character;\r
+ else\r
+ attributes[pos-1].justification = HB_NoJustification;\r
+\r
+ lastCat = cat;\r
+ }\r
+ pos = logClusters[length-1];\r
+ if (lastCat == HB_Separator_Space)\r
+ attributes[pos].justification = HB_Space;\r
+ else\r
+ attributes[pos].justification = HB_Character;\r
+}\r
+\r
+#ifndef NO_OPENTYPE\r
+static const HB_OpenTypeFeature basic_features[] = {\r
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },\r
+ { HB_MAKE_TAG('l', 'i', 'g', 'a'), CcmpProperty },\r
+ { HB_MAKE_TAG('c', 'l', 'i', 'g'), CcmpProperty },\r
+ {0, 0}\r
+};\r
+#endif\r
+\r
+HB_Bool HB_ConvertStringToGlyphIndices(HB_ShaperItem *shaper_item)\r
+{\r
+ if (shaper_item->glyphIndicesPresent) {\r
+ shaper_item->num_glyphs = shaper_item->initialGlyphCount;\r
+ shaper_item->glyphIndicesPresent = false;\r
+ return true;\r
+ }\r
+ return shaper_item->font->klass\r
+ ->convertStringToGlyphIndices(shaper_item->font,\r
+ shaper_item->string + shaper_item->item.pos, shaper_item->item.length,\r
+ shaper_item->glyphs, &shaper_item->num_glyphs,\r
+ shaper_item->item.bidiLevel % 2);\r
+}\r
+\r
+HB_Bool HB_BasicShape(HB_ShaperItem *shaper_item)\r
+{\r
+#ifndef NO_OPENTYPE\r
+ const int availableGlyphs = shaper_item->num_glyphs;\r
+#endif\r
+\r
+ if (!HB_ConvertStringToGlyphIndices(shaper_item))\r
+ return false;\r
+\r
+ HB_HeuristicSetGlyphAttributes(shaper_item);\r
+\r
+#ifndef NO_OPENTYPE\r
+ if (HB_SelectScript(shaper_item, basic_features)) {\r
+ HB_OpenTypeShape(shaper_item, /*properties*/0);\r
+ return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/true);\r
+ }\r
+#endif\r
+\r
+ HB_HeuristicPosition(shaper_item);\r
+ return true;\r
+}\r
+\r
+const HB_ScriptEngine HB_ScriptEngines[] = {\r
+ // Common\r
+ { HB_BasicShape, 0},\r
+ // Greek\r
+ { HB_BasicShape, 0},\r
+ // Cyrillic\r
+ { HB_BasicShape, 0},\r
+ // Armenian\r
+ { HB_BasicShape, 0},\r
+ // Hebrew\r
+ { HB_HebrewShape, 0 },\r
+ // Arabic\r
+ { HB_ArabicShape, 0},\r
+ // Syriac\r
+ { HB_ArabicShape, 0},\r
+ // Thaana\r
+ { HB_BasicShape, 0 },\r
+ // Devanagari\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Bengali\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Gurmukhi\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Gujarati\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Oriya\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Tamil\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Telugu\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Kannada\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Malayalam\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Sinhala\r
+ { HB_IndicShape, HB_IndicAttributes },\r
+ // Thai\r
+ { HB_BasicShape, HB_ThaiAttributes },\r
+ // Lao\r
+ { HB_BasicShape, 0 },\r
+ // Tibetan\r
+ { HB_TibetanShape, HB_TibetanAttributes },\r
+ // Myanmar\r
+ { HB_MyanmarShape, HB_MyanmarAttributes },\r
+ // Georgian\r
+ { HB_BasicShape, 0 },\r
+ // Hangul\r
+ { HB_HangulShape, 0 },\r
+ // Ogham\r
+ { HB_BasicShape, 0 },\r
+ // Runic\r
+ { HB_BasicShape, 0 },\r
+ // Khmer\r
+ { HB_KhmerShape, HB_KhmerAttributes },\r
+ // N'Ko\r
+ { HB_ArabicShape, 0}\r
+};\r
+\r
+void HB_GetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,\r
+ const HB_ScriptItem *items, hb_uint32 numItems,\r
+ HB_CharAttributes *attributes)\r
+{\r
+ hb_uint32 i ;\r
+ calcLineBreaks(string, stringLength, attributes);\r
+\r
+ for (i = 0; i < numItems; ++i) {\r
+ HB_Script script = items[i].script;\r
+ HB_AttributeFunction attributeFunction = NULL ;\r
+ if (script == HB_Script_Inherited)\r
+ script = HB_Script_Common;\r
+ attributeFunction = HB_ScriptEngines[script].charAttributes;\r
+ if (!attributeFunction)\r
+ continue;\r
+ attributeFunction(script, string, items[i].pos, items[i].length, attributes);\r
+ }\r
+}\r
+\r
+\r
+enum _BreakRule { NoBreak = 0, Break = 1, Middle = 2 };\r
+typedef enum _BreakRule BreakRule ;\r
+\r
+static const hb_uint8 wordbreakTable[HB_Word_ExtendNumLet + 1][HB_Word_ExtendNumLet + 1] = {\r
+// Other Format Katakana ALetter MidLetter MidNum Numeric ExtendNumLet\r
+ { Break, Break, Break, Break, Break, Break, Break, Break }, // Other\r
+ { Break, Break, Break, Break, Break, Break, Break, Break }, // Format \r
+ { Break, Break, NoBreak, Break, Break, Break, Break, NoBreak }, // Katakana\r
+ { Break, Break, Break, NoBreak, Middle, Break, NoBreak, NoBreak }, // ALetter\r
+ { Break, Break, Break, Break, Break, Break, Break, Break }, // MidLetter\r
+ { Break, Break, Break, Break, Break, Break, Break, Break }, // MidNum\r
+ { Break, Break, Break, NoBreak, Break, Middle, NoBreak, NoBreak }, // Numeric\r
+ { Break, Break, NoBreak, NoBreak, Break, Break, NoBreak, NoBreak }, // ExtendNumLet\r
+};\r
+\r
+void HB_GetWordBoundaries(const HB_UChar16 *string, hb_uint32 stringLength,\r
+ const HB_ScriptItem * items, hb_uint32 numItems,\r
+ HB_CharAttributes *attributes)\r
+{\r
+ hb_uint32 i;\r
+ if (stringLength == 0)\r
+ return;\r
+ unsigned int brk = HB_GetWordClass(string[0]);\r
+ attributes[0].wordBoundary = true;\r
+ for ( i = 1; i < stringLength; ++i) {\r
+ hb_uint32 nbrk=0;\r
+ BreakRule rule;\r
+ if (!attributes[i].charStop) {\r
+ attributes[i].wordBoundary = false;\r
+ continue;\r
+ }\r
+ nbrk = HB_GetWordClass(string[i]);\r
+ if (nbrk == HB_Word_Format) {\r
+ attributes[i].wordBoundary = (HB_GetSentenceClass(string[i-1]) == HB_Sentence_Sep);\r
+ continue;\r
+ }\r
+ rule = (BreakRule)wordbreakTable[brk][nbrk];\r
+ if (rule == Middle) {\r
+ rule = Break;\r
+ hb_uint32 lookahead = i + 1;\r
+ while (lookahead < stringLength) {\r
+ hb_uint32 testbrk = HB_GetWordClass(string[lookahead]);\r
+ if (testbrk == HB_Word_Format && HB_GetSentenceClass(string[lookahead]) != HB_Sentence_Sep) {\r
+ ++lookahead;\r
+ continue;\r
+ }\r
+ if (testbrk == brk) {\r
+ rule = NoBreak;\r
+ while (i < lookahead)\r
+ attributes[i++].wordBoundary = false;\r
+ nbrk = testbrk;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ attributes[i].wordBoundary = (rule == Break);\r
+ brk = nbrk;\r
+ }\r
+}\r
+\r
+\r
+enum SentenceBreakStates {\r
+ SB_Initial,\r
+ SB_Upper,\r
+ SB_UpATerm, \r
+ SB_ATerm,\r
+ SB_ATermC, \r
+ SB_ACS, \r
+ SB_STerm, \r
+ SB_STermC, \r
+ SB_SCS,\r
+ SB_BAfter, \r
+ SB_Break,\r
+ SB_Look\r
+};\r
+\r
+static const hb_uint8 sentenceBreakTable[HB_Sentence_Close + 1][HB_Sentence_Close + 1] = {\r
+// Other Sep Format Sp Lower Upper OLetter Numeric ATerm STerm Close\r
+ { SB_Initial, SB_BAfter , SB_Initial, SB_Initial, SB_Initial, SB_Upper , SB_Initial, SB_Initial, SB_ATerm , SB_STerm , SB_Initial }, // SB_Initial,\r
+ { SB_Initial, SB_BAfter , SB_Upper , SB_Initial, SB_Initial, SB_Upper , SB_Initial, SB_Initial, SB_UpATerm, SB_STerm , SB_Initial }, // SB_Upper\r
+ \r
+ { SB_Look , SB_BAfter , SB_UpATerm, SB_ACS , SB_Initial, SB_Upper , SB_Break , SB_Initial, SB_ATerm , SB_STerm , SB_ATermC }, // SB_UpATerm\r
+ { SB_Look , SB_BAfter , SB_ATerm , SB_ACS , SB_Initial, SB_Break , SB_Break , SB_Initial, SB_ATerm , SB_STerm , SB_ATermC }, // SB_ATerm\r
+ { SB_Look , SB_BAfter , SB_ATermC , SB_ACS , SB_Initial, SB_Break , SB_Break , SB_Look , SB_ATerm , SB_STerm , SB_ATermC }, // SB_ATermC,\r
+ { SB_Look , SB_BAfter , SB_ACS , SB_ACS , SB_Initial, SB_Break , SB_Break , SB_Look , SB_ATerm , SB_STerm , SB_Look }, // SB_ACS,\r
+ \r
+ { SB_Break , SB_BAfter , SB_STerm , SB_SCS , SB_Break , SB_Break , SB_Break , SB_Break , SB_ATerm , SB_STerm , SB_STermC }, // SB_STerm,\r
+ { SB_Break , SB_BAfter , SB_STermC , SB_SCS , SB_Break , SB_Break , SB_Break , SB_Break , SB_ATerm , SB_STerm , SB_STermC }, // SB_STermC,\r
+ { SB_Break , SB_BAfter , SB_SCS , SB_SCS , SB_Break , SB_Break , SB_Break , SB_Break , SB_ATerm , SB_STerm , SB_Break }, // SB_SCS,\r
+ { SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break , SB_Break }, // SB_BAfter,\r
+};\r
+\r
+void HB_GetSentenceBoundaries(const HB_UChar16 *string, hb_uint32 stringLength,\r
+ const HB_ScriptItem * items, hb_uint32 numItems,\r
+ HB_CharAttributes *attributes)\r
+{\r
+ hb_uint32 i;\r
+ if (stringLength == 0)\r
+ return;\r
+ hb_uint32 brk = sentenceBreakTable[SB_Initial][HB_GetSentenceClass(string[0])];\r
+ attributes[0].sentenceBoundary = true;\r
+ for (i = 1; i < stringLength; ++i) {\r
+ if (!attributes[i].charStop) {\r
+ attributes[i].sentenceBoundary = false;\r
+ continue;\r
+ }\r
+ brk = sentenceBreakTable[brk][HB_GetSentenceClass(string[i])];\r
+ if (brk == SB_Look) {\r
+ hb_uint32 lookahead = i + 1;\r
+ brk = SB_Break;\r
+ while (lookahead < stringLength) {\r
+ hb_uint32 sbrk = HB_GetSentenceClass(string[lookahead]);\r
+ if (sbrk != HB_Sentence_Other && sbrk != HB_Sentence_Numeric && sbrk != HB_Sentence_Close) {\r
+ break;\r
+ } else if (sbrk == HB_Sentence_Lower) {\r
+ brk = SB_Initial;\r
+ break;\r
+ }\r
+ ++lookahead;\r
+ }\r
+ if (brk == SB_Initial) {\r
+ while (i < lookahead)\r
+ attributes[i++].sentenceBoundary = false;\r
+ }\r
+ }\r
+ if (brk == SB_Break) {\r
+ attributes[i].sentenceBoundary = true;\r
+ brk = sentenceBreakTable[SB_Initial][HB_GetSentenceClass(string[i])];\r
+ } else {\r
+ attributes[i].sentenceBoundary = false;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+static inline char *tag_to_string(HB_UInt tag)\r
+{\r
+ static char string[5];\r
+ string[0] = (tag >> 24)&0xff;\r
+ string[1] = (tag >> 16)&0xff;\r
+ string[2] = (tag >> 8)&0xff;\r
+ string[3] = tag&0xff;\r
+ string[4] = 0;\r
+ return string;\r
+}\r
+\r
+#ifdef OT_DEBUG\r
+static void dump_string(HB_Buffer buffer)\r
+{\r
+ for (uint i = 0; i < buffer->in_length; ++i) {\r
+ qDebug(" %x: cluster=%d", buffer->in_string[i].gindex, buffer->in_string[i].cluster);\r
+ }\r
+}\r
+#define DEBUG printf\r
+#else\r
+#define DEBUG if (1) ; else printf\r
+#endif\r
+\r
+#define DefaultLangSys 0xffff\r
+#define DefaultScript HB_MAKE_TAG('D', 'F', 'L', 'T')\r
+\r
+enum {\r
+ RequiresGsub = 1,\r
+ RequiresGpos = 2\r
+};\r
+\r
+struct _OTScripts {\r
+ unsigned int tag;\r
+ int flags;\r
+};\r
+\r
+typedef struct _OTScripts OTScripts;\r
+\r
+static const OTScripts ot_scripts [] = {\r
+ // Common\r
+ { HB_MAKE_TAG('l', 'a', 't', 'n'), 0 },\r
+ // Greek\r
+ { HB_MAKE_TAG('g', 'r', 'e', 'k'), 0 },\r
+ // Cyrillic\r
+ { HB_MAKE_TAG('c', 'y', 'r', 'l'), 0 },\r
+ // Armenian\r
+ { HB_MAKE_TAG('a', 'r', 'm', 'n'), 0 },\r
+ // Hebrew\r
+ { HB_MAKE_TAG('h', 'e', 'b', 'r'), 1 },\r
+ // Arabic\r
+ { HB_MAKE_TAG('a', 'r', 'a', 'b'), 1 },\r
+ // Syriac\r
+ { HB_MAKE_TAG('s', 'y', 'r', 'c'), 1 },\r
+ // Thaana\r
+ { HB_MAKE_TAG('t', 'h', 'a', 'a'), 1 },\r
+ // Devanagari\r
+ { HB_MAKE_TAG('d', 'e', 'v', 'a'), 1 },\r
+ // Bengali\r
+ { HB_MAKE_TAG('b', 'e', 'n', 'g'), 1 },\r
+ // Gurmukhi\r
+ { HB_MAKE_TAG('g', 'u', 'r', 'u'), 1 },\r
+ // Gujarati\r
+ { HB_MAKE_TAG('g', 'u', 'j', 'r'), 1 },\r
+ // Oriya\r
+ { HB_MAKE_TAG('o', 'r', 'y', 'a'), 1 },\r
+ // Tamil\r
+ { HB_MAKE_TAG('t', 'a', 'm', 'l'), 1 },\r
+ // Telugu\r
+ { HB_MAKE_TAG('t', 'e', 'l', 'u'), 1 },\r
+ // Kannada\r
+ { HB_MAKE_TAG('k', 'n', 'd', 'a'), 1 },\r
+ // Malayalam\r
+ { HB_MAKE_TAG('m', 'l', 'y', 'm'), 1 },\r
+ // Sinhala\r
+ { HB_MAKE_TAG('s', 'i', 'n', 'h'), 1 },\r
+ // Thai\r
+ { HB_MAKE_TAG('t', 'h', 'a', 'i'), 1 },\r
+ // Lao\r
+ { HB_MAKE_TAG('l', 'a', 'o', ' '), 1 },\r
+ // Tibetan\r
+ { HB_MAKE_TAG('t', 'i', 'b', 't'), 1 },\r
+ // Myanmar\r
+ { HB_MAKE_TAG('m', 'y', 'm', 'r'), 1 },\r
+ // Georgian\r
+ { HB_MAKE_TAG('g', 'e', 'o', 'r'), 0 },\r
+ // Hangul\r
+ { HB_MAKE_TAG('h', 'a', 'n', 'g'), 1 },\r
+ // Ogham\r
+ { HB_MAKE_TAG('o', 'g', 'a', 'm'), 0 },\r
+ // Runic\r
+ { HB_MAKE_TAG('r', 'u', 'n', 'r'), 0 },\r
+ // Khmer\r
+ { HB_MAKE_TAG('k', 'h', 'm', 'r'), 1 },\r
+ // N'Ko\r
+ { HB_MAKE_TAG('n', 'k', 'o', ' '), 1 }\r
+};\r
+enum { NumOTScripts = sizeof(ot_scripts)/sizeof(OTScripts) };\r
+\r
+static HB_Bool checkScript(HB_Face face, int script)\r
+{\r
+ assert(script < HB_ScriptCount);\r
+\r
+ if (!face->gsub && !face->gpos)\r
+ return false;\r
+\r
+ unsigned int tag = ot_scripts[script].tag;\r
+ int requirements = ot_scripts[script].flags;\r
+\r
+ if (requirements & RequiresGsub) {\r
+ if (!face->gsub)\r
+ return false;\r
+\r
+ HB_UShort script_index;\r
+ HB_Error error = HB_GSUB_Select_Script(face->gsub, tag, &script_index);\r
+ if (error) {\r
+ DEBUG("could not select script %d in GSub table: %d", (int)script, error);\r
+ error = HB_GSUB_Select_Script(face->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &script_index);\r
+ if (error)\r
+ return false;\r
+ }\r
+ }\r
+\r
+ if (requirements & RequiresGpos) {\r
+ if (!face->gpos)\r
+ return false;\r
+\r
+ HB_UShort script_index;\r
+ HB_Error error = HB_GPOS_Select_Script(face->gpos, script, &script_index);\r
+ if (error) {\r
+ DEBUG("could not select script in gpos table: %d", error);\r
+ error = HB_GPOS_Select_Script(face->gpos, HB_MAKE_TAG('D', 'F', 'L', 'T'), &script_index);\r
+ if (error)\r
+ return false;\r
+ }\r
+\r
+ }\r
+ return true;\r
+}\r
+\r
+static HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Tag tag)\r
+{\r
+ HB_Error error;\r
+ HB_UInt length = 0;\r
+ HB_Stream stream = 0;\r
+\r
+ if (!font)\r
+ return 0;\r
+\r
+ error = tableFunc(font, tag, 0, &length);\r
+ if (error)\r
+ return 0;\r
+ stream = (HB_Stream)malloc(sizeof(HB_StreamRec));\r
+ if (!stream)\r
+ return 0;\r
+ stream->base = (HB_Byte*)malloc(length);\r
+ if (!stream->base) {\r
+ free(stream);\r
+ return 0;\r
+ }\r
+ error = tableFunc(font, tag, stream->base, &length);\r
+ if (error) {\r
+ _hb_close_stream(stream);\r
+ return 0;\r
+ }\r
+ stream->size = length;\r
+ stream->pos = 0;\r
+ stream->cursor = NULL;\r
+ return stream;\r
+}\r
+\r
+HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc)\r
+{\r
+ unsigned int i;\r
+ HB_Face face = (HB_Face )malloc(sizeof(HB_FaceRec));\r
+ HB_Error error;\r
+ HB_Stream stream;\r
+ HB_Stream gdefStream;\r
+ \r
+ if (!face)\r
+ return 0;\r
+\r
+ face->isSymbolFont = false;\r
+ face->gdef = 0;\r
+ face->gpos = 0;\r
+ face->gsub = 0;\r
+ face->current_script = HB_ScriptCount;\r
+ face->current_flags = HB_ShaperFlag_Default;\r
+ face->has_opentype_kerning = false;\r
+ face->tmpAttributes = 0;\r
+ face->tmpLogClusters = 0;\r
+ face->glyphs_substituted = false;\r
+ face->buffer = 0;\r
+\r
+ gdefStream = getTableStream(font, tableFunc, TTAG_GDEF);\r
+ if (!gdefStream || (error = HB_Load_GDEF_Table(gdefStream, &face->gdef))) {\r
+ //DEBUG("error loading gdef table: %d", error);\r
+ face->gdef = 0;\r
+ }\r
+\r
+ //DEBUG() << "trying to load gsub table";\r
+ stream = getTableStream(font, tableFunc, TTAG_GSUB);\r
+ if (!stream || (error = HB_Load_GSUB_Table(stream, &face->gsub, face->gdef, gdefStream))) {\r
+ face->gsub = 0;\r
+ if (error != HB_Err_Not_Covered) {\r
+ //DEBUG("error loading gsub table: %d", error);\r
+ } else {\r
+ //DEBUG("face doesn't have a gsub table");\r
+ }\r
+ }\r
+ _hb_close_stream(stream);\r
+\r
+ stream = getTableStream(font, tableFunc, TTAG_GPOS);\r
+ if (!stream || (error = HB_Load_GPOS_Table(stream, &face->gpos, face->gdef, gdefStream))) {\r
+ face->gpos = 0;\r
+ DEBUG("error loading gpos table: %d", error);\r
+ }\r
+ _hb_close_stream(stream);\r
+\r
+ _hb_close_stream(gdefStream);\r
+\r
+ for (i = 0; i < HB_ScriptCount; ++i)\r
+ face->supported_scripts[i] = checkScript(face, i);\r
+\r
+ if (hb_buffer_new(&face->buffer) != HB_Err_Ok) {\r
+ HB_FreeFace(face);\r
+ return 0;\r
+ }\r
+\r
+ return face;\r
+}\r
+\r
+void HB_FreeFace(HB_Face face)\r
+{\r
+ if (!face)\r
+ return;\r
+ if (face->gpos)\r
+ HB_Done_GPOS_Table(face->gpos);\r
+ if (face->gsub)\r
+ HB_Done_GSUB_Table(face->gsub);\r
+ if (face->gdef)\r
+ HB_Done_GDEF_Table(face->gdef);\r
+ if (face->buffer)\r
+ hb_buffer_free(face->buffer);\r
+ if (face->tmpAttributes)\r
+ free(face->tmpAttributes);\r
+ if (face->tmpLogClusters)\r
+ free(face->tmpLogClusters);\r
+ free(face);\r
+}\r
+\r
+HB_Bool HB_SelectScript(HB_ShaperItem *shaper_item, const HB_OpenTypeFeature *features)\r
+{\r
+ HB_Script script = shaper_item->item.script;\r
+\r
+ if (!shaper_item->face->supported_scripts[script])\r
+ return false;\r
+\r
+ HB_Face face = shaper_item->face;\r
+ if (face->current_script == script && face->current_flags == shaper_item->shaperFlags)\r
+ return true;\r
+\r
+ face->current_script = script;\r
+ face->current_flags = shaper_item->shaperFlags;\r
+\r
+ assert(script < HB_ScriptCount);\r
+ // find script in our list of supported scripts.\r
+ unsigned int tag = ot_scripts[script].tag;\r
+\r
+ if (face->gsub && features) {\r
+#ifdef OT_DEBUG\r
+ {\r
+ HB_FeatureList featurelist = face->gsub->FeatureList;\r
+ int numfeatures = featurelist.FeatureCount;\r
+ DEBUG("gsub table has %d features", numfeatures);\r
+ for (int i = 0; i < numfeatures; i++) {\r
+ HB_FeatureRecord *r = featurelist.FeatureRecord + i;\r
+ DEBUG(" feature '%s'", tag_to_string(r->FeatureTag));\r
+ }\r
+ }\r
+#endif\r
+ HB_GSUB_Clear_Features(face->gsub);\r
+ HB_UShort script_index;\r
+ HB_Error error = HB_GSUB_Select_Script(face->gsub, tag, &script_index);\r
+ if (!error) {\r
+ DEBUG("script %s has script index %d", tag_to_string(script), script_index);\r
+ while (features->tag) {\r
+ HB_UShort feature_index;\r
+ error = HB_GSUB_Select_Feature(face->gsub, features->tag, script_index, 0xffff, &feature_index);\r
+ if (!error) {\r
+ DEBUG(" adding feature %s", tag_to_string(features->tag));\r
+ HB_GSUB_Add_Feature(face->gsub, feature_index, features->property);\r
+ }\r
+ ++features;\r
+ }\r
+ }\r
+ }\r
+\r
+ // reset\r
+ face->has_opentype_kerning = false;\r
+\r
+ if (face->gpos) {\r
+ HB_GPOS_Clear_Features(face->gpos);\r
+ HB_UShort script_index;\r
+ HB_Error error = HB_GPOS_Select_Script(face->gpos, tag, &script_index);\r
+ if (!error) {\r
+#ifdef OT_DEBUG\r
+ {\r
+ HB_FeatureList featurelist = face->gpos->FeatureList;\r
+ int numfeatures = featurelist.FeatureCount;\r
+ DEBUG("gpos table has %d features", numfeatures);\r
+ for(int i = 0; i < numfeatures; i++) {\r
+ HB_FeatureRecord *r = featurelist.FeatureRecord + i;\r
+ HB_UShort feature_index;\r
+ HB_GPOS_Select_Feature(face->gpos, r->FeatureTag, script_index, 0xffff, &feature_index);\r
+ DEBUG(" feature '%s'", tag_to_string(r->FeatureTag));\r
+ }\r
+ }\r
+#endif\r
+ HB_UInt *feature_tag_list_buffer;\r
+ error = HB_GPOS_Query_Features(face->gpos, script_index, 0xffff, &feature_tag_list_buffer);\r
+ if (!error) {\r
+ HB_UInt *feature_tag_list = feature_tag_list_buffer;\r
+ while (*feature_tag_list) {\r
+ HB_UShort feature_index;\r
+ if (*feature_tag_list == HB_MAKE_TAG('k', 'e', 'r', 'n')) {\r
+ if (face->current_flags & HB_ShaperFlag_NoKerning) {\r
+ ++feature_tag_list;\r
+ continue;\r
+ }\r
+ face->has_opentype_kerning = true;\r
+ }\r
+ error = HB_GPOS_Select_Feature(face->gpos, *feature_tag_list, script_index, 0xffff, &feature_index);\r
+ if (!error)\r
+ HB_GPOS_Add_Feature(face->gpos, feature_index, PositioningProperties);\r
+ ++feature_tag_list;\r
+ }\r
+ FREE(feature_tag_list_buffer);\r
+ }\r
+ }\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+HB_Bool HB_OpenTypeShape(HB_ShaperItem *item, const hb_uint32 *properties)\r
+{\r
+ HB_GlyphAttributes *tmpAttributes;\r
+ unsigned int *tmpLogClusters;\r
+ int i ;\r
+\r
+ HB_Face face = item->face;\r
+\r
+ face->length = item->num_glyphs;\r
+\r
+ hb_buffer_clear(face->buffer);\r
+\r
+ tmpAttributes = (HB_GlyphAttributes *) realloc(face->tmpAttributes, face->length*sizeof(HB_GlyphAttributes));\r
+ if (!tmpAttributes)\r
+ return false;\r
+ face->tmpAttributes = tmpAttributes;\r
+\r
+ tmpLogClusters = (unsigned int *) realloc(face->tmpLogClusters, face->length*sizeof(unsigned int));\r
+ if (!tmpLogClusters)\r
+ return false;\r
+ face->tmpLogClusters = tmpLogClusters;\r
+\r
+ for (i = 0; i < face->length; ++i) {\r
+ hb_buffer_add_glyph(face->buffer, item->glyphs[i], properties ? properties[i] : 0, i);\r
+ face->tmpAttributes[i] = item->attributes[i];\r
+ face->tmpLogClusters[i] = item->log_clusters[i];\r
+ }\r
+\r
+#ifdef OT_DEBUG\r
+ DEBUG("-----------------------------------------");\r
+// DEBUG("log clusters before shaping:");\r
+// for (int j = 0; j < length; j++)\r
+// DEBUG(" log[%d] = %d", j, item->log_clusters[j]);\r
+ DEBUG("original glyphs: %p", item->glyphs);\r
+ for (int i = 0; i < length; ++i)\r
+ DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex);\r
+// dump_string(hb_buffer);\r
+#endif\r
+\r
+ face->glyphs_substituted = false;\r
+ if (face->gsub) {\r
+ unsigned int error = HB_GSUB_Apply_String(face->gsub, face->buffer);\r
+ if (error && error != HB_Err_Not_Covered)\r
+ return false;\r
+ face->glyphs_substituted = (error != HB_Err_Not_Covered);\r
+ }\r
+\r
+#ifdef OT_DEBUG\r
+// DEBUG("log clusters before shaping:");\r
+// for (int j = 0; j < length; j++)\r
+// DEBUG(" log[%d] = %d", j, item->log_clusters[j]);\r
+ DEBUG("shaped glyphs:");\r
+ for (int i = 0; i < length; ++i)\r
+ DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex);\r
+ DEBUG("-----------------------------------------");\r
+// dump_string(hb_buffer);\r
+#endif\r
+\r
+ return true;\r
+}\r
+\r
+HB_Bool HB_OpenTypePosition(HB_ShaperItem *item, int availableGlyphs, HB_Bool doLogClusters)\r
+{\r
+ HB_Face face = item->face;\r
+ unsigned int i;\r
+ \r
+ HB_Glyph *glyphs = item->glyphs;\r
+ HB_GlyphAttributes *attributes = item->attributes;\r
+\r
+ bool glyphs_positioned = false;\r
+ if (face->gpos) {\r
+ if (face->buffer->positions)\r
+ memset(face->buffer->positions, 0, face->buffer->in_length*sizeof(HB_PositionRec));\r
+ // #### check that passing "false,false" is correct\r
+ glyphs_positioned = HB_GPOS_Apply_String(item->font, face->gpos, face->current_flags, face->buffer, false, false) != HB_Err_Not_Covered;\r
+ }\r
+\r
+ if (!face->glyphs_substituted && !glyphs_positioned) {\r
+ HB_GetGlyphAdvances(item);\r
+ return true; // nothing to do for us\r
+ }\r
+\r
+ // make sure we have enough space to write everything back\r
+ if (availableGlyphs < (int)face->buffer->in_length) {\r
+ item->num_glyphs = face->buffer->in_length;\r
+ return false;\r
+ }\r
+\r
+\r
+ for (i = 0; i < face->buffer->in_length; ++i) {\r
+ glyphs[i] = face->buffer->in_string[i].gindex;\r
+ attributes[i] = face->tmpAttributes[face->buffer->in_string[i].cluster];\r
+ if (i && face->buffer->in_string[i].cluster == face->buffer->in_string[i-1].cluster)\r
+ attributes[i].clusterStart = false;\r
+ }\r
+ item->num_glyphs = face->buffer->in_length;\r
+\r
+ if (doLogClusters && face->glyphs_substituted) {\r
+ unsigned int i;\r
+ int j;\r
+ // we can't do this for indic, as we pass the stuf in syllables and it's easier to do it in the shaper.\r
+ unsigned short *logClusters = item->log_clusters;\r
+ int clusterStart = 0;\r
+ int oldCi = 0;\r
+ // #### the reconstruction of the logclusters currently does not work if the original string\r
+ // contains surrogate pairs\r
+ for (i = 0; i < face->buffer->in_length; ++i) {\r
+ int ci = face->buffer->in_string[i].cluster;\r
+ // DEBUG(" ci[%d] = %d mark=%d, cmb=%d, cs=%d",\r
+ // i, ci, glyphAttributes[i].mark, glyphAttributes[i].combiningClass, glyphAttributes[i].clusterStart);\r
+ if (!attributes[i].mark && attributes[i].clusterStart && ci != oldCi) {\r
+ for ( j = oldCi; j < ci; j++)\r
+ logClusters[j] = clusterStart;\r
+ clusterStart = i;\r
+ oldCi = ci;\r
+ }\r
+ }\r
+ for (j = oldCi; j < face->length; j++)\r
+ logClusters[j] = clusterStart;\r
+ }\r
+\r
+ // calulate the advances for the shaped glyphs\r
+// DEBUG("unpositioned: ");\r
+\r
+ // positioning code:\r
+ if (glyphs_positioned) {\r
+ unsigned int i;\r
+ HB_Position positions = face->buffer->positions;\r
+ HB_Fixed *advances = item->advances;\r
+ HB_GetGlyphAdvances(item);\r
+\r
+// DEBUG("positioned glyphs:");\r
+ for (i = 0; i < face->buffer->in_length; i++) {\r
+// DEBUG(" %d:\t orig advance: (%d/%d)\tadv=(%d/%d)\tpos=(%d/%d)\tback=%d\tnew_advance=%d", i,\r
+// glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(),\r
+// (int)(positions[i].x_advance >> 6), (int)(positions[i].y_advance >> 6),\r
+// (int)(positions[i].x_pos >> 6), (int)(positions[i].y_pos >> 6),\r
+// positions[i].back, positions[i].new_advance);\r
+\r
+ HB_Fixed adjustment = (item->item.bidiLevel % 2) ? -positions[i].x_advance : positions[i].x_advance;\r
+\r
+ if (!(face->current_flags & HB_ShaperFlag_UseDesignMetrics))\r
+ adjustment = HB_FIXED_ROUND(adjustment);\r
+\r
+ if (positions[i].new_advance) {\r
+ advances[i] = adjustment;\r
+ } else {\r
+ advances[i] += adjustment;\r
+ }\r
+\r
+ int back = 0;\r
+ HB_FixedPoint *offsets = item->offsets;\r
+ offsets[i].x = positions[i].x_pos;\r
+ offsets[i].y = positions[i].y_pos;\r
+ while (positions[i - back].back) {\r
+ back += positions[i - back].back;\r
+ offsets[i].x += positions[i - back].x_pos;\r
+ offsets[i].y += positions[i - back].y_pos;\r
+ }\r
+ offsets[i].y = -offsets[i].y;\r
+\r
+ if (item->item.bidiLevel % 2) {\r
+ // ### may need to go back multiple glyphs like in ltr\r
+ back = positions[i].back;\r
+ while (back--)\r
+ offsets[i].x -= advances[i-back];\r
+ } else {\r
+ back = 0;\r
+ while (positions[i - back].back) {\r
+ back += positions[i - back].back;\r
+ offsets[i].x -= advances[i-back];\r
+ }\r
+ }\r
+// DEBUG(" ->\tadv=%d\tpos=(%d/%d)",\r
+// glyphs[i].advance.x.toInt(), glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt());\r
+ }\r
+ item->kerning_applied = face->has_opentype_kerning;\r
+ } else {\r
+ HB_HeuristicPosition(item);\r
+ }\r
+\r
+#ifdef OT_DEBUG\r
+ if (doLogClusters) {\r
+ DEBUG("log clusters after shaping:");\r
+ for (int j = 0; j < length; j++)\r
+ DEBUG(" log[%d] = %d", j, item->log_clusters[j]);\r
+ }\r
+ DEBUG("final glyphs:");\r
+ for (int i = 0; i < (int)hb_buffer->in_length; ++i)\r
+ DEBUG(" glyph=%4x char_index=%d mark: %d cmp: %d, clusterStart: %d advance=%d/%d offset=%d/%d",\r
+ glyphs[i].glyph, hb_buffer->in_string[i].cluster, glyphs[i].attributes.mark,\r
+ glyphs[i].attributes.combiningClass, glyphs[i].attributes.clusterStart,\r
+ glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(),\r
+ glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt());\r
+ DEBUG("-----------------------------------------");\r
+#endif\r
+ return true;\r
+}\r
+\r
+HB_Bool HB_ShapeItem(HB_ShaperItem *shaper_item)\r
+{\r
+ HB_Bool result = false;\r
+ if (shaper_item->num_glyphs < shaper_item->item.length) {\r
+ shaper_item->num_glyphs = shaper_item->item.length;\r
+ return false;\r
+ }\r
+ assert(shaper_item->item.script < HB_ScriptCount);\r
+ result = HB_ScriptEngines[shaper_item->item.script].shape(shaper_item);\r
+ shaper_item->glyphIndicesPresent = false;\r
+ return result;\r
+}\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ *\r
+ * Red Hat Author(s): Behdad Esfahbod\r
+ */\r
+\r
+#include "harfbuzz-impl.h"\r
+#include "harfbuzz-stream-private.h"\r
+#include <stdlib.h>\r
+\r
+#if 0\r
+#include <stdio.h>\r
+#define LOG(x) _hb_log x\r
+\r
+static void\r
+_hb_log( const char* format, ... )\r
+{\r
+ va_list ap;\r
+ \r
+ va_start( ap, format );\r
+ vfprintf( stderr, format, ap );\r
+ va_end( ap );\r
+}\r
+\r
+#else\r
+#define LOG(x) do {} while (0)\r
+#endif\r
+\r
+HB_INTERNAL void\r
+_hb_close_stream( HB_Stream stream )\r
+{\r
+ if (!stream)\r
+ return;\r
+ free(stream->base);\r
+ free(stream);\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Int\r
+_hb_stream_pos( HB_Stream stream )\r
+{\r
+ LOG(( "_hb_stream_pos() -> %ld\n", stream->pos ));\r
+ return stream->pos;\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_stream_seek( HB_Stream stream,\r
+ HB_UInt pos )\r
+{\r
+ HB_Error error = (HB_Error)0;\r
+\r
+ stream->pos = pos;\r
+ if (pos > stream->size)\r
+ error = ERR_HB(HB_Err_Read_Error);\r
+\r
+ LOG(( "_hb_stream_seek(%ld) -> 0x%04X\n", pos, error ));\r
+ return error;\r
+}\r
+\r
+\r
+HB_INTERNAL HB_Error\r
+_hb_stream_frame_enter( HB_Stream stream,\r
+ HB_UInt count )\r
+{\r
+ HB_Error error = HB_Err_Ok;\r
+\r
+ /* check new position, watch for overflow */\r
+ if (HB_UNLIKELY (stream->pos + count > stream->size ||\r
+ stream->pos + count < stream->pos))\r
+ {\r
+ error = ERR_HB(HB_Err_Read_Error);\r
+ goto Exit;\r
+ }\r
+\r
+ /* set cursor */\r
+ stream->cursor = stream->base + stream->pos;\r
+ stream->pos += count;\r
+\r
+Exit:\r
+ LOG(( "_hb_stream_frame_enter(%ld) -> 0x%04X\n", count, error ));\r
+ return error;\r
+}\r
+\r
+\r
+HB_INTERNAL void\r
+_hb_stream_frame_exit( HB_Stream stream )\r
+{\r
+ stream->cursor = NULL;\r
+\r
+ LOG(( "_hb_stream_frame_exit()\n" ));\r
+}\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+#include "harfbuzz-external.h"\r
+\r
+#include <assert.h>\r
+\r
+static void thaiWordBreaks(const HB_UChar16 *string, hb_uint32 len, HB_CharAttributes *attributes)\r
+{\r
+ typedef int (*th_brk_def)(const char*, int[], int);\r
+ static void *thaiCodec = 0;\r
+ static th_brk_def th_brk = 0;\r
+ char *cstr = 0;\r
+ int brp[128];\r
+ int *break_positions = brp;\r
+ hb_uint32 numbreaks;\r
+ hb_uint32 i;\r
+\r
+ if (!thaiCodec)\r
+ thaiCodec = HB_TextCodecForMib(2259);\r
+\r
+ /* load libthai dynamically */\r
+ if (!th_brk && thaiCodec) {\r
+ th_brk = (th_brk_def)HB_Library_Resolve("thai", "th_brk");\r
+ if (!th_brk)\r
+ thaiCodec = 0;\r
+ }\r
+\r
+ if (!th_brk)\r
+ return;\r
+\r
+ cstr = HB_TextCodec_ConvertFromUnicode(thaiCodec, string, len, 0);\r
+ if (!cstr)\r
+ return;\r
+\r
+ break_positions = brp;\r
+ numbreaks = th_brk(cstr, break_positions, 128);\r
+ if (numbreaks > 128) {\r
+ break_positions = (int *)malloc(numbreaks * sizeof(int));\r
+ numbreaks = th_brk(cstr, break_positions, numbreaks);\r
+ }\r
+\r
+ for (i = 0; i < len; ++i)\r
+ attributes[i].lineBreakType = HB_NoBreak;\r
+\r
+ for (i = 0; i < numbreaks; ++i) {\r
+ if (break_positions[i] > 0)\r
+ attributes[break_positions[i]-1].lineBreakType = HB_Break;\r
+ }\r
+\r
+ if (break_positions != brp)\r
+ free(break_positions);\r
+\r
+ HB_TextCodec_FreeResult(cstr);\r
+}\r
+\r
+\r
+void HB_ThaiAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)\r
+{\r
+ assert(script == HB_Script_Thai);\r
+ attributes += from;\r
+ thaiWordBreaks(text + from, len, attributes);\r
+}\r
+\r
--- /dev/null
+/*\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz-shaper.h"\r
+#include "harfbuzz-shaper-private.h"\r
+\r
+#include <assert.h>\r
+\r
+/*\r
+ tibetan syllables are of the form:\r
+ head position consonant\r
+ first sub-joined consonant\r
+ ....intermediate sub-joined consonants (if any)\r
+ last sub-joined consonant\r
+ sub-joined vowel (a-chung U+0F71)\r
+ standard or compound vowel sign (or 'virama' for devanagari transliteration)\r
+*/\r
+\r
+typedef enum {\r
+ TibetanOther,\r
+ TibetanHeadConsonant,\r
+ TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedVowel,\r
+ TibetanVowel\r
+} TibetanForm;\r
+\r
+/* this table starts at U+0f40 */\r
+static const unsigned char tibetanForm[0x80] = {\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,\r
+ TibetanOther, TibetanOther, TibetanOther, TibetanOther,\r
+\r
+ TibetanOther, TibetanVowel, TibetanVowel, TibetanVowel,\r
+ TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,\r
+ TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,\r
+ TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,\r
+\r
+ TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,\r
+ TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,\r
+ TibetanOther, TibetanOther, TibetanOther, TibetanOther,\r
+ TibetanOther, TibetanOther, TibetanOther, TibetanOther,\r
+\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,\r
+ TibetanSubjoinedConsonant, TibetanOther, TibetanOther, TibetanOther\r
+};\r
+\r
+\r
+#define tibetan_form(c) \\r
+ (TibetanForm)tibetanForm[c - 0x0f40]\r
+\r
+static const HB_OpenTypeFeature tibetan_features[] = {\r
+ { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },\r
+ { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },\r
+ { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },\r
+ { HB_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty },\r
+ {0, 0}\r
+};\r
+\r
+static HB_Bool tibetan_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_Bool invalid)\r
+{\r
+ hb_uint32 i;\r
+ const HB_UChar16 *str = item->string + item->item.pos;\r
+ int len = item->item.length;\r
+#ifndef NO_OPENTYPE\r
+ const int availableGlyphs = item->num_glyphs;\r
+#endif\r
+ HB_Bool haveGlyphs;\r
+ HB_STACKARRAY(HB_UChar16, reordered, len + 4);\r
+\r
+ if (item->num_glyphs < item->item.length + 4) {\r
+ item->num_glyphs = item->item.length + 4;\r
+ return FALSE;\r
+ }\r
+\r
+ if (invalid) {\r
+ *reordered = 0x25cc;\r
+ memcpy(reordered+1, str, len*sizeof(HB_UChar16));\r
+ len++;\r
+ str = reordered;\r
+ }\r
+\r
+ haveGlyphs = item->font->klass->convertStringToGlyphIndices(item->font,\r
+ str, len,\r
+ item->glyphs, &item->num_glyphs,\r
+ item->item.bidiLevel % 2);\r
+\r
+ HB_FREE_STACKARRAY(reordered);\r
+\r
+ if (!haveGlyphs)\r
+ return FALSE;\r
+\r
+ for (i = 0; i < item->item.length; i++) {\r
+ item->attributes[i].mark = FALSE;\r
+ item->attributes[i].clusterStart = FALSE;\r
+ item->attributes[i].justification = 0;\r
+ item->attributes[i].zeroWidth = FALSE;\r
+/* IDEBUG(" %d: %4x", i, str[i]); */\r
+ }\r
+\r
+ /* now we have the syllable in the right order, and can start running it through open type. */\r
+\r
+#ifndef NO_OPENTYPE\r
+ if (openType) {\r
+ HB_OpenTypeShape(item, /*properties*/0);\r
+ if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))\r
+ return FALSE;\r
+ } else {\r
+ HB_HeuristicPosition(item);\r
+ }\r
+#endif\r
+\r
+ item->attributes[0].clusterStart = TRUE;\r
+ return TRUE;\r
+}\r
+\r
+/* SAMSUNG - Kaja Changes -Start */\r
+//static int tibetan_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+int tibetan_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)\r
+/* SAMSUNG - Kaja Changes -End */\r
+{\r
+ const HB_UChar16 *uc = s + start;\r
+\r
+ int pos = 0;\r
+ TibetanForm state = tibetan_form(*uc);\r
+\r
+/* qDebug("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);*/\r
+ pos++;\r
+\r
+ if (state != TibetanHeadConsonant) {\r
+ if (state != TibetanOther)\r
+ *invalid = TRUE;\r
+ goto finish;\r
+ }\r
+\r
+ while (pos < end - start) {\r
+ TibetanForm newState = tibetan_form(uc[pos]);\r
+ switch(newState) {\r
+ case TibetanSubjoinedConsonant:\r
+ case TibetanSubjoinedVowel:\r
+ if (state != TibetanHeadConsonant &&\r
+ state != TibetanSubjoinedConsonant)\r
+ goto finish;\r
+ state = newState;\r
+ break;\r
+ case TibetanVowel:\r
+ if (state != TibetanHeadConsonant &&\r
+ state != TibetanSubjoinedConsonant &&\r
+ state != TibetanSubjoinedVowel)\r
+ goto finish;\r
+ break;\r
+ case TibetanOther:\r
+ case TibetanHeadConsonant:\r
+ goto finish;\r
+ }\r
+ pos++;\r
+ }\r
+\r
+finish:\r
+ *invalid = FALSE;\r
+ return start+pos;\r
+}\r
+\r
+HB_Bool HB_TibetanShape(HB_ShaperItem *item)\r
+{\r
+\r
+ HB_Bool openType = FALSE;\r
+ unsigned short *logClusters = item->log_clusters;\r
+\r
+ HB_ShaperItem syllable = *item;\r
+ int first_glyph = 0;\r
+\r
+ int sstart = item->item.pos;\r
+ int end = sstart + item->item.length;\r
+\r
+ assert(item->item.script == HB_Script_Tibetan);\r
+\r
+#ifndef QT_NO_OPENTYPE\r
+ openType = HB_SelectScript(item, tibetan_features);\r
+#endif\r
+\r
+ while (sstart < end) {\r
+ HB_Bool invalid;\r
+ int i;\r
+ int send = tibetan_nextSyllableBoundary(item->string, sstart, end, &invalid);\r
+/* IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,\r
+ invalid ? "TRUE" : "FALSE"); */\r
+ syllable.item.pos = sstart;\r
+ syllable.item.length = send-sstart;\r
+ syllable.glyphs = item->glyphs + first_glyph;\r
+ syllable.attributes = item->attributes + first_glyph;\r
+ syllable.offsets = item->offsets + first_glyph;\r
+ syllable.advances = item->advances + first_glyph;\r
+ syllable.num_glyphs = item->num_glyphs - first_glyph;\r
+ if (!tibetan_shape_syllable(openType, &syllable, invalid)) {\r
+ item->num_glyphs += syllable.num_glyphs;\r
+ return FALSE;\r
+ }\r
+ /* fix logcluster array */\r
+ for (i = sstart; i < send; ++i)\r
+ logClusters[i-item->item.pos] = first_glyph;\r
+ sstart = send;\r
+ first_glyph += syllable.num_glyphs;\r
+ }\r
+ item->num_glyphs = first_glyph;\r
+ return TRUE;\r
+}\r
+\r
+void HB_TibetanAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)\r
+{\r
+ int end = from + len;\r
+ const HB_UChar16 *uc = text + from;\r
+ hb_uint32 i = 0;\r
+ HB_UNUSED(script);\r
+ attributes += from;\r
+ while (i < len) {\r
+ HB_Bool invalid;\r
+ hb_uint32 boundary = tibetan_nextSyllableBoundary(text, from+i, end, &invalid) - from;\r
+\r
+ attributes[i].charStop = TRUE;\r
+\r
+ if (boundary > len-1) boundary = len;\r
+ i++;\r
+ while (i < boundary) {\r
+ attributes[i].charStop = FALSE;\r
+ ++uc;\r
+ ++i;\r
+ }\r
+ assert(i == boundary);\r
+ }\r
+}\r
+\r
+\r
--- /dev/null
+/*\r
+ * Copyright (C) 2006 Behdad Esfahbod\r
+ *\r
+ * This is part of HarfBuzz, an OpenType Layout engine library.\r
+ *\r
+ * Permission is hereby granted, without written agreement and without\r
+ * license or royalty fees, to use, copy, modify, and distribute this\r
+ * software and its documentation for any purpose, provided that the\r
+ * above copyright notice and the following two paragraphs appear in\r
+ * all copies of this software.\r
+ *\r
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR\r
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES\r
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+ * DAMAGE.\r
+ *\r
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\r
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO\r
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\r
+ */\r
+\r
+#include "harfbuzz.h"\r
+#include "hb_unicode_tables.h"\r
+\r
+#include "harfbuzz-buffer.c"\r
+#include "harfbuzz-gdef.c"\r
+#include "harfbuzz-gsub.c"\r
+#include "harfbuzz-gpos.c"\r
+#include "harfbuzz-impl.c"\r
+#include "harfbuzz-open.c"\r
+#include "harfbuzz-stream.c"\r
+\r
+\r
+HB_Error hb_getScriptID(HB_UShort value, HB_Script *scriptID)\r
+{\r
+ HB_Error error = HB_Err_Ok;\r
+ hb_uint8 script = value>>8;\r
+\r
+ *scriptID = HB_Script_Common;\r
+\r
+ if(0 == scriptTableStruct[script].pSubTable)\r
+ {\r
+ *scriptID = (HB_Script)scriptTableStruct[script].scriptID;\r
+ }\r
+ else if(scriptTableStruct[script].pSubTable != 0)\r
+ {\r
+ if((value&0xFF) < scriptTableStruct[script].scriptID)//check the size of the sub table array\r
+ {\r
+ *scriptID = scriptTableStruct[script].pSubTable[(value&0xFF)];\r
+ }\r
+ else\r
+ {\r
+ error = HB_Err_Not_Covered;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ error = HB_Err_Invalid_SubTable;\r
+ }\r
+\r
+ return error;\r
+}\r
+\r
+HB_Error hb_getTextWithScriptID(HB_UShort *text, int textLen, HB_Script *scriptID, int *scriptLen)\r
+{\r
+ HB_Script cur_script_id;\r
+ HB_Error error = HB_Err_Ok;\r
+ HB_UShort *curText = text ; \r
+\r
+ *scriptID = HB_Script_Common;\r
+ *scriptLen = 0 ;\r
+ \r
+ if((NULL == curText) || (0 == textLen))\r
+ {\r
+ return HB_Err_Invalid_Argument;\r
+ }\r
+\r
+ hb_getScriptID(*curText, scriptID); \r
+ \r
+ curText++;\r
+ textLen--; \r
+\r
+ while(textLen)\r
+ {\r
+ if(HB_DOTTED_CIRCLE == *curText || HB_ZWJ == *curText || HB_ZWNJ == *curText)\r
+ {\r
+ curText++;\r
+ textLen--;\r
+ continue;\r
+ } \r
+\r
+ hb_getScriptID(*curText, &cur_script_id); \r
+\r
+ if(*scriptID != cur_script_id)\r
+ {\r
+ break;\r
+ } \r
+\r
+ curText++;\r
+ textLen--;\r
+ } \r
+\r
+ *scriptLen = curText -text ;\r
+ return error;\r
+\r
+}\r
+\r
+\r
+int hb_getSyllableLength(HB_UShort *text, int textLen, HB_Script *scriptID)\r
+{\r
+ int len = 0 ;\r
+ HB_Bool invalid ;\r
+ switch (*scriptID)\r
+ {\r
+ case HB_Script_Devanagari:\r
+ case HB_Script_Bengali:\r
+ case HB_Script_Gurmukhi:\r
+ case HB_Script_Gujarati:\r
+ case HB_Script_Oriya:\r
+ case HB_Script_Tamil:\r
+ case HB_Script_Telugu:\r
+ case HB_Script_Kannada:\r
+ case HB_Script_Malayalam:\r
+ case HB_Script_Sinhala:\r
+ len = indic_nextSyllableBoundary(*scriptID, (const HB_UChar16*)text, 0, textLen, &invalid); \r
+ break ;\r
+ case HB_Script_Khmer:\r
+ len = khmer_nextSyllableBoundary(text, 0, textLen, &invalid);\r
+ break ;\r
+ case HB_Script_Myanmar:\r
+ len = myanmar_nextSyllableBoundary(text, 0, textLen, &invalid);\r
+ break ;\r
+ case HB_Script_Tibetan:\r
+ len = tibetan_nextSyllableBoundary(text, 0, textLen, &invalid);\r
+ break ;\r
+ default:\r
+ len = 1 ;\r
+ }\r
+\r
+ return len ;\r
+}\r
+\r