summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
Diffstat (limited to 'pango')
-rw-r--r--pango/Makefile.am4
-rw-r--r--pango/opentype/COPYING15
-rw-r--r--pango/opentype/COPYING.FTL (renamed from pango/opentype/FTL.TXT)0
-rw-r--r--pango/opentype/COPYING.GPL340
-rw-r--r--pango/opentype/FT-license.txt28
-rw-r--r--pango/opentype/Makefile.am89
-rw-r--r--pango/opentype/README44
-rw-r--r--pango/opentype/ftglue.c88
-rw-r--r--pango/opentype/ftglue.h68
-rw-r--r--pango/opentype/ftxgdef.c1225
-rw-r--r--pango/opentype/ftxgdef.h224
-rw-r--r--pango/opentype/ftxgpos.c6199
-rw-r--r--pango/opentype/ftxgpos.h838
-rw-r--r--pango/opentype/ftxgsub.c4533
-rw-r--r--pango/opentype/ftxgsub.h594
-rw-r--r--pango/opentype/ftxopen.c1552
-rw-r--r--pango/opentype/ftxopen.h317
-rw-r--r--pango/opentype/ftxopenf.h166
-rw-r--r--pango/opentype/harfbuzz-buffer.c227
-rw-r--r--pango/opentype/harfbuzz-buffer.h106
-rw-r--r--pango/opentype/harfbuzz-dump-main.c (renamed from pango/opentype/ottest.c)84
-rw-r--r--pango/opentype/harfbuzz-dump.c (renamed from pango/opentype/disasm.c)186
-rw-r--r--pango/opentype/harfbuzz-dump.h (renamed from pango/opentype/disasm.h)18
-rw-r--r--pango/opentype/harfbuzz-gdef-private.h101
-rw-r--r--pango/opentype/harfbuzz-gdef.c1228
-rw-r--r--pango/opentype/harfbuzz-gdef.h127
-rw-r--r--pango/opentype/harfbuzz-gpos-private.h683
-rw-r--r--pango/opentype/harfbuzz-gpos.c6269
-rw-r--r--pango/opentype/harfbuzz-gpos.h168
-rw-r--r--pango/opentype/harfbuzz-gsub-private.h448
-rw-r--r--pango/opentype/harfbuzz-gsub.c4581
-rw-r--r--pango/opentype/harfbuzz-gsub.h132
-rw-r--r--pango/opentype/harfbuzz-impl.h64
-rw-r--r--pango/opentype/harfbuzz-open-private.h81
-rw-r--r--pango/opentype/harfbuzz-open.c1426
-rw-r--r--pango/opentype/harfbuzz-open.h285
-rw-r--r--pango/opentype/harfbuzz.c19
-rw-r--r--pango/opentype/harfbuzz.h23
-rw-r--r--pango/opentype/otlbuffer.c238
-rw-r--r--pango/opentype/otlbuffer.h103
-rw-r--r--pango/pango-ot-buffer.c22
-rw-r--r--pango/pango-ot-info.c81
-rw-r--r--pango/pango-ot-private.h26
-rw-r--r--pango/pango-ot-ruleset.c19
-rw-r--r--pango/pango-ot.h6
45 files changed, 16661 insertions, 16414 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am
index ebd40994..7c205ec3 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -180,14 +180,14 @@ endif
libpangoft2_1_0_la_LDFLAGS = $(LIBRARY_LIBTOOL_OPTIONS)
libpangoft2_1_0_la_LIBADD = \
- opentype/libmini-harfbuzz.la \
+ opentype/libharfbuzz-1.la \
libpango-$(PANGO_API_VERSION).la \
$(INCLUDED_FC_MODULES) \
$(GLIB_LIBS) \
$(FREETYPE_LIBS) \
$(libm)
libpangoft2_1_0_la_DEPENDENCIES = \
- opentype/libmini-harfbuzz.la \
+ opentype/libharfbuzz-1.la \
libpango-$(PANGO_API_VERSION).la \
$(INCLUDED_FC_MODULES)
libpangoft2_1_0_la_SOURCES = \
diff --git a/pango/opentype/COPYING b/pango/opentype/COPYING
new file mode 100644
index 00000000..cde91010
--- /dev/null
+++ b/pango/opentype/COPYING
@@ -0,0 +1,15 @@
+HarfBuzz is distributed under two mutually exclusive open-source licenses.
+This means that *you* must choose *one* of the two licenses described
+below, then obey all its terms and conditions when using HarfBuzz in
+any of your projects or products.
+
+ - The FreeType License, found in the file `COPYING.FTL', which is similar to
+ the original BSD license *with* an advertising clause that forces you to
+ explicitly cite the FreeType project in your product's documentation.
+ All details are in the license file. This license is suited to
+ products which don't use the GNU General Public License.
+
+ - The GNU General Public License version 2, found in `COPYING.GPL' (any
+ later version can be used also), for programs which already use the GPL.
+ Note that the FTL is incompatible with the GPL due to its
+ advertisement clause.
diff --git a/pango/opentype/FTL.TXT b/pango/opentype/COPYING.FTL
index 459bda32..459bda32 100644
--- a/pango/opentype/FTL.TXT
+++ b/pango/opentype/COPYING.FTL
diff --git a/pango/opentype/COPYING.GPL b/pango/opentype/COPYING.GPL
new file mode 100644
index 00000000..14db8fc7
--- /dev/null
+++ b/pango/opentype/COPYING.GPL
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/pango/opentype/FT-license.txt b/pango/opentype/FT-license.txt
deleted file mode 100644
index 102a03d6..00000000
--- a/pango/opentype/FT-license.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-
-The FreeType 2 font engine is copyrighted work and cannot be used
-legally without a software license. In order to make this project
-usable to a vast majority of developers, we distribute it under two
-mutually exclusive open-source licenses.
-
-This means that *you* must choose *one* of the two licenses described
-below, then obey all its terms and conditions when using FreeType 2 in
-any of your projects or products.
-
- - The FreeType License, found in the file `FTL.TXT', which is similar
- to the original BSD license *with* an advertising clause that forces
- you to explicitly cite the FreeType project in your product's
- documentation. All details are in the license file. This license
- is suited to products which don't use the GNU General Public
- License.
-
- - The GNU General Public License version 2, found in `GPL.TXT' (any
- later version can be used also), for programs which already use the
- GPL. Note that the FTL is incompatible with the GPL due to its
- advertisement clause.
-
-The contributed PCF driver comes with a license similar to that of the X
-Window System. It is compatible to the above two licenses (see file
-src/pcf/readme).
-
-
---- end of LICENSE.TXT ---
diff --git a/pango/opentype/Makefile.am b/pango/opentype/Makefile.am
index 7c0ba69c..8d65294e 100644
--- a/pango/opentype/Makefile.am
+++ b/pango/opentype/Makefile.am
@@ -1,51 +1,58 @@
## Process this file with automake to produce Makefile.in
INCLUDES = \
- -DSYSCONFDIR=\"$(sysconfdir)\" \
- -DLIBDIR=\"$(libdir)\" \
- $(PANGO_DEBUG_FLAGS) \
- -I$(top_srcdir) \
- $(GLIB_CFLAGS) \
$(FREETYPE_CFLAGS)
-noinst_LTLIBRARIES = libmini-harfbuzz.la
-
-libmini_harfbuzz_la_SOURCES = \
- ftglue.h \
- ftglue.c \
- ftxopen.c \
- ftxopen.h \
- ftxopenf.h \
- ftxgdef.c \
- ftxgdef.h \
- ftxgpos.c \
- ftxgpos.h \
- ftxgsub.c \
- ftxgsub.h \
- otlbuffer.c \
- otlbuffer.h
-
-libmini_harfbuzz_la_LIBADD = \
- $(x_ldflags) \
- $(x_libs) \
- $(GLIB_LIBS) \
- -lm
-
-if BUILD_OT_TESTS
-noinst_PROGRAMS = ottest
-endif
-
-ottest_SOURCES = \
- ottest.c \
- disasm.c \
- disasm.h
-
-ottest_LDADD = \
- libmini-harfbuzz.la \
+noinst_LTLIBRARIES = libharfbuzz-1.la
+
+SOURCES = \
+ ftglue.c \
+ harfbuzz-buffer.c \
+ harfbuzz-dump.c \
+ harfbuzz-gdef.c \
+ harfbuzz-gpos.c \
+ harfbuzz-gsub.c \
+ harfbuzz-open.c
+
+EXTRA_SOURCES = harfbuzz.c
+
+PUBLICHEADERS = \
+ harfbuzz.h \
+ harfbuzz-buffer.h \
+ harfbuzz-dump.h \
+ harfbuzz-gdef.h \
+ harfbuzz-gpos.h \
+ harfbuzz-gsub.h \
+ harfbuzz-open.h
+
+PRIVATEHEADERS = \
+ ftglue.h \
+ harfbuzz-impl.h \
+ harfbuzz-gdef-private.h \
+ harfbuzz-gpos-private.h \
+ harfbuzz-gsub-private.h \
+ harfbuzz-open-private.h
+
+libharfbuzz_1_la_SOURCES = \
+ $(SOURCES) \
+ $(PUBLICHEADERS) \
+ $(PRIVATEHEADERS)
+
+libharfbuzz_1_la_LIBADD = \
$(FREETYPE_LIBS)
+noinst_PROGRAMS = harfbuzz-dump
+
+harfbuzz_dump_SOURCES = \
+ harfbuzz-dump-main.c
+
+harfbuzz_dump_LDADD = \
+ libharfbuzz-1.la
+
EXTRA_DIST = \
README \
- FTL.TXT \
- FT-license.txt
+ COPYING.FTL \
+ COPYING.GPL \
+ COPYING \
+ $(EXTRA_SOURCES)
diff --git a/pango/opentype/README b/pango/opentype/README
index 20035644..f7746efc 100644
--- a/pango/opentype/README
+++ b/pango/opentype/README
@@ -1,36 +1,18 @@
-This directory includes code for using OpenType Layout tables from
-OpenType fonts with FreeType and
+This is HarfBuzz, an OpenType Layout engine.
-The table reading code in:
+It was derived originally from the OpenType code in FreeType-1.x, ported to
+FreeType2. (This code has been abandoned for FreeType2, but until something
+better comes along, should serve our purposes.) In addition to porting to
+FreeType-2, it has been modified in various other ways.
- ftxopen.[ch]
- ftxopenf.h
- ftxgdef.[ch]
- ftxgpos.[ch]
- ftxgdef.[ch]
+It also includes a partial XML dumper for OpenType Layout tables useful for
+figuring out what is going on. Please extend to cover additional parts of the
+tables as you encounter fonts using them. The dumper is written by Owen Taylor.
-Is derived from the OpenType code in FreeType-1.x, ported to FreeType2.
-(This code has been abandoned for FreeType2, but until something better
-comes along, should serve our purposes.)
+Bug reports on these files should be sent to the HarfBuzz mailing list as
+listed on http://freedesktop.org/wiki/Software/harfbuzz
-This code should be left following the FreeType indentation style and
-coding conventions.
+For license information, see the file COPYING.
-In addition to porting to FreeType-2, it has been modified to
-add support for PangoGlyphString's log_clusters, and in various
-other ways. Bug reports on these files should be sent to
-gtk-i18n-list@gtk.org, NOT to the freetype maintainers.
-
-The license for these files is in the file FT-license.txt.
-
-
-Most of the additional files in this directory implement a high-level
-interface to this that follows Pango conventions and integrates with
-Pango.
-
-disasm.[ch] is a partial dumper for OpenType layout tables useful
-in figuring out what is going on. Please extend to cover additional
-parts of the tables as you encounter fonts using them.
-
-Owen Taylor
-17 December 2000
+Behdad Esfahbod
+April 1st, 2006
diff --git a/pango/opentype/ftglue.c b/pango/opentype/ftglue.c
index b3fd5b2d..5bb72745 100644
--- a/pango/opentype/ftglue.c
+++ b/pango/opentype/ftglue.c
@@ -8,15 +8,14 @@
* See ftglue.h for more information.
*/
-#include <config.h>
#include "ftglue.h"
#if 0
#include <stdio.h>
-#define LOG(x) ftglue_log x
+#define LOG(x) _hb_ftglue_log x
static void
-ftglue_log( const char* format, ... )
+_hb_ftglue_log( const char* format, ... )
{
va_list ap;
@@ -31,7 +30,7 @@ ftglue_log( const char* format, ... )
/* only used internally */
static FT_Pointer
-ftglue_qalloc( FT_Memory memory,
+_hb_ftglue_qalloc( FT_Memory memory,
FT_ULong size,
FT_Error *perror )
{
@@ -50,11 +49,11 @@ ftglue_qalloc( FT_Memory memory,
}
#undef QALLOC /* just in case */
-#define QALLOC(ptr,size) ( (ptr) = ftglue_qalloc( memory, (size), &error ), error != 0 )
+#define QALLOC(ptr,size) ( (ptr) = _hb_ftglue_qalloc( memory, (size), &error ), error != 0 )
FTGLUE_APIDEF( FT_Pointer )
-ftglue_alloc( FT_Memory memory,
+_hb_ftglue_alloc( FT_Memory memory,
FT_ULong size,
FT_Error *perror )
{
@@ -76,7 +75,7 @@ ftglue_alloc( FT_Memory memory,
FTGLUE_APIDEF( FT_Pointer )
-ftglue_realloc( FT_Memory memory,
+_hb_ftglue_realloc( FT_Memory memory,
FT_Pointer block,
FT_ULong old_size,
FT_ULong new_size,
@@ -87,11 +86,11 @@ ftglue_realloc( FT_Memory memory,
if ( old_size == 0 || block == NULL )
{
- block2 = ftglue_alloc( memory, new_size, &error );
+ block2 = _hb_ftglue_alloc( memory, new_size, &error );
}
else if ( new_size == 0 )
{
- ftglue_free( memory, block );
+ _hb_ftglue_free( memory, block );
}
else
{
@@ -111,7 +110,7 @@ ftglue_realloc( FT_Memory memory,
FTGLUE_APIDEF( void )
-ftglue_free( FT_Memory memory,
+_hb_ftglue_free( FT_Memory memory,
FT_Pointer block )
{
if ( block )
@@ -120,7 +119,7 @@ ftglue_free( FT_Memory memory,
FTGLUE_APIDEF( FT_Long )
-ftglue_stream_pos( FT_Stream stream )
+_hb_ftglue_stream_pos( FT_Stream stream )
{
LOG(( "ftglue:stream:pos() -> %ld\n", stream->pos ));
return stream->pos;
@@ -128,7 +127,7 @@ ftglue_stream_pos( FT_Stream stream )
FTGLUE_APIDEF( FT_Error )
-ftglue_stream_seek( FT_Stream stream,
+_hb_ftglue_stream_seek( FT_Stream stream,
FT_Long pos )
{
FT_Error error = 0;
@@ -136,7 +135,7 @@ ftglue_stream_seek( FT_Stream stream,
stream->pos = pos;
if ( stream->read )
{
- if ( stream->read( stream, pos, 0, 0 ) )
+ if ( stream->read( stream, pos, NULL, 0 ) )
error = FT_Err_Invalid_Stream_Operation;
}
else if ( pos > (FT_Long)stream->size )
@@ -148,7 +147,7 @@ ftglue_stream_seek( FT_Stream stream,
FTGLUE_APIDEF( FT_Error )
-ftglue_stream_frame_enter( FT_Stream stream,
+_hb_ftglue_stream_frame_enter( FT_Stream stream,
FT_ULong count )
{
FT_Error error = FT_Err_Ok;
@@ -198,7 +197,7 @@ Exit:
FTGLUE_APIDEF( void )
-ftglue_stream_frame_exit( FT_Stream stream )
+_hb_ftglue_stream_frame_exit( FT_Stream stream )
{
if ( stream->read )
{
@@ -206,68 +205,21 @@ ftglue_stream_frame_exit( FT_Stream stream )
FREE( stream->base );
}
- stream->cursor = 0;
- stream->limit = 0;
+ stream->cursor = NULL;
+ stream->limit = NULL;
LOG(( "ftglue:stream:frame_exit()\n" ));
}
-FTGLUE_APIDEF( FT_Byte )
-ftglue_stream_get_byte( FT_Stream stream )
-{
- FT_Byte result = 0;
-
- if ( stream->cursor < stream->limit )
- result = *stream->cursor++;
-
- return result;
-}
-
-
-FTGLUE_APIDEF( FT_Short )
-ftglue_stream_get_short( FT_Stream stream )
-{
- FT_Byte* p;
- FT_Short result = 0;
-
- p = stream->cursor;
- if ( p + 2 <= stream->limit )
- {
- result = (FT_Short)((p[0] << 8) | p[1]);
- stream->cursor = p+2;
- }
- return result;
-}
-
-
-FTGLUE_APIDEF( FT_Long )
-ftglue_stream_get_long( FT_Stream stream )
-{
- FT_Byte* p;
- FT_Long result = 0;
-
- p = stream->cursor;
- if ( p + 4 <= stream->limit )
- {
- result = (FT_Long)(((FT_Long)p[0] << 24) |
- ((FT_Long)p[1] << 16) |
- ((FT_Long)p[2] << 8) |
- p[3] );
- stream->cursor = p+4;
- }
- return result;
-}
-
-
FTGLUE_APIDEF( FT_Error )
-ftglue_face_goto_table( FT_Face face,
+_hb_ftglue_face_goto_table( FT_Face face,
FT_ULong the_tag,
FT_Stream stream )
{
FT_Error error;
- LOG(( "ftglue_face_goto_table( %p, %c%c%c%c, %p )\n",
+ LOG(( "_hb_ftglue_face_goto_table( %p, %c%c%c%c, %p )\n",
face,
(int)((the_tag >> 24) & 0xFF),
(int)((the_tag >> 16) & 0xFF),
@@ -331,11 +283,11 @@ ftglue_face_goto_table( FT_Face face,
if ( tag == the_tag )
{
LOG(( "TrueType table (start: %ld) (size: %ld)\n", start, size ));
- error = ftglue_stream_seek( stream, offset+start );
+ error = _hb_ftglue_stream_seek( stream, offset+start );
goto FoundIt;
}
}
- error = TT_Err_Table_Missing;
+ error = FT_Err_Table_Missing;
FoundIt:
FORGET_Frame();
diff --git a/pango/opentype/ftglue.h b/pango/opentype/ftglue.h
index 57c5ebe9..84de7f35 100644
--- a/pango/opentype/ftglue.h
+++ b/pango/opentype/ftglue.h
@@ -1,4 +1,4 @@
-/* ftglue.c: Glue code for compiling the OpenType code from
+/* ftglue.h: Glue code for compiling the OpenType code from
* FreeType 1 using only the public API of FreeType 2
*
* By David Turner, The FreeType Project (www.freetype.org)
@@ -40,8 +40,8 @@
*
* PS: This "glue" code is explicitely put in the public domain
*/
-#ifndef __OPENTYPE_FTGLUE_H__
-#define __OPENTYPE_FTGLUE_H__
+#ifndef FTGLUE_H
+#define FTGLUE_H
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -50,10 +50,6 @@ FT_BEGIN_HEADER
/* utility macros */
-#define TT_Err_Ok FT_Err_Ok
-#define TT_Err_Invalid_Argument FT_Err_Invalid_Argument
-#define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
-#define TT_Err_Table_Missing FT_Err_Table_Missing
#define SET_ERR(c) ( (error = (c)) != 0 )
@@ -66,14 +62,23 @@ FT_BEGIN_HEADER
#endif
/* stream macros used by the OpenType parser */
-#define FILE_Pos() ftglue_stream_pos( stream )
-#define FILE_Seek(pos) SET_ERR( ftglue_stream_seek( stream, pos ) )
-#define ACCESS_Frame(size) SET_ERR( ftglue_stream_frame_enter( stream, size ) )
-#define FORGET_Frame() ftglue_stream_frame_exit( stream )
+#define FILE_Pos() _hb_ftglue_stream_pos( stream )
+#define FILE_Seek(pos) SET_ERR( _hb_ftglue_stream_seek( stream, pos ) )
+#define ACCESS_Frame(size) SET_ERR( _hb_ftglue_stream_frame_enter( stream, size ) )
+#define FORGET_Frame() _hb_ftglue_stream_frame_exit( stream )
+
+#define GET_Byte() (*stream->cursor++)
+#define GET_Short() (stream->cursor += 2, (FT_Short)( \
+ (*(((FT_Byte*)stream->cursor)-2) << 8) | \
+ *(((FT_Byte*)stream->cursor)-1) \
+ ))
+#define GET_Long() (stream->cursor += 4, (FT_Long)( \
+ (*(((FT_Byte*)stream->cursor)-4) << 24) | \
+ (*(((FT_Byte*)stream->cursor)-3) << 16) | \
+ (*(((FT_Byte*)stream->cursor)-2) << 8) | \
+ *(((FT_Byte*)stream->cursor)-1) \
+ ))
-#define GET_Byte() ftglue_stream_get_byte( stream )
-#define GET_Short() ftglue_stream_get_short( stream )
-#define GET_Long() ftglue_stream_get_long( stream )
#define GET_Char() ((FT_Char)GET_Byte())
#define GET_UShort() ((FT_UShort)GET_Short())
@@ -81,45 +86,36 @@ FT_BEGIN_HEADER
#define GET_Tag4() GET_ULong()
FTGLUE_API( FT_Long )
-ftglue_stream_pos( FT_Stream stream );
+_hb_ftglue_stream_pos( FT_Stream stream );
FTGLUE_API( FT_Error )
-ftglue_stream_seek( FT_Stream stream,
+_hb_ftglue_stream_seek( FT_Stream stream,
FT_Long pos );
FTGLUE_API( FT_Error )
-ftglue_stream_frame_enter( FT_Stream stream,
+_hb_ftglue_stream_frame_enter( FT_Stream stream,
FT_ULong size );
FTGLUE_API( void )
-ftglue_stream_frame_exit( FT_Stream stream );
-
-FTGLUE_API( FT_Byte )
-ftglue_stream_get_byte( FT_Stream stream );
-
-FTGLUE_API( FT_Short )
-ftglue_stream_get_short( FT_Stream stream );
-
-FTGLUE_API( FT_Long )
-ftglue_stream_get_long( FT_Stream stream );
+_hb_ftglue_stream_frame_exit( FT_Stream stream );
FTGLUE_API( FT_Error )
-ftglue_face_goto_table( FT_Face face,
+_hb_ftglue_face_goto_table( FT_Face face,
FT_ULong tag,
FT_Stream stream );
/* memory macros used by the OpenType parser */
#define ALLOC(_ptr,_size) \
- ( (_ptr) = ftglue_alloc( memory, _size, &error ), error != 0 )
+ ( (_ptr) = _hb_ftglue_alloc( memory, _size, &error ), error != 0 )
#define REALLOC(_ptr,_oldsz,_newsz) \
- ( (_ptr) = ftglue_realloc( memory, (_ptr), (_oldsz), (_newsz), &error ), error != 0 )
+ ( (_ptr) = _hb_ftglue_realloc( memory, (_ptr), (_oldsz), (_newsz), &error ), error != 0 )
#define FREE(_ptr) \
do { \
if ( (_ptr) ) \
{ \
- ftglue_free( memory, _ptr ); \
+ _hb_ftglue_free( memory, _ptr ); \
_ptr = NULL; \
} \
} while (0)
@@ -134,23 +130,21 @@ ftglue_face_goto_table( FT_Face face,
FTGLUE_API( FT_Pointer )
-ftglue_alloc( FT_Memory memory,
+_hb_ftglue_alloc( FT_Memory memory,
FT_ULong size,
FT_Error *perror_ );
FTGLUE_API( FT_Pointer )
-ftglue_realloc( FT_Memory memory,
+_hb_ftglue_realloc( FT_Memory memory,
FT_Pointer block,
FT_ULong old_size,
FT_ULong new_size,
FT_Error *perror_ );
FTGLUE_API( void )
-ftglue_free( FT_Memory memory,
+_hb_ftglue_free( FT_Memory memory,
FT_Pointer block );
-/* */
-
FT_END_HEADER
-#endif /* __OPENTYPE_FTGLUE_H__ */
+#endif /* FTGLUE_H */
diff --git a/pango/opentype/ftxgdef.c b/pango/opentype/ftxgdef.c
deleted file mode 100644
index 8701b326..00000000
--- a/pango/opentype/ftxgdef.c
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*******************************************************************
- *
- * ftxgdef.c
- *
- * TrueType Open GDEF table support.
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#include <config.h>
-#include "ftxopen.h"
-#include "ftxopenf.h"
-
-#include "ftglue.h"
-
-#include FT_TRUETYPE_TAGS_H
-
-#define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' )
-
- static FT_Error Load_AttachList( TTO_AttachList* al,
- FT_Stream stream );
- static FT_Error Load_LigCaretList( TTO_LigCaretList* lcl,
- FT_Stream stream );
-
- static void Free_AttachList( TTO_AttachList* al,
- FT_Memory memory );
- static void Free_LigCaretList( TTO_LigCaretList* lcl,
- FT_Memory memory );
-
- static void Free_NewGlyphClasses( TTO_GDEFHeader* gdef,
- FT_Memory memory );
-
-
-
- /**********************
- * Extension Functions
- **********************/
-
-#if 0
-#define GDEF_ID Build_Extension_ID( 'G', 'D', 'E', 'F' )
-
-
- static FT_Error GDEF_Create( void* ext,
- PFace face )
- {
- DEFINE_LOAD_LOCALS( face->stream );
-
- TTO_GDEFHeader* gdef = (TTO_GDEFHeader*)ext;
- Long table;
-
-
- /* by convention */
-
- if ( !gdef )
- return TT_Err_Ok;
-
- /* a null offset indicates that there is no GDEF table */
-
- gdef->offset = 0;
-
- /* we store the start offset and the size of the subtable */
-
- table = TT_LookUp_Table( face, TTAG_GDEF );
- if ( table < 0 )
- return TT_Err_Ok; /* The table is optional */
-
- if ( FILE_Seek( face->dirTables[table].Offset ) ||
- ACCESS_Frame( 4L ) )
- return error;
-
- gdef->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
- gdef->Version = GET_ULong();
-
- FORGET_Frame();
-
- gdef->loaded = FALSE;
-
- return TT_Err_Ok;
- }
-
-
- static FT_Error GDEF_Destroy( void* ext,
- PFace face )
- {
- TTO_GDEFHeader* gdef = (TTO_GDEFHeader*)ext;
-
-
- /* by convention */
-
- if ( !gdef )
- return TT_Err_Ok;
-
- if ( gdef->loaded )
- {
- Free_LigCaretList( &gdef->LigCaretList, memory );
- Free_AttachList( &gdef->AttachList, memory );
- Free_ClassDefinition( &gdef->GlyphClassDef, memory );
- Free_ClassDefinition( &gdef->MarkAttachClassDef, memory );
-
- Free_NewGlyphClasses( gdef, memory );
- }
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_Init_GDEF_Extension( TT_Engine engine )
- {
- PEngine_Instance _engine = HANDLE_Engine( engine );
-
-
- if ( !_engine )
- return TT_Err_Invalid_Engine;
-
- return TT_Register_Extension( _engine,
- GDEF_ID,
- sizeof ( TTO_GDEFHeader ),
- GDEF_Create,
- GDEF_Destroy );
- }
-#endif
-
- EXPORT_FUNC
- FT_Error TT_New_GDEF_Table( FT_Face face,
- TTO_GDEFHeader** retptr )
- {
- FT_Error error;
- FT_Memory memory = face->memory;
-
- TTO_GDEFHeader* gdef;
-
- if ( !retptr )
- return TT_Err_Invalid_Argument;
-
- if ( ALLOC( gdef, sizeof( *gdef ) ) )
- return error;
-
- gdef->memory = face->memory;
-
- gdef->GlyphClassDef.loaded = FALSE;
- gdef->AttachList.loaded = FALSE;
- gdef->LigCaretList.loaded = FALSE;
- gdef->MarkAttachClassDef_offset = 0;
- gdef->MarkAttachClassDef.loaded = FALSE;
-
- gdef->LastGlyph = 0;
- gdef->NewGlyphClasses = NULL;
-
- *retptr = gdef;
-
- return TT_Err_Ok;
- }
-
- EXPORT_FUNC
- FT_Error TT_Load_GDEF_Table( FT_Face face,
- TTO_GDEFHeader** retptr )
- {
- FT_Error error;
- FT_Memory memory = face->memory;
- FT_Stream stream = face->stream;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_GDEFHeader* gdef;
-
-
- if ( !retptr )
- return TT_Err_Invalid_Argument;
-
- if (( error = ftglue_face_goto_table( face, TTAG_GDEF, stream ) ))
- return error;
-
- if (( error = TT_New_GDEF_Table ( face, &gdef ) ))
- return error;
-
- base_offset = FILE_Pos();
-
- /* skip version */
-
- if ( FILE_Seek( base_offset + 4L ) ||
- ACCESS_Frame( 2L ) )
- goto Fail0;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- /* all GDEF subtables are optional */
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- /* only classes 1-4 are allowed here */
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ClassDefinition( &gdef->GlyphClassDef, 5,
- stream ) ) != TT_Err_Ok )
- goto Fail0;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_AttachList( &gdef->AttachList,
- stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LigCaretList( &gdef->LigCaretList,
- stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
- }
-
- /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We
- first have to scan the LookupFlag values to find out whether we
- must load it or not. Here we only store the offset of the table. */
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- gdef->MarkAttachClassDef_offset = new_offset + base_offset;
- else
- gdef->MarkAttachClassDef_offset = 0;
-
- *retptr = gdef;
-
- return TT_Err_Ok;
-
- Fail3:
- Free_LigCaretList( &gdef->LigCaretList, memory );
-
- Fail2:
- Free_AttachList( &gdef->AttachList, memory );
-
- Fail1:
- Free_ClassDefinition( &gdef->GlyphClassDef, memory );
-
- Fail0:
- FREE( gdef );
-
- return error;
- }
-
- EXPORT_FUNC
- FT_Error TT_Done_GDEF_Table ( TTO_GDEFHeader* gdef )
- {
- FT_Memory memory = gdef->memory;
-
- Free_LigCaretList( &gdef->LigCaretList, memory );
- Free_AttachList( &gdef->AttachList, memory );
- Free_ClassDefinition( &gdef->GlyphClassDef, memory );
- Free_ClassDefinition( &gdef->MarkAttachClassDef, memory );
-
- Free_NewGlyphClasses( gdef, memory );
-
- FREE( gdef );
-
- return TT_Err_Ok;
- }
-
-
-
-
- /*******************************
- * AttachList related functions
- *******************************/
-
-
- /* AttachPoint */
-
- static FT_Error Load_AttachPoint( TTO_AttachPoint* ap,
- FT_Stream stream )
- {
- FT_Memory memory = stream->memory;
- FT_Error error;
-
- FT_UShort n, count;
- FT_UShort* pi;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = ap->PointCount = GET_UShort();
-
- FORGET_Frame();
-
- ap->PointIndex = NULL;
-
- if ( count )
- {
- if ( ALLOC_ARRAY( ap->PointIndex, count, FT_UShort ) )
- return error;
-
- pi = ap->PointIndex;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( pi );
- return error;
- }
-
- for ( n = 0; n < count; n++ )
- pi[n] = GET_UShort();
-
- FORGET_Frame();
- }
-
- return TT_Err_Ok;
- }
-
-
- static void Free_AttachPoint( TTO_AttachPoint* ap,
- FT_Memory memory )
- {
- FREE( ap->PointIndex );
- }
-
-
- /* AttachList */
-
- static FT_Error Load_AttachList( TTO_AttachList* al,
- FT_Stream stream )
- {
- FT_Memory memory = stream->memory;
- FT_Error error;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_AttachPoint* ap;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &al->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = al->GlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- al->AttachPoint = NULL;
-
- if ( ALLOC_ARRAY( al->AttachPoint, count, TTO_AttachPoint ) )
- goto Fail2;
-
- ap = al->AttachPoint;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_AttachPoint( &ap[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- al->loaded = TRUE;
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_AttachPoint( &ap[m], memory );
-
- FREE( ap );
-
- Fail2:
- Free_Coverage( &al->Coverage, memory );
- return error;
- }
-
-
- static void Free_AttachList( TTO_AttachList* al,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_AttachPoint* ap;
-
-
- if ( !al->loaded )
- return;
-
- if ( al->AttachPoint )
- {
- count = al->GlyphCount;
- ap = al->AttachPoint;
-
- for ( n = 0; n < count; n++ )
- Free_AttachPoint( &ap[n], memory );
-
- FREE( ap );
- }
-
- Free_Coverage( &al->Coverage, memory );
- }
-
-
-
- /*********************************
- * LigCaretList related functions
- *********************************/
-
-
- /* CaretValueFormat1 */
- /* CaretValueFormat2 */
- /* CaretValueFormat3 */
- /* CaretValueFormat4 */
-
- static FT_Error Load_CaretValue( TTO_CaretValue* cv,
- FT_Stream stream )
- {
- FT_Error error;
-
- FT_ULong cur_offset, new_offset, base_offset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cv->CaretValueFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( cv->CaretValueFormat )
- {
- case 1:
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cv->cvf.cvf1.Coordinate = GET_Short();
-
- FORGET_Frame();
-
- break;
-
- case 2:
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cv->cvf.cvf2.CaretValuePoint = GET_UShort();
-
- FORGET_Frame();
-
- break;
-
- case 3:
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- cv->cvf.cvf3.Coordinate = GET_Short();
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Device( &cv->cvf.cvf3.Device,
- stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- break;
-
- case 4:
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cv->cvf.cvf4.IdCaretValue = GET_UShort();
-
- FORGET_Frame();
- break;
-
- default:
- return TTO_Err_Invalid_GDEF_SubTable_Format;
- }
-
- return TT_Err_Ok;
- }
-
-
- static void Free_CaretValue( TTO_CaretValue* cv,
- FT_Memory memory )
- {
- if ( cv->CaretValueFormat == 3 )
- Free_Device( &cv->cvf.cvf3.Device, memory );
- }
-
-
- /* LigGlyph */
-
- static FT_Error Load_LigGlyph( TTO_LigGlyph* lg,
- FT_Stream stream )
- {
- FT_Memory memory = stream->memory;
- FT_Error error;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_CaretValue* cv;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = lg->CaretCount = GET_UShort();
-
- FORGET_Frame();
-
- lg->CaretValue = NULL;
-
- if ( ALLOC_ARRAY( lg->CaretValue, count, TTO_CaretValue ) )
- return error;
-
- cv = lg->CaretValue;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_CaretValue( &cv[n], stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_CaretValue( &cv[m], memory );
-
- FREE( cv );
- return error;
- }
-
-
- static void Free_LigGlyph( TTO_LigGlyph* lg,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_CaretValue* cv;
-
-
- if ( lg->CaretValue )
- {
- count = lg->CaretCount;
- cv = lg->CaretValue;
-
- for ( n = 0; n < count; n++ )
- Free_CaretValue( &cv[n], memory );
-
- FREE( cv );
- }
- }
-
-
- /* LigCaretList */
-
- static FT_Error Load_LigCaretList( TTO_LigCaretList* lcl,
- FT_Stream stream )
- {
- FT_Memory memory = stream->memory;
- FT_Error error;
-
- FT_UShort m, n, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_LigGlyph* lg;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &lcl->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = lcl->LigGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- lcl->LigGlyph = NULL;
-
- if ( ALLOC_ARRAY( lcl->LigGlyph, count, TTO_LigGlyph ) )
- goto Fail2;
-
- lg = lcl->LigGlyph;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LigGlyph( &lg[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- lcl->loaded = TRUE;
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_LigGlyph( &lg[m], memory );
-
- FREE( lg );
-
- Fail2:
- Free_Coverage( &lcl->Coverage, memory );
- return error;
- }
-
-
- static void Free_LigCaretList( TTO_LigCaretList* lcl,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_LigGlyph* lg;
-
-
- if ( !lcl->loaded )
- return;
-
- if ( lcl->LigGlyph )
- {
- count = lcl->LigGlyphCount;
- lg = lcl->LigGlyph;
-
- for ( n = 0; n < count; n++ )
- Free_LigGlyph( &lg[n], memory );
-
- FREE( lg );
- }
-
- Free_Coverage( &lcl->Coverage, memory );
- }
-
-
-
- /***********
- * GDEF API
- ***********/
-
-
- static FT_UShort Get_New_Class( TTO_GDEFHeader* gdef,
- FT_UShort glyphID,
- FT_UShort index )
- {
- FT_UShort glyph_index, array_index, count;
- FT_UShort byte, bits;
-
- TTO_ClassRangeRecord* gcrr;
- FT_UShort** ngc;
-
-
- if ( glyphID >= gdef->LastGlyph )
- return 0;
-
- count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
- gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
- ngc = gdef->NewGlyphClasses;
-
- if ( index < count && glyphID < gcrr[index].Start )
- {
- array_index = index;
- if ( index == 0 )
- glyph_index = glyphID;
- else
- glyph_index = glyphID - gcrr[index - 1].End - 1;
- }
- else
- {
- array_index = index + 1;
- glyph_index = glyphID - gcrr[index].End - 1;
- }
-
- byte = ngc[array_index][glyph_index / 4];
- bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
-
- return bits & 0x000F;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GDEF_Get_Glyph_Property( TTO_GDEFHeader* gdef,
- FT_UShort glyphID,
- FT_UShort* property )
- {
- FT_UShort class, index;
-
- FT_Error error;
-
-
- if ( !gdef || !property )
- return TT_Err_Invalid_Argument;
-
- /* first, we check for mark attach classes */
-
- if ( gdef->MarkAttachClassDef.loaded )
- {
- error = Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
- if ( !error )
- {
- *property = class << 8;
- return TT_Err_Ok;
- }
- }
-
- error = Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- /* if we have a constructed class table, check whether additional
- values have been assigned */
-
- if ( error == TTO_Err_Not_Covered && gdef->NewGlyphClasses )
- class = Get_New_Class( gdef, glyphID, index );
-
- switch ( class )
- {
- case UNCLASSIFIED_GLYPH:
- *property = 0;
- break;
-
- case SIMPLE_GLYPH:
- *property = TTO_BASE_GLYPH;
- break;
-
- case LIGATURE_GLYPH:
- *property = TTO_LIGATURE;
- break;
-
- case MARK_GLYPH:
- *property = TTO_MARK;
- break;
-
- case COMPONENT_GLYPH:
- *property = TTO_COMPONENT;
- break;
- }
-
- return TT_Err_Ok;
- }
-
-
- static FT_Error Make_ClassRange( TTO_ClassDefinition* cd,
- FT_UShort start,
- FT_UShort end,
- FT_UShort class,
- FT_Memory memory )
- {
- FT_Error error;
- FT_UShort index;
-
- TTO_ClassDefFormat2* cdf2;
- TTO_ClassRangeRecord* crr;
-
-
- cdf2 = &cd->cd.cd2;
-
- if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,
- cdf2->ClassRangeCount,
- cdf2->ClassRangeCount + 1 ,
- TTO_ClassRangeRecord ) )
- return error;
-
- cdf2->ClassRangeCount++;
-
- crr = cdf2->ClassRangeRecord;
- index = cdf2->ClassRangeCount - 1;
-
- crr[index].Start = start;
- crr[index].End = end;
- crr[index].Class = class;
-
- cd->Defined[class] = TRUE;
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GDEF_Build_ClassDefinition( TTO_GDEFHeader* gdef,
- FT_UShort num_glyphs,
- FT_UShort glyph_count,
- FT_UShort* glyph_array,
- FT_UShort* class_array )
- {
- FT_UShort start, curr_glyph, curr_class;
- FT_UShort n, m, count;
- FT_Error error;
- FT_Memory memory = gdef->memory;
-
- TTO_ClassDefinition* gcd;
- TTO_ClassRangeRecord* gcrr;
- FT_UShort** ngc;
-
-
- if ( !gdef || !glyph_array || !class_array )
- return TT_Err_Invalid_Argument;
-
- gcd = &gdef->GlyphClassDef;
-
- /* We build a format 2 table */
-
- gcd->ClassFormat = 2;
-
- /* A GlyphClassDef table contains at most 5 different class values */
-
- if ( ALLOC_ARRAY( gcd->Defined, 5, FT_Bool ) )
- return error;
-
- gcd->cd.cd2.ClassRangeCount = 0;
- gcd->cd.cd2.ClassRangeRecord = NULL;
-
- start = glyph_array[0];
- curr_class = class_array[0];
- curr_glyph = start;
-
- if ( curr_class >= 5 )
- {
- error = TT_Err_Invalid_Argument;
- goto Fail4;
- }
-
- glyph_count--;
-
- for ( n = 0; n <= glyph_count; n++ )
- {
- if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )
- {
- if ( n == glyph_count )
- {
- if ( ( error = Make_ClassRange( gcd, start,
- curr_glyph,
- curr_class,
- memory ) ) != TT_Err_Ok )
- goto Fail3;
- }
- else
- {
- if ( curr_glyph == 0xFFFF )
- {
- error = TT_Err_Invalid_Argument;
- goto Fail3;
- }
- else
- curr_glyph++;
- }
- }
- else
- {
- if ( ( error = Make_ClassRange( gcd, start,
- curr_glyph - 1,
- curr_class,
- memory ) ) != TT_Err_Ok )
- goto Fail3;
-
- if ( curr_glyph > glyph_array[n] )
- {
- error = TT_Err_Invalid_Argument;
- goto Fail3;
- }
-
- start = glyph_array[n];
- curr_class = class_array[n];
- curr_glyph = start;
-
- if ( curr_class >= 5 )
- {
- error = TT_Err_Invalid_Argument;
- goto Fail3;
- }
-
- if ( n == glyph_count )
- {
- if ( ( error = Make_ClassRange( gcd, start,
- curr_glyph,
- curr_class,
- memory ) ) != TT_Err_Ok )
- goto Fail3;
- }
- else
- {
- if ( curr_glyph == 0xFFFF )
- {
- error = TT_Err_Invalid_Argument;
- goto Fail3;
- }
- else
- curr_glyph++;
- }
- }
- }
-
- /* now prepare the arrays for class values assigned during the lookup
- process */
-
- if ( ALLOC_ARRAY( gdef->NewGlyphClasses,
- gcd->cd.cd2.ClassRangeCount + 1, FT_UShort* ) )
- goto Fail3;
-
- count = gcd->cd.cd2.ClassRangeCount;
- gcrr = gcd->cd.cd2.ClassRangeRecord;
- ngc = gdef->NewGlyphClasses;
-
- /* We allocate arrays for all glyphs not covered by the class range
- records. Each element holds four class values. */
-
- if ( count > 0 )
- {
- if ( gcrr[0].Start )
- {
- if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, FT_UShort ) )
- goto Fail2;
- }
-
- for ( n = 1; n < count; n++ )
- {
- if ( gcrr[n].Start - gcrr[n - 1].End > 1 )
- if ( ALLOC_ARRAY( ngc[n],
- ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4,
- FT_UShort ) )
- goto Fail1;
- }
-
- if ( gcrr[count - 1].End != num_glyphs - 1 )
- {
- if ( ALLOC_ARRAY( ngc[count],
- ( num_glyphs - gcrr[count - 1].End + 2 ) / 4,
- FT_UShort ) )
- goto Fail1;
- }
- }
- else if ( num_glyphs > 0 )
- {
- if ( ALLOC_ARRAY( ngc[count],
- ( num_glyphs + 3 ) / 4,
- FT_UShort ) )
- goto Fail2;
- }
-
- gdef->LastGlyph = num_glyphs - 1;
-
- gdef->MarkAttachClassDef_offset = 0L;
- gdef->MarkAttachClassDef.loaded = FALSE;
-
- gcd->loaded = TRUE;
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- FREE( ngc[m] );
-
- Fail2:
- FREE( gdef->NewGlyphClasses );
-
- Fail3:
- FREE( gcd->cd.cd2.ClassRangeRecord );
-
- Fail4:
- FREE( gcd->Defined );
- return error;
- }
-
-
- static void Free_NewGlyphClasses( TTO_GDEFHeader* gdef,
- FT_Memory memory )
- {
- FT_UShort** ngc;
- FT_UShort n, count;
-
-
- if ( gdef->NewGlyphClasses )
- {
- count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1;
- ngc = gdef->NewGlyphClasses;
-
- for ( n = 0; n < count; n++ )
- FREE( ngc[n] );
-
- FREE( ngc );
- }
- }
-
-
- FT_Error Add_Glyph_Property( TTO_GDEFHeader* gdef,
- FT_UShort glyphID,
- FT_UShort property )
- {
- FT_Error error;
- FT_UShort class, new_class, index;
- FT_UShort byte, bits, mask;
- FT_UShort array_index, glyph_index, count;
-
- TTO_ClassRangeRecord* gcrr;
- FT_UShort** ngc;
-
-
- error = Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- /* we don't accept glyphs covered in `GlyphClassDef' */
-
- if ( !error )
- return TTO_Err_Not_Covered;
-
- switch ( property )
- {
- case 0:
- new_class = UNCLASSIFIED_GLYPH;
- break;
-
- case TTO_BASE_GLYPH:
- new_class = SIMPLE_GLYPH;
- break;
-
- case TTO_LIGATURE:
- new_class = LIGATURE_GLYPH;
- break;
-
- case TTO_MARK:
- new_class = MARK_GLYPH;
- break;
-
- case TTO_COMPONENT:
- new_class = COMPONENT_GLYPH;
- break;
-
- default:
- return TT_Err_Invalid_Argument;
- }
-
- count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
- gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
- ngc = gdef->NewGlyphClasses;
-
- if ( index < count && glyphID < gcrr[index].Start )
- {
- array_index = index;
- if ( index == 0 )
- glyph_index = glyphID;
- else
- glyph_index = glyphID - gcrr[index - 1].End - 1;
- }
- else
- {
- array_index = index + 1;
- glyph_index = glyphID - gcrr[index].End - 1;
- }
-
- byte = ngc[array_index][glyph_index / 4];
- bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
- class = bits & 0x000F;
-
- /* we don't overwrite existing entries */
-
- if ( !class )
- {
- bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 );
- mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) );
-
- ngc[array_index][glyph_index / 4] &= mask;
- ngc[array_index][glyph_index / 4] |= bits;
- }
-
- return TT_Err_Ok;
- }
-
-
- FT_Error Check_Property( TTO_GDEFHeader* gdef,
- OTL_GlyphItem gitem,
- FT_UShort flags,
- FT_UShort* property )
- {
- FT_Error error;
-
- if ( gdef )
- {
- FT_UShort basic_glyph_class;
- FT_UShort desired_attachment_class;
-
- if ( gitem->gproperties == OTL_GLYPH_PROPERTIES_UNKNOWN )
- {
- error = TT_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties );
- if ( error )
- return error;
- }
-
- *property = gitem->gproperties;
-
- /* If the glyph was found in the MarkAttachmentClass table,
- * then that class value is the high byte of the result,
- * otherwise the low byte contains the basic type of the glyph
- * as defined by the GlyphClassDef table.
- */
- if ( *property & IGNORE_SPECIAL_MARKS )
- basic_glyph_class = TTO_MARK;
- else
- basic_glyph_class = *property;
-
- /* Return Not_Covered, if, for example, basic_glyph_class
- * is TTO_LIGATURE and LookFlags includes IGNORE_LIGATURES
- */
- if ( flags & basic_glyph_class )
- return TTO_Err_Not_Covered;
-
- /* The high byte of LookupFlags has the meaning
- * "ignore marks of attachment type different than
- * the attachment type specified."
- */
- desired_attachment_class = flags & IGNORE_SPECIAL_MARKS;
- if ( desired_attachment_class )
- {
- if ( basic_glyph_class == TTO_MARK &&
- *property != desired_attachment_class )
- return TTO_Err_Not_Covered;
- }
- }
-
- return TT_Err_Ok;
- }
-
-
-/* END */
diff --git a/pango/opentype/ftxgdef.h b/pango/opentype/ftxgdef.h
deleted file mode 100644
index f22438eb..00000000
--- a/pango/opentype/ftxgdef.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*******************************************************************
- *
- * ftxgdef.h
- *
- * TrueType Open GDEF table support
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#ifndef FTXOPEN_H
-#error "Don't include this file! Use ftxopen.h instead."
-#endif
-
-#ifndef FTXGDEF_H
-#define FTXGDEF_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define TTO_Err_Invalid_GDEF_SubTable_Format 0x1030
-#define TTO_Err_Invalid_GDEF_SubTable 0x1031
-
-
-/* GDEF glyph classes */
-
-#define UNCLASSIFIED_GLYPH 0
-#define SIMPLE_GLYPH 1
-#define LIGATURE_GLYPH 2
-#define MARK_GLYPH 3
-#define COMPONENT_GLYPH 4
-
-/* GDEF glyph properties, corresponding to class values 1-4. Note that
- TTO_COMPONENT has no corresponding flag in the LookupFlag field. */
-
-#define TTO_BASE_GLYPH 0x0002
-#define TTO_LIGATURE 0x0004
-#define TTO_MARK 0x0008
-#define TTO_COMPONENT 0x0010
-
-
- /* Attachment related structures */
-
- struct TTO_AttachPoint_
- {
- FT_UShort PointCount; /* size of the PointIndex array */
- FT_UShort* PointIndex; /* array of contour points */
- };
-
- typedef struct TTO_AttachPoint_ TTO_AttachPoint;
-
-
- struct TTO_AttachList_
- {
- FT_Bool loaded;
-
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort GlyphCount; /* number of glyphs with
- attachments */
- TTO_AttachPoint* AttachPoint; /* array of AttachPoint tables */
- };
-
- typedef struct TTO_AttachList_ TTO_AttachList;
-
-
- /* Ligature Caret related structures */
-
- struct TTO_CaretValueFormat1_
- {
- FT_Short Coordinate; /* x or y value (in design units) */
- };
-
- typedef struct TTO_CaretValueFormat1_ TTO_CaretValueFormat1;
-
-
- struct TTO_CaretValueFormat2_
- {
- FT_UShort CaretValuePoint; /* contour point index on glyph */
- };
-
- typedef struct TTO_CaretValueFormat2_ TTO_CaretValueFormat2;
-
-
- struct TTO_CaretValueFormat3_
- {
- FT_Short Coordinate; /* x or y value (in design units) */
- TTO_Device Device; /* Device table for x or y value */
- };
-
- typedef struct TTO_CaretValueFormat3_ TTO_CaretValueFormat3;
-
-
- struct TTO_CaretValueFormat4_
- {
- FT_UShort IdCaretValue; /* metric ID */
- };
-
- typedef struct TTO_CaretValueFormat4_ TTO_CaretValueFormat4;
-
-
- struct TTO_CaretValue_
- {
- FT_UShort CaretValueFormat; /* 1, 2, 3, or 4 */
-
- union
- {
- TTO_CaretValueFormat1 cvf1;
- TTO_CaretValueFormat2 cvf2;
- TTO_CaretValueFormat3 cvf3;
- TTO_CaretValueFormat4 cvf4;
- } cvf;
- };
-
- typedef struct TTO_CaretValue_ TTO_CaretValue;
-
-
- struct TTO_LigGlyph_
- {
- FT_Bool loaded;
-
- FT_UShort CaretCount; /* number of caret values */
- TTO_CaretValue* CaretValue; /* array of caret values */
- };
-
- typedef struct TTO_LigGlyph_ TTO_LigGlyph;
-
-
- struct TTO_LigCaretList_
- {
- FT_Bool loaded;
-
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort LigGlyphCount; /* number of ligature glyphs */
- TTO_LigGlyph* LigGlyph; /* array of LigGlyph tables */
- };
-
- typedef struct TTO_LigCaretList_ TTO_LigCaretList;
-
-
- /* The `NewGlyphClasses' field is not defined in the TTO specification.
- We use it for fonts with a constructed `GlyphClassDef' structure
- (i.e., which don't have a GDEF table) to collect glyph classes
- assigned during the lookup process. The number of arrays in this
- pointer array is GlyphClassDef->cd.cd2.ClassRangeCount+1; the nth
- array then contains the glyph class values of the glyphs not covered
- by the ClassRangeRecords structures with index n-1 and n. We store
- glyph class values for four glyphs in a single array element.
-
- `LastGlyph' is identical to the number of glyphs minus one in the
- font; we need it only if `NewGlyphClasses' is not NULL (to have an
- upper bound for the last array).
-
- Note that we first store the file offset to the `MarkAttachClassDef'
- field (which has been introduced in OpenType 1.2) -- since the
- `Version' field value hasn't been increased to indicate that we have
- one more field for some obscure reason, we must parse the GSUB table
- to find out whether class values refer to this table. Only then we
- can finally load the MarkAttachClassDef structure if necessary. */
-
- struct TTO_GDEFHeader_
- {
- FT_Memory memory;
- FT_ULong offset;
-
- FT_Fixed Version;
-
- TTO_ClassDefinition GlyphClassDef;
- TTO_AttachList AttachList;
- TTO_LigCaretList LigCaretList;
- FT_ULong MarkAttachClassDef_offset;
- TTO_ClassDefinition MarkAttachClassDef; /* new in OT 1.2 */
-
- FT_UShort LastGlyph;
- FT_UShort** NewGlyphClasses;
- };
-
- typedef struct TTO_GDEFHeader_ TTO_GDEFHeader;
- typedef struct TTO_GDEFHeader_* TTO_GDEF;
-
-
- /* finally, the GDEF API */
-
- /* EXPORT_DEF
- FT_Error TT_Init_GDEF_Extension( TT_Engine engine ); */
-
- EXPORT_FUNC
- FT_Error TT_New_GDEF_Table( FT_Face face,
- TTO_GDEFHeader** retptr );
-
- EXPORT_DEF
- FT_Error TT_Load_GDEF_Table( FT_Face face,
- TTO_GDEFHeader** gdef );
-
- EXPORT_DEF
- FT_Error TT_Done_GDEF_Table ( TTO_GDEFHeader* gdef );
-
- EXPORT_DEF
- FT_Error TT_GDEF_Get_Glyph_Property( TTO_GDEFHeader* gdef,
- FT_UShort glyphID,
- FT_UShort* property );
- EXPORT_DEF
- FT_Error TT_GDEF_Build_ClassDefinition( TTO_GDEFHeader* gdef,
- FT_UShort num_glyphs,
- FT_UShort glyph_count,
- FT_UShort* glyph_array,
- FT_UShort* class_array );
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* FTXGDEF_H */
-
-
-/* END */
diff --git a/pango/opentype/ftxgpos.c b/pango/opentype/ftxgpos.c
deleted file mode 100644
index 69efd070..00000000
--- a/pango/opentype/ftxgpos.c
+++ /dev/null
@@ -1,6199 +0,0 @@
-/*******************************************************************
- *
- * ftxgpos.c
- *
- * TrueType Open GPOS table support.
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#include <config.h>
-
-/* XXX There is *a lot* of duplicated code (cf. formats 7 and 8), but
- I don't care currently. I believe that it would be possible to
- save about 50% of TTO code by carefully designing the structures,
- sharing as much as possible with extensive use of macros. This
- is something for a volunteer :-) */
-
-#include "ftxopen.h"
-#include "ftxopenf.h"
-
-#include "ftglue.h"
-
-#include FT_TRUETYPE_TAGS_H
-
-#define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
-
- struct GPOS_Instance_
- {
- TTO_GPOSHeader* gpos;
- FT_Face face;
- FT_Bool dvi;
- FT_UShort load_flags; /* how the glyph should be loaded */
- FT_Bool r2l;
-
- FT_UShort last; /* the last valid glyph -- used
- with cursive positioning */
- FT_Pos anchor_x; /* the coordinates of the anchor point */
- FT_Pos anchor_y; /* of the last valid glyph */
- };
-
- typedef struct GPOS_Instance_ GPOS_Instance;
-
-
- static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
- FT_UShort lookup_index,
- OTL_Buffer buffer,
- FT_UShort context_length,
- int nesting_level );
-
-
-#define IN_GLYPH( pos ) (buffer->in_string[(pos)].gindex)
-#define IN_ITEM( pos ) (&buffer->in_string[(pos)])
-#define IN_CURGLYPH() (buffer->in_string[buffer->in_pos].gindex)
-#define IN_CURITEM() (&buffer->in_string[buffer->in_pos])
-#define IN_PROPERTIES( pos ) (buffer->in_string[(pos)].properties)
-#define IN_LIGID( pos ) (buffer->in_string[(pos)].ligID)
-#define IN_COMPONENT( pos ) (buffer->in_string[(pos)].component)
-#define POSITION( pos ) (&buffer->positions[(pos)])
-
-/* the client application must replace this with something more
- meaningful if multiple master fonts are to be supported. */
-
- static FT_Error default_mmfunc( FT_Face face,
- FT_UShort metric_id,
- FT_Pos* metric_value,
- void* data )
- {
- return TTO_Err_No_MM_Interpreter;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_Load_GPOS_Table( FT_Face face,
- TTO_GPOSHeader** retptr,
- TTO_GDEFHeader* gdef )
- {
- FT_ULong cur_offset, new_offset, base_offset;
-
- FT_UShort i, num_lookups;
- TTO_GPOSHeader* gpos;
- TTO_Lookup* lo;
-
- FT_Stream stream = face->stream;
- FT_Error error;
- FT_Memory memory = face->memory;
-
-
- if ( !retptr )
- return TT_Err_Invalid_Argument;
-
- if ( !stream )
- return TT_Err_Invalid_Face_Handle;
-
- if (( error = ftglue_face_goto_table( face, TTAG_GPOS, stream ) ))
- return error;
-
- base_offset = FILE_Pos();
-
- if ( ALLOC ( gpos, sizeof( *gpos ) ) )
- return error;
-
- gpos->memory = memory;
- gpos->gfunc = FT_Load_Glyph;
- gpos->mmfunc = default_mmfunc;
-
- /* skip version */
-
- if ( FILE_Seek( base_offset + 4L ) ||
- ACCESS_Frame( 2L ) )
- goto Fail4;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ScriptList( &gpos->ScriptList,
- stream ) ) != TT_Err_Ok )
- goto Fail4;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_FeatureList( &gpos->FeatureList,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LookupList( &gpos->LookupList,
- stream, GPOS ) ) != TT_Err_Ok )
- goto Fail2;
-
- gpos->gdef = gdef; /* can be NULL */
-
- /* We now check the LookupFlags for values larger than 0xFF to find
- out whether we need to load the `MarkAttachClassDef' field of the
- GDEF table -- this hack is necessary for OpenType 1.2 tables since
- the version field of the GDEF table hasn't been incremented.
-
- For constructed GDEF tables, we only load it if
- `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
- a constructed mark attach table is not supported currently). */
-
- if ( gdef &&
- gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
- {
- lo = gpos->LookupList.Lookup;
- num_lookups = gpos->LookupList.LookupCount;
-
- for ( i = 0; i < num_lookups; i++ )
- {
- if ( lo[i].LookupFlag & IGNORE_SPECIAL_MARKS )
- {
- if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
- ( error = Load_ClassDefinition( &gdef->MarkAttachClassDef,
- 256, stream ) ) != TT_Err_Ok )
- goto Fail1;
-
- break;
- }
- }
- }
-
- *retptr = gpos;
-
- return TT_Err_Ok;
-
- Fail1:
- Free_LookupList( &gpos->LookupList, GPOS, memory );
-
- Fail2:
- Free_FeatureList( &gpos->FeatureList, memory );
-
- Fail3:
- Free_ScriptList( &gpos->ScriptList, memory );
-
- Fail4:
- FREE( gpos );
-
- return error;
- }
-
- EXPORT_FUNC
- FT_Error TT_Done_GPOS_Table( TTO_GPOSHeader* gpos )
- {
- FT_Memory memory = gpos->memory;
-
- Free_LookupList( &gpos->LookupList, GPOS, memory );
- Free_FeatureList( &gpos->FeatureList, memory );
- Free_ScriptList( &gpos->ScriptList, memory );
-
- return FT_Err_Ok;
- }
-
-
- /*****************************
- * SubTable related functions
- *****************************/
-
- /* shared tables */
-
- /* ValueRecord */
-
- /* There is a subtle difference in the specs between a `table' and a
- `record' -- offsets for device tables in ValueRecords are taken from
- the parent table and not the parent record. */
-
- static FT_Error Load_ValueRecord( TTO_ValueRecord* vr,
- FT_UShort format,
- FT_ULong base_offset,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_ULong cur_offset, new_offset;
-
-
- if ( format & HAVE_X_PLACEMENT )
- {
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- vr->XPlacement = GET_Short();
-
- FORGET_Frame();
- }
- else
- vr->XPlacement = 0;
-
- if ( format & HAVE_Y_PLACEMENT )
- {
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- vr->YPlacement = GET_Short();
-
- FORGET_Frame();
- }
- else
- vr->YPlacement = 0;
-
- if ( format & HAVE_X_ADVANCE )
- {
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- vr->XAdvance = GET_Short();
-
- FORGET_Frame();
- }
- else
- vr->XAdvance = 0;
-
- if ( format & HAVE_Y_ADVANCE )
- {
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- vr->YAdvance = GET_Short();
-
- FORGET_Frame();
- }
- else
- vr->YAdvance = 0;
-
- if ( format & HAVE_X_PLACEMENT_DEVICE )
- {
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Device( &vr->XPlacementDevice,
- stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
- }
- else
- goto empty1;
- }
- else
- {
- empty1:
- vr->XPlacementDevice.StartSize = 0;
- vr->XPlacementDevice.EndSize = 0;
- vr->XPlacementDevice.DeltaValue = NULL;
- }
-
- if ( format & HAVE_Y_PLACEMENT_DEVICE )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Device( &vr->YPlacementDevice,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
- }
- else
- goto empty2;
- }
- else
- {
- empty2:
- vr->YPlacementDevice.StartSize = 0;
- vr->YPlacementDevice.EndSize = 0;
- vr->YPlacementDevice.DeltaValue = NULL;
- }
-
- if ( format & HAVE_X_ADVANCE_DEVICE )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Device( &vr->XAdvanceDevice,
- stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
- }
- else
- goto empty3;
- }
- else
- {
- empty3:
- vr->XAdvanceDevice.StartSize = 0;
- vr->XAdvanceDevice.EndSize = 0;
- vr->XAdvanceDevice.DeltaValue = NULL;
- }
-
- if ( format & HAVE_Y_ADVANCE_DEVICE )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Device( &vr->YAdvanceDevice,
- stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
- else
- goto empty4;
- }
- else
- {
- empty4:
- vr->YAdvanceDevice.StartSize = 0;
- vr->YAdvanceDevice.EndSize = 0;
- vr->YAdvanceDevice.DeltaValue = NULL;
- }
-
- if ( format & HAVE_X_ID_PLACEMENT )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- vr->XIdPlacement = GET_UShort();
-
- FORGET_Frame();
- }
- else
- vr->XIdPlacement = 0;
-
- if ( format & HAVE_Y_ID_PLACEMENT )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- vr->YIdPlacement = GET_UShort();
-
- FORGET_Frame();
- }
- else
- vr->YIdPlacement = 0;
-
- if ( format & HAVE_X_ID_ADVANCE )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- vr->XIdAdvance = GET_UShort();
-
- FORGET_Frame();
- }
- else
- vr->XIdAdvance = 0;
-
- if ( format & HAVE_Y_ID_ADVANCE )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- vr->YIdAdvance = GET_UShort();
-
- FORGET_Frame();
- }
- else
- vr->YIdAdvance = 0;
-
- return TT_Err_Ok;
-
- Fail1:
- Free_Device( &vr->YAdvanceDevice, memory );
-
- Fail2:
- Free_Device( &vr->XAdvanceDevice, memory );
-
- Fail3:
- Free_Device( &vr->YPlacementDevice, memory );
- return error;
- }
-
-
- static void Free_ValueRecord( TTO_ValueRecord* vr,
- FT_UShort format,
- FT_Memory memory )
- {
- if ( format & HAVE_Y_ADVANCE_DEVICE )
- Free_Device( &vr->YAdvanceDevice, memory );
- if ( format & HAVE_X_ADVANCE_DEVICE )
- Free_Device( &vr->XAdvanceDevice, memory );
- if ( format & HAVE_Y_PLACEMENT_DEVICE )
- Free_Device( &vr->YPlacementDevice, memory );
- if ( format & HAVE_X_PLACEMENT_DEVICE )
- Free_Device( &vr->XPlacementDevice, memory );
- }
-
-
- static FT_Error Get_ValueRecord( GPOS_Instance* gpi,
- TTO_ValueRecord* vr,
- FT_UShort format,
- OTL_Position gd )
- {
- FT_Pos value;
- FT_Short pixel_value;
- FT_Error error = TT_Err_Ok;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- FT_UShort x_ppem, y_ppem;
- FT_Fixed x_scale, y_scale;
-
-
- if ( !format )
- return TT_Err_Ok;
-
- x_ppem = gpi->face->size->metrics.x_ppem;
- y_ppem = gpi->face->size->metrics.y_ppem;
- x_scale = gpi->face->size->metrics.x_scale;
- y_scale = gpi->face->size->metrics.y_scale;
-
- /* design units -> fractional pixel */
-
- if ( format & HAVE_X_PLACEMENT )
- gd->x_pos += x_scale * vr->XPlacement / 0x10000;
- if ( format & HAVE_Y_PLACEMENT )
- gd->y_pos += y_scale * vr->YPlacement / 0x10000;
- if ( format & HAVE_X_ADVANCE )
- gd->x_advance += x_scale * vr->XAdvance / 0x10000;
- if ( format & HAVE_Y_ADVANCE )
- gd->y_advance += y_scale * vr->YAdvance / 0x10000;
-
- if ( !gpi->dvi )
- {
- /* pixel -> fractional pixel */
-
- if ( format & HAVE_X_PLACEMENT_DEVICE )
- {
- Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );
- gd->x_pos += pixel_value << 6;
- }
- if ( format & HAVE_Y_PLACEMENT_DEVICE )
- {
- Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );
- gd->y_pos += pixel_value << 6;
- }
- if ( format & HAVE_X_ADVANCE_DEVICE )
- {
- Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );
- gd->x_advance += pixel_value << 6;
- }
- if ( format & HAVE_Y_ADVANCE_DEVICE )
- {
- Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );
- gd->y_advance += pixel_value << 6;
- }
- }
-
- /* values returned from mmfunc() are already in fractional pixels */
-
- if ( format & HAVE_X_ID_PLACEMENT )
- {
- error = (gpos->mmfunc)( gpi->face, vr->XIdPlacement,
- &value, gpos->data );
- if ( error )
- return error;
- gd->x_pos += value;
- }
- if ( format & HAVE_Y_ID_PLACEMENT )
- {
- error = (gpos->mmfunc)( gpi->face, vr->YIdPlacement,
- &value, gpos->data );
- if ( error )
- return error;
- gd->y_pos += value;
- }
- if ( format & HAVE_X_ID_ADVANCE )
- {
- error = (gpos->mmfunc)( gpi->face, vr->XIdAdvance,
- &value, gpos->data );
- if ( error )
- return error;
- gd->x_advance += value;
- }
- if ( format & HAVE_Y_ID_ADVANCE )
- {
- error = (gpos->mmfunc)( gpi->face, vr->YIdAdvance,
- &value, gpos->data );
- if ( error )
- return error;
- gd->y_advance += value;
- }
-
- return error;
- }
-
-
- /* AnchorFormat1 */
- /* AnchorFormat2 */
- /* AnchorFormat3 */
- /* AnchorFormat4 */
-
- static FT_Error Load_Anchor( TTO_Anchor* an,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_ULong cur_offset, new_offset, base_offset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- an->PosFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( an->PosFormat )
- {
- case 1:
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- an->af.af1.XCoordinate = GET_Short();
- an->af.af1.YCoordinate = GET_Short();
-
- FORGET_Frame();
- break;
-
- case 2:
- if ( ACCESS_Frame( 6L ) )
- return error;
-
- an->af.af2.XCoordinate = GET_Short();
- an->af.af2.YCoordinate = GET_Short();
- an->af.af2.AnchorPoint = GET_UShort();
-
- FORGET_Frame();
- break;
-
- case 3:
- if ( ACCESS_Frame( 6L ) )
- return error;
-
- an->af.af3.XCoordinate = GET_Short();
- an->af.af3.YCoordinate = GET_Short();
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Device( &an->af.af3.XDeviceTable,
- stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
- }
- else
- {
- an->af.af3.XDeviceTable.StartSize = 0;
- an->af.af3.XDeviceTable.EndSize = 0;
- an->af.af3.XDeviceTable.DeltaValue = NULL;
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Device( &an->af.af3.YDeviceTable,
- stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
- else
- {
- an->af.af3.YDeviceTable.StartSize = 0;
- an->af.af3.YDeviceTable.EndSize = 0;
- an->af.af3.YDeviceTable.DeltaValue = NULL;
- }
- break;
-
- case 4:
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- an->af.af4.XIdAnchor = GET_UShort();
- an->af.af4.YIdAnchor = GET_UShort();
-
- FORGET_Frame();
- break;
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok;
-
- Fail:
- Free_Device( &an->af.af3.XDeviceTable, memory );
- return error;
- }
-
-
- static void Free_Anchor( TTO_Anchor* an,
- FT_Memory memory)
- {
- if ( an->PosFormat == 3 )
- {
- Free_Device( &an->af.af3.YDeviceTable, memory );
- Free_Device( &an->af.af3.XDeviceTable, memory );
- }
- }
-
-
- static FT_Error Get_Anchor( GPOS_Instance* gpi,
- TTO_Anchor* an,
- FT_UShort glyph_index,
- FT_Pos* x_value,
- FT_Pos* y_value )
- {
- FT_Error error = TT_Err_Ok;
-
- FT_Outline outline;
- TTO_GPOSHeader* gpos = gpi->gpos;
- FT_UShort ap;
-
- FT_Short pixel_value;
- FT_UShort load_flags;
-
- FT_UShort x_ppem, y_ppem;
- FT_Fixed x_scale, y_scale;
-
-
- x_ppem = gpi->face->size->metrics.x_ppem;
- y_ppem = gpi->face->size->metrics.y_ppem;
- x_scale = gpi->face->size->metrics.x_scale;
- y_scale = gpi->face->size->metrics.y_scale;
-
- switch ( an->PosFormat )
- {
- case 0:
- /* The special case of an empty AnchorTable */
-
- return TTO_Err_Not_Covered;
-
- case 1:
- *x_value = x_scale * an->af.af1.XCoordinate / 0x10000;
- *y_value = y_scale * an->af.af1.YCoordinate / 0x10000;
- break;
-
- case 2:
- /* glyphs must be scaled */
-
- load_flags = gpi->load_flags & ~FT_LOAD_NO_SCALE;
-
- if ( !gpi->dvi )
- {
- error = (gpos->gfunc)( gpi->face, glyph_index, load_flags );
- if ( error )
- return error;
-
- if ( gpi->face->glyph->format != ft_glyph_format_outline )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- ap = an->af.af2.AnchorPoint;
-
- outline = gpi->face->glyph->outline;
-
- /* if outline.n_points is set to zero by gfunc(), we use the
- design coordinate value pair. This can happen e.g. for
- sbit glyphs */
-
- if ( !outline.n_points )
- goto no_contour_point;
-
- if ( ap >= outline.n_points )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- *x_value = outline.points[ap].x;
- *y_value = outline.points[ap].y;
- }
- else
- {
- no_contour_point:
- *x_value = x_scale * an->af.af3.XCoordinate / 0x10000;
- *y_value = y_scale * an->af.af3.YCoordinate / 0x10000;
- }
- break;
-
- case 3:
- if ( !gpi->dvi )
- {
- Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );
- *x_value = pixel_value << 6;
- Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value );
- *y_value = pixel_value << 6;
- }
- else
- *x_value = *y_value = 0;
-
- *x_value += x_scale * an->af.af3.XCoordinate / 0x10000;
- *y_value += y_scale * an->af.af3.YCoordinate / 0x10000;
- break;
-
- case 4:
- error = (gpos->mmfunc)( gpi->face, an->af.af4.XIdAnchor,
- x_value, gpos->data );
- if ( error )
- return error;
-
- error = (gpos->mmfunc)( gpi->face, an->af.af4.YIdAnchor,
- y_value, gpos->data );
- if ( error )
- return error;
- break;
- }
-
- return error;
- }
-
-
- /* MarkArray */
-
- static FT_Error Load_MarkArray ( TTO_MarkArray* ma,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_MarkRecord* mr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = ma->MarkCount = GET_UShort();
-
- FORGET_Frame();
-
- ma->MarkRecord = NULL;
-
- if ( ALLOC_ARRAY( ma->MarkRecord, count, TTO_MarkRecord ) )
- return error;
-
- mr = ma->MarkRecord;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 4L ) )
- goto Fail;
-
- mr[n].Class = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_Anchor( &mr[m].MarkAnchor, memory );
-
- FREE( mr );
- return error;
- }
-
-
- static void Free_MarkArray( TTO_MarkArray* ma,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_MarkRecord* mr;
-
-
- if ( ma->MarkRecord )
- {
- count = ma->MarkCount;
- mr = ma->MarkRecord;
-
- for ( n = 0; n < count; n++ )
- Free_Anchor( &mr[n].MarkAnchor, memory );
-
- FREE( mr );
- }
- }
-
-
- /* LookupType 1 */
-
- /* SinglePosFormat1 */
- /* SinglePosFormat2 */
-
- FT_Error Load_SinglePos( TTO_SinglePos* sp,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count, format;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ValueRecord* vr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 6L ) )
- return error;
-
- sp->PosFormat = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- format = sp->ValueFormat = GET_UShort();
-
- FORGET_Frame();
-
- if ( !format )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &sp->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- switch ( sp->PosFormat )
- {
- case 1:
- error = Load_ValueRecord( &sp->spf.spf1.Value, format,
- base_offset, stream );
- if ( error )
- goto Fail2;
- break;
-
- case 2:
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = sp->spf.spf2.ValueCount = GET_UShort();
-
- FORGET_Frame();
-
- sp->spf.spf2.Value = NULL;
-
- if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, TTO_ValueRecord ) )
- goto Fail2;
-
- vr = sp->spf.spf2.Value;
-
- for ( n = 0; n < count; n++ )
- {
- error = Load_ValueRecord( &vr[n], format, base_offset, stream );
- if ( error )
- goto Fail1;
- }
- break;
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_ValueRecord( &vr[m], format, memory );
-
- FREE( vr );
-
- Fail2:
- Free_Coverage( &sp->Coverage, memory );
- return error;
- }
-
-
- void Free_SinglePos( TTO_SinglePos* sp,
- FT_Memory memory )
- {
- FT_UShort n, count, format;
-
- TTO_ValueRecord* v;
-
-
- format = sp->ValueFormat;
-
- switch ( sp->PosFormat )
- {
- case 1:
- Free_ValueRecord( &sp->spf.spf1.Value, format, memory );
- break;
-
- case 2:
- if ( sp->spf.spf2.Value )
- {
- count = sp->spf.spf2.ValueCount;
- v = sp->spf.spf2.Value;
-
- for ( n = 0; n < count; n++ )
- Free_ValueRecord( &v[n], format, memory );
-
- FREE( v );
- }
- break;
- }
-
- Free_Coverage( &sp->Coverage, memory );
- }
-
- static FT_Error Lookup_DefaultPos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- return TTO_Err_Not_Covered;
- }
-
- static FT_Error Lookup_SinglePos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
- TTO_SinglePos* sp = &st->single;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- return TTO_Err_Not_Covered;
-
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- switch ( sp->PosFormat )
- {
- case 1:
- error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
- sp->ValueFormat, POSITION( buffer->in_pos ) );
- if ( error )
- return error;
- break;
-
- case 2:
- if ( index >= sp->spf.spf2.ValueCount )
- return TTO_Err_Invalid_GPOS_SubTable;
- error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
- sp->ValueFormat, POSITION( buffer->in_pos ) );
- if ( error )
- return error;
- break;
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable;
- }
-
- (buffer->in_pos)++;
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 2 */
-
- /* PairSet */
-
- static FT_Error Load_PairSet ( TTO_PairSet* ps,
- FT_UShort format1,
- FT_UShort format2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong base_offset;
-
- TTO_PairValueRecord* pvr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = ps->PairValueCount = GET_UShort();
-
- FORGET_Frame();
-
- ps->PairValueRecord = NULL;
-
- if ( ALLOC_ARRAY( ps->PairValueRecord, count, TTO_PairValueRecord ) )
- return error;
-
- pvr = ps->PairValueRecord;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- pvr[n].SecondGlyph = GET_UShort();
-
- FORGET_Frame();
-
- if ( format1 )
- {
- error = Load_ValueRecord( &pvr[n].Value1, format1,
- base_offset, stream );
- if ( error )
- goto Fail;
- }
- if ( format2 )
- {
- error = Load_ValueRecord( &pvr[n].Value2, format2,
- base_offset, stream );
- if ( error )
- {
- if ( format1 )
- Free_ValueRecord( &pvr[n].Value1, format1, memory );
- goto Fail;
- }
- }
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- {
- if ( format1 )
- Free_ValueRecord( &pvr[m].Value1, format1, memory );
- if ( format2 )
- Free_ValueRecord( &pvr[m].Value2, format2, memory );
- }
-
- FREE( pvr );
- return error;
- }
-
-
- static void Free_PairSet( TTO_PairSet* ps,
- FT_UShort format1,
- FT_UShort format2,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_PairValueRecord* pvr;
-
-
- if ( ps->PairValueRecord )
- {
- count = ps->PairValueCount;
- pvr = ps->PairValueRecord;
-
- for ( n = 0; n < count; n++ )
- {
- if ( format1 )
- Free_ValueRecord( &pvr[n].Value1, format1, memory );
- if ( format2 )
- Free_ValueRecord( &pvr[n].Value2, format2, memory );
- }
-
- FREE( pvr );
- }
- }
-
-
- /* PairPosFormat1 */
-
- static FT_Error Load_PairPos1( TTO_PairPosFormat1* ppf1,
- FT_UShort format1,
- FT_UShort format2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_PairSet* ps;
-
-
- base_offset = FILE_Pos() - 8L;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = ppf1->PairSetCount = GET_UShort();
-
- FORGET_Frame();
-
- ppf1->PairSet = NULL;
-
- if ( ALLOC_ARRAY( ppf1->PairSet, count, TTO_PairSet ) )
- return error;
-
- ps = ppf1->PairSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_PairSet( &ps[n], format1,
- format2, stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_PairSet( &ps[m], format1, format2, memory );
-
- FREE( ps );
- return error;
- }
-
-
- static void Free_PairPos1( TTO_PairPosFormat1* ppf1,
- FT_UShort format1,
- FT_UShort format2,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_PairSet* ps;
-
-
- if ( ppf1->PairSet )
- {
- count = ppf1->PairSetCount;
- ps = ppf1->PairSet;
-
- for ( n = 0; n < count; n++ )
- Free_PairSet( &ps[n], format1, format2, memory );
-
- FREE( ps );
- }
- }
-
-
- /* PairPosFormat2 */
-
- static FT_Error Load_PairPos2( TTO_PairPosFormat2* ppf2,
- FT_UShort format1,
- FT_UShort format2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort m, n, k, count1, count2;
- FT_ULong cur_offset, new_offset1, new_offset2, base_offset;
-
- TTO_Class1Record* c1r;
- TTO_Class2Record* c2r;
-
-
- base_offset = FILE_Pos() - 8L;
-
- if ( ACCESS_Frame( 8L ) )
- return error;
-
- new_offset1 = GET_UShort() + base_offset;
- new_offset2 = GET_UShort() + base_offset;
-
- /* `Class1Count' and `Class2Count' are the upper limits for class
- values, thus we read it now to make additional safety checks. */
-
- count1 = ppf2->Class1Count = GET_UShort();
- count2 = ppf2->Class2Count = GET_UShort();
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset1 ) ||
- ( error = Load_ClassDefinition( &ppf2->ClassDef1, count1,
- stream ) ) != TT_Err_Ok )
- return error;
- if ( FILE_Seek( new_offset2 ) ||
- ( error = Load_ClassDefinition( &ppf2->ClassDef2, count2,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- ppf2->Class1Record = NULL;
-
- if ( ALLOC_ARRAY( ppf2->Class1Record, count1, TTO_Class1Record ) )
- goto Fail2;
-
- c1r = ppf2->Class1Record;
-
- for ( m = 0; m < count1; m++ )
- {
- c1r[m].Class2Record = NULL;
-
- if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, TTO_Class2Record ) )
- goto Fail1;
-
- c2r = c1r[m].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- {
- error = Load_ValueRecord( &c2r[n].Value1, format1,
- base_offset, stream );
- if ( error )
- goto Fail0;
- }
- if ( format2 )
- {
- error = Load_ValueRecord( &c2r[n].Value2, format2,
- base_offset, stream );
- if ( error )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1, memory );
- goto Fail0;
- }
- }
- }
-
- continue;
-
- Fail0:
- for ( k = 0; k < n; k++ )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[k].Value1, format1, memory );
- if ( format2 )
- Free_ValueRecord( &c2r[k].Value2, format2, memory );
- }
- goto Fail1;
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( k = 0; k < m; k++ )
- {
- c2r = c1r[k].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1, memory );
- if ( format2 )
- Free_ValueRecord( &c2r[n].Value2, format2, memory );
- }
-
- FREE( c2r );
- }
-
- FREE( c1r );
- Fail2:
-
- Free_ClassDefinition( &ppf2->ClassDef2, memory );
-
- Fail3:
- Free_ClassDefinition( &ppf2->ClassDef1, memory );
- return error;
- }
-
-
- static void Free_PairPos2( TTO_PairPosFormat2* ppf2,
- FT_UShort format1,
- FT_UShort format2,
- FT_Memory memory )
- {
- FT_UShort m, n, count1, count2;
-
- TTO_Class1Record* c1r;
- TTO_Class2Record* c2r;
-
-
- if ( ppf2->Class1Record )
- {
- c1r = ppf2->Class1Record;
- count1 = ppf2->Class1Count;
- count2 = ppf2->Class2Count;
-
- for ( m = 0; m < count1; m++ )
- {
- c2r = c1r[m].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1, memory );
- if ( format2 )
- Free_ValueRecord( &c2r[n].Value2, format2, memory );
- }
-
- FREE( c2r );
- }
-
- FREE( c1r );
-
- Free_ClassDefinition( &ppf2->ClassDef2, memory );
- Free_ClassDefinition( &ppf2->ClassDef1, memory );
- }
- }
-
-
- FT_Error Load_PairPos( TTO_PairPos* pp,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort format1, format2;
- FT_ULong cur_offset, new_offset, base_offset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 8L ) )
- return error;
-
- pp->PosFormat = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- format1 = pp->ValueFormat1 = GET_UShort();
- format2 = pp->ValueFormat2 = GET_UShort();
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &pp->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- switch ( pp->PosFormat )
- {
- case 1:
- error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );
- if ( error )
- goto Fail;
- break;
-
- case 2:
- error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );
- if ( error )
- goto Fail;
- break;
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok;
-
- Fail:
- Free_Coverage( &pp->Coverage, memory );
- return error;
- }
-
-
- void Free_PairPos( TTO_PairPos* pp,
- FT_Memory memory )
- {
- FT_UShort format1, format2;
-
-
- format1 = pp->ValueFormat1;
- format2 = pp->ValueFormat2;
-
- switch ( pp->PosFormat )
- {
- case 1:
- Free_PairPos1( &pp->ppf.ppf1, format1, format2, memory );
- break;
-
- case 2:
- Free_PairPos2( &pp->ppf.ppf2, format1, format2, memory );
- break;
- }
-
- Free_Coverage( &pp->Coverage, memory );
- }
-
-
- static FT_Error Lookup_PairPos1( GPOS_Instance* gpi,
- TTO_PairPosFormat1* ppf1,
- OTL_Buffer buffer,
- FT_UShort first_pos,
- FT_UShort index,
- FT_UShort format1,
- FT_UShort format2 )
- {
- FT_Error error;
- FT_UShort numpvr, glyph2;
-
- TTO_PairValueRecord* pvr;
-
-
- if ( index >= ppf1->PairSetCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- pvr = ppf1->PairSet[index].PairValueRecord;
- if ( !pvr )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- glyph2 = IN_CURGLYPH();
-
- for ( numpvr = ppf1->PairSet[index].PairValueCount;
- numpvr;
- numpvr--, pvr++ )
- {
- if ( glyph2 == pvr->SecondGlyph )
- {
- error = Get_ValueRecord( gpi, &pvr->Value1, format1,
- POSITION( first_pos ) );
- if ( error )
- return error;
- return Get_ValueRecord( gpi, &pvr->Value2, format2,
- POSITION( buffer->in_pos ) );
- }
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- static FT_Error Lookup_PairPos2( GPOS_Instance* gpi,
- TTO_PairPosFormat2* ppf2,
- OTL_Buffer buffer,
- FT_UShort first_pos,
- FT_UShort format1,
- FT_UShort format2 )
- {
- FT_Error error;
- FT_UShort cl1, cl2;
-
- TTO_Class1Record* c1r;
- TTO_Class2Record* c2r;
-
-
- error = Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
- &cl1, NULL );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
- error = Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),
- &cl2, NULL );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- c1r = &ppf2->Class1Record[cl1];
- if ( !c1r )
- return TTO_Err_Invalid_GPOS_SubTable;
- c2r = &c1r->Class2Record[cl2];
-
- error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
- if ( error )
- return error;
- return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
- }
-
-
- static FT_Error Lookup_PairPos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_Error error;
- FT_UShort index, property, first_pos;
- TTO_GPOSHeader* gpos = gpi->gpos;
- TTO_PairPos* pp = &st->pair;
-
-
- if ( buffer->in_pos >= buffer->in_length - 1 )
- return TTO_Err_Not_Covered; /* Not enough glyphs in stream */
-
- if ( context_length != 0xFFFF && context_length < 2 )
- return TTO_Err_Not_Covered;
-
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- /* second glyph */
-
- first_pos = buffer->in_pos;
- (buffer->in_pos)++;
-
- while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
- flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( buffer->in_pos == buffer->in_length )
- return TTO_Err_Not_Covered;
- (buffer->in_pos)++;
- }
-
- switch ( pp->PosFormat )
- {
- case 1:
- error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
- first_pos, index,
- pp->ValueFormat1, pp->ValueFormat2 );
- break;
-
- case 2:
- error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
- pp->ValueFormat1, pp->ValueFormat2 );
- break;
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- /* adjusting the `next' glyph */
-
- if ( pp->ValueFormat2 )
- (buffer->in_pos)++;
-
- return error;
- }
-
-
- /* LookupType 3 */
-
- /* CursivePosFormat1 */
-
- FT_Error Load_CursivePos( TTO_CursivePos* cp,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_EntryExitRecord* eer;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- cp->PosFormat = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &cp->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = cp->EntryExitCount = GET_UShort();
-
- FORGET_Frame();
-
- cp->EntryExitRecord = NULL;
-
- if ( ALLOC_ARRAY( cp->EntryExitRecord, count, TTO_EntryExitRecord ) )
- goto Fail2;
-
- eer = cp->EntryExitRecord;
-
- for ( n = 0; n < count; n++ )
- {
- FT_ULong entry_offset;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- entry_offset = new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Anchor( &eer[n].EntryAnchor,
- stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
- else
- eer[n].EntryAnchor.PosFormat = 0;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Anchor( &eer[n].ExitAnchor,
- stream ) ) != TT_Err_Ok )
- {
- if ( entry_offset )
- Free_Anchor( &eer[n].EntryAnchor, memory );
- goto Fail1;
- }
- (void)FILE_Seek( cur_offset );
- }
- else
- eer[n].ExitAnchor.PosFormat = 0;
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- {
- Free_Anchor( &eer[m].EntryAnchor, memory );
- Free_Anchor( &eer[m].ExitAnchor, memory );
- }
-
- FREE( eer );
-
- Fail2:
- Free_Coverage( &cp->Coverage, memory );
- return error;
- }
-
-
- void Free_CursivePos( TTO_CursivePos* cp,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_EntryExitRecord* eer;
-
-
- if ( cp->EntryExitRecord )
- {
- count = cp->EntryExitCount;
- eer = cp->EntryExitRecord;
-
- for ( n = 0; n < count; n++ )
- {
- Free_Anchor( &eer[n].EntryAnchor, memory );
- Free_Anchor( &eer[n].ExitAnchor, memory );
- }
-
- FREE( eer );
- }
-
- Free_Coverage( &cp->Coverage, memory );
- }
-
-
- static FT_Error Lookup_CursivePos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
- TTO_CursivePos* cp = &st->cursive;
-
- TTO_EntryExitRecord* eer;
- FT_Pos entry_x, entry_y;
- FT_Pos exit_x, exit_y;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- {
- gpi->last = 0xFFFF;
- return TTO_Err_Not_Covered;
- }
-
- /* Glyphs not having the right GDEF properties will be ignored, i.e.,
- gpi->last won't be reset (contrary to user defined properties). */
-
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- /* We don't handle mark glyphs here. According to Andrei, this isn't
- possible, but who knows... */
-
- if ( property == MARK_GLYPH )
- {
- gpi->last = 0xFFFF;
- return TTO_Err_Not_Covered;
- }
-
- error = Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- {
- gpi->last = 0xFFFF;
- return error;
- }
-
- if ( index >= cp->EntryExitCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- eer = &cp->EntryExitRecord[index];
-
- /* Now comes the messiest part of the whole OpenType
- specification. At first glance, cursive connections seem easy
- to understand, but there are pitfalls! The reason is that
- the specs don't mention how to compute the advance values
- resp. glyph offsets. I was told it would be an omission, to
- be fixed in the next OpenType version... Again many thanks to
- Andrei Burago <andreib@microsoft.com> for clarifications.
-
- Consider the following example:
-
- | xadv1 |
- +---------+
- | |
- +-----+--+ 1 |
- | | .| |
- | 0+--+------+
- | 2 |
- | |
- 0+--------+
- | xadv2 |
-
- glyph1: advance width = 12
- anchor point = (3,1)
-
- glyph2: advance width = 11
- anchor point = (9,4)
-
- LSB is 1 for both glyphs (so the boxes drawn above are glyph
- bboxes). Writing direction is R2L; `0' denotes the glyph's
- coordinate origin.
-
- Now the surprising part: The advance width of the *left* glyph
- (resp. of the *bottom* glyph) will be modified, no matter
- whether the writing direction is L2R or R2L (resp. T2B or
- B2T)! This assymetry is caused by the fact that the glyph's
- coordinate origin is always the lower left corner for all
- writing directions.
-
- Continuing the above example, we can compute the new
- (horizontal) advance width of glyph2 as
-
- 9 - 3 = 6 ,
-
- and the new vertical offset of glyph2 as
-
- 1 - 4 = -3 .
-
-
- Vertical writing direction is far more complicated:
-
- a) Assuming that we recompute the advance height of the lower glyph:
-
- --
- +---------+
- -- | |
- +-----+--+ 1 | yadv1
- | | .| |
- yadv2 | 0+--+------+ -- BSB1 --
- | 2 | -- -- y_offset
- | |
- BSB2 -- 0+--------+ --
- -- --
-
- glyph1: advance height = 6
- anchor point = (3,1)
-
- glyph2: advance height = 7
- anchor point = (9,4)
-
- TSB is 1 for both glyphs; writing direction is T2B.
-
-
- BSB1 = yadv1 - (TSB1 + ymax1)
- BSB2 = yadv2 - (TSB2 + ymax2)
- y_offset = y2 - y1
-
- vertical advance width of glyph2
- = y_offset + BSB2 - BSB1
- = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
- = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
- = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
-
-
- b) Assuming that we recompute the advance height of the upper glyph:
-
- -- --
- +---------+ -- TSB1
- -- -- | |
- TSB2 -- +-----+--+ 1 | yadv1 ymax1
- | | .| |
- yadv2 | 0+--+------+ -- --
- ymax2 | 2 | -- y_offset
- | |
- -- 0+--------+ --
- --
-
- glyph1: advance height = 6
- anchor point = (3,1)
-
- glyph2: advance height = 7
- anchor point = (9,4)
-
- TSB is 1 for both glyphs; writing direction is T2B.
-
- y_offset = y2 - y1
-
- vertical advance width of glyph2
- = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
- = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
-
-
- Comparing a) with b) shows that b) is easier to compute. I'll wait
- for a reply from Andrei to see what should really be implemented...
-
- Since horizontal advance widths or vertical advance heights
- can be used alone but not together, no ambiguity occurs. */
-
- if ( gpi->last == 0xFFFF )
- goto end;
-
- /* Get_Anchor() returns TTO_Err_Not_Covered if there is no anchor
- table. */
-
- error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),
- &entry_x, &entry_y );
- if ( error == TTO_Err_Not_Covered )
- goto end;
- if ( error )
- return error;
-
- if ( gpi->r2l )
- {
- POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
- POSITION( buffer->in_pos )->new_advance = TRUE;
- }
- else
- {
- POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
- POSITION( gpi->last )->new_advance = TRUE;
- }
-
- if ( flags & RIGHT_TO_LEFT )
- {
- POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
- POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
- }
- else
- {
- POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
- POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
- }
-
- end:
- error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),
- &exit_x, &exit_y );
- if ( error == TTO_Err_Not_Covered )
- gpi->last = 0xFFFF;
- else
- {
- gpi->last = buffer->in_pos;
- gpi->anchor_x = exit_x;
- gpi->anchor_y = exit_y;
- }
- if ( error )
- return error;
-
- (buffer->in_pos)++;
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 4 */
-
- /* BaseArray */
-
- static FT_Error Load_BaseArray( TTO_BaseArray* ba,
- FT_UShort num_classes,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort m, n, k, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_BaseRecord* br;
- TTO_Anchor* ban;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = ba->BaseCount = GET_UShort();
-
- FORGET_Frame();
-
- ba->BaseRecord = NULL;
-
- if ( ALLOC_ARRAY( ba->BaseRecord, count, TTO_BaseRecord ) )
- return error;
-
- br = ba->BaseRecord;
-
- for ( m = 0; m < count; m++ )
- {
- br[m].BaseAnchor = NULL;
-
- if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, TTO_Anchor ) )
- goto Fail;
-
- ban = br[m].BaseAnchor;
-
- for ( n = 0; n < num_classes; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail0;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- if (new_offset == base_offset) {
- /* Doulos SIL Regular is buggy and has zer offsets here. Skip */
- ban[n].PosFormat = 0;
- continue;
- }
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Anchor( &ban[n], stream ) ) != TT_Err_Ok )
- goto Fail0;
- (void)FILE_Seek( cur_offset );
- }
-
- continue;
- Fail0:
- for ( k = 0; k < n; k++ )
- Free_Anchor( &ban[k], memory );
- goto Fail;
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( k = 0; k < m; k++ )
- {
- ban = br[k].BaseAnchor;
-
- for ( n = 0; n < num_classes; n++ )
- Free_Anchor( &ban[n], memory );
-
- FREE( ban );
- }
-
- FREE( br );
- return error;
- }
-
-
- static void Free_BaseArray( TTO_BaseArray* ba,
- FT_UShort num_classes,
- FT_Memory memory )
- {
- FT_UShort m, n, count;
-
- TTO_BaseRecord* br;
- TTO_Anchor* ban;
-
-
- if ( ba->BaseRecord )
- {
- count = ba->BaseCount;
- br = ba->BaseRecord;
-
- for ( m = 0; m < count; m++ )
- {
- ban = br[m].BaseAnchor;
-
- for ( n = 0; n < num_classes; n++ )
- Free_Anchor( &ban[n], memory );
-
- FREE( ban );
- }
-
- FREE( br );
- }
- }
-
-
- /* MarkBasePosFormat1 */
-
- FT_Error Load_MarkBasePos( TTO_MarkBasePos* mbp,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_ULong cur_offset, new_offset, base_offset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- mbp->PosFormat = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- if (mbp->PosFormat != 1)
- return TTO_Err_Invalid_SubTable_Format;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &mbp->MarkCoverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &mbp->BaseCoverage, stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 4L ) )
- goto Fail2;
-
- mbp->ClassCount = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount,
- stream ) ) != TT_Err_Ok )
- goto Fail1;
-
- return TT_Err_Ok;
-
- Fail1:
- Free_MarkArray( &mbp->MarkArray, memory );
-
- Fail2:
- Free_Coverage( &mbp->BaseCoverage, memory );
-
- Fail3:
- Free_Coverage( &mbp->MarkCoverage, memory );
- return error;
- }
-
-
- void Free_MarkBasePos( TTO_MarkBasePos* mbp,
- FT_Memory memory )
- {
- Free_BaseArray( &mbp->BaseArray, mbp->ClassCount, memory );
- Free_MarkArray( &mbp->MarkArray, memory );
- Free_Coverage( &mbp->BaseCoverage, memory );
- Free_Coverage( &mbp->MarkCoverage, memory );
- }
-
-
- static FT_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort i, j, mark_index, base_index, property, class;
- FT_Pos x_mark_value, y_mark_value, x_base_value, y_base_value;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
- TTO_MarkBasePos* mbp = &st->markbase;
-
- TTO_MarkArray* ma;
- TTO_BaseArray* ba;
- TTO_BaseRecord* br;
- TTO_Anchor* mark_anchor;
- TTO_Anchor* base_anchor;
-
- OTL_Position o;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- return TTO_Err_Not_Covered;
-
- if ( flags & IGNORE_BASE_GLYPHS )
- return TTO_Err_Not_Covered;
-
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
- flags, &property ) )
- return error;
-
- error = Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),
- &mark_index );
- if ( error )
- return error;
-
- /* now we search backwards for a non-mark glyph */
-
- i = 1;
- j = buffer->in_pos - 1;
-
- while ( i <= buffer->in_pos )
- {
- error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
- &property );
- if ( error )
- return error;
-
- if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) )
- break;
-
- i++;
- j--;
- }
-
- /* The following assertion is too strong -- at least for mangal.ttf. */
-#if 0
- if ( property != TTO_BASE_GLYPH )
- return TTO_Err_Not_Covered;
-#endif
-
- if ( i > buffer->in_pos )
- return TTO_Err_Not_Covered;
-
- error = Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
- &base_index );
- if ( error )
- return error;
-
- ma = &mbp->MarkArray;
-
- if ( mark_index >= ma->MarkCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- class = ma->MarkRecord[mark_index].Class;
- mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
-
- if ( class >= mbp->ClassCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- ba = &mbp->BaseArray;
-
- if ( base_index >= ba->BaseCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- br = &ba->BaseRecord[base_index];
- base_anchor = &br->BaseAnchor[class];
-
- error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
- &x_mark_value, &y_mark_value );
- if ( error )
- return error;
-
- error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
- &x_base_value, &y_base_value );
- if ( error )
- return error;
-
- /* anchor points are not cumulative */
-
- o = POSITION( buffer->in_pos );
-
- o->x_pos = x_base_value - x_mark_value;
- o->y_pos = y_base_value - y_mark_value;
- o->x_advance = 0;
- o->y_advance = 0;
- o->back = i;
-
- (buffer->in_pos)++;
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 5 */
-
- /* LigatureAttach */
-
- static FT_Error Load_LigatureAttach( TTO_LigatureAttach* lat,
- FT_UShort num_classes,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort m, n, k, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ComponentRecord* cr;
- TTO_Anchor* lan;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = lat->ComponentCount = GET_UShort();
-
- FORGET_Frame();
-
- lat->ComponentRecord = NULL;
-
- if ( ALLOC_ARRAY( lat->ComponentRecord, count, TTO_ComponentRecord ) )
- return error;
-
- cr = lat->ComponentRecord;
-
- for ( m = 0; m < count; m++ )
- {
- cr[m].LigatureAnchor = NULL;
-
- if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, TTO_Anchor ) )
- goto Fail;
-
- lan = cr[m].LigatureAnchor;
-
- for ( n = 0; n < num_classes; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail0;
-
- new_offset = GET_UShort();
-
- FORGET_Frame();
-
- if ( new_offset )
- {
- new_offset += base_offset;
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Anchor( &lan[n], stream ) ) != TT_Err_Ok )
- goto Fail0;
- (void)FILE_Seek( cur_offset );
- }
- else
- lan[n].PosFormat = 0;
- }
-
- continue;
- Fail0:
- for ( k = 0; k < n; k++ )
- Free_Anchor( &lan[k], memory );
- goto Fail;
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( k = 0; k < m; k++ )
- {
- lan = cr[k].LigatureAnchor;
-
- for ( n = 0; n < num_classes; n++ )
- Free_Anchor( &lan[n], memory );
-
- FREE( lan );
- }
-
- FREE( cr );
- return error;
- }
-
-
- static void Free_LigatureAttach( TTO_LigatureAttach* lat,
- FT_UShort num_classes,
- FT_Memory memory )
- {
- FT_UShort m, n, count;
-
- TTO_ComponentRecord* cr;
- TTO_Anchor* lan;
-
-
- if ( lat->ComponentRecord )
- {
- count = lat->ComponentCount;
- cr = lat->ComponentRecord;
-
- for ( m = 0; m < count; m++ )
- {
- lan = cr[m].LigatureAnchor;
-
- for ( n = 0; n < num_classes; n++ )
- Free_Anchor( &lan[n], memory );
-
- FREE( lan );
- }
-
- FREE( cr );
- }
- }
-
-
- /* LigatureArray */
-
- static FT_Error Load_LigatureArray( TTO_LigatureArray* la,
- FT_UShort num_classes,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_LigatureAttach* lat;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = la->LigatureCount = GET_UShort();
-
- FORGET_Frame();
-
- la->LigatureAttach = NULL;
-
- if ( ALLOC_ARRAY( la->LigatureAttach, count, TTO_LigatureAttach ) )
- return error;
-
- lat = la->LigatureAttach;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LigatureAttach( &lat[n], num_classes,
- stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_LigatureAttach( &lat[m], num_classes, memory );
-
- FREE( lat );
- return error;
- }
-
-
- static void Free_LigatureArray( TTO_LigatureArray* la,
- FT_UShort num_classes,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_LigatureAttach* lat;
-
-
- if ( la->LigatureAttach )
- {
- count = la->LigatureCount;
- lat = la->LigatureAttach;
-
- for ( n = 0; n < count; n++ )
- Free_LigatureAttach( &lat[n], num_classes, memory );
-
- FREE( lat );
- }
- }
-
-
- /* MarkLigPosFormat1 */
-
- FT_Error Load_MarkLigPos( TTO_MarkLigPos* mlp,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_ULong cur_offset, new_offset, base_offset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- mlp->PosFormat = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &mlp->MarkCoverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &mlp->LigatureCoverage,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 4L ) )
- goto Fail2;
-
- mlp->ClassCount = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount,
- stream ) ) != TT_Err_Ok )
- goto Fail1;
-
- return TT_Err_Ok;
-
- Fail1:
- Free_MarkArray( &mlp->MarkArray, memory );
-
- Fail2:
- Free_Coverage( &mlp->LigatureCoverage, memory );
-
- Fail3:
- Free_Coverage( &mlp->MarkCoverage, memory );
- return error;
- }
-
-
- void Free_MarkLigPos( TTO_MarkLigPos* mlp,
- FT_Memory memory)
- {
- Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, memory );
- Free_MarkArray( &mlp->MarkArray, memory );
- Free_Coverage( &mlp->LigatureCoverage, memory );
- Free_Coverage( &mlp->MarkCoverage, memory );
- }
-
-
- static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort i, j, mark_index, lig_index, property, class;
- FT_UShort mark_glyph;
- FT_Pos x_mark_value, y_mark_value, x_lig_value, y_lig_value;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
- TTO_MarkLigPos* mlp = &st->marklig;
-
- TTO_MarkArray* ma;
- TTO_LigatureArray* la;
- TTO_LigatureAttach* lat;
- TTO_ComponentRecord* cr;
- FT_UShort comp_index;
- TTO_Anchor* mark_anchor;
- TTO_Anchor* lig_anchor;
-
- OTL_Position o;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- return TTO_Err_Not_Covered;
-
- if ( flags & IGNORE_LIGATURES )
- return TTO_Err_Not_Covered;
-
- mark_glyph = IN_CURGLYPH();
-
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
- if ( error )
- return error;
-
- /* now we search backwards for a non-mark glyph */
-
- i = 1;
- j = buffer->in_pos - 1;
-
- while ( i <= buffer->in_pos )
- {
- error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
- &property );
- if ( error )
- return error;
-
- if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) )
- break;
-
- i++;
- j--;
- }
-
- /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
- too strong, thus it is commented out. */
-#if 0
- if ( property != TTO_LIGATURE )
- return TTO_Err_Not_Covered;
-#endif
-
- if ( i > buffer->in_pos )
- return TTO_Err_Not_Covered;
-
- error = Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
- &lig_index );
- if ( error )
- return error;
-
- ma = &mlp->MarkArray;
-
- if ( mark_index >= ma->MarkCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- class = ma->MarkRecord[mark_index].Class;
- mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
-
- if ( class >= mlp->ClassCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- la = &mlp->LigatureArray;
-
- if ( lig_index >= la->LigatureCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- lat = &la->LigatureAttach[lig_index];
-
- /* We must now check whether the ligature ID of the current mark glyph
- is identical to the ligature ID of the found ligature. If yes, we
- can directly use the component index. If not, we attach the mark
- glyph to the last component of the ligature. */
-
- if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
- {
- comp_index = IN_COMPONENT( buffer->in_pos );
- if ( comp_index >= lat->ComponentCount )
- return TTO_Err_Not_Covered;
- }
- else
- comp_index = lat->ComponentCount - 1;
-
- cr = &lat->ComponentRecord[comp_index];
- lig_anchor = &cr->LigatureAnchor[class];
-
- error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
- &x_mark_value, &y_mark_value );
- if ( error )
- return error;
- error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
- &x_lig_value, &y_lig_value );
- if ( error )
- return error;
-
- /* anchor points are not cumulative */
-
- o = POSITION( buffer->in_pos );
-
- o->x_pos = x_lig_value - x_mark_value;
- o->y_pos = y_lig_value - y_mark_value;
- o->x_advance = 0;
- o->y_advance = 0;
- o->back = i;
-
- (buffer->in_pos)++;
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 6 */
-
- /* Mark2Array */
-
- static FT_Error Load_Mark2Array( TTO_Mark2Array* m2a,
- FT_UShort num_classes,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort k, m, n, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Mark2Record* m2r;
- TTO_Anchor* m2an;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = m2a->Mark2Count = GET_UShort();
-
- FORGET_Frame();
-
- m2a->Mark2Record = NULL;
-
- if ( ALLOC_ARRAY( m2a->Mark2Record, count, TTO_Mark2Record ) )
- return error;
-
- m2r = m2a->Mark2Record;
-
- for ( m = 0; m < count; m++ )
- {
- m2r[m].Mark2Anchor = NULL;
-
- if ( ALLOC_ARRAY( m2r[m].Mark2Anchor, num_classes, TTO_Anchor ) )
- goto Fail;
-
- m2an = m2r[m].Mark2Anchor;
-
- for ( n = 0; n < num_classes; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail0;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Anchor( &m2an[n], stream ) ) != TT_Err_Ok )
- goto Fail0;
- (void)FILE_Seek( cur_offset );
- }
-
- continue;
- Fail0:
- for ( k = 0; k < n; k++ )
- Free_Anchor( &m2an[k], memory );
- goto Fail;
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( k = 0; k < m; k++ )
- {
- m2an = m2r[k].Mark2Anchor;
-
- for ( n = 0; n < num_classes; n++ )
- Free_Anchor( &m2an[n], memory );
-
- FREE( m2an );
- }
-
- FREE( m2r );
- return error;
- }
-
-
- static void Free_Mark2Array( TTO_Mark2Array* m2a,
- FT_UShort num_classes,
- FT_Memory memory )
- {
- FT_UShort m, n, count;
-
- TTO_Mark2Record* m2r;
- TTO_Anchor* m2an;
-
-
- if ( m2a->Mark2Record )
- {
- count = m2a->Mark2Count;
- m2r = m2a->Mark2Record;
-
- for ( m = 0; m < count; m++ )
- {
- m2an = m2r[m].Mark2Anchor;
-
- for ( n = 0; n < num_classes; n++ )
- Free_Anchor( &m2an[n], memory );
-
- FREE( m2an );
- }
-
- FREE( m2r );
- }
- }
-
-
- /* MarkMarkPosFormat1 */
-
- FT_Error Load_MarkMarkPos( TTO_MarkMarkPos* mmp,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_ULong cur_offset, new_offset, base_offset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- mmp->PosFormat = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &mmp->Mark1Coverage,
- stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &mmp->Mark2Coverage,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 4L ) )
- goto Fail2;
-
- mmp->ClassCount = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount,
- stream ) ) != TT_Err_Ok )
- goto Fail1;
-
- return TT_Err_Ok;
-
- Fail1:
- Free_MarkArray( &mmp->Mark1Array, memory );
-
- Fail2:
- Free_Coverage( &mmp->Mark2Coverage, memory );
-
- Fail3:
- Free_Coverage( &mmp->Mark1Coverage, memory );
- return error;
- }
-
-
- void Free_MarkMarkPos( TTO_MarkMarkPos* mmp,
- FT_Memory memory)
- {
- Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, memory );
- Free_MarkArray( &mmp->Mark1Array, memory );
- Free_Coverage( &mmp->Mark2Coverage, memory );
- Free_Coverage( &mmp->Mark1Coverage, memory );
- }
-
-
- static FT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort j, mark1_index, mark2_index, property, class;
- FT_Pos x_mark1_value, y_mark1_value,
- x_mark2_value, y_mark2_value;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
- TTO_MarkMarkPos* mmp = &st->markmark;
-
- TTO_MarkArray* ma1;
- TTO_Mark2Array* ma2;
- TTO_Mark2Record* m2r;
- TTO_Anchor* mark1_anchor;
- TTO_Anchor* mark2_anchor;
-
- OTL_Position o;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- return TTO_Err_Not_Covered;
-
- if ( flags & IGNORE_MARKS )
- return TTO_Err_Not_Covered;
-
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
- flags, &property ) )
- return error;
-
- error = Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),
- &mark1_index );
- if ( error )
- return error;
-
- /* now we check the preceding glyph whether it is a suitable
- mark glyph */
-
- if ( buffer->in_pos == 0 )
- return TTO_Err_Not_Covered;
-
- j = buffer->in_pos - 1;
- error = TT_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
- &property );
- if ( error )
- return error;
-
- if ( flags & IGNORE_SPECIAL_MARKS )
- {
- if ( property != (flags & 0xFF00) )
- return TTO_Err_Not_Covered;
- }
- else
- {
- if ( property != TTO_MARK )
- return TTO_Err_Not_Covered;
- }
-
- error = Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
- &mark2_index );
- if ( error )
- return error;
-
- ma1 = &mmp->Mark1Array;
-
- if ( mark1_index >= ma1->MarkCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- class = ma1->MarkRecord[mark1_index].Class;
- mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
-
- if ( class >= mmp->ClassCount )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- ma2 = &mmp->Mark2Array;
-
- if ( mark2_index >= ma2->Mark2Count )
- return TTO_Err_Invalid_GPOS_SubTable;
-
- m2r = &ma2->Mark2Record[mark2_index];
- mark2_anchor = &m2r->Mark2Anchor[class];
-
- error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),
- &x_mark1_value, &y_mark1_value );
- if ( error )
- return error;
- error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
- &x_mark2_value, &y_mark2_value );
- if ( error )
- return error;
-
- /* anchor points are not cumulative */
-
- o = POSITION( buffer->in_pos );
-
- o->x_pos = x_mark2_value - x_mark1_value;
- o->y_pos = y_mark2_value - y_mark1_value;
- o->x_advance = 0;
- o->y_advance = 0;
- o->back = 1;
-
- (buffer->in_pos)++;
-
- return TT_Err_Ok;
- }
-
-
- /* Do the actual positioning for a context positioning (either format
- 7 or 8). This is only called after we've determined that the stream
- matches the subrule. */
-
- static FT_Error Do_ContextPos( GPOS_Instance* gpi,
- FT_UShort GlyphCount,
- FT_UShort PosCount,
- TTO_PosLookupRecord* pos,
- OTL_Buffer buffer,
- int nesting_level )
- {
- FT_Error error;
- FT_UShort i, old_pos;
-
-
- i = 0;
-
- while ( i < GlyphCount )
- {
- if ( PosCount && i == pos->SequenceIndex )
- {
- old_pos = buffer->in_pos;
-
- /* Do a positioning */
-
- error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
- GlyphCount, nesting_level );
-
- if ( error )
- return error;
-
- pos++;
- PosCount--;
- i += buffer->in_pos - old_pos;
- }
- else
- {
- i++;
- (buffer->in_pos)++;
- }
- }
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 7 */
-
- /* PosRule */
-
- static FT_Error Load_PosRule( TTO_PosRule* pr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_UShort* i;
-
- TTO_PosLookupRecord* plr;
-
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- pr->GlyphCount = GET_UShort();
- pr->PosCount = GET_UShort();
-
- FORGET_Frame();
-
- pr->Input = NULL;
-
- count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( pr->Input, count, FT_UShort ) )
- return error;
-
- i = pr->Input;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- i[n] = GET_UShort();
-
- FORGET_Frame();
-
- pr->PosLookupRecord = NULL;
-
- count = pr->PosCount;
-
- if ( ALLOC_ARRAY( pr->PosLookupRecord, count, TTO_PosLookupRecord ) )
- goto Fail2;
-
- plr = pr->PosLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- plr[n].SequenceIndex = GET_UShort();
- plr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( plr );
-
- Fail2:
- FREE( i );
- return error;
- }
-
-
- static void Free_PosRule( TTO_PosRule* pr,
- FT_Memory memory )
- {
- FREE( pr->PosLookupRecord );
- FREE( pr->Input );
- }
-
-
- /* PosRuleSet */
-
- static FT_Error Load_PosRuleSet( TTO_PosRuleSet* prs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_PosRule* pr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = prs->PosRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- prs->PosRule = NULL;
-
- if ( ALLOC_ARRAY( prs->PosRule, count, TTO_PosRule ) )
- return error;
-
- pr = prs->PosRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_PosRule( &pr[n], stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_PosRule( &pr[m], memory );
-
- FREE( pr );
- return error;
- }
-
-
- static void Free_PosRuleSet( TTO_PosRuleSet* prs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_PosRule* pr;
-
-
- if ( prs->PosRule )
- {
- count = prs->PosRuleCount;
- pr = prs->PosRule;
-
- for ( n = 0; n < count; n++ )
- Free_PosRule( &pr[n], memory );
-
- FREE( pr );
- }
- }
-
-
- /* ContextPosFormat1 */
-
- static FT_Error Load_ContextPos1( TTO_ContextPosFormat1* cpf1,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_PosRuleSet* prs;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &cpf1->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = cpf1->PosRuleSetCount = GET_UShort();
-
- FORGET_Frame();
-
- cpf1->PosRuleSet = NULL;
-
- if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, TTO_PosRuleSet ) )
- goto Fail2;
-
- prs = cpf1->PosRuleSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_PosRuleSet( &prs[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_PosRuleSet( &prs[m], memory );
-
- FREE( prs );
-
- Fail2:
- Free_Coverage( &cpf1->Coverage, memory );
- return error;
- }
-
-
- static void Free_Context1( TTO_ContextPosFormat1* cpf1,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_PosRuleSet* prs;
-
-
- if ( cpf1->PosRuleSet )
- {
- count = cpf1->PosRuleSetCount;
- prs = cpf1->PosRuleSet;
-
- for ( n = 0; n < count; n++ )
- Free_PosRuleSet( &prs[n], memory );
-
- FREE( prs );
- }
-
- Free_Coverage( &cpf1->Coverage, memory );
- }
-
-
- /* PosClassRule */
-
- static FT_Error Load_PosClassRule( TTO_ContextPosFormat2* cpf2,
- TTO_PosClassRule* pcr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* c;
- TTO_PosLookupRecord* plr;
- FT_Bool* d;
-
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- pcr->GlyphCount = GET_UShort();
- pcr->PosCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( pcr->GlyphCount > cpf2->MaxContextLength )
- cpf2->MaxContextLength = pcr->GlyphCount;
-
- pcr->Class = NULL;
-
- count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( pcr->Class, count, FT_UShort ) )
- return error;
-
- c = pcr->Class;
- d = cpf2->ClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- {
- c[n] = GET_UShort();
-
- /* We check whether the specific class is used at all. If not,
- class 0 is used instead. */
-
- if ( !d[c[n]] )
- c[n] = 0;
- }
-
- FORGET_Frame();
-
- pcr->PosLookupRecord = NULL;
-
- count = pcr->PosCount;
-
- if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, TTO_PosLookupRecord ) )
- goto Fail2;
-
- plr = pcr->PosLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- plr[n].SequenceIndex = GET_UShort();
- plr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( plr );
-
- Fail2:
- FREE( c );
- return error;
- }
-
-
- static void Free_PosClassRule( TTO_PosClassRule* pcr,
- FT_Memory memory )
- {
- FREE( pcr->PosLookupRecord );
- FREE( pcr->Class );
- }
-
-
- /* PosClassSet */
-
- static FT_Error Load_PosClassSet( TTO_ContextPosFormat2* cpf2,
- TTO_PosClassSet* pcs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_PosClassRule* pcr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = pcs->PosClassRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- pcs->PosClassRule = NULL;
-
- if ( ALLOC_ARRAY( pcs->PosClassRule, count, TTO_PosClassRule ) )
- return error;
-
- pcr = pcs->PosClassRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_PosClassRule( cpf2, &pcr[n],
- stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_PosClassRule( &pcr[m], memory );
-
- FREE( pcr );
- return error;
- }
-
-
- static void Free_PosClassSet( TTO_PosClassSet* pcs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_PosClassRule* pcr;
-
-
- if ( pcs->PosClassRule )
- {
- count = pcs->PosClassRuleCount;
- pcr = pcs->PosClassRule;
-
- for ( n = 0; n < count; n++ )
- Free_PosClassRule( &pcr[n], memory );
-
- FREE( pcr );
- }
- }
-
-
- /* ContextPosFormat2 */
-
- static FT_Error Load_ContextPos2( TTO_ContextPosFormat2* cpf2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_PosClassSet* pcs;
-
-
- base_offset = FILE_Pos() - 2;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &cpf2->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 4L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- /* `PosClassSetCount' is the upper limit for class values, thus we
- read it now to make an additional safety check. */
-
- count = cpf2->PosClassSetCount = GET_UShort();
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ClassDefinition( &cpf2->ClassDef, count,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- cpf2->PosClassSet = NULL;
- cpf2->MaxContextLength = 0;
-
- if ( ALLOC_ARRAY( cpf2->PosClassSet, count, TTO_PosClassSet ) )
- goto Fail2;
-
- pcs = cpf2->PosClassSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- if ( new_offset != base_offset ) /* not a NULL offset */
- {
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_PosClassSet( cpf2, &pcs[n],
- stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
- else
- {
- /* we create a PosClassSet table with no entries */
-
- cpf2->PosClassSet[n].PosClassRuleCount = 0;
- cpf2->PosClassSet[n].PosClassRule = NULL;
- }
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; n++ )
- Free_PosClassSet( &pcs[m], memory );
-
- FREE( pcs );
-
- Fail2:
- Free_ClassDefinition( &cpf2->ClassDef, memory );
-
- Fail3:
- Free_Coverage( &cpf2->Coverage, memory );
- return error;
- }
-
-
- static void Free_Context2( TTO_ContextPosFormat2* cpf2,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_PosClassSet* pcs;
-
-
- if ( cpf2->PosClassSet )
- {
- count = cpf2->PosClassSetCount;
- pcs = cpf2->PosClassSet;
-
- for ( n = 0; n < count; n++ )
- Free_PosClassSet( &pcs[n], memory );
-
- FREE( pcs );
- }
-
- Free_ClassDefinition( &cpf2->ClassDef, memory );
- Free_Coverage( &cpf2->Coverage, memory );
- }
-
-
- /* ContextPosFormat3 */
-
- static FT_Error Load_ContextPos3( TTO_ContextPosFormat3* cpf3,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Coverage* c;
- TTO_PosLookupRecord* plr;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- cpf3->GlyphCount = GET_UShort();
- cpf3->PosCount = GET_UShort();
-
- FORGET_Frame();
-
- cpf3->Coverage = NULL;
-
- count = cpf3->GlyphCount;
-
- if ( ALLOC_ARRAY( cpf3->Coverage, count, TTO_Coverage ) )
- return error;
-
- c = cpf3->Coverage;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &c[n], stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
- }
-
- cpf3->PosLookupRecord = NULL;
-
- count = cpf3->PosCount;
-
- if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, TTO_PosLookupRecord ) )
- goto Fail2;
-
- plr = cpf3->PosLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- plr[n].SequenceIndex = GET_UShort();
- plr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( plr );
-
- Fail2:
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- return error;
- }
-
-
- static void Free_Context3( TTO_ContextPosFormat3* cpf3,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Coverage* c;
-
-
- FREE( cpf3->PosLookupRecord );
-
- if ( cpf3->Coverage )
- {
- count = cpf3->GlyphCount;
- c = cpf3->Coverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
- }
-
-
- /* ContextPos */
-
- FT_Error Load_ContextPos( TTO_ContextPos* cp,
- FT_Stream stream )
- {
- FT_Error error;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cp->PosFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( cp->PosFormat )
- {
- case 1:
- return Load_ContextPos1( &cp->cpf.cpf1, stream );
-
- case 2:
- return Load_ContextPos2( &cp->cpf.cpf2, stream );
-
- case 3:
- return Load_ContextPos3( &cp->cpf.cpf3, stream );
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- void Free_ContextPos( TTO_ContextPos* cp,
- FT_Memory memory )
- {
- switch ( cp->PosFormat )
- {
- case 1:
- Free_Context1( &cp->cpf.cpf1, memory );
- break;
-
- case 2:
- Free_Context2( &cp->cpf.cpf2, memory );
- break;
-
- case 3:
- Free_Context3( &cp->cpf.cpf3, memory );
- break;
- }
- }
-
-
- static FT_Error Lookup_ContextPos1( GPOS_Instance* gpi,
- TTO_ContextPosFormat1* cpf1,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_UShort i, j, k, numpr;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- TTO_PosRule* pr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gpos->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- pr = cpf1->PosRuleSet[index].PosRule;
- numpr = cpf1->PosRuleSet[index].PosRuleCount;
-
- for ( k = 0; k < numpr; k++ )
- {
- if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
- goto next_posrule;
-
- if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
- goto next_posrule; /* context is too long */
-
- for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + pr[k].GlyphCount - i == buffer->in_length )
- goto next_posrule;
- j++;
- }
-
- if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
- goto next_posrule;
- }
-
- return Do_ContextPos( gpi, pr[k].GlyphCount,
- pr[k].PosCount, pr[k].PosLookupRecord,
- buffer,
- nesting_level );
-
- next_posrule:
- ;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- static FT_Error Lookup_ContextPos2( GPOS_Instance* gpi,
- TTO_ContextPosFormat2* cpf2,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_Error error;
- FT_Memory memory = gpi->face->memory;
- FT_UShort i, j, k, known_classes;
-
- FT_UShort* classes;
- FT_UShort* cl;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- TTO_PosClassSet* pcs;
- TTO_PosClassRule* pr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gpos->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- /* Note: The coverage table in format 2 doesn't give an index into
- anything. It just lets us know whether or not we need to
- do any lookup at all. */
-
- error = Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) )
- return error;
-
- error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),
- &classes[0], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End;
- known_classes = 0;
-
- pcs = &cpf2->PosClassSet[classes[0]];
- if ( !pcs )
- {
- error = TTO_Err_Invalid_GPOS_SubTable;
- goto End;
- }
-
- for ( k = 0; k < pcs->PosClassRuleCount; k++ )
- {
- pr = &pcs->PosClassRule[k];
-
- if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
- goto next_posclassrule;
-
- if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
- goto next_posclassrule; /* context is too long */
-
- cl = pr->Class;
-
- /* Start at 1 because [0] is implied */
-
- for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End;
-
- if ( j + pr->GlyphCount - i == buffer->in_length )
- goto next_posclassrule;
- j++;
- }
-
- if ( i > known_classes )
- {
- /* Keeps us from having to do this for each rule */
-
- error = Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End;
- known_classes = i;
- }
-
- if ( cl[i - 1] != classes[i] )
- goto next_posclassrule;
- }
-
- error = Do_ContextPos( gpi, pr->GlyphCount,
- pr->PosCount, pr->PosLookupRecord,
- buffer,
- nesting_level );
- goto End;
-
- next_posclassrule:
- ;
- }
-
- error = TTO_Err_Not_Covered;
-
- End:
- FREE( classes );
- return error;
- }
-
-
- static FT_Error Lookup_ContextPos3( GPOS_Instance* gpi,
- TTO_ContextPosFormat3* cpf3,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_Error error;
- FT_UShort index, i, j, property;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- TTO_Coverage* c;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gpos->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
- return TTO_Err_Not_Covered;
-
- if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
- return TTO_Err_Not_Covered; /* context is too long */
-
- c = cpf3->Coverage;
-
- for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + cpf3->GlyphCount - i == buffer->in_length )
- return TTO_Err_Not_Covered;
- j++;
- }
-
- error = Coverage_Index( &c[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
-
- return Do_ContextPos( gpi, cpf3->GlyphCount,
- cpf3->PosCount, cpf3->PosLookupRecord,
- buffer,
- nesting_level );
- }
-
-
- static FT_Error Lookup_ContextPos( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- TTO_ContextPos* cp = &st->context;
-
- switch ( cp->PosFormat )
- {
- case 1:
- return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
- flags, context_length, nesting_level );
-
- case 2:
- return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
- flags, context_length, nesting_level );
-
- case 3:
- return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
- flags, context_length, nesting_level );
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- /* LookupType 8 */
-
- /* ChainPosRule */
-
- static FT_Error Load_ChainPosRule( TTO_ChainPosRule* cpr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_UShort* b;
- FT_UShort* i;
- FT_UShort* l;
-
- TTO_PosLookupRecord* plr;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cpr->BacktrackGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- cpr->Backtrack = NULL;
-
- count = cpr->BacktrackGlyphCount;
-
- if ( ALLOC_ARRAY( cpr->Backtrack, count, FT_UShort ) )
- return error;
-
- b = cpr->Backtrack;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail4;
-
- for ( n = 0; n < count; n++ )
- b[n] = GET_UShort();
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- cpr->InputGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- cpr->Input = NULL;
-
- count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( cpr->Input, count, FT_UShort ) )
- goto Fail4;
-
- i = cpr->Input;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail3;
-
- for ( n = 0; n < count; n++ )
- i[n] = GET_UShort();
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- cpr->LookaheadGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- cpr->Lookahead = NULL;
-
- count = cpr->LookaheadGlyphCount;
-
- if ( ALLOC_ARRAY( cpr->Lookahead, count, FT_UShort ) )
- goto Fail3;
-
- l = cpr->Lookahead;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- l[n] = GET_UShort();
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- cpr->PosCount = GET_UShort();
-
- FORGET_Frame();
-
- cpr->PosLookupRecord = NULL;
-
- count = cpr->PosCount;
-
- if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, TTO_PosLookupRecord ) )
- goto Fail2;
-
- plr = cpr->PosLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- plr[n].SequenceIndex = GET_UShort();
- plr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( plr );
-
- Fail2:
- FREE( l );
-
- Fail3:
- FREE( i );
-
- Fail4:
- FREE( b );
- return error;
- }
-
-
- static void Free_ChainPosRule( TTO_ChainPosRule* cpr,
- FT_Memory memory )
- {
- FREE( cpr->PosLookupRecord );
- FREE( cpr->Lookahead );
- FREE( cpr->Input );
- FREE( cpr->Backtrack );
- }
-
-
- /* ChainPosRuleSet */
-
- static FT_Error Load_ChainPosRuleSet( TTO_ChainPosRuleSet* cprs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ChainPosRule* cpr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = cprs->ChainPosRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- cprs->ChainPosRule = NULL;
-
- if ( ALLOC_ARRAY( cprs->ChainPosRule, count, TTO_ChainPosRule ) )
- return error;
-
- cpr = cprs->ChainPosRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainPosRule( &cpr[n], stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_ChainPosRule( &cpr[m], memory );
-
- FREE( cpr );
- return error;
- }
-
-
- static void Free_ChainPosRuleSet( TTO_ChainPosRuleSet* cprs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainPosRule* cpr;
-
-
- if ( cprs->ChainPosRule )
- {
- count = cprs->ChainPosRuleCount;
- cpr = cprs->ChainPosRule;
-
- for ( n = 0; n < count; n++ )
- Free_ChainPosRule( &cpr[n], memory );
-
- FREE( cpr );
- }
- }
-
-
- /* ChainContextPosFormat1 */
-
- static FT_Error Load_ChainContextPos1( TTO_ChainContextPosFormat1* ccpf1,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ChainPosRuleSet* cprs;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &ccpf1->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = ccpf1->ChainPosRuleSetCount = GET_UShort();
-
- FORGET_Frame();
-
- ccpf1->ChainPosRuleSet = NULL;
-
- if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, TTO_ChainPosRuleSet ) )
- goto Fail2;
-
- cprs = ccpf1->ChainPosRuleSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_ChainPosRuleSet( &cprs[m], memory );
-
- FREE( cprs );
-
- Fail2:
- Free_Coverage( &ccpf1->Coverage, memory );
- return error;
- }
-
-
- static void Free_ChainContext1( TTO_ChainContextPosFormat1* ccpf1,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainPosRuleSet* cprs;
-
-
- if ( ccpf1->ChainPosRuleSet )
- {
- count = ccpf1->ChainPosRuleSetCount;
- cprs = ccpf1->ChainPosRuleSet;
-
- for ( n = 0; n < count; n++ )
- Free_ChainPosRuleSet( &cprs[n], memory );
-
- FREE( cprs );
- }
-
- Free_Coverage( &ccpf1->Coverage, memory );
- }
-
-
- /* ChainPosClassRule */
-
- static FT_Error Load_ChainPosClassRule(
- TTO_ChainContextPosFormat2* ccpf2,
- TTO_ChainPosClassRule* cpcr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* b;
- FT_UShort* i;
- FT_UShort* l;
- TTO_PosLookupRecord* plr;
- FT_Bool* d;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cpcr->BacktrackGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength )
- ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount;
-
- cpcr->Backtrack = NULL;
-
- count = cpcr->BacktrackGlyphCount;
-
- if ( ALLOC_ARRAY( cpcr->Backtrack, count, FT_UShort ) )
- return error;
-
- b = cpcr->Backtrack;
- d = ccpf2->BacktrackClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail4;
-
- for ( n = 0; n < count; n++ )
- {
- b[n] = GET_UShort();
-
- /* We check whether the specific class is used at all. If not,
- class 0 is used instead. */
-
- if ( !d[b[n]] )
- b[n] = 0;
- }
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- cpcr->InputGlyphCount = GET_UShort();
-
- if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength )
- ccpf2->MaxInputLength = cpcr->InputGlyphCount;
-
- FORGET_Frame();
-
- cpcr->Input = NULL;
-
- count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( cpcr->Input, count, FT_UShort ) )
- goto Fail4;
-
- i = cpcr->Input;
- d = ccpf2->InputClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail3;
-
- for ( n = 0; n < count; n++ )
- {
- i[n] = GET_UShort();
-
- if ( !d[i[n]] )
- i[n] = 0;
- }
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- cpcr->LookaheadGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength )
- ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount;
-
- cpcr->Lookahead = NULL;
-
- count = cpcr->LookaheadGlyphCount;
-
- if ( ALLOC_ARRAY( cpcr->Lookahead, count, FT_UShort ) )
- goto Fail3;
-
- l = cpcr->Lookahead;
- d = ccpf2->LookaheadClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- {
- l[n] = GET_UShort();
-
- if ( !d[l[n]] )
- l[n] = 0;
- }
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- cpcr->PosCount = GET_UShort();
-
- FORGET_Frame();
-
- cpcr->PosLookupRecord = NULL;
-
- count = cpcr->PosCount;
-
- if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, TTO_PosLookupRecord ) )
- goto Fail2;
-
- plr = cpcr->PosLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- plr[n].SequenceIndex = GET_UShort();
- plr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( plr );
-
- Fail2:
- FREE( l );
-
- Fail3:
- FREE( i );
-
- Fail4:
- FREE( b );
- return error;
- }
-
-
- static void Free_ChainPosClassRule( TTO_ChainPosClassRule* cpcr,
- FT_Memory memory )
- {
- FREE( cpcr->PosLookupRecord );
- FREE( cpcr->Lookahead );
- FREE( cpcr->Input );
- FREE( cpcr->Backtrack );
- }
-
-
- /* PosClassSet */
-
- static FT_Error Load_ChainPosClassSet(
- TTO_ChainContextPosFormat2* ccpf2,
- TTO_ChainPosClassSet* cpcs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ChainPosClassRule* cpcr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = cpcs->ChainPosClassRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- cpcs->ChainPosClassRule = NULL;
-
- if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count,
- TTO_ChainPosClassRule ) )
- return error;
-
- cpcr = cpcs->ChainPosClassRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n],
- stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_ChainPosClassRule( &cpcr[m], memory );
-
- FREE( cpcr );
- return error;
- }
-
-
- static void Free_ChainPosClassSet( TTO_ChainPosClassSet* cpcs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainPosClassRule* cpcr;
-
-
- if ( cpcs->ChainPosClassRule )
- {
- count = cpcs->ChainPosClassRuleCount;
- cpcr = cpcs->ChainPosClassRule;
-
- for ( n = 0; n < count; n++ )
- Free_ChainPosClassRule( &cpcr[n], memory );
-
- FREE( cpcr );
- }
- }
-
-
- static FT_Error Load_EmptyOrClassDefinition( TTO_ClassDefinition* cd,
- FT_UShort limit,
- FT_ULong class_offset,
- FT_ULong base_offset,
- FT_Stream stream )
- {
- FT_Error error;
- FT_ULong cur_offset;
-
- cur_offset = FILE_Pos();
-
- if ( class_offset )
- {
- if ( !FILE_Seek( class_offset + base_offset ) )
- error = Load_ClassDefinition( cd, limit, stream );
- }
- else
- error = Load_EmptyClassDefinition ( cd, stream );
-
- if (error == TT_Err_Ok)
- (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
-
- return error;
- }
-
- /* ChainContextPosFormat2 */
-
- static FT_Error Load_ChainContextPos2( TTO_ChainContextPosFormat2* ccpf2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
- FT_ULong backtrack_offset, input_offset, lookahead_offset;
-
- TTO_ChainPosClassSet* cpcs;
-
-
- base_offset = FILE_Pos() - 2;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &ccpf2->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 8L ) )
- goto Fail5;
-
- backtrack_offset = GET_UShort();
- input_offset = GET_UShort();
- lookahead_offset = GET_UShort();
-
- /* `ChainPosClassSetCount' is the upper limit for input class values,
- thus we read it now to make an additional safety check. No limit
- is known or needed for the other two class definitions */
-
- count = ccpf2->ChainPosClassSetCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( ( error = Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
- backtrack_offset, base_offset,
- stream ) ) != TT_Err_Ok )
- goto Fail5;
- if ( ( error = Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
- input_offset, base_offset,
- stream ) ) != TT_Err_Ok )
- goto Fail4;
- if ( ( error = Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
- lookahead_offset, base_offset,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
-
- ccpf2->ChainPosClassSet = NULL;
- ccpf2->MaxBacktrackLength = 0;
- ccpf2->MaxInputLength = 0;
- ccpf2->MaxLookaheadLength = 0;
-
- if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, TTO_ChainPosClassSet ) )
- goto Fail2;
-
- cpcs = ccpf2->ChainPosClassSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- if ( new_offset != base_offset ) /* not a NULL offset */
- {
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n],
- stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
- else
- {
- /* we create a ChainPosClassSet table with no entries */
-
- ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0;
- ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL;
- }
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_ChainPosClassSet( &cpcs[m], memory );
-
- FREE( cpcs );
-
- Fail2:
- Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
-
- Fail3:
- Free_ClassDefinition( &ccpf2->InputClassDef, memory );
-
- Fail4:
- Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
-
- Fail5:
- Free_Coverage( &ccpf2->Coverage, memory );
- return error;
- }
-
-
- static void Free_ChainContext2( TTO_ChainContextPosFormat2* ccpf2,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainPosClassSet* cpcs;
-
-
- if ( ccpf2->ChainPosClassSet )
- {
- count = ccpf2->ChainPosClassSetCount;
- cpcs = ccpf2->ChainPosClassSet;
-
- for ( n = 0; n < count; n++ )
- Free_ChainPosClassSet( &cpcs[n], memory );
-
- FREE( cpcs );
- }
-
- Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
- Free_ClassDefinition( &ccpf2->InputClassDef, memory );
- Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
-
- Free_Coverage( &ccpf2->Coverage, memory );
- }
-
-
- /* ChainContextPosFormat3 */
-
- static FT_Error Load_ChainContextPos3( TTO_ChainContextPosFormat3* ccpf3,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, nb, ni, nl, m, count;
- FT_UShort backtrack_count, input_count, lookahead_count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Coverage* b;
- TTO_Coverage* i;
- TTO_Coverage* l;
- TTO_PosLookupRecord* plr;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- ccpf3->BacktrackGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- ccpf3->BacktrackCoverage = NULL;
-
- backtrack_count = ccpf3->BacktrackGlyphCount;
-
- if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count,
- TTO_Coverage ) )
- return error;
-
- b = ccpf3->BacktrackCoverage;
-
- for ( nb = 0; nb < backtrack_count; nb++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &b[nb], stream ) ) != TT_Err_Ok )
- goto Fail4;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- ccpf3->InputGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- ccpf3->InputCoverage = NULL;
-
- input_count = ccpf3->InputGlyphCount;
-
- if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, TTO_Coverage ) )
- goto Fail4;
-
- i = ccpf3->InputCoverage;
-
- for ( ni = 0; ni < input_count; ni++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &i[ni], stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- ccpf3->LookaheadGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- ccpf3->LookaheadCoverage = NULL;
-
- lookahead_count = ccpf3->LookaheadGlyphCount;
-
- if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count,
- TTO_Coverage ) )
- goto Fail3;
-
- l = ccpf3->LookaheadCoverage;
-
- for ( nl = 0; nl < lookahead_count; nl++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &l[nl], stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- ccpf3->PosCount = GET_UShort();
-
- FORGET_Frame();
-
- ccpf3->PosLookupRecord = NULL;
-
- count = ccpf3->PosCount;
-
- if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, TTO_PosLookupRecord ) )
- goto Fail2;
-
- plr = ccpf3->PosLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- plr[n].SequenceIndex = GET_UShort();
- plr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( plr );
-
- Fail2:
- for ( m = 0; m < nl; nl++ )
- Free_Coverage( &l[m], memory );
-
- FREE( l );
-
- Fail3:
- for ( m = 0; m < ni; n++ )
- Free_Coverage( &i[m], memory );
-
- FREE( i );
-
- Fail4:
- for ( m = 0; m < nb; n++ )
- Free_Coverage( &b[m], memory );
-
- FREE( b );
- return error;
- }
-
-
- static void Free_ChainContext3( TTO_ChainContextPosFormat3* ccpf3,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Coverage* c;
-
-
- FREE( ccpf3->PosLookupRecord );
-
- if ( ccpf3->LookaheadCoverage )
- {
- count = ccpf3->LookaheadGlyphCount;
- c = ccpf3->LookaheadCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
-
- if ( ccpf3->InputCoverage )
- {
- count = ccpf3->InputGlyphCount;
- c = ccpf3->InputCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
-
- if ( ccpf3->BacktrackCoverage )
- {
- count = ccpf3->BacktrackGlyphCount;
- c = ccpf3->BacktrackCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
- }
-
-
- /* ChainContextPos */
-
- FT_Error Load_ChainContextPos( TTO_ChainContextPos* ccp,
- FT_Stream stream )
- {
- FT_Error error;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- ccp->PosFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( ccp->PosFormat )
- {
- case 1:
- return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );
-
- case 2:
- return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );
-
- case 3:
- return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- void Free_ChainContextPos( TTO_ChainContextPos* ccp,
- FT_Memory memory )
- {
- switch ( ccp->PosFormat )
- {
- case 1:
- Free_ChainContext1( &ccp->ccpf.ccpf1, memory );
- break;
-
- case 2:
- Free_ChainContext2( &ccp->ccpf.ccpf2, memory );
- break;
-
- case 3:
- Free_ChainContext3( &ccp->ccpf.ccpf3, memory );
- break;
- }
- }
-
-
- static FT_Error Lookup_ChainContextPos1(
- GPOS_Instance* gpi,
- TTO_ChainContextPosFormat1* ccpf1,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_UShort i, j, k, num_cpr;
- FT_UShort bgc, igc, lgc;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- TTO_ChainPosRule* cpr;
- TTO_ChainPosRule curr_cpr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gpos->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule;
- num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount;
-
- for ( k = 0; k < num_cpr; k++ )
- {
- curr_cpr = cpr[k];
- bgc = curr_cpr.BacktrackGlyphCount;
- igc = curr_cpr.InputGlyphCount;
- lgc = curr_cpr.LookaheadGlyphCount;
-
- if ( context_length != 0xFFFF && context_length < igc )
- goto next_chainposrule;
-
- /* check whether context is too long; it is a first guess only */
-
- if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
- goto next_chainposrule;
-
- if ( bgc )
- {
- /* Since we don't know in advance the number of glyphs to inspect,
- we search backwards for matches in the backtrack glyph array */
-
- for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + 1 == bgc - i )
- goto next_chainposrule;
- j--;
- }
-
- /* In OpenType 1.3, it is undefined whether the offsets of
- backtrack glyphs is in logical order or not. Version 1.4
- will clarify this:
-
- Logical order - a b c d e f g h i j
- i
- Input offsets - 0 1
- Backtrack offsets - 3 2 1 0
- Lookahead offsets - 0 1 2 3 */
-
- if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
- goto next_chainposrule;
- }
- }
-
- /* Start at 1 because [0] is implied */
-
- for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + igc - i + lgc == buffer->in_length )
- goto next_chainposrule;
- j++;
- }
-
- if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
- goto next_chainposrule;
- }
-
- /* we are starting to check for lookahead glyphs right after the
- last context glyph */
-
- for ( i = 0; i < lgc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + lgc - i == buffer->in_length )
- goto next_chainposrule;
- j++;
- }
-
- if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
- goto next_chainposrule;
- }
-
- return Do_ContextPos( gpi, igc,
- curr_cpr.PosCount,
- curr_cpr.PosLookupRecord,
- buffer,
- nesting_level );
-
- next_chainposrule:
- ;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- static FT_Error Lookup_ChainContextPos2(
- GPOS_Instance* gpi,
- TTO_ChainContextPosFormat2* ccpf2,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_Memory memory = gpi->face->memory;
- FT_Error error;
- FT_UShort i, j, k;
- FT_UShort bgc, igc, lgc;
- FT_UShort known_backtrack_classes,
- known_input_classes,
- known_lookahead_classes;
-
- FT_UShort* backtrack_classes;
- FT_UShort* input_classes;
- FT_UShort* lookahead_classes;
-
- FT_UShort* bc;
- FT_UShort* ic;
- FT_UShort* lc;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- TTO_ChainPosClassSet* cpcs;
- TTO_ChainPosClassRule cpcr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gpos->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- /* Note: The coverage table in format 2 doesn't give an index into
- anything. It just lets us know whether or not we need to
- do any lookup at all. */
-
- error = Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, FT_UShort ) )
- return error;
- known_backtrack_classes = 0;
-
- if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, FT_UShort ) )
- goto End3;
- known_input_classes = 1;
-
- if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, FT_UShort ) )
- goto End2;
- known_lookahead_classes = 0;
-
- error = Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),
- &input_classes[0], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
- if ( !cpcs )
- {
- error = TTO_Err_Invalid_GPOS_SubTable;
- goto End1;
- }
-
- for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ )
- {
- cpcr = cpcs->ChainPosClassRule[k];
- bgc = cpcr.BacktrackGlyphCount;
- igc = cpcr.InputGlyphCount;
- lgc = cpcr.LookaheadGlyphCount;
-
- if ( context_length != 0xFFFF && context_length < igc )
- goto next_chainposclassrule;
-
- /* check whether context is too long; it is a first guess only */
-
- if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
- goto next_chainposclassrule;
-
- if ( bgc )
- {
- /* Since we don't know in advance the number of glyphs to inspect,
- we search backwards for matches in the backtrack glyph array.
- Note that `known_backtrack_classes' starts at index 0. */
-
- bc = cpcr.Backtrack;
-
- for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- if ( j + 1 == bgc - i )
- goto next_chainposclassrule;
- j++;
- }
-
- if ( i >= known_backtrack_classes )
- {
- /* Keeps us from having to do this for each rule */
-
- error = Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
- &backtrack_classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
- known_backtrack_classes = i;
- }
-
- if ( bc[i] != backtrack_classes[i] )
- goto next_chainposclassrule;
- }
- }
-
- ic = cpcr.Input;
-
- /* Start at 1 because [0] is implied */
-
- for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- if ( j + igc - i + lgc == buffer->in_length )
- goto next_chainposclassrule;
- j++;
- }
-
- if ( i >= known_input_classes )
- {
- error = Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
- &input_classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
- known_input_classes = i;
- }
-
- if ( ic[i - 1] != input_classes[i] )
- goto next_chainposclassrule;
- }
-
- /* we are starting to check for lookahead glyphs right after the
- last context glyph */
-
- lc = cpcr.Lookahead;
-
- for ( i = 0; i < lgc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- if ( j + lgc - i == buffer->in_length )
- goto next_chainposclassrule;
- j++;
- }
-
- if ( i >= known_lookahead_classes )
- {
- error = Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
- &lookahead_classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
- known_lookahead_classes = i;
- }
-
- if ( lc[i] != lookahead_classes[i] )
- goto next_chainposclassrule;
- }
-
- error = Do_ContextPos( gpi, igc,
- cpcr.PosCount,
- cpcr.PosLookupRecord,
- buffer,
- nesting_level );
- goto End1;
-
- next_chainposclassrule:
- ;
- }
-
- error = TTO_Err_Not_Covered;
-
- End1:
- FREE( lookahead_classes );
-
- End2:
- FREE( input_classes );
-
- End3:
- FREE( backtrack_classes );
- return error;
- }
-
-
- static FT_Error Lookup_ChainContextPos3(
- GPOS_Instance* gpi,
- TTO_ChainContextPosFormat3* ccpf3,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, i, j, property;
- FT_UShort bgc, igc, lgc;
- FT_Error error;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- TTO_Coverage* bc;
- TTO_Coverage* ic;
- TTO_Coverage* lc;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gpos->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- bgc = ccpf3->BacktrackGlyphCount;
- igc = ccpf3->InputGlyphCount;
- lgc = ccpf3->LookaheadGlyphCount;
-
- if ( context_length != 0xFFFF && context_length < igc )
- return TTO_Err_Not_Covered;
-
- /* check whether context is too long; it is a first guess only */
-
- if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
- return TTO_Err_Not_Covered;
-
- if ( bgc )
- {
- /* Since we don't know in advance the number of glyphs to inspect,
- we search backwards for matches in the backtrack glyph array */
-
- bc = ccpf3->BacktrackCoverage;
-
- for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + 1 == bgc - i )
- return TTO_Err_Not_Covered;
- j--;
- }
-
- error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
- }
-
- ic = ccpf3->InputCoverage;
-
- for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
- {
- /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
- while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + igc - i + lgc == buffer->in_length )
- return TTO_Err_Not_Covered;
- j++;
- }
-
- error = Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
-
- /* we are starting to check for lookahead glyphs right after the
- last context glyph */
-
- lc = ccpf3->LookaheadCoverage;
-
- for ( i = 0; i < lgc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + lgc - i == buffer->in_length )
- return TTO_Err_Not_Covered;
- j++;
- }
-
- error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
-
- return Do_ContextPos( gpi, igc,
- ccpf3->PosCount,
- ccpf3->PosLookupRecord,
- buffer,
- nesting_level );
- }
-
-
- static FT_Error Lookup_ChainContextPos(
- GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- TTO_ChainContextPos* ccp = &st->chain;
-
- switch ( ccp->PosFormat )
- {
- case 1:
- return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
- flags, context_length,
- nesting_level );
-
- case 2:
- return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
- flags, context_length,
- nesting_level );
-
- case 3:
- return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
- flags, context_length,
- nesting_level );
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
-
- /***********
- * GPOS API
- ***********/
-
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Select_Script( TTO_GPOSHeader* gpos,
- FT_ULong script_tag,
- FT_UShort* script_index )
- {
- FT_UShort n;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
-
-
- if ( !gpos || !script_index )
- return TT_Err_Invalid_Argument;
-
- sl = &gpos->ScriptList;
- sr = sl->ScriptRecord;
-
- for ( n = 0; n < sl->ScriptCount; n++ )
- if ( script_tag == sr[n].ScriptTag )
- {
- *script_index = n;
-
- return TT_Err_Ok;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Select_Language( TTO_GPOSHeader* gpos,
- FT_ULong language_tag,
- FT_UShort script_index,
- FT_UShort* language_index,
- FT_UShort* req_feature_index )
- {
- FT_UShort n;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
-
-
- if ( !gpos || !language_index || !req_feature_index )
- return TT_Err_Invalid_Argument;
-
- sl = &gpos->ScriptList;
- sr = sl->ScriptRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- for ( n = 0; n < s->LangSysCount; n++ )
- if ( language_tag == lsr[n].LangSysTag )
- {
- *language_index = n;
- *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
-
- return TT_Err_Ok;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- /* selecting 0xFFFF for language_index asks for the values of the
- default language (DefaultLangSys) */
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Select_Feature( TTO_GPOSHeader* gpos,
- FT_ULong feature_tag,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_UShort* feature_index )
- {
- FT_UShort n;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
- TTO_LangSys* ls;
- FT_UShort* fi;
-
- TTO_FeatureList* fl;
- TTO_FeatureRecord* fr;
-
-
- if ( !gpos || !feature_index )
- return TT_Err_Invalid_Argument;
-
- sl = &gpos->ScriptList;
- sr = sl->ScriptRecord;
-
- fl = &gpos->FeatureList;
- fr = fl->FeatureRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- if ( language_index == 0xFFFF )
- ls = &s->DefaultLangSys;
- else
- {
- if ( language_index >= s->LangSysCount )
- return TT_Err_Invalid_Argument;
-
- ls = &lsr[language_index].LangSys;
- }
-
- fi = ls->FeatureIndex;
-
- for ( n = 0; n < ls->FeatureCount; n++ )
- {
- if ( fi[n] >= fl->FeatureCount )
- return TTO_Err_Invalid_GPOS_SubTable_Format;
-
- if ( feature_tag == fr[fi[n]].FeatureTag )
- {
- *feature_index = fi[n];
-
- return TT_Err_Ok;
- }
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- /* The next three functions return a null-terminated list */
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Query_Scripts( TTO_GPOSHeader* gpos,
- FT_ULong** script_tag_list )
- {
- FT_Error error;
- FT_Memory memory = gpos->memory;
- FT_UShort n;
- FT_ULong* stl;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
-
-
- if ( !gpos || !script_tag_list )
- return TT_Err_Invalid_Argument;
-
- sl = &gpos->ScriptList;
- sr = sl->ScriptRecord;
-
- if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) )
- return error;
-
- for ( n = 0; n < sl->ScriptCount; n++ )
- stl[n] = sr[n].ScriptTag;
- stl[n] = 0;
-
- *script_tag_list = stl;
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Query_Languages( TTO_GPOSHeader* gpos,
- FT_UShort script_index,
- FT_ULong** language_tag_list )
- {
- FT_Error error;
- FT_Memory memory = gpos->memory;
- FT_UShort n;
- FT_ULong* ltl;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
-
-
- if ( !gpos || !language_tag_list )
- return TT_Err_Invalid_Argument;
-
- sl = &gpos->ScriptList;
- sr = sl->ScriptRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) )
- return error;
-
- for ( n = 0; n < s->LangSysCount; n++ )
- ltl[n] = lsr[n].LangSysTag;
- ltl[n] = 0;
-
- *language_tag_list = ltl;
-
- return TT_Err_Ok;
- }
-
-
- /* selecting 0xFFFF for language_index asks for the values of the
- default language (DefaultLangSys) */
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Query_Features( TTO_GPOSHeader* gpos,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_ULong** feature_tag_list )
- {
- FT_UShort n;
- FT_Error error;
- FT_Memory memory = gpos->memory;
- FT_ULong* ftl;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
- TTO_LangSys* ls;
- FT_UShort* fi;
-
- TTO_FeatureList* fl;
- TTO_FeatureRecord* fr;
-
-
- if ( !gpos || !feature_tag_list )
- return TT_Err_Invalid_Argument;
-
- sl = &gpos->ScriptList;
- sr = sl->ScriptRecord;
-
- fl = &gpos->FeatureList;
- fr = fl->FeatureRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- if ( language_index == 0xFFFF )
- ls = &s->DefaultLangSys;
- else
- {
- if ( language_index >= s->LangSysCount )
- return TT_Err_Invalid_Argument;
-
- ls = &lsr[language_index].LangSys;
- }
-
- fi = ls->FeatureIndex;
-
- if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) )
- return error;
-
- for ( n = 0; n < ls->FeatureCount; n++ )
- {
- if ( fi[n] >= fl->FeatureCount )
- {
- FREE( ftl );
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
- ftl[n] = fr[fi[n]].FeatureTag;
- }
- ftl[n] = 0;
-
- *feature_tag_list = ftl;
-
- return TT_Err_Ok;
- }
-
-
- typedef FT_Error (*Lookup_Func_Type) ( GPOS_Instance* gpi,
- TTO_GPOS_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level );
- static const Lookup_Func_Type Lookup_Call_Table[] = {
- Lookup_DefaultPos,
- Lookup_SinglePos, /* GPOS_LOOKUP_SINGLE 1 */
- Lookup_PairPos, /* GPOS_LOOKUP_PAIR 2 */
- Lookup_CursivePos, /* GPOS_LOOKUP_CURSIVE 3 */
- Lookup_MarkBasePos, /* GPOS_LOOKUP_MARKBASE 4 */
- Lookup_MarkLigPos, /* GPOS_LOOKUP_MARKLIG 5 */
- Lookup_MarkMarkPos, /* GPOS_LOOKUP_MARKMARK 6 */
- Lookup_ContextPos, /* GPOS_LOOKUP_CONTEXT 7 */
- Lookup_ChainContextPos, /* GPOS_LOOKUP_CHAIN 8 */
- Lookup_DefaultPos, /* GPOS_LOOKUP_EXTENSION 9 */
- };
-
- /* Do an individual subtable lookup. Returns TT_Err_Ok if positioning
- has been done, or TTO_Err_Not_Covered if not. */
-
- static FT_Error Do_Glyph_Lookup( GPOS_Instance* gpi,
- FT_UShort lookup_index,
- OTL_Buffer buffer,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_Error error = TTO_Err_Not_Covered;
- FT_UShort i, flags, lookup_count;
- TTO_GPOSHeader* gpos = gpi->gpos;
- TTO_Lookup* lo;
- int lt;
- Lookup_Func_Type Lookup_Func;
-
-
- nesting_level++;
-
- if ( nesting_level > TTO_MAX_NESTING_LEVEL )
- return TTO_Err_Too_Many_Nested_Contexts;
-
- lookup_count = gpos->LookupList.LookupCount;
- if (lookup_index >= lookup_count)
- return error;
-
- lo = &gpos->LookupList.Lookup[lookup_index];
- flags = lo->LookupFlag;
- lt = lo->LookupType;
- if (lt >= sizeof Lookup_Call_Table / sizeof Lookup_Call_Table[0])
- lt = 0;
- Lookup_Func = Lookup_Call_Table[lt];
-
- for ( i = 0; i < lo->SubTableCount; i++ )
- {
- error = Lookup_Func ( gpi,
- &lo->SubTable[i].st.gpos,
- buffer,
- flags, context_length,
- nesting_level );
-
- /* Check whether we have a successful positioning or an error other
- than TTO_Err_Not_Covered */
-
- if ( error != TTO_Err_Not_Covered )
- return error;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- /* apply one lookup to the input string object */
-
- static FT_Error Do_String_Lookup( GPOS_Instance* gpi,
- FT_UShort lookup_index,
- OTL_Buffer buffer )
- {
- FT_Error error, retError = TTO_Err_Not_Covered;
- TTO_GPOSHeader* gpos = gpi->gpos;
-
- FT_UInt* properties = gpos->LookupList.Properties;
-
- int nesting_level = 0;
-
-
- gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */
-
- buffer->in_pos = 0;
-
- while ( buffer->in_pos < buffer->in_length )
- {
- if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
- {
- /* 0xFFFF indicates that we don't have a context length yet. */
-
- /* Note that the connection between mark and base glyphs hold
- exactly one (string) lookup. For example, it would be possible
- that in the first lookup, mark glyph X is attached to base
- glyph A, and in the next lookup it is attached to base glyph B.
- It is up to the font designer to provide meaningful lookups and
- lookup order. */
-
- error = Do_Glyph_Lookup( gpi, lookup_index, buffer,
- 0xFFFF, nesting_level );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
- }
- else
- {
- /* Contrary to properties defined in GDEF, user-defined properties
- will always stop a possible cursive positioning. */
- gpi->last = 0xFFFF;
-
- error = TTO_Err_Not_Covered;
- }
-
- if ( error == TTO_Err_Not_Covered )
- (buffer->in_pos)++;
- else
- retError = error;
- }
-
- return retError;
- }
-
-
- static FT_Error Position_CursiveChain ( OTL_Buffer buffer )
- {
- FT_ULong i, j;
- OTL_Position positions = buffer->positions;
-
- /* First handle all left-to-right connections */
- for (j = 0; j < buffer->in_length; j--)
- {
- if (positions[j].cursive_chain > 0)
- positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
- }
-
- /* Then handle all right-to-left connections */
- for (i = buffer->in_length; i > 0; i--)
- {
- j = i - 1;
-
- if (positions[j].cursive_chain < 0)
- positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
- }
-
- return TT_Err_Ok;
- }
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos,
- FT_UShort feature_index,
- FT_UInt property )
- {
- FT_UShort i;
-
- TTO_Feature feature;
- FT_UInt* properties;
- FT_UShort* index;
- FT_UShort lookup_count;
-
- /* Each feature can only be added once */
-
- if ( !gpos ||
- feature_index >= gpos->FeatureList.FeatureCount ||
- gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
- return TT_Err_Invalid_Argument;
-
- gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
-
- properties = gpos->LookupList.Properties;
-
- feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
- index = feature.LookupListIndex;
- lookup_count = gpos->LookupList.LookupCount;
-
- for ( i = 0; i < feature.LookupListCount; i++ )
- {
- FT_UShort lookup_index = index[i];
- if (lookup_index < lookup_count)
- properties[lookup_index] |= property;
- }
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Clear_Features( TTO_GPOSHeader* gpos )
- {
- FT_UShort i;
-
- FT_UInt* properties;
-
-
- if ( !gpos )
- return TT_Err_Invalid_Argument;
-
- gpos->FeatureList.ApplyCount = 0;
-
- properties = gpos->LookupList.Properties;
-
- for ( i = 0; i < gpos->LookupList.LookupCount; i++ )
- properties[i] = 0;
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Register_Glyph_Function( TTO_GPOSHeader* gpos,
- TTO_GlyphFunction gfunc )
- {
- if ( !gpos )
- return TT_Err_Invalid_Argument;
-
- gpos->gfunc = gfunc;
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Register_MM_Function( TTO_GPOSHeader* gpos,
- TTO_MMFunction mmfunc,
- void* data )
- {
- if ( !gpos )
- return TT_Err_Invalid_Argument;
-
- gpos->mmfunc = mmfunc;
- gpos->data = data;
-
- return TT_Err_Ok;
- }
-
- /* If `dvi' is TRUE, glyph contour points for anchor points and device
- tables are ignored -- you will get device independent values. */
-
- EXPORT_FUNC
- FT_Error TT_GPOS_Apply_String( FT_Face face,
- TTO_GPOSHeader* gpos,
- FT_UShort load_flags,
- OTL_Buffer buffer,
- FT_Bool dvi,
- FT_Bool r2l )
- {
- FT_Error error, retError = TTO_Err_Not_Covered;
- GPOS_Instance gpi;
- FT_UShort i, j, feature_index, lookup_count;
- TTO_Feature feature;
-
- if ( !face || !gpos ||
- !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
- return TT_Err_Invalid_Argument;
-
- gpi.face = face;
- gpi.gpos = gpos;
- gpi.load_flags = load_flags;
- gpi.r2l = r2l;
- gpi.dvi = dvi;
-
- lookup_count = gpos->LookupList.LookupCount;
-
- for ( i = 0; i < gpos->FeatureList.ApplyCount; i++ )
- {
- /* index of i'th feature */
- feature_index = gpos->FeatureList.ApplyOrder[i];
- feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
-
- for ( j = 0; j < feature.LookupListCount; j++ )
- {
- FT_UShort lookup_index = feature.LookupListIndex[j];
-
- /* Skip nonexistant lookups */
- if (lookup_index >= lookup_count)
- continue;
-
- error = Do_String_Lookup( &gpi, lookup_index, buffer );
- if ( error )
- {
- if ( error != TTO_Err_Not_Covered )
- return error;
- }
- else
- retError = error;
- }
- }
-
- error = Position_CursiveChain ( buffer );
- if ( error )
- return error;
-
- return retError;
- }
-
-/* END */
diff --git a/pango/opentype/ftxgpos.h b/pango/opentype/ftxgpos.h
deleted file mode 100644
index 28d1bae0..00000000
--- a/pango/opentype/ftxgpos.h
+++ /dev/null
@@ -1,838 +0,0 @@
-/*******************************************************************
- *
- * ftxgpos.h
- *
- * TrueType Open GPOS table support
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#ifndef FTXOPEN_H
-#error "Don't include this file! Use ftxopen.h instead."
-#endif
-
-#ifndef FTXGPOS_H
-#define FTXGPOS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define TTO_Err_Invalid_GPOS_SubTable_Format 0x1020
-#define TTO_Err_Invalid_GPOS_SubTable 0x1021
-
-
-/* Lookup types for glyph positioning */
-
-#define GPOS_LOOKUP_SINGLE 1
-#define GPOS_LOOKUP_PAIR 2
-#define GPOS_LOOKUP_CURSIVE 3
-#define GPOS_LOOKUP_MARKBASE 4
-#define GPOS_LOOKUP_MARKLIG 5
-#define GPOS_LOOKUP_MARKMARK 6
-#define GPOS_LOOKUP_CONTEXT 7
-#define GPOS_LOOKUP_CHAIN 8
-#define GPOS_LOOKUP_EXTENSION 9
-
-
- /* A pointer to a function which loads a glyph. Its parameters are
- the same as in a call to TT_Load_Glyph() -- if no glyph loading
- function will be registered with TTO_GPOS_Register_Glyph_Function(),
- TT_Load_Glyph() will be called indeed. The purpose of this function
- pointer is to provide a hook for caching glyph outlines and sbits
- (using the instance's generic pointer to hold the data).
-
- If for some reason no outline data is available (e.g. for an
- embedded bitmap glyph), _glyph->outline.n_points should be set to
- zero. _glyph can be computed with
-
- _glyph = HANDLE_Glyph( glyph ) */
-
- typedef FT_Error (*TTO_GlyphFunction)(FT_Face face,
- FT_UInt glyphIndex,
- FT_Int loadFlags );
-
-
- /* A pointer to a function which accesses the PostScript interpreter.
- Multiple Master fonts need this interface to convert a metric ID
- (as stored in an OpenType font version 1.2 or higher) `metric_id'
- into a metric value (returned in `metric_value').
-
- `data' points to the user-defined structure specified during a
- call to TT_GPOS_Register_MM_Function().
-
- `metric_value' must be returned as a scaled value (but shouldn't
- be rounded). */
-
- typedef FT_Error (*TTO_MMFunction)(FT_Face face,
- FT_UShort metric_id,
- FT_Pos* metric_value,
- void* data );
-
-
- struct TTO_GPOSHeader_
- {
- FT_Memory memory;
-
- FT_Fixed Version;
-
- TTO_ScriptList ScriptList;
- TTO_FeatureList FeatureList;
- TTO_LookupList LookupList;
-
- TTO_GDEFHeader* gdef;
-
- /* the next field is used for a callback function to get the
- glyph outline. */
-
- TTO_GlyphFunction gfunc;
-
- /* this is OpenType 1.2 -- Multiple Master fonts need this
- callback function to get various metric values from the
- PostScript interpreter. */
-
- TTO_MMFunction mmfunc;
- void* data;
- };
-
- typedef struct TTO_GPOSHeader_ TTO_GPOSHeader;
- typedef struct TTO_GPOSHeader_* TTO_GPOS;
-
-
- /* shared tables */
-
- struct TTO_ValueRecord_
- {
- FT_Short XPlacement; /* horizontal adjustment for
- placement */
- FT_Short YPlacement; /* vertical adjustment for
- placement */
- FT_Short XAdvance; /* horizontal adjustment for
- advance */
- FT_Short YAdvance; /* vertical adjustment for
- advance */
- TTO_Device XPlacementDevice; /* device table for horizontal
- placement */
- TTO_Device YPlacementDevice; /* device table for vertical
- placement */
- TTO_Device XAdvanceDevice; /* device table for horizontal
- advance */
- TTO_Device YAdvanceDevice; /* device table for vertical
- advance */
- FT_UShort XIdPlacement; /* horizontal placement metric ID */
- FT_UShort YIdPlacement; /* vertical placement metric ID */
- FT_UShort XIdAdvance; /* horizontal advance metric ID */
- FT_UShort YIdAdvance; /* vertical advance metric ID */
- };
-
- typedef struct TTO_ValueRecord_ TTO_ValueRecord;
-
-
-/* Mask values to scan the value format of the ValueRecord structure.
- We always expand compressed ValueRecords of the font. */
-
-#define HAVE_X_PLACEMENT 0x0001
-#define HAVE_Y_PLACEMENT 0x0002
-#define HAVE_X_ADVANCE 0x0004
-#define HAVE_Y_ADVANCE 0x0008
-#define HAVE_X_PLACEMENT_DEVICE 0x0010
-#define HAVE_Y_PLACEMENT_DEVICE 0x0020
-#define HAVE_X_ADVANCE_DEVICE 0x0040
-#define HAVE_Y_ADVANCE_DEVICE 0x0080
-#define HAVE_X_ID_PLACEMENT 0x0100
-#define HAVE_Y_ID_PLACEMENT 0x0200
-#define HAVE_X_ID_ADVANCE 0x0400
-#define HAVE_Y_ID_ADVANCE 0x0800
-
-
- struct TTO_AnchorFormat1_
- {
- FT_Short XCoordinate; /* horizontal value */
- FT_Short YCoordinate; /* vertical value */
- };
-
- typedef struct TTO_AnchorFormat1_ TTO_AnchorFormat1;
-
-
- struct TTO_AnchorFormat2_
- {
- FT_Short XCoordinate; /* horizontal value */
- FT_Short YCoordinate; /* vertical value */
- FT_UShort AnchorPoint; /* index to glyph contour point */
- };
-
- typedef struct TTO_AnchorFormat2_ TTO_AnchorFormat2;
-
-
- struct TTO_AnchorFormat3_
- {
- FT_Short XCoordinate; /* horizontal value */
- FT_Short YCoordinate; /* vertical value */
- TTO_Device XDeviceTable; /* device table for X coordinate */
- TTO_Device YDeviceTable; /* device table for Y coordinate */
- };
-
- typedef struct TTO_AnchorFormat3_ TTO_AnchorFormat3;
-
-
- struct TTO_AnchorFormat4_
- {
- FT_UShort XIdAnchor; /* horizontal metric ID */
- FT_UShort YIdAnchor; /* vertical metric ID */
- };
-
- typedef struct TTO_AnchorFormat4_ TTO_AnchorFormat4;
-
-
- struct TTO_Anchor_
- {
- FT_UShort PosFormat; /* 1, 2, 3, or 4 -- 0 indicates
- that there is no Anchor table */
-
- union
- {
- TTO_AnchorFormat1 af1;
- TTO_AnchorFormat2 af2;
- TTO_AnchorFormat3 af3;
- TTO_AnchorFormat4 af4;
- } af;
- };
-
- typedef struct TTO_Anchor_ TTO_Anchor;
-
-
- struct TTO_MarkRecord_
- {
- FT_UShort Class; /* mark class */
- TTO_Anchor MarkAnchor; /* anchor table */
- };
-
- typedef struct TTO_MarkRecord_ TTO_MarkRecord;
-
-
- struct TTO_MarkArray_
- {
- FT_UShort MarkCount; /* number of MarkRecord tables */
- TTO_MarkRecord* MarkRecord; /* array of MarkRecord tables */
- };
-
- typedef struct TTO_MarkArray_ TTO_MarkArray;
-
-
- /* LookupType 1 */
-
- struct TTO_SinglePosFormat1_
- {
- TTO_ValueRecord Value; /* ValueRecord for all covered
- glyphs */
- };
-
- typedef struct TTO_SinglePosFormat1_ TTO_SinglePosFormat1;
-
-
- struct TTO_SinglePosFormat2_
- {
- FT_UShort ValueCount; /* number of ValueRecord tables */
- TTO_ValueRecord* Value; /* array of ValueRecord tables */
- };
-
- typedef struct TTO_SinglePosFormat2_ TTO_SinglePosFormat2;
-
-
- struct TTO_SinglePos_
- {
- FT_UShort PosFormat; /* 1 or 2 */
- TTO_Coverage Coverage; /* Coverage table */
-
- FT_UShort ValueFormat; /* format of ValueRecord table */
-
- union
- {
- TTO_SinglePosFormat1 spf1;
- TTO_SinglePosFormat2 spf2;
- } spf;
- };
-
- typedef struct TTO_SinglePos_ TTO_SinglePos;
-
-
- /* LookupType 2 */
-
- struct TTO_PairValueRecord_
- {
- FT_UShort SecondGlyph; /* glyph ID for second glyph */
- TTO_ValueRecord Value1; /* pos. data for first glyph */
- TTO_ValueRecord Value2; /* pos. data for second glyph */
- };
-
- typedef struct TTO_PairValueRecord_ TTO_PairValueRecord;
-
-
- struct TTO_PairSet_
- {
- FT_UShort PairValueCount;
- /* number of PairValueRecord tables */
- TTO_PairValueRecord* PairValueRecord;
- /* array of PairValueRecord tables */
- };
-
- typedef struct TTO_PairSet_ TTO_PairSet;
-
-
- struct TTO_PairPosFormat1_
- {
- FT_UShort PairSetCount; /* number of PairSet tables */
- TTO_PairSet* PairSet; /* array of PairSet tables */
- };
-
- typedef struct TTO_PairPosFormat1_ TTO_PairPosFormat1;
-
-
- struct TTO_Class2Record_
- {
- TTO_ValueRecord Value1; /* pos. data for first glyph */
- TTO_ValueRecord Value2; /* pos. data for second glyph */
- };
-
- typedef struct TTO_Class2Record_ TTO_Class2Record;
-
-
- struct TTO_Class1Record_
- {
- TTO_Class2Record* Class2Record; /* array of Class2Record tables */
- };
-
- typedef struct TTO_Class1Record_ TTO_Class1Record;
-
-
- struct TTO_PairPosFormat2_
- {
- TTO_ClassDefinition ClassDef1; /* class def. for first glyph */
- TTO_ClassDefinition ClassDef2; /* class def. for second glyph */
- FT_UShort Class1Count; /* number of classes in ClassDef1
- table */
- FT_UShort Class2Count; /* number of classes in ClassDef2
- table */
- TTO_Class1Record* Class1Record; /* array of Class1Record tables */
- };
-
- typedef struct TTO_PairPosFormat2_ TTO_PairPosFormat2;
-
-
- struct TTO_PairPos_
- {
- FT_UShort PosFormat; /* 1 or 2 */
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort ValueFormat1; /* format of ValueRecord table
- for first glyph */
- FT_UShort ValueFormat2; /* format of ValueRecord table
- for second glyph */
-
- union
- {
- TTO_PairPosFormat1 ppf1;
- TTO_PairPosFormat2 ppf2;
- } ppf;
- };
-
- typedef struct TTO_PairPos_ TTO_PairPos;
-
-
- /* LookupType 3 */
-
- struct TTO_EntryExitRecord_
- {
- TTO_Anchor EntryAnchor; /* entry Anchor table */
- TTO_Anchor ExitAnchor; /* exit Anchor table */
- };
-
-
- typedef struct TTO_EntryExitRecord_ TTO_EntryExitRecord;
-
- struct TTO_CursivePos_
- {
- FT_UShort PosFormat; /* always 1 */
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort EntryExitCount;
- /* number of EntryExitRecord tables */
- TTO_EntryExitRecord* EntryExitRecord;
- /* array of EntryExitRecord tables */
- };
-
- typedef struct TTO_CursivePos_ TTO_CursivePos;
-
-
- /* LookupType 4 */
-
- struct TTO_BaseRecord_
- {
- TTO_Anchor* BaseAnchor; /* array of base glyph anchor
- tables */
- };
-
- typedef struct TTO_BaseRecord_ TTO_BaseRecord;
-
-
- struct TTO_BaseArray_
- {
- FT_UShort BaseCount; /* number of BaseRecord tables */
- TTO_BaseRecord* BaseRecord; /* array of BaseRecord tables */
- };
-
- typedef struct TTO_BaseArray_ TTO_BaseArray;
-
-
- struct TTO_MarkBasePos_
- {
- FT_UShort PosFormat; /* always 1 */
- TTO_Coverage MarkCoverage; /* mark glyph coverage table */
- TTO_Coverage BaseCoverage; /* base glyph coverage table */
- FT_UShort ClassCount; /* number of mark classes */
- TTO_MarkArray MarkArray; /* mark array table */
- TTO_BaseArray BaseArray; /* base array table */
- };
-
- typedef struct TTO_MarkBasePos_ TTO_MarkBasePos;
-
-
- /* LookupType 5 */
-
- struct TTO_ComponentRecord_
- {
- TTO_Anchor* LigatureAnchor; /* array of ligature glyph anchor
- tables */
- };
-
- typedef struct TTO_ComponentRecord_ TTO_ComponentRecord;
-
-
- struct TTO_LigatureAttach_
- {
- FT_UShort ComponentCount;
- /* number of ComponentRecord tables */
- TTO_ComponentRecord* ComponentRecord;
- /* array of ComponentRecord tables */
- };
-
- typedef struct TTO_LigatureAttach_ TTO_LigatureAttach;
-
-
- struct TTO_LigatureArray_
- {
- FT_UShort LigatureCount; /* number of LigatureAttach tables */
- TTO_LigatureAttach* LigatureAttach;
- /* array of LigatureAttach tables */
- };
-
- typedef struct TTO_LigatureArray_ TTO_LigatureArray;
-
-
- struct TTO_MarkLigPos_
- {
- FT_UShort PosFormat; /* always 1 */
- TTO_Coverage MarkCoverage; /* mark glyph coverage table */
- TTO_Coverage LigatureCoverage;
- /* ligature glyph coverage table */
- FT_UShort ClassCount; /* number of mark classes */
- TTO_MarkArray MarkArray; /* mark array table */
- TTO_LigatureArray LigatureArray; /* ligature array table */
- };
-
- typedef struct TTO_MarkLigPos_ TTO_MarkLigPos;
-
-
- /* LookupType 6 */
-
- struct TTO_Mark2Record_
- {
- TTO_Anchor* Mark2Anchor; /* array of mark glyph anchor
- tables */
- };
-
- typedef struct TTO_Mark2Record_ TTO_Mark2Record;
-
-
- struct TTO_Mark2Array_
- {
- FT_UShort Mark2Count; /* number of Mark2Record tables */
- TTO_Mark2Record* Mark2Record; /* array of Mark2Record tables */
- };
-
- typedef struct TTO_Mark2Array_ TTO_Mark2Array;
-
-
- struct TTO_MarkMarkPos_
- {
- FT_UShort PosFormat; /* always 1 */
- TTO_Coverage Mark1Coverage; /* first mark glyph coverage table */
- TTO_Coverage Mark2Coverage; /* second mark glyph coverave table */
- FT_UShort ClassCount; /* number of combining mark classes */
- TTO_MarkArray Mark1Array; /* MarkArray table for first mark */
- TTO_Mark2Array Mark2Array; /* MarkArray table for second mark */
- };
-
- typedef struct TTO_MarkMarkPos_ TTO_MarkMarkPos;
-
-
- /* needed by both lookup type 7 and 8 */
-
- struct TTO_PosLookupRecord_
- {
- FT_UShort SequenceIndex; /* index into current
- glyph sequence */
- FT_UShort LookupListIndex; /* Lookup to apply to that pos. */
- };
-
- typedef struct TTO_PosLookupRecord_ TTO_PosLookupRecord;
-
-
- /* LookupType 7 */
-
- struct TTO_PosRule_
- {
- FT_UShort GlyphCount; /* total number of input glyphs */
- FT_UShort PosCount; /* number of PosLookupRecord tables */
- FT_UShort* Input; /* array of input glyph IDs */
- TTO_PosLookupRecord* PosLookupRecord;
- /* array of PosLookupRecord tables */
- };
-
- typedef struct TTO_PosRule_ TTO_PosRule;
-
-
- struct TTO_PosRuleSet_
- {
- FT_UShort PosRuleCount; /* number of PosRule tables */
- TTO_PosRule* PosRule; /* array of PosRule tables */
- };
-
- typedef struct TTO_PosRuleSet_ TTO_PosRuleSet;
-
-
- struct TTO_ContextPosFormat1_
- {
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort PosRuleSetCount; /* number of PosRuleSet tables */
- TTO_PosRuleSet* PosRuleSet; /* array of PosRuleSet tables */
- };
-
- typedef struct TTO_ContextPosFormat1_ TTO_ContextPosFormat1;
-
-
- struct TTO_PosClassRule_
- {
- FT_UShort GlyphCount; /* total number of context classes */
- FT_UShort PosCount; /* number of PosLookupRecord tables */
- FT_UShort* Class; /* array of classes */
- TTO_PosLookupRecord* PosLookupRecord;
- /* array of PosLookupRecord tables */
- };
-
- typedef struct TTO_PosClassRule_ TTO_PosClassRule;
-
-
- struct TTO_PosClassSet_
- {
- FT_UShort PosClassRuleCount;
- /* number of PosClassRule tables */
- TTO_PosClassRule* PosClassRule; /* array of PosClassRule tables */
- };
-
- typedef struct TTO_PosClassSet_ TTO_PosClassSet;
-
-
- /* The `MaxContextLength' field is not defined in the TTO specification
- but simplifies the implementation of this format. It holds the
- maximal context length used in the context rules. */
-
- struct TTO_ContextPosFormat2_
- {
- FT_UShort MaxContextLength;
- /* maximal context length */
- TTO_Coverage Coverage; /* Coverage table */
- TTO_ClassDefinition ClassDef; /* ClassDef table */
- FT_UShort PosClassSetCount;
- /* number of PosClassSet tables */
- TTO_PosClassSet* PosClassSet; /* array of PosClassSet tables */
- };
-
- typedef struct TTO_ContextPosFormat2_ TTO_ContextPosFormat2;
-
-
- struct TTO_ContextPosFormat3_
- {
- FT_UShort GlyphCount; /* number of input glyphs */
- FT_UShort PosCount; /* number of PosLookupRecord tables */
- TTO_Coverage* Coverage; /* array of Coverage tables */
- TTO_PosLookupRecord* PosLookupRecord;
- /* array of PosLookupRecord tables */
- };
-
- typedef struct TTO_ContextPosFormat3_ TTO_ContextPosFormat3;
-
-
- struct TTO_ContextPos_
- {
- FT_UShort PosFormat; /* 1, 2, or 3 */
-
- union
- {
- TTO_ContextPosFormat1 cpf1;
- TTO_ContextPosFormat2 cpf2;
- TTO_ContextPosFormat3 cpf3;
- } cpf;
- };
-
- typedef struct TTO_ContextPos_ TTO_ContextPos;
-
-
- /* LookupType 8 */
-
- struct TTO_ChainPosRule_
- {
- FT_UShort BacktrackGlyphCount;
- /* total number of backtrack glyphs */
- FT_UShort* Backtrack; /* array of backtrack glyph IDs */
- FT_UShort InputGlyphCount;
- /* total number of input glyphs */
- FT_UShort* Input; /* array of input glyph IDs */
- FT_UShort LookaheadGlyphCount;
- /* total number of lookahead glyphs */
- FT_UShort* Lookahead; /* array of lookahead glyph IDs */
- FT_UShort PosCount; /* number of PosLookupRecords */
- TTO_PosLookupRecord* PosLookupRecord;
- /* array of PosLookupRecords */
- };
-
- typedef struct TTO_ChainPosRule_ TTO_ChainPosRule;
-
-
- struct TTO_ChainPosRuleSet_
- {
- FT_UShort ChainPosRuleCount;
- /* number of ChainPosRule tables */
- TTO_ChainPosRule* ChainPosRule; /* array of ChainPosRule tables */
- };
-
- typedef struct TTO_ChainPosRuleSet_ TTO_ChainPosRuleSet;
-
-
- struct TTO_ChainContextPosFormat1_
- {
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort ChainPosRuleSetCount;
- /* number of ChainPosRuleSet tables */
- TTO_ChainPosRuleSet* ChainPosRuleSet;
- /* array of ChainPosRuleSet tables */
- };
-
- typedef struct TTO_ChainContextPosFormat1_ TTO_ChainContextPosFormat1;
-
-
- struct TTO_ChainPosClassRule_
- {
- FT_UShort BacktrackGlyphCount;
- /* total number of backtrack
- classes */
- FT_UShort* Backtrack; /* array of backtrack classes */
- FT_UShort InputGlyphCount;
- /* total number of context classes */
- FT_UShort* Input; /* array of context classes */
- FT_UShort LookaheadGlyphCount;
- /* total number of lookahead
- classes */
- FT_UShort* Lookahead; /* array of lookahead classes */
- FT_UShort PosCount; /* number of PosLookupRecords */
- TTO_PosLookupRecord* PosLookupRecord;
- /* array of substitution lookups */
- };
-
- typedef struct TTO_ChainPosClassRule_ TTO_ChainPosClassRule;
-
-
- struct TTO_ChainPosClassSet_
- {
- FT_UShort ChainPosClassRuleCount;
- /* number of ChainPosClassRule
- tables */
- TTO_ChainPosClassRule* ChainPosClassRule;
- /* array of ChainPosClassRule
- tables */
- };
-
- typedef struct TTO_ChainPosClassSet_ TTO_ChainPosClassSet;
-
-
- /* The `MaxXXXLength' fields are not defined in the TTO specification
- but simplifies the implementation of this format. It holds the
- maximal context length used in the specific context rules. */
-
- struct TTO_ChainContextPosFormat2_
- {
- TTO_Coverage Coverage; /* Coverage table */
-
- FT_UShort MaxBacktrackLength;
- /* maximal backtrack length */
- TTO_ClassDefinition BacktrackClassDef;
- /* BacktrackClassDef table */
- FT_UShort MaxInputLength;
- /* maximal input length */
- TTO_ClassDefinition InputClassDef;
- /* InputClassDef table */
- FT_UShort MaxLookaheadLength;
- /* maximal lookahead length */
- TTO_ClassDefinition LookaheadClassDef;
- /* LookaheadClassDef table */
-
- FT_UShort ChainPosClassSetCount;
- /* number of ChainPosClassSet
- tables */
- TTO_ChainPosClassSet* ChainPosClassSet;
- /* array of ChainPosClassSet
- tables */
- };
-
- typedef struct TTO_ChainContextPosFormat2_ TTO_ChainContextPosFormat2;
-
-
- struct TTO_ChainContextPosFormat3_
- {
- FT_UShort BacktrackGlyphCount;
- /* number of backtrack glyphs */
- TTO_Coverage* BacktrackCoverage;
- /* array of backtrack Coverage
- tables */
- FT_UShort InputGlyphCount;
- /* number of input glyphs */
- TTO_Coverage* InputCoverage;
- /* array of input coverage
- tables */
- FT_UShort LookaheadGlyphCount;
- /* number of lookahead glyphs */
- TTO_Coverage* LookaheadCoverage;
- /* array of lookahead coverage
- tables */
- FT_UShort PosCount; /* number of PosLookupRecords */
- TTO_PosLookupRecord* PosLookupRecord;
- /* array of substitution lookups */
- };
-
- typedef struct TTO_ChainContextPosFormat3_ TTO_ChainContextPosFormat3;
-
-
- struct TTO_ChainContextPos_
- {
- FT_UShort PosFormat; /* 1, 2, or 3 */
-
- union
- {
- TTO_ChainContextPosFormat1 ccpf1;
- TTO_ChainContextPosFormat2 ccpf2;
- TTO_ChainContextPosFormat3 ccpf3;
- } ccpf;
- };
-
- typedef struct TTO_ChainContextPos_ TTO_ChainContextPos;
-
-
- union TTO_GPOS_SubTable_
- {
- TTO_SinglePos single;
- TTO_PairPos pair;
- TTO_CursivePos cursive;
- TTO_MarkBasePos markbase;
- TTO_MarkLigPos marklig;
- TTO_MarkMarkPos markmark;
- TTO_ContextPos context;
- TTO_ChainContextPos chain;
- };
-
- typedef union TTO_GPOS_SubTable_ TTO_GPOS_SubTable;
-
-
- /* finally, the GPOS API */
-
- /* EXPORT_DEF
- FT_Export ( FT_Error ) TT_Init_GPOS_Extension( TT_Engine engine ); */
-
- EXPORT_DEF
- FT_Error TT_Load_GPOS_Table( FT_Face face,
- TTO_GPOSHeader** gpos,
- TTO_GDEFHeader* gdef );
-
- EXPORT_DEF
- FT_Error TT_Done_GPOS_Table( TTO_GPOSHeader* gpos );
-
- EXPORT_DEF
- FT_Error TT_GPOS_Select_Script( TTO_GPOSHeader* gpos,
- FT_ULong script_tag,
- FT_UShort* script_index );
- EXPORT_DEF
- FT_Error TT_GPOS_Select_Language( TTO_GPOSHeader* gpos,
- FT_ULong language_tag,
- FT_UShort script_index,
- FT_UShort* language_index,
- FT_UShort* req_feature_index );
- EXPORT_DEF
- FT_Error TT_GPOS_Select_Feature( TTO_GPOSHeader* gpos,
- FT_ULong feature_tag,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_UShort* feature_index );
-
- EXPORT_DEF
- FT_Error TT_GPOS_Query_Scripts( TTO_GPOSHeader* gpos,
- FT_ULong** script_tag_list );
- EXPORT_DEF
- FT_Error TT_GPOS_Query_Languages( TTO_GPOSHeader* gpos,
- FT_UShort script_index,
- FT_ULong** language_tag_list );
- EXPORT_DEF
- FT_Error TT_GPOS_Query_Features( TTO_GPOSHeader* gpos,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_ULong** feature_tag_list );
-
- EXPORT_DEF
- FT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos,
- FT_UShort feature_index,
- FT_UInt property );
- EXPORT_DEF
- FT_Error TT_GPOS_Clear_Features( TTO_GPOSHeader* gpos );
-
- EXPORT_DEF
- FT_Error TT_GPOS_Register_Glyph_Function( TTO_GPOSHeader* gpos,
- TTO_GlyphFunction gfunc );
-
- EXPORT_DEF
- FT_Error TT_GPOS_Register_MM_Function( TTO_GPOSHeader* gpos,
- TTO_MMFunction mmfunc,
- void* data );
-
- /* If `dvi' is TRUE, glyph contour points for anchor points and device
- tables are ignored -- you will get device independent values. */
-
- EXPORT_DEF
- FT_Error TT_GPOS_Apply_String( FT_Face face,
- TTO_GPOSHeader* gpos,
- FT_UShort load_flags,
- OTL_Buffer buffer,
- FT_Bool dvi,
- FT_Bool r2l );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* FTXGPOS_H */
-
-
-/* END */
diff --git a/pango/opentype/ftxgsub.c b/pango/opentype/ftxgsub.c
deleted file mode 100644
index ce306976..00000000
--- a/pango/opentype/ftxgsub.c
+++ /dev/null
@@ -1,4533 +0,0 @@
-/*******************************************************************
- *
- * ftxgsub.c
- *
- * TrueType Open GSUB table support.
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#include <config.h>
-
-/* XXX There is *a lot* of duplicated code (cf. formats 5 and 6), but
- I don't care currently. I believe that it would be possible to
- save about 50% of TTO code by carefully designing the structures,
- sharing as much as possible with extensive use of macros. This
- is something for a volunteer :-) */
-
-#define EXPORT_FUNC
-
-#include "ftxopen.h"
-#include "ftxopenf.h"
-
-#include "ftglue.h"
-
-#include FT_TRUETYPE_TAGS_H
-
-#define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' )
-
-
-#define IN_GLYPH( pos ) buffer->in_string[(pos)].gindex
-#define IN_ITEM( pos ) (&buffer->in_string[(pos)])
-#define IN_CURGLYPH() buffer->in_string[buffer->in_pos].gindex
-#define IN_CURITEM() (&buffer->in_string[buffer->in_pos])
-#define IN_PROPERTIES( pos ) buffer->in_string[(pos)].properties
-#define IN_LIGID( pos ) buffer->in_string[(pos)].ligID
-
-#define OUT_GLYPH( pos ) buffer->out_string[(pos)].gindex
-#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])
-
-#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
- ( ( error = otl_buffer_add_output_glyphs( (buffer), \
- (num_in), (num_out), \
- (glyph_data), (component), (ligID) \
- ) ) != TT_Err_Ok )
-#define ADD_Glyph( buffer, glyph_index, component, ligID ) \
- ( ( error = otl_buffer_add_output_glyph( (buffer), \
- (glyph_index), (component), (ligID) \
- ) ) != TT_Err_Ok )
-
-
- static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
- FT_UShort lookup_index,
- OTL_Buffer buffer,
- FT_UShort context_length,
- int nesting_level );
-
-
-
- /**********************
- * Auxiliary functions
- **********************/
-
-
- EXPORT_FUNC
- FT_Error TT_Load_GSUB_Table( FT_Face face,
- TTO_GSUBHeader** retptr,
- TTO_GDEFHeader* gdef )
- {
- FT_Stream stream = face->stream;
- FT_Memory memory = face->memory;
- FT_Error error;
- FT_ULong cur_offset, new_offset, base_offset;
-
- FT_UShort i, num_lookups;
- TTO_GSUBHeader* gsub;
- TTO_Lookup* lo;
-
- if ( !retptr )
- return TT_Err_Invalid_Argument;
-
- if (( error = ftglue_face_goto_table( face, TTAG_GSUB, stream ) ))
- return error;
-
- base_offset = FILE_Pos();
-
- if ( ALLOC ( gsub, sizeof( *gsub ) ) )
- return error;
-
- gsub->memory = memory;
-
- /* skip version */
-
- if ( FILE_Seek( base_offset + 4L ) ||
- ACCESS_Frame( 2L ) )
- goto Fail4;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ScriptList( &gsub->ScriptList,
- stream ) ) != TT_Err_Ok )
- goto Fail4;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_FeatureList( &gsub->FeatureList,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LookupList( &gsub->LookupList,
- stream, GSUB ) ) != TT_Err_Ok )
- goto Fail2;
-
- gsub->gdef = gdef; /* can be NULL */
-
- /* We now check the LookupFlags for values larger than 0xFF to find
- out whether we need to load the `MarkAttachClassDef' field of the
- GDEF table -- this hack is necessary for OpenType 1.2 tables since
- the version field of the GDEF table hasn't been incremented.
-
- For constructed GDEF tables, we only load it if
- `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
- a constructed mark attach table is not supported currently). */
-
- if ( gdef &&
- gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
- {
- lo = gsub->LookupList.Lookup;
- num_lookups = gsub->LookupList.LookupCount;
-
- for ( i = 0; i < num_lookups; i++ )
- {
-
- if ( lo[i].LookupFlag & IGNORE_SPECIAL_MARKS )
- {
- if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
- ( error = Load_ClassDefinition( &gdef->MarkAttachClassDef,
- 256, stream ) ) != TT_Err_Ok )
- goto Fail1;
-
- break;
- }
- }
- }
-
- *retptr = gsub;
-
- return TT_Err_Ok;
-
- Fail1:
- Free_LookupList( &gsub->LookupList, GSUB, memory );
-
- Fail2:
- Free_FeatureList( &gsub->FeatureList, memory );
-
- Fail3:
- Free_ScriptList( &gsub->ScriptList, memory );
-
- Fail4:
- FREE ( gsub );
-
-
- return error;
- }
-
- EXPORT_FUNC
- FT_Error TT_Done_GSUB_Table( TTO_GSUBHeader* gsub )
- {
- FT_Memory memory = gsub->memory;
-
- Free_LookupList( &gsub->LookupList, GSUB, memory );
- Free_FeatureList( &gsub->FeatureList, memory );
- Free_ScriptList( &gsub->ScriptList, memory );
-
- FREE( gsub );
-
- return TT_Err_Ok;
- }
-
- /*****************************
- * SubTable related functions
- *****************************/
-
- static FT_Error Lookup_DefaultSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- return TTO_Err_Not_Covered;
- }
-
-
- /* LookupType 1 */
-
- /* SingleSubstFormat1 */
- /* SingleSubstFormat2 */
-
- FT_Error Load_SingleSubst( TTO_SingleSubst* ss,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- FT_UShort* s;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- ss->SubstFormat = GET_UShort();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &ss->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- switch ( ss->SubstFormat )
- {
- case 1:
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- ss->ssf.ssf1.DeltaGlyphID = GET_UShort();
-
- FORGET_Frame();
-
- break;
-
- case 2:
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = ss->ssf.ssf2.GlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- ss->ssf.ssf2.Substitute = NULL;
-
- if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, FT_UShort ) )
- goto Fail2;
-
- s = ss->ssf.ssf2.Substitute;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- s[n] = GET_UShort();
-
- FORGET_Frame();
-
- break;
-
- default:
- return TTO_Err_Invalid_GSUB_SubTable_Format;
- }
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( s );
-
- Fail2:
- Free_Coverage( &ss->Coverage, memory );
- return error;
- }
-
-
- void Free_SingleSubst( TTO_SingleSubst* ss,
- FT_Memory memory )
- {
- switch ( ss->SubstFormat )
- {
- case 1:
- break;
-
- case 2:
- FREE( ss->ssf.ssf2.Substitute );
- break;
- }
-
- Free_Coverage( &ss->Coverage, memory );
- }
-
-
- static FT_Error Lookup_SingleSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, value, property;
- FT_Error error;
- TTO_SingleSubst* ss = &st->single;
- TTO_GDEFHeader* gdef = gsub->gdef;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- return TTO_Err_Not_Covered;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- switch ( ss->SubstFormat )
- {
- case 1:
- value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
- if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
- return error;
- break;
-
- case 2:
- if ( index >= ss->ssf.ssf2.GlyphCount )
- return TTO_Err_Invalid_GSUB_SubTable;
- value = ss->ssf.ssf2.Substitute[index];
- if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
- return error;
- break;
-
- default:
- return TTO_Err_Invalid_GSUB_SubTable;
- }
-
- if ( gdef && gdef->NewGlyphClasses )
- {
- /* we inherit the old glyph class to the substituted glyph */
-
- error = Add_Glyph_Property( gdef, value, property );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
- }
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 2 */
-
- /* Sequence */
-
- static FT_Error Load_Sequence( TTO_Sequence* s,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_UShort* sub;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = s->GlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- s->Substitute = NULL;
-
- if ( count )
- {
- if ( ALLOC_ARRAY( s->Substitute, count, FT_UShort ) )
- return error;
-
- sub = s->Substitute;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( sub );
- return error;
- }
-
- for ( n = 0; n < count; n++ )
- sub[n] = GET_UShort();
-
- FORGET_Frame();
- }
-
- return TT_Err_Ok;
- }
-
-
- static void Free_Sequence( TTO_Sequence* s,
- FT_Memory memory )
- {
- FREE( s->Substitute );
- }
-
-
- /* MultipleSubstFormat1 */
-
- FT_Error Load_MultipleSubst( TTO_MultipleSubst* ms,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Sequence* s;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- ms->SubstFormat = GET_UShort(); /* should be 1 */
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &ms->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = ms->SequenceCount = GET_UShort();
-
- FORGET_Frame();
-
- ms->Sequence = NULL;
-
- if ( ALLOC_ARRAY( ms->Sequence, count, TTO_Sequence ) )
- goto Fail2;
-
- s = ms->Sequence;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Sequence( &s[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_Sequence( &s[m], memory );
-
- FREE( s );
-
- Fail2:
- Free_Coverage( &ms->Coverage, memory );
- return error;
- }
-
-
- void Free_MultipleSubst( TTO_MultipleSubst* ms,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Sequence* s;
-
-
- if ( ms->Sequence )
- {
- count = ms->SequenceCount;
- s = ms->Sequence;
-
- for ( n = 0; n < count; n++ )
- Free_Sequence( &s[n], memory );
-
- FREE( s );
- }
-
- Free_Coverage( &ms->Coverage, memory );
- }
-
-
- static FT_Error Lookup_MultipleSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_Error error;
- FT_UShort index, property, n, count;
- FT_UShort*s;
- TTO_MultipleSubst* ms = &st->multiple;
- TTO_GDEFHeader* gdef = gsub->gdef;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- return TTO_Err_Not_Covered;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- if ( index >= ms->SequenceCount )
- return TTO_Err_Invalid_GSUB_SubTable;
-
- count = ms->Sequence[index].GlyphCount;
- s = ms->Sequence[index].Substitute;
-
- if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
- return error;
-
- if ( gdef && gdef->NewGlyphClasses )
- {
- /* this is a guess only ... */
-
- if ( property == TTO_LIGATURE )
- property = TTO_BASE_GLYPH;
-
- for ( n = 0; n < count; n++ )
- {
- error = Add_Glyph_Property( gdef, s[n], property );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
- }
- }
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 3 */
-
- /* AlternateSet */
-
- static FT_Error Load_AlternateSet( TTO_AlternateSet* as,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_UShort* a;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = as->GlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- as->Alternate = NULL;
-
- if ( ALLOC_ARRAY( as->Alternate, count, FT_UShort ) )
- return error;
-
- a = as->Alternate;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( a );
- return error;
- }
-
- for ( n = 0; n < count; n++ )
- a[n] = GET_UShort();
-
- FORGET_Frame();
-
- return TT_Err_Ok;
- }
-
-
- static void Free_AlternateSet( TTO_AlternateSet* as,
- FT_Memory memory )
- {
- FREE( as->Alternate );
- }
-
-
- /* AlternateSubstFormat1 */
-
- FT_Error Load_AlternateSubst( TTO_AlternateSubst* as,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_AlternateSet* aset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- as->SubstFormat = GET_UShort(); /* should be 1 */
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &as->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = as->AlternateSetCount = GET_UShort();
-
- FORGET_Frame();
-
- as->AlternateSet = NULL;
-
- if ( ALLOC_ARRAY( as->AlternateSet, count, TTO_AlternateSet ) )
- goto Fail2;
-
- aset = as->AlternateSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_AlternateSet( &aset[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_AlternateSet( &aset[m], memory );
-
- FREE( aset );
-
- Fail2:
- Free_Coverage( &as->Coverage, memory );
- return error;
- }
-
-
- void Free_AlternateSubst( TTO_AlternateSubst* as,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_AlternateSet* aset;
-
-
- if ( as->AlternateSet )
- {
- count = as->AlternateSetCount;
- aset = as->AlternateSet;
-
- for ( n = 0; n < count; n++ )
- Free_AlternateSet( &aset[n], memory );
-
- FREE( aset );
- }
-
- Free_Coverage( &as->Coverage, memory );
- }
-
-
- static FT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_Error error;
- FT_UShort index, alt_index, property;
- TTO_AlternateSubst* as = &st->alternate;
- TTO_GDEFHeader* gdef = gsub->gdef;
-
-
- TTO_AlternateSet aset;
-
-
- if ( context_length != 0xFFFF && context_length < 1 )
- return TTO_Err_Not_Covered;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- aset = as->AlternateSet[index];
-
- /* we use a user-defined callback function to get the alternate index */
-
- if ( gsub->altfunc )
- alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(),
- aset.GlyphCount, aset.Alternate,
- gsub->data );
- else
- alt_index = 0;
-
- if ( ADD_Glyph( buffer, aset.Alternate[alt_index],
- 0xFFFF, 0xFFFF ) )
- return error;
-
- if ( gdef && gdef->NewGlyphClasses )
- {
- /* we inherit the old glyph class to the substituted glyph */
-
- error = Add_Glyph_Property( gdef, aset.Alternate[alt_index],
- property );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
- }
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 4 */
-
- /* Ligature */
-
- static FT_Error Load_Ligature( TTO_Ligature* l,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_UShort* c;
-
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- l->LigGlyph = GET_UShort();
- l->ComponentCount = GET_UShort();
-
- FORGET_Frame();
-
- l->Component = NULL;
-
- count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */
-
- if ( ALLOC_ARRAY( l->Component, count, FT_UShort ) )
- return error;
-
- c = l->Component;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( c );
- return error;
- }
-
- for ( n = 0; n < count; n++ )
- c[n] = GET_UShort();
-
- FORGET_Frame();
-
- return TT_Err_Ok;
- }
-
-
- static void Free_Ligature( TTO_Ligature* l,
- FT_Memory memory )
- {
- FREE( l->Component );
- }
-
-
- /* LigatureSet */
-
- static FT_Error Load_LigatureSet( TTO_LigatureSet* ls,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Ligature* l;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = ls->LigatureCount = GET_UShort();
-
- FORGET_Frame();
-
- ls->Ligature = NULL;
-
- if ( ALLOC_ARRAY( ls->Ligature, count, TTO_Ligature ) )
- return error;
-
- l = ls->Ligature;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Ligature( &l[n], stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_Ligature( &l[m], memory );
-
- FREE( l );
- return error;
- }
-
-
- static void Free_LigatureSet( TTO_LigatureSet* ls,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Ligature* l;
-
-
- if ( ls->Ligature )
- {
- count = ls->LigatureCount;
- l = ls->Ligature;
-
- for ( n = 0; n < count; n++ )
- Free_Ligature( &l[n], memory );
-
- FREE( l );
- }
- }
-
-
- /* LigatureSubstFormat1 */
-
- FT_Error Load_LigatureSubst( TTO_LigatureSubst* ls,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_LigatureSet* lset;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- ls->SubstFormat = GET_UShort(); /* should be 1 */
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &ls->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = ls->LigatureSetCount = GET_UShort();
-
- FORGET_Frame();
-
- ls->LigatureSet = NULL;
-
- if ( ALLOC_ARRAY( ls->LigatureSet, count, TTO_LigatureSet ) )
- goto Fail2;
-
- lset = ls->LigatureSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LigatureSet( &lset[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_LigatureSet( &lset[m], memory );
-
- FREE( lset );
-
- Fail2:
- Free_Coverage( &ls->Coverage, memory );
- return error;
- }
-
-
- void Free_LigatureSubst( TTO_LigatureSubst* ls,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_LigatureSet* lset;
-
-
- if ( ls->LigatureSet )
- {
- count = ls->LigatureSetCount;
- lset = ls->LigatureSet;
-
- for ( n = 0; n < count; n++ )
- Free_LigatureSet( &lset[n], memory );
-
- FREE( lset );
- }
-
- Free_Coverage( &ls->Coverage, memory );
- }
-
-
- static FT_Error Lookup_LigatureSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_Error error;
- FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
- FT_UShort* c;
- TTO_LigatureSubst* ls = &st->ligature;
- TTO_GDEFHeader* gdef = gsub->gdef;
-
- TTO_Ligature* lig;
-
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- if ( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS )
- first_is_mark = TRUE;
-
- error = Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- if ( index >= ls->LigatureSetCount )
- return TTO_Err_Invalid_GSUB_SubTable;
-
- lig = ls->LigatureSet[index].Ligature;
-
- for ( numlig = ls->LigatureSet[index].LigatureCount;
- numlig;
- numlig--, lig++ )
- {
- if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
- goto next_ligature; /* Not enough glyphs in input */
-
- c = lig->Component;
-
- is_mark = first_is_mark;
-
- if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
- break;
-
- for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + lig->ComponentCount - i == buffer->in_length )
- goto next_ligature;
- j++;
- }
-
- if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) )
- is_mark = FALSE;
-
- if ( IN_GLYPH( j ) != c[i - 1] )
- goto next_ligature;
- }
-
- if ( gdef && gdef->NewGlyphClasses )
- {
- /* this is just a guess ... */
-
- error = Add_Glyph_Property( gdef, lig->LigGlyph,
- is_mark ? TTO_MARK : TTO_LIGATURE );
- if ( error && error != TTO_Err_Not_Covered )
- return error;
- }
-
- if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
- {
- /* We don't use a new ligature ID if there are no skipped
- glyphs and the ligature already has an ID. */
-
- if ( IN_LIGID( buffer->in_pos ) )
- {
- if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
- 0xFFFF, 0xFFFF ) )
- return error;
- }
- else
- {
- FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
- if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
- 0xFFFF, ligID ) )
- return error;
- }
- }
- else
- {
- FT_UShort ligID = otl_buffer_allocate_ligid( buffer );
- if ( ADD_Glyph( buffer, lig->LigGlyph,
- 0xFFFF, ligID ) )
- return error;
-
- /* Now we must do a second loop to copy the skipped glyphs to
- `out' and assign component values to it. We start with the
- glyph after the first component. Glyphs between component
- i and i+1 belong to component i. Together with the ligID
- value it is later possible to check whether a specific
- component value really belongs to a given ligature. */
-
- for ( i = 0; i < lig->ComponentCount - 1; i++ )
- {
- while ( CHECK_Property( gdef, IN_CURITEM(),
- flags, &property ) )
- if ( ADD_Glyph( buffer, IN_CURGLYPH(),
- i, ligID ) )
- return error;
-
- (buffer->in_pos)++;
- }
- }
-
- return TT_Err_Ok;
-
- next_ligature:
- ;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- /* Do the actual substitution for a context substitution (either format
- 5 or 6). This is only called after we've determined that the input
- matches the subrule. */
-
- static FT_Error Do_ContextSubst( TTO_GSUBHeader* gsub,
- FT_UShort GlyphCount,
- FT_UShort SubstCount,
- TTO_SubstLookupRecord* subst,
- OTL_Buffer buffer,
- int nesting_level )
- {
- FT_Error error;
- FT_UShort i, old_pos;
-
-
- i = 0;
-
- while ( i < GlyphCount )
- {
- if ( SubstCount && i == subst->SequenceIndex )
- {
- old_pos = buffer->in_pos;
-
- /* Do a substitution */
-
- error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
- GlyphCount, nesting_level );
-
- subst++;
- SubstCount--;
- i += buffer->in_pos - old_pos;
-
- if ( error == TTO_Err_Not_Covered )
- {
- /* XXX "can't happen" -- but don't count on it */
-
- if ( ADD_Glyph( buffer, IN_CURGLYPH(),
- 0xFFFF, 0xFFFF ) )
- return error;
- i++;
- }
- else if ( error )
- return error;
- }
- else
- {
- /* No substitution for this index */
-
- if ( ADD_Glyph( buffer, IN_CURGLYPH(),
- 0xFFFF, 0xFFFF ) )
- return error;
- i++;
- }
- }
-
- return TT_Err_Ok;
- }
-
-
- /* LookupType 5 */
-
- /* SubRule */
-
- static FT_Error Load_SubRule( TTO_SubRule* sr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_UShort* i;
-
- TTO_SubstLookupRecord* slr;
-
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- sr->GlyphCount = GET_UShort();
- sr->SubstCount = GET_UShort();
-
- FORGET_Frame();
-
- sr->Input = NULL;
-
- count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( sr->Input, count, FT_UShort ) )
- return error;
-
- i = sr->Input;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- i[n] = GET_UShort();
-
- FORGET_Frame();
-
- sr->SubstLookupRecord = NULL;
-
- count = sr->SubstCount;
-
- if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, TTO_SubstLookupRecord ) )
- goto Fail2;
-
- slr = sr->SubstLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- slr[n].SequenceIndex = GET_UShort();
- slr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( slr );
-
- Fail2:
- FREE( i );
- return error;
- }
-
-
- static void Free_SubRule( TTO_SubRule* sr,
- FT_Memory memory )
- {
- FREE( sr->SubstLookupRecord );
- FREE( sr->Input );
- }
-
-
- /* SubRuleSet */
-
- static FT_Error Load_SubRuleSet( TTO_SubRuleSet* srs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_SubRule* sr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = srs->SubRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- srs->SubRule = NULL;
-
- if ( ALLOC_ARRAY( srs->SubRule, count, TTO_SubRule ) )
- return error;
-
- sr = srs->SubRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_SubRule( &sr[n], stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_SubRule( &sr[m], memory );
-
- FREE( sr );
- return error;
- }
-
-
- static void Free_SubRuleSet( TTO_SubRuleSet* srs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_SubRule* sr;
-
-
- if ( srs->SubRule )
- {
- count = srs->SubRuleCount;
- sr = srs->SubRule;
-
- for ( n = 0; n < count; n++ )
- Free_SubRule( &sr[n], memory );
-
- FREE( sr );
- }
- }
-
-
- /* ContextSubstFormat1 */
-
- static FT_Error Load_ContextSubst1( TTO_ContextSubstFormat1* csf1,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_SubRuleSet* srs;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &csf1->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = csf1->SubRuleSetCount = GET_UShort();
-
- FORGET_Frame();
-
- csf1->SubRuleSet = NULL;
-
- if ( ALLOC_ARRAY( csf1->SubRuleSet, count, TTO_SubRuleSet ) )
- goto Fail2;
-
- srs = csf1->SubRuleSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_SubRuleSet( &srs[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_SubRuleSet( &srs[m], memory );
-
- FREE( srs );
-
- Fail2:
- Free_Coverage( &csf1->Coverage, memory );
- return error;
- }
-
-
- static void Free_Context1( TTO_ContextSubstFormat1* csf1,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_SubRuleSet* srs;
-
-
- if ( csf1->SubRuleSet )
- {
- count = csf1->SubRuleSetCount;
- srs = csf1->SubRuleSet;
-
- for ( n = 0; n < count; n++ )
- Free_SubRuleSet( &srs[n], memory );
-
- FREE( srs );
- }
-
- Free_Coverage( &csf1->Coverage, memory );
- }
-
-
- /* SubClassRule */
-
- static FT_Error Load_SubClassRule( TTO_ContextSubstFormat2* csf2,
- TTO_SubClassRule* scr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* c;
- TTO_SubstLookupRecord* slr;
- FT_Bool* d;
-
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- scr->GlyphCount = GET_UShort();
- scr->SubstCount = GET_UShort();
-
- if ( scr->GlyphCount > csf2->MaxContextLength )
- csf2->MaxContextLength = scr->GlyphCount;
-
- FORGET_Frame();
-
- scr->Class = NULL;
-
- count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( scr->Class, count, FT_UShort ) )
- return error;
-
- c = scr->Class;
- d = csf2->ClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- {
- c[n] = GET_UShort();
-
- /* We check whether the specific class is used at all. If not,
- class 0 is used instead. */
- if ( !d[c[n]] )
- c[n] = 0;
- }
-
- FORGET_Frame();
-
- scr->SubstLookupRecord = NULL;
-
- count = scr->SubstCount;
-
- if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, TTO_SubstLookupRecord ) )
- goto Fail2;
-
- slr = scr->SubstLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- slr[n].SequenceIndex = GET_UShort();
- slr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( slr );
-
- Fail2:
- FREE( c );
- return error;
- }
-
-
- static void Free_SubClassRule( TTO_SubClassRule* scr,
- FT_Memory memory )
- {
- FREE( scr->SubstLookupRecord );
- FREE( scr->Class );
- }
-
-
- /* SubClassSet */
-
- static FT_Error Load_SubClassSet( TTO_ContextSubstFormat2* csf2,
- TTO_SubClassSet* scs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_SubClassRule* scr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = scs->SubClassRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- scs->SubClassRule = NULL;
-
- if ( ALLOC_ARRAY( scs->SubClassRule, count, TTO_SubClassRule ) )
- return error;
-
- scr = scs->SubClassRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_SubClassRule( csf2, &scr[n],
- stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_SubClassRule( &scr[m], memory );
-
- FREE( scr );
- return error;
- }
-
-
- static void Free_SubClassSet( TTO_SubClassSet* scs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_SubClassRule* scr;
-
-
- if ( scs->SubClassRule )
- {
- count = scs->SubClassRuleCount;
- scr = scs->SubClassRule;
-
- for ( n = 0; n < count; n++ )
- Free_SubClassRule( &scr[n], memory );
-
- FREE( scr );
- }
- }
-
-
- /* ContextSubstFormat2 */
-
- static FT_Error Load_ContextSubst2( TTO_ContextSubstFormat2* csf2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_SubClassSet* scs;
-
-
- base_offset = FILE_Pos() - 2;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &csf2->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 4L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- /* `SubClassSetCount' is the upper limit for class values, thus we
- read it now to make an additional safety check. */
-
- count = csf2->SubClassSetCount = GET_UShort();
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ClassDefinition( &csf2->ClassDef, count,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
-
- csf2->SubClassSet = NULL;
- csf2->MaxContextLength = 0;
-
- if ( ALLOC_ARRAY( csf2->SubClassSet, count, TTO_SubClassSet ) )
- goto Fail2;
-
- scs = csf2->SubClassSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- if ( new_offset != base_offset ) /* not a NULL offset */
- {
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_SubClassSet( csf2, &scs[n],
- stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
- else
- {
- /* we create a SubClassSet table with no entries */
-
- csf2->SubClassSet[n].SubClassRuleCount = 0;
- csf2->SubClassSet[n].SubClassRule = NULL;
- }
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_SubClassSet( &scs[m], memory );
-
- FREE( scs );
-
- Fail2:
- Free_ClassDefinition( &csf2->ClassDef, memory );
-
- Fail3:
- Free_Coverage( &csf2->Coverage, memory );
- return error;
- }
-
-
- static void Free_Context2( TTO_ContextSubstFormat2* csf2,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_SubClassSet* scs;
-
-
- if ( csf2->SubClassSet )
- {
- count = csf2->SubClassSetCount;
- scs = csf2->SubClassSet;
-
- for ( n = 0; n < count; n++ )
- Free_SubClassSet( &scs[n], memory );
-
- FREE( scs );
- }
-
- Free_ClassDefinition( &csf2->ClassDef, memory );
- Free_Coverage( &csf2->Coverage, memory );
- }
-
-
- /* ContextSubstFormat3 */
-
- static FT_Error Load_ContextSubst3( TTO_ContextSubstFormat3* csf3,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Coverage* c;
- TTO_SubstLookupRecord* slr;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- csf3->GlyphCount = GET_UShort();
- csf3->SubstCount = GET_UShort();
-
- FORGET_Frame();
-
- csf3->Coverage = NULL;
-
- count = csf3->GlyphCount;
-
- if ( ALLOC_ARRAY( csf3->Coverage, count, TTO_Coverage ) )
- return error;
-
- c = csf3->Coverage;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &c[n], stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
- }
-
- csf3->SubstLookupRecord = NULL;
-
- count = csf3->SubstCount;
-
- if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
- TTO_SubstLookupRecord ) )
- goto Fail2;
-
- slr = csf3->SubstLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- slr[n].SequenceIndex = GET_UShort();
- slr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( slr );
-
- Fail2:
- for ( m = 0; m < n; m++ )
- Free_Coverage( &c[m], memory );
-
- FREE( c );
- return error;
- }
-
-
- static void Free_Context3( TTO_ContextSubstFormat3* csf3,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Coverage* c;
-
-
- FREE( csf3->SubstLookupRecord );
-
- if ( csf3->Coverage )
- {
- count = csf3->GlyphCount;
- c = csf3->Coverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
- }
-
-
- /* ContextSubst */
-
- FT_Error Load_ContextSubst( TTO_ContextSubst* cs,
- FT_Stream stream )
- {
- FT_Error error;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cs->SubstFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( cs->SubstFormat )
- {
- case 1:
- return Load_ContextSubst1( &cs->csf.csf1, stream );
-
- case 2:
- return Load_ContextSubst2( &cs->csf.csf2, stream );
-
- case 3:
- return Load_ContextSubst3( &cs->csf.csf3, stream );
-
- default:
- return TTO_Err_Invalid_GSUB_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- void Free_ContextSubst( TTO_ContextSubst* cs,
- FT_Memory memory )
- {
- switch ( cs->SubstFormat )
- {
- case 1:
- Free_Context1( &cs->csf.csf1, memory );
- break;
-
- case 2:
- Free_Context2( &cs->csf.csf2, memory );
- break;
-
- case 3:
- Free_Context3( &cs->csf.csf3, memory );
- break;
- }
- }
-
-
- static FT_Error Lookup_ContextSubst1( TTO_GSUBHeader* gsub,
- TTO_ContextSubstFormat1* csf1,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_UShort i, j, k, numsr;
- FT_Error error;
-
- TTO_SubRule* sr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gsub->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- sr = csf1->SubRuleSet[index].SubRule;
- numsr = csf1->SubRuleSet[index].SubRuleCount;
-
- for ( k = 0; k < numsr; k++ )
- {
- if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
- goto next_subrule;
-
- if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
- goto next_subrule; /* context is too long */
-
- for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + sr[k].GlyphCount - i == buffer->in_length )
- goto next_subrule;
- j++;
- }
-
- if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
- goto next_subrule;
- }
-
- return Do_ContextSubst( gsub, sr[k].GlyphCount,
- sr[k].SubstCount, sr[k].SubstLookupRecord,
- buffer,
- nesting_level );
- next_subrule:
- ;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- static FT_Error Lookup_ContextSubst2( TTO_GSUBHeader* gsub,
- TTO_ContextSubstFormat2* csf2,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_Error error;
- FT_Memory memory = gsub->memory;
- FT_UShort i, j, k, known_classes;
-
- FT_UShort* classes;
- FT_UShort* cl;
-
- TTO_SubClassSet* scs;
- TTO_SubClassRule* sr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gsub->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- /* Note: The coverage table in format 2 doesn't give an index into
- anything. It just lets us know whether or not we need to
- do any lookup at all. */
-
- error = Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) )
- return error;
-
- error = Get_Class( &csf2->ClassDef, IN_CURGLYPH(),
- &classes[0], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End;
- known_classes = 0;
-
- scs = &csf2->SubClassSet[classes[0]];
- if ( !scs )
- {
- error = TTO_Err_Invalid_GSUB_SubTable;
- goto End;
- }
-
- for ( k = 0; k < scs->SubClassRuleCount; k++ )
- {
- sr = &scs->SubClassRule[k];
-
- if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
- goto next_subclassrule;
-
- if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
- goto next_subclassrule; /* context is too long */
-
- cl = sr->Class;
-
- /* Start at 1 because [0] is implied */
-
- for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End;
-
- if ( j + sr->GlyphCount - i < buffer->in_length )
- goto next_subclassrule;
- j++;
- }
-
- if ( i > known_classes )
- {
- /* Keeps us from having to do this for each rule */
-
- error = Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End;
- known_classes = i;
- }
-
- if ( cl[i - 1] != classes[i] )
- goto next_subclassrule;
- }
-
- error = Do_ContextSubst( gsub, sr->GlyphCount,
- sr->SubstCount, sr->SubstLookupRecord,
- buffer,
- nesting_level );
- goto End;
-
- next_subclassrule:
- ;
- }
-
- error = TTO_Err_Not_Covered;
-
- End:
- FREE( classes );
- return error;
- }
-
-
- static FT_Error Lookup_ContextSubst3( TTO_GSUBHeader* gsub,
- TTO_ContextSubstFormat3* csf3,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_Error error;
- FT_UShort index, i, j, property;
-
- TTO_Coverage* c;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gsub->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
- return TTO_Err_Not_Covered;
-
- if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
- return TTO_Err_Not_Covered; /* context is too long */
-
- c = csf3->Coverage;
-
- for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + csf3->GlyphCount - i == buffer->in_length )
- return TTO_Err_Not_Covered;
- j++;
- }
-
- error = Coverage_Index( &c[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
-
- return Do_ContextSubst( gsub, csf3->GlyphCount,
- csf3->SubstCount, csf3->SubstLookupRecord,
- buffer,
- nesting_level );
- }
-
-
- static FT_Error Lookup_ContextSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- TTO_ContextSubst* cs = &st->context;
-
- switch ( cs->SubstFormat )
- {
- case 1:
- return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer,
- flags, context_length, nesting_level );
-
- case 2:
- return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer,
- flags, context_length, nesting_level );
-
- case 3:
- return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer,
- flags, context_length, nesting_level );
-
- default:
- return TTO_Err_Invalid_GSUB_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- /* LookupType 6 */
-
- /* ChainSubRule */
-
- static FT_Error Load_ChainSubRule( TTO_ChainSubRule* csr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
- FT_UShort* b;
- FT_UShort* i;
- FT_UShort* l;
-
- TTO_SubstLookupRecord* slr;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- csr->BacktrackGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- csr->Backtrack = NULL;
-
- count = csr->BacktrackGlyphCount;
-
- if ( ALLOC_ARRAY( csr->Backtrack, count, FT_UShort ) )
- return error;
-
- b = csr->Backtrack;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail4;
-
- for ( n = 0; n < count; n++ )
- b[n] = GET_UShort();
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- csr->InputGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- csr->Input = NULL;
-
- count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( csr->Input, count, FT_UShort ) )
- goto Fail4;
-
- i = csr->Input;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail3;
-
- for ( n = 0; n < count; n++ )
- i[n] = GET_UShort();
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- csr->LookaheadGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- csr->Lookahead = NULL;
-
- count = csr->LookaheadGlyphCount;
-
- if ( ALLOC_ARRAY( csr->Lookahead, count, FT_UShort ) )
- goto Fail3;
-
- l = csr->Lookahead;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- l[n] = GET_UShort();
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- csr->SubstCount = GET_UShort();
-
- FORGET_Frame();
-
- csr->SubstLookupRecord = NULL;
-
- count = csr->SubstCount;
-
- if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, TTO_SubstLookupRecord ) )
- goto Fail2;
-
- slr = csr->SubstLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- slr[n].SequenceIndex = GET_UShort();
- slr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( slr );
-
- Fail2:
- FREE( l );
-
- Fail3:
- FREE( i );
-
- Fail4:
- FREE( b );
- return error;
- }
-
-
- static void Free_ChainSubRule( TTO_ChainSubRule* csr,
- FT_Memory memory )
- {
- FREE( csr->SubstLookupRecord );
- FREE( csr->Lookahead );
- FREE( csr->Input );
- FREE( csr->Backtrack );
- }
-
-
- /* ChainSubRuleSet */
-
- static FT_Error Load_ChainSubRuleSet( TTO_ChainSubRuleSet* csrs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ChainSubRule* csr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = csrs->ChainSubRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- csrs->ChainSubRule = NULL;
-
- if ( ALLOC_ARRAY( csrs->ChainSubRule, count, TTO_ChainSubRule ) )
- return error;
-
- csr = csrs->ChainSubRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainSubRule( &csr[n], stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_ChainSubRule( &csr[m], memory );
-
- FREE( csr );
- return error;
- }
-
-
- static void Free_ChainSubRuleSet( TTO_ChainSubRuleSet* csrs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainSubRule* csr;
-
-
- if ( csrs->ChainSubRule )
- {
- count = csrs->ChainSubRuleCount;
- csr = csrs->ChainSubRule;
-
- for ( n = 0; n < count; n++ )
- Free_ChainSubRule( &csr[n], memory );
-
- FREE( csr );
- }
- }
-
-
- /* ChainContextSubstFormat1 */
-
- static FT_Error Load_ChainContextSubst1(
- TTO_ChainContextSubstFormat1* ccsf1,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ChainSubRuleSet* csrs;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &ccsf1->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = ccsf1->ChainSubRuleSetCount = GET_UShort();
-
- FORGET_Frame();
-
- ccsf1->ChainSubRuleSet = NULL;
-
- if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, TTO_ChainSubRuleSet ) )
- goto Fail2;
-
- csrs = ccsf1->ChainSubRuleSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_ChainSubRuleSet( &csrs[m], memory );
-
- FREE( csrs );
-
- Fail2:
- Free_Coverage( &ccsf1->Coverage, memory );
- return error;
- }
-
-
- static void Free_ChainContext1( TTO_ChainContextSubstFormat1* ccsf1,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainSubRuleSet* csrs;
-
-
- if ( ccsf1->ChainSubRuleSet )
- {
- count = ccsf1->ChainSubRuleSetCount;
- csrs = ccsf1->ChainSubRuleSet;
-
- for ( n = 0; n < count; n++ )
- Free_ChainSubRuleSet( &csrs[n], memory );
-
- FREE( csrs );
- }
-
- Free_Coverage( &ccsf1->Coverage, memory );
- }
-
-
- /* ChainSubClassRule */
-
- static FT_Error Load_ChainSubClassRule(
- TTO_ChainContextSubstFormat2* ccsf2,
- TTO_ChainSubClassRule* cscr,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* b;
- FT_UShort* i;
- FT_UShort* l;
- TTO_SubstLookupRecord* slr;
- FT_Bool* d;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- cscr->BacktrackGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
- ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
-
- cscr->Backtrack = NULL;
-
- count = cscr->BacktrackGlyphCount;
-
- if ( ALLOC_ARRAY( cscr->Backtrack, count, FT_UShort ) )
- return error;
-
- b = cscr->Backtrack;
- d = ccsf2->BacktrackClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail4;
-
- for ( n = 0; n < count; n++ )
- {
- b[n] = GET_UShort();
-
- /* We check whether the specific class is used at all. If not,
- class 0 is used instead. */
-
- if ( !d[b[n]] )
- b[n] = 0;
- }
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- cscr->InputGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
- ccsf2->MaxInputLength = cscr->InputGlyphCount;
-
- cscr->Input = NULL;
-
- count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
-
- if ( ALLOC_ARRAY( cscr->Input, count, FT_UShort ) )
- goto Fail4;
-
- i = cscr->Input;
- d = ccsf2->InputClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail3;
-
- for ( n = 0; n < count; n++ )
- {
- i[n] = GET_UShort();
-
- if ( !d[i[n]] )
- i[n] = 0;
- }
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- cscr->LookaheadGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )
- ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;
-
- cscr->Lookahead = NULL;
-
- count = cscr->LookaheadGlyphCount;
-
- if ( ALLOC_ARRAY( cscr->Lookahead, count, FT_UShort ) )
- goto Fail3;
-
- l = cscr->Lookahead;
- d = ccsf2->LookaheadClassDef.Defined;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
-
- for ( n = 0; n < count; n++ )
- {
- l[n] = GET_UShort();
-
- if ( !d[l[n]] )
- l[n] = 0;
- }
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- cscr->SubstCount = GET_UShort();
-
- FORGET_Frame();
-
- cscr->SubstLookupRecord = NULL;
-
- count = cscr->SubstCount;
-
- if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,
- TTO_SubstLookupRecord ) )
- goto Fail2;
-
- slr = cscr->SubstLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- slr[n].SequenceIndex = GET_UShort();
- slr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( slr );
-
- Fail2:
- FREE( l );
-
- Fail3:
- FREE( i );
-
- Fail4:
- FREE( b );
- return error;
- }
-
-
- static void Free_ChainSubClassRule( TTO_ChainSubClassRule* cscr,
- FT_Memory memory )
- {
- FREE( cscr->SubstLookupRecord );
- FREE( cscr->Lookahead );
- FREE( cscr->Input );
- FREE( cscr->Backtrack );
- }
-
-
- /* SubClassSet */
-
- static FT_Error Load_ChainSubClassSet(
- TTO_ChainContextSubstFormat2* ccsf2,
- TTO_ChainSubClassSet* cscs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ChainSubClassRule* cscr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = cscs->ChainSubClassRuleCount = GET_UShort();
-
- FORGET_Frame();
-
- cscs->ChainSubClassRule = NULL;
-
- if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,
- TTO_ChainSubClassRule ) )
- return error;
-
- cscr = cscs->ChainSubClassRule;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],
- stream ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_ChainSubClassRule( &cscr[m], memory );
-
- FREE( cscr );
- return error;
- }
-
-
- static void Free_ChainSubClassSet( TTO_ChainSubClassSet* cscs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainSubClassRule* cscr;
-
-
- if ( cscs->ChainSubClassRule )
- {
- count = cscs->ChainSubClassRuleCount;
- cscr = cscs->ChainSubClassRule;
-
- for ( n = 0; n < count; n++ )
- Free_ChainSubClassRule( &cscr[n], memory );
-
- FREE( cscr );
- }
- }
-
- static FT_Error Load_EmptyOrClassDefinition( TTO_ClassDefinition* cd,
- FT_UShort limit,
- FT_ULong class_offset,
- FT_ULong base_offset,
- FT_Stream stream )
- {
- FT_Error error;
- FT_ULong cur_offset;
-
- cur_offset = FILE_Pos();
-
- if ( class_offset )
- {
- if ( !FILE_Seek( class_offset + base_offset ) )
- error = Load_ClassDefinition( cd, limit, stream );
- }
- else
- error = Load_EmptyClassDefinition ( cd, stream );
-
- if (error == TT_Err_Ok)
- (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
-
- return error;
- }
-
-
- /* ChainContextSubstFormat2 */
-
- static FT_Error Load_ChainContextSubst2(
- TTO_ChainContextSubstFormat2* ccsf2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n = 0, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
- FT_ULong backtrack_offset, input_offset, lookahead_offset;
-
- TTO_ChainSubClassSet* cscs;
-
-
- base_offset = FILE_Pos() - 2;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &ccsf2->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
- if ( ACCESS_Frame( 8L ) )
- goto Fail5;
-
- backtrack_offset = GET_UShort();
- input_offset = GET_UShort();
- lookahead_offset = GET_UShort();
-
- /* `ChainSubClassSetCount' is the upper limit for input class values,
- thus we read it now to make an additional safety check. No limit
- is known or needed for the other two class definitions */
-
- count = ccsf2->ChainSubClassSetCount = GET_UShort();
-
- FORGET_Frame();
-
- if ( ( error = Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
- backtrack_offset, base_offset,
- stream ) ) != TT_Err_Ok )
- goto Fail5;
-
- if ( ( error = Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
- input_offset, base_offset,
- stream ) ) != TT_Err_Ok )
- goto Fail4;
- if ( ( error = Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
- lookahead_offset, base_offset,
- stream ) ) != TT_Err_Ok )
- goto Fail3;
-
- ccsf2->ChainSubClassSet = NULL;
- ccsf2->MaxBacktrackLength = 0;
- ccsf2->MaxInputLength = 0;
- ccsf2->MaxLookaheadLength = 0;
-
- if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, TTO_ChainSubClassSet ) )
- goto Fail2;
-
- cscs = ccsf2->ChainSubClassSet;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- if ( new_offset != base_offset ) /* not a NULL offset */
- {
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],
- stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
- else
- {
- /* we create a ChainSubClassSet table with no entries */
-
- ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;
- ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL;
- }
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_ChainSubClassSet( &cscs[m], memory );
-
- FREE( cscs );
-
- Fail2:
- Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory );
-
- Fail3:
- Free_ClassDefinition( &ccsf2->InputClassDef, memory );
-
- Fail4:
- Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory );
-
- Fail5:
- Free_Coverage( &ccsf2->Coverage, memory );
- return error;
- }
-
-
- static void Free_ChainContext2( TTO_ChainContextSubstFormat2* ccsf2,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ChainSubClassSet* cscs;
-
-
- if ( ccsf2->ChainSubClassSet )
- {
- count = ccsf2->ChainSubClassSetCount;
- cscs = ccsf2->ChainSubClassSet;
-
- for ( n = 0; n < count; n++ )
- Free_ChainSubClassSet( &cscs[n], memory );
-
- FREE( cscs );
- }
-
- Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory );
- Free_ClassDefinition( &ccsf2->InputClassDef, memory );
- Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory );
-
- Free_Coverage( &ccsf2->Coverage, memory );
- }
-
-
- /* ChainContextSubstFormat3 */
-
- static FT_Error Load_ChainContextSubst3(
- TTO_ChainContextSubstFormat3* ccsf3,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, nb = 0, ni =0, nl = 0, m, count;
- FT_UShort backtrack_count, input_count, lookahead_count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Coverage* b;
- TTO_Coverage* i;
- TTO_Coverage* l;
- TTO_SubstLookupRecord* slr;
-
-
- base_offset = FILE_Pos() - 2L;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- ccsf3->BacktrackGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- ccsf3->BacktrackCoverage = NULL;
-
- backtrack_count = ccsf3->BacktrackGlyphCount;
-
- if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,
- TTO_Coverage ) )
- return error;
-
- b = ccsf3->BacktrackCoverage;
-
- for ( nb = 0; nb < backtrack_count; nb++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &b[nb], stream ) ) != TT_Err_Ok )
- goto Fail4;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- ccsf3->InputGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- ccsf3->InputCoverage = NULL;
-
- input_count = ccsf3->InputGlyphCount;
-
- if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, TTO_Coverage ) )
- goto Fail4;
-
- i = ccsf3->InputCoverage;
-
- for ( ni = 0; ni < input_count; ni++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &i[ni], stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- ccsf3->LookaheadGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- ccsf3->LookaheadCoverage = NULL;
-
- lookahead_count = ccsf3->LookaheadGlyphCount;
-
- if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,
- TTO_Coverage ) )
- goto Fail3;
-
- l = ccsf3->LookaheadCoverage;
-
- for ( nl = 0; nl < lookahead_count; nl++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &l[nl], stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- ccsf3->SubstCount = GET_UShort();
-
- FORGET_Frame();
-
- ccsf3->SubstLookupRecord = NULL;
-
- count = ccsf3->SubstCount;
-
- if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,
- TTO_SubstLookupRecord ) )
- goto Fail2;
-
- slr = ccsf3->SubstLookupRecord;
-
- if ( ACCESS_Frame( count * 4L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- {
- slr[n].SequenceIndex = GET_UShort();
- slr[n].LookupListIndex = GET_UShort();
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( slr );
-
- Fail2:
- for ( m = 0; m < nl; m++ )
- Free_Coverage( &l[m], memory );
-
- FREE( l );
-
- Fail3:
- for ( m = 0; m < ni; m++ )
- Free_Coverage( &i[m], memory );
-
- FREE( i );
-
- Fail4:
- for ( m = 0; m < nb; m++ )
- Free_Coverage( &b[m], memory );
-
- FREE( b );
- return error;
- }
-
-
- static void Free_ChainContext3( TTO_ChainContextSubstFormat3* ccsf3,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Coverage* c;
-
-
- FREE( ccsf3->SubstLookupRecord );
-
- if ( ccsf3->LookaheadCoverage )
- {
- count = ccsf3->LookaheadGlyphCount;
- c = ccsf3->LookaheadCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
-
- if ( ccsf3->InputCoverage )
- {
- count = ccsf3->InputGlyphCount;
- c = ccsf3->InputCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
-
- if ( ccsf3->BacktrackCoverage )
- {
- count = ccsf3->BacktrackGlyphCount;
- c = ccsf3->BacktrackCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
- }
-
-
- /* ChainContextSubst */
-
- FT_Error Load_ChainContextSubst( TTO_ChainContextSubst* ccs,
- FT_Stream stream )
- {
- FT_Error error;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- ccs->SubstFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( ccs->SubstFormat )
- {
- case 1:
- return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
-
- case 2:
- return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
-
- case 3:
- return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
-
- default:
- return TTO_Err_Invalid_GSUB_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- void Free_ChainContextSubst( TTO_ChainContextSubst* ccs,
- FT_Memory memory )
- {
- switch ( ccs->SubstFormat )
- {
- case 1:
- Free_ChainContext1( &ccs->ccsf.ccsf1, memory );
- break;
-
- case 2:
- Free_ChainContext2( &ccs->ccsf.ccsf2, memory );
- break;
-
- case 3:
- Free_ChainContext3( &ccs->ccsf.ccsf3, memory );
- break;
- }
- }
-
-
- static FT_Error Lookup_ChainContextSubst1( TTO_GSUBHeader* gsub,
- TTO_ChainContextSubstFormat1* ccsf1,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_UShort i, j, k, num_csr;
- FT_UShort bgc, igc, lgc;
- FT_Error error;
-
- TTO_ChainSubRule* csr;
- TTO_ChainSubRule curr_csr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gsub->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- error = Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- csr = ccsf1->ChainSubRuleSet[index].ChainSubRule;
- num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;
-
- for ( k = 0; k < num_csr; k++ )
- {
- curr_csr = csr[k];
- bgc = curr_csr.BacktrackGlyphCount;
- igc = curr_csr.InputGlyphCount;
- lgc = curr_csr.LookaheadGlyphCount;
-
- if ( context_length != 0xFFFF && context_length < igc )
- goto next_chainsubrule;
-
- /* check whether context is too long; it is a first guess only */
-
- if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
- goto next_chainsubrule;
-
- if ( bgc )
- {
- /* since we don't know in advance the number of glyphs to inspect,
- we search backwards for matches in the backtrack glyph array */
-
- for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
- {
- while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + 1 == bgc - i )
- goto next_chainsubrule;
- j--;
- }
-
- /* In OpenType 1.3, it is undefined whether the offsets of
- backtrack glyphs is in logical order or not. Version 1.4
- will clarify this:
-
- Logical order - a b c d e f g h i j
- i
- Input offsets - 0 1
- Backtrack offsets - 3 2 1 0
- Lookahead offsets - 0 1 2 3 */
-
- if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )
- goto next_chainsubrule;
- }
- }
-
- /* Start at 1 because [0] is implied */
-
- for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + igc - i + lgc == buffer->in_length )
- goto next_chainsubrule;
- j++;
- }
-
- if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
- goto next_chainsubrule;
- }
-
- /* we are starting to check for lookahead glyphs right after the
- last context glyph */
-
- for ( i = 0; i < lgc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + lgc - i == buffer->in_length )
- goto next_chainsubrule;
- j++;
- }
-
- if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
- goto next_chainsubrule;
- }
-
- return Do_ContextSubst( gsub, igc,
- curr_csr.SubstCount,
- curr_csr.SubstLookupRecord,
- buffer,
- nesting_level );
-
- next_chainsubrule:
- ;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- static FT_Error Lookup_ChainContextSubst2( TTO_GSUBHeader* gsub,
- TTO_ChainContextSubstFormat2* ccsf2,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, property;
- FT_Memory memory;
- FT_Error error;
- FT_UShort i, j, k;
- FT_UShort bgc, igc, lgc;
- FT_UShort known_backtrack_classes,
- known_input_classes,
- known_lookahead_classes;
-
- FT_UShort* backtrack_classes;
- FT_UShort* input_classes;
- FT_UShort* lookahead_classes;
-
- FT_UShort* bc;
- FT_UShort* ic;
- FT_UShort* lc;
-
- TTO_ChainSubClassSet* cscs;
- TTO_ChainSubClassRule ccsr;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gsub->gdef;
- memory = gsub->memory;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- /* Note: The coverage table in format 2 doesn't give an index into
- anything. It just lets us know whether or not we need to
- do any lookup at all. */
-
- error = Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index );
- if ( error )
- return error;
-
- if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, FT_UShort ) )
- return error;
- known_backtrack_classes = 0;
-
- if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, FT_UShort ) )
- goto End3;
- known_input_classes = 1;
-
- if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, FT_UShort ) )
- goto End2;
- known_lookahead_classes = 0;
-
- error = Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(),
- &input_classes[0], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- cscs = &ccsf2->ChainSubClassSet[input_classes[0]];
- if ( !cscs )
- {
- error = TTO_Err_Invalid_GSUB_SubTable;
- goto End1;
- }
-
- for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ )
- {
- ccsr = cscs->ChainSubClassRule[k];
- bgc = ccsr.BacktrackGlyphCount;
- igc = ccsr.InputGlyphCount;
- lgc = ccsr.LookaheadGlyphCount;
-
- if ( context_length != 0xFFFF && context_length < igc )
- goto next_chainsubclassrule;
-
- /* check whether context is too long; it is a first guess only */
-
- if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
- goto next_chainsubclassrule;
-
- if ( bgc )
- {
- /* Since we don't know in advance the number of glyphs to inspect,
- we search backwards for matches in the backtrack glyph array.
- Note that `known_backtrack_classes' starts at index 0. */
-
- bc = ccsr.Backtrack;
-
- for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
- {
- while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- if ( j + 1 == bgc - i )
- goto next_chainsubclassrule;
- j--;
- }
-
- if ( i >= known_backtrack_classes )
- {
- /* Keeps us from having to do this for each rule */
-
- error = Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ),
- &backtrack_classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
- known_backtrack_classes = i;
- }
-
- if ( bc[i] != backtrack_classes[i] )
- goto next_chainsubclassrule;
- }
- }
-
- ic = ccsr.Input;
-
- /* Start at 1 because [0] is implied */
-
- for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- if ( j + igc - i + lgc == buffer->in_length )
- goto next_chainsubclassrule;
- j++;
- }
-
- if ( i >= known_input_classes )
- {
- error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),
- &input_classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
- known_input_classes = i;
- }
-
- if ( ic[i - 1] != input_classes[i] )
- goto next_chainsubclassrule;
- }
-
- /* we are starting to check for lookahead glyphs right after the
- last context glyph */
-
- lc = ccsr.Lookahead;
-
- for ( i = 0; i < lgc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
-
- if ( j + lgc - i == buffer->in_length )
- goto next_chainsubclassrule;
- j++;
- }
-
- if ( i >= known_lookahead_classes )
- {
- error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),
- &lookahead_classes[i], NULL );
- if ( error && error != TTO_Err_Not_Covered )
- goto End1;
- known_lookahead_classes = i;
- }
-
- if ( lc[i] != lookahead_classes[i] )
- goto next_chainsubclassrule;
- }
-
- error = Do_ContextSubst( gsub, igc,
- ccsr.SubstCount,
- ccsr.SubstLookupRecord,
- buffer,
- nesting_level );
- goto End1;
-
- next_chainsubclassrule:
- ;
- }
-
- error = TTO_Err_Not_Covered;
-
- End1:
- FREE( lookahead_classes );
-
- End2:
- FREE( input_classes );
-
- End3:
- FREE( backtrack_classes );
- return error;
- }
-
-
- static FT_Error Lookup_ChainContextSubst3( TTO_GSUBHeader* gsub,
- TTO_ChainContextSubstFormat3* ccsf3,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_UShort index, i, j, property;
- FT_UShort bgc, igc, lgc;
- FT_Error error;
-
- TTO_Coverage* bc;
- TTO_Coverage* ic;
- TTO_Coverage* lc;
- TTO_GDEFHeader* gdef;
-
-
- gdef = gsub->gdef;
-
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
- return error;
-
- bgc = ccsf3->BacktrackGlyphCount;
- igc = ccsf3->InputGlyphCount;
- lgc = ccsf3->LookaheadGlyphCount;
-
- if ( context_length != 0xFFFF && context_length < igc )
- return TTO_Err_Not_Covered;
-
- /* check whether context is too long; it is a first guess only */
-
- if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
- return TTO_Err_Not_Covered;
-
- if ( bgc )
- {
- /* Since we don't know in advance the number of glyphs to inspect,
- we search backwards for matches in the backtrack glyph array */
-
- bc = ccsf3->BacktrackCoverage;
-
- for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
- {
- while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + 1 == bgc - i )
- return TTO_Err_Not_Covered;
- j--;
- }
-
- error = Coverage_Index( &bc[i], OUT_GLYPH( j ), &index );
- if ( error )
- return error;
- }
- }
-
- ic = ccsf3->InputCoverage;
-
- for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
- {
- /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
- while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + igc - i + lgc == buffer->in_length )
- return TTO_Err_Not_Covered;
- j++;
- }
-
- error = Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
-
- /* we are starting for lookahead glyphs right after the last context
- glyph */
-
- lc = ccsf3->LookaheadCoverage;
-
- for ( i = 0; i < lgc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + lgc - i == buffer->in_length )
- return TTO_Err_Not_Covered;
- j++;
- }
-
- error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
-
- return Do_ContextSubst( gsub, igc,
- ccsf3->SubstCount,
- ccsf3->SubstLookupRecord,
- buffer,
- nesting_level );
- }
-
-
- static FT_Error Lookup_ChainContextSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level )
- {
- TTO_ChainContextSubst* ccs = &st->chain;
-
- switch ( ccs->SubstFormat )
- {
- case 1:
- return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer,
- flags, context_length,
- nesting_level );
-
- case 2:
- return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer,
- flags, context_length,
- nesting_level );
-
- case 3:
- return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer,
- flags, context_length,
- nesting_level );
-
- default:
- return TTO_Err_Invalid_GSUB_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- FT_Error Load_ReverseChainContextSubst( TTO_ReverseChainContextSubst* rccs,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort m, count;
-
- FT_UShort nb = 0, nl = 0, n;
- FT_UShort backtrack_count, lookahead_count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Coverage* b;
- TTO_Coverage* l;
- FT_UShort* sub;
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- rccs->SubstFormat = GET_UShort();
-
- if ( rccs->SubstFormat != 1 )
- return TTO_Err_Invalid_GSUB_SubTable_Format;
-
- FORGET_Frame();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &rccs->Coverage, stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
-
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
-
- rccs->BacktrackGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- rccs->BacktrackCoverage = NULL;
-
- backtrack_count = rccs->BacktrackGlyphCount;
-
- if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count,
- TTO_Coverage ) )
- goto Fail4;
-
- b = rccs->BacktrackCoverage;
-
- for ( nb = 0; nb < backtrack_count; nb++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &b[nb], stream ) ) != TT_Err_Ok )
- goto Fail3;
- (void)FILE_Seek( cur_offset );
- }
-
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
-
- rccs->LookaheadGlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- rccs->LookaheadCoverage = NULL;
-
- lookahead_count = rccs->LookaheadGlyphCount;
-
- if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count,
- TTO_Coverage ) )
- goto Fail3;
-
- l = rccs->LookaheadCoverage;
-
- for ( nl = 0; nl < lookahead_count; nl++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Coverage( &l[nl], stream ) ) != TT_Err_Ok )
- goto Fail2;
- (void)FILE_Seek( cur_offset );
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- rccs->GlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- rccs->Substitute = NULL;
-
- count = rccs->GlyphCount;
-
- if ( ALLOC_ARRAY( rccs->Substitute, count,
- FT_UShort ) )
- goto Fail2;
-
- sub = rccs->Substitute;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail1;
-
- for ( n = 0; n < count; n++ )
- sub[n] = GET_UShort();
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( sub );
-
- Fail2:
- for ( m = 0; m < nl; m++ )
- Free_Coverage( &l[m], memory );
-
- FREE( l );
-
- Fail3:
- for ( m = 0; m < nb; m++ )
- Free_Coverage( &b[m], memory );
-
- FREE( b );
-
- Fail4:
- Free_Coverage( &rccs->Coverage, memory );
- return error;
- }
-
-
- void Free_ReverseChainContextSubst( TTO_ReverseChainContextSubst* rccs,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Coverage* c;
-
- Free_Coverage( &rccs->Coverage, memory );
-
- if ( rccs->LookaheadCoverage )
- {
- count = rccs->LookaheadGlyphCount;
- c = rccs->LookaheadCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
-
- if ( rccs->BacktrackCoverage )
- {
- count = rccs->BacktrackGlyphCount;
- c = rccs->BacktrackCoverage;
-
- for ( n = 0; n < count; n++ )
- Free_Coverage( &c[n], memory );
-
- FREE( c );
- }
-
- FREE ( rccs->Substitute );
- }
-
-
- static FT_Error Lookup_ReverseChainContextSubst( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- /* note different signature here: */ FT_ULong string_index )
- {
- FT_UShort index, input_index, i, j, property;
- FT_UShort bgc, lgc;
- FT_Error error;
-
- TTO_ReverseChainContextSubst* rccs = &st->reverse;
- TTO_Coverage* bc;
- TTO_Coverage* lc;
- TTO_GDEFHeader* gdef;
-
- gdef = gsub->gdef;
-
- if ( CHECK_Property( gdef, IN_ITEM( string_index ), flags, &property ) )
- return error;
-
- bgc = rccs->BacktrackGlyphCount;
- lgc = rccs->LookaheadGlyphCount;
-
- /* check whether context is too long; it is a first guess only */
-
- if ( bgc > string_index || string_index + 1 + lgc > buffer->in_length )
- return TTO_Err_Not_Covered;
-
- if ( bgc )
- {
- /* Since we don't know in advance the number of glyphs to inspect,
- we search backwards for matches in the backtrack glyph array */
-
- bc = rccs->BacktrackCoverage;
-
- for ( i = 0, j = string_index - 1; i < bgc; i++, j-- )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + 1 == bgc - i )
- return TTO_Err_Not_Covered;
- j--;
- }
-
- error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
- }
-
- j = string_index;
-
- error = Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );
- if ( error )
- return error;
-
- /* we are starting for lookahead glyphs right after the last context
- glyph */
-
- j += 1;
-
- lc = rccs->LookaheadCoverage;
-
- for ( i = 0; i < lgc; i++, j++ )
- {
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
- {
- if ( error && error != TTO_Err_Not_Covered )
- return error;
-
- if ( j + lgc - i == buffer->in_length )
- return TTO_Err_Not_Covered;
- j++;
- }
-
- error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
- if ( error )
- return error;
- }
-
- IN_GLYPH( string_index ) = rccs->Substitute[input_index];
-
- return error;
- }
-
-
-
- /***********
- * GSUB API
- ***********/
-
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Select_Script( TTO_GSUBHeader* gsub,
- FT_ULong script_tag,
- FT_UShort* script_index )
- {
- FT_UShort n;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
-
-
- if ( !gsub || !script_index )
- return TT_Err_Invalid_Argument;
-
- sl = &gsub->ScriptList;
- sr = sl->ScriptRecord;
-
- for ( n = 0; n < sl->ScriptCount; n++ )
- if ( script_tag == sr[n].ScriptTag )
- {
- *script_index = n;
-
- return TT_Err_Ok;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Select_Language( TTO_GSUBHeader* gsub,
- FT_ULong language_tag,
- FT_UShort script_index,
- FT_UShort* language_index,
- FT_UShort* req_feature_index )
- {
- FT_UShort n;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
-
-
- if ( !gsub || !language_index || !req_feature_index )
- return TT_Err_Invalid_Argument;
-
- sl = &gsub->ScriptList;
- sr = sl->ScriptRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- for ( n = 0; n < s->LangSysCount; n++ )
- if ( language_tag == lsr[n].LangSysTag )
- {
- *language_index = n;
- *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
-
- return TT_Err_Ok;
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- /* selecting 0xFFFF for language_index asks for the values of the
- default language (DefaultLangSys) */
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Select_Feature( TTO_GSUBHeader* gsub,
- FT_ULong feature_tag,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_UShort* feature_index )
- {
- FT_UShort n;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
- TTO_LangSys* ls;
- FT_UShort* fi;
-
- TTO_FeatureList* fl;
- TTO_FeatureRecord* fr;
-
-
- if ( !gsub || !feature_index )
- return TT_Err_Invalid_Argument;
-
- sl = &gsub->ScriptList;
- sr = sl->ScriptRecord;
-
- fl = &gsub->FeatureList;
- fr = fl->FeatureRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- if ( language_index == 0xFFFF )
- ls = &s->DefaultLangSys;
- else
- {
- if ( language_index >= s->LangSysCount )
- return TT_Err_Invalid_Argument;
-
- ls = &lsr[language_index].LangSys;
- }
-
- fi = ls->FeatureIndex;
-
- for ( n = 0; n < ls->FeatureCount; n++ )
- {
- if ( fi[n] >= fl->FeatureCount )
- return TTO_Err_Invalid_GSUB_SubTable_Format;
-
- if ( feature_tag == fr[fi[n]].FeatureTag )
- {
- *feature_index = fi[n];
-
- return TT_Err_Ok;
- }
- }
-
- return TTO_Err_Not_Covered;
- }
-
-
- /* The next three functions return a null-terminated list */
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Query_Scripts( TTO_GSUBHeader* gsub,
- FT_ULong** script_tag_list )
- {
- FT_UShort n;
- FT_Error error;
- FT_Memory memory;
- FT_ULong* stl;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
-
-
- if ( !gsub || !script_tag_list )
- return TT_Err_Invalid_Argument;
-
- memory = gsub->memory;
-
- sl = &gsub->ScriptList;
- sr = sl->ScriptRecord;
-
- if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) )
- return error;
-
- for ( n = 0; n < sl->ScriptCount; n++ )
- stl[n] = sr[n].ScriptTag;
- stl[n] = 0;
-
- *script_tag_list = stl;
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Query_Languages( TTO_GSUBHeader* gsub,
- FT_UShort script_index,
- FT_ULong** language_tag_list )
- {
- FT_UShort n;
- FT_Error error;
- FT_Memory memory;
- FT_ULong* ltl;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
-
-
- if ( !gsub || !language_tag_list )
- return TT_Err_Invalid_Argument;
-
- memory = gsub->memory;
-
- sl = &gsub->ScriptList;
- sr = sl->ScriptRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) )
- return error;
-
- for ( n = 0; n < s->LangSysCount; n++ )
- ltl[n] = lsr[n].LangSysTag;
- ltl[n] = 0;
-
- *language_tag_list = ltl;
-
- return TT_Err_Ok;
- }
-
-
- /* selecting 0xFFFF for language_index asks for the values of the
- default language (DefaultLangSys) */
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Query_Features( TTO_GSUBHeader* gsub,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_ULong** feature_tag_list )
- {
- FT_UShort n;
- FT_Error error;
- FT_Memory memory;
- FT_ULong* ftl;
-
- TTO_ScriptList* sl;
- TTO_ScriptRecord* sr;
- TTO_Script* s;
- TTO_LangSysRecord* lsr;
- TTO_LangSys* ls;
- FT_UShort* fi;
-
- TTO_FeatureList* fl;
- TTO_FeatureRecord* fr;
-
-
- if ( !gsub || !feature_tag_list )
- return TT_Err_Invalid_Argument;
-
- memory = gsub->memory;
-
- sl = &gsub->ScriptList;
- sr = sl->ScriptRecord;
-
- fl = &gsub->FeatureList;
- fr = fl->FeatureRecord;
-
- if ( script_index >= sl->ScriptCount )
- return TT_Err_Invalid_Argument;
-
- s = &sr[script_index].Script;
- lsr = s->LangSysRecord;
-
- if ( language_index == 0xFFFF )
- ls = &s->DefaultLangSys;
- else
- {
- if ( language_index >= s->LangSysCount )
- return TT_Err_Invalid_Argument;
-
- ls = &lsr[language_index].LangSys;
- }
-
- fi = ls->FeatureIndex;
-
- if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) )
- return error;
-
- for ( n = 0; n < ls->FeatureCount; n++ )
- {
- if ( fi[n] >= fl->FeatureCount )
- {
- FREE( ftl );
- return TTO_Err_Invalid_GSUB_SubTable_Format;
- }
- ftl[n] = fr[fi[n]].FeatureTag;
- }
- ftl[n] = 0;
-
- *feature_tag_list = ftl;
-
- return TT_Err_Ok;
- }
-
-
- typedef FT_Error (*Lookup_Func_Type)( TTO_GSUBHeader* gsub,
- TTO_GSUB_SubTable* st,
- OTL_Buffer buffer,
- FT_UShort flags,
- FT_UShort context_length,
- int nesting_level );
- static const Lookup_Func_Type Lookup_Call_Table[] = {
- Lookup_DefaultSubst,
- Lookup_SingleSubst, /* GSUB_LOOKUP_SINGLE 1 */
- Lookup_MultipleSubst, /* GSUB_LOOKUP_MULTIPLE 2 */
- Lookup_AlternateSubst, /* GSUB_LOOKUP_ALTERNATE 3 */
- Lookup_LigatureSubst, /* GSUB_LOOKUP_LIGATURE 4 */
- Lookup_ContextSubst, /* GSUB_LOOKUP_CONTEXT 5 */
- Lookup_ChainContextSubst, /* GSUB_LOOKUP_CHAIN 6 */
- Lookup_DefaultSubst, /* GSUB_LOOKUP_EXTENSION 7 */
- };
- /* Note that the following lookup does not belong to the table above:
- * Lookup_ReverseChainContextSubst, GSUB_LOOKUP_REVERSE_CHAIN 8
- * because it's invalid to happen where this table is used. It's
- * signature is different too...
- */
-
- /* Do an individual subtable lookup. Returns TT_Err_Ok if substitution
- has been done, or TTO_Err_Not_Covered if not. */
-
- static FT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub,
- FT_UShort lookup_index,
- OTL_Buffer buffer,
- FT_UShort context_length,
- int nesting_level )
- {
- FT_Error error = TTO_Err_Not_Covered;
- FT_UShort i, flags, lookup_count;
- TTO_Lookup* lo;
- int lt;
- Lookup_Func_Type Lookup_Func;
-
-
- nesting_level++;
-
- if ( nesting_level > TTO_MAX_NESTING_LEVEL )
- return TTO_Err_Too_Many_Nested_Contexts;
-
- lookup_count = gsub->LookupList.LookupCount;
- if (lookup_index >= lookup_count)
- return error;
-
- lo = &gsub->LookupList.Lookup[lookup_index];
- flags = lo->LookupFlag;
- lt = lo->LookupType;
- if (lt >= sizeof Lookup_Call_Table / sizeof Lookup_Call_Table[0])
- lt = 0;
- Lookup_Func = Lookup_Call_Table[lt];
-
- for ( i = 0; i < lo->SubTableCount; i++ )
- {
- error = Lookup_Func ( gsub,
- &lo->SubTable[i].st.gsub,
- buffer,
- flags, context_length,
- nesting_level );
-
- /* Check whether we have a successful substitution or an error other
- than TTO_Err_Not_Covered */
-
- if ( error != TTO_Err_Not_Covered )
- return error;
- }
-
- return TTO_Err_Not_Covered;
- }
-
- /* apply one lookup to the input string object */
-
- static FT_Error Do_String_Lookup( TTO_GSUBHeader* gsub,
- FT_UShort lookup_index,
- OTL_Buffer buffer )
- {
- FT_Error error, retError = TTO_Err_Not_Covered;
-
- FT_UInt* properties = gsub->LookupList.Properties;
-
- int nesting_level = 0;
-
-
- while ( buffer->in_pos < buffer->in_length )
- {
- if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
- {
- /* 0xFFFF indicates that we don't have a context length yet */
- error = Do_Glyph_Lookup( gsub, lookup_index, buffer,
- 0xFFFF, nesting_level );
- if ( error )
- {
- if ( error != TTO_Err_Not_Covered )
- return error;
- }
- else
- retError = error;
- }
- else
- error = TTO_Err_Not_Covered;
-
- if ( error == TTO_Err_Not_Covered )
- if ( otl_buffer_copy_output_glyph ( buffer ) )
- return error;
- }
-
- return retError;
- }
-
-
- static FT_Error Apply_ReverseChainContextSubst( TTO_GSUBHeader* gsub,
- FT_UShort lookup_index,
- OTL_Buffer buffer )
- {
- FT_UInt* properties = gsub->LookupList.Properties;
- FT_Error error, retError = TTO_Err_Not_Covered;
- FT_ULong subtable_Count, string_index;
- FT_UShort flags;
- TTO_Lookup* lo;
-
- if ( buffer->in_length == 0 )
- return TTO_Err_Not_Covered;
-
- lo = &gsub->LookupList.Lookup[lookup_index];
- flags = lo->LookupFlag;
-
- for ( subtable_Count = 0; subtable_Count < lo->SubTableCount; subtable_Count++ )
- {
- string_index = buffer->in_length - 1;
- do
- {
- if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
- {
- error = Lookup_ReverseChainContextSubst( gsub, &lo->SubTable[subtable_Count].st.gsub,
- buffer, flags, string_index );
- if ( error )
- {
- if ( error != TTO_Err_Not_Covered )
- return error;
- }
- else
- retError = error;
- }
- }
- while (string_index--);
- }
-
- return retError;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Add_Feature( TTO_GSUBHeader* gsub,
- FT_UShort feature_index,
- FT_UInt property )
- {
- FT_UShort i;
-
- TTO_Feature feature;
- FT_UInt* properties;
- FT_UShort* index;
- FT_UShort lookup_count;
-
- /* Each feature can only be added once */
-
- if ( !gsub ||
- feature_index >= gsub->FeatureList.FeatureCount ||
- gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )
- return TT_Err_Invalid_Argument;
-
- gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;
-
- properties = gsub->LookupList.Properties;
-
- feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
- index = feature.LookupListIndex;
- lookup_count = gsub->LookupList.LookupCount;
-
- for ( i = 0; i < feature.LookupListCount; i++ )
- {
- FT_UShort lookup_index = index[i];
- if (lookup_index < lookup_count)
- properties[lookup_index] |= property;
- }
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Clear_Features( TTO_GSUBHeader* gsub )
- {
- FT_UShort i;
-
- FT_UInt* properties;
-
-
- if ( !gsub )
- return TT_Err_Invalid_Argument;
-
- gsub->FeatureList.ApplyCount = 0;
-
- properties = gsub->LookupList.Properties;
-
- for ( i = 0; i < gsub->LookupList.LookupCount; i++ )
- properties[i] = 0;
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Register_Alternate_Function( TTO_GSUBHeader* gsub,
- TTO_AltFunction altfunc,
- void* data )
- {
- if ( !gsub )
- return TT_Err_Invalid_Argument;
-
- gsub->altfunc = altfunc;
- gsub->data = data;
-
- return TT_Err_Ok;
- }
-
-
- EXPORT_FUNC
- FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
- OTL_Buffer buffer )
- {
- FT_Error error, retError = TTO_Err_Not_Covered;
- FT_UShort i, j, lookup_count;
-
- if ( !gsub ||
- !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
- return TT_Err_Invalid_Argument;
-
- lookup_count = gsub->LookupList.LookupCount;
-
- for ( i = 0; i < gsub->FeatureList.ApplyCount; i++)
- {
- FT_UShort feature_index;
- TTO_Feature feature;
-
- feature_index = gsub->FeatureList.ApplyOrder[i];
- feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
-
- for ( j = 0; j < feature.LookupListCount; j++ )
- {
- FT_UShort lookup_index;
- TTO_Lookup* lookup;
- FT_Bool need_swap;
-
- lookup_index = feature.LookupListIndex[j];
-
- /* Skip nonexistant lookups */
- if (lookup_index >= lookup_count)
- continue;
-
- lookup = &gsub->LookupList.Lookup[lookup_index];
-
- if ( lookup->LookupType == GSUB_LOOKUP_REVERSE_CHAIN )
- {
- error = Apply_ReverseChainContextSubst( gsub, lookup_index, buffer);
- need_swap = FALSE; /* We do ReverseChainContextSubst in-place */
- }
- else
- {
- error = Do_String_Lookup( gsub, lookup_index, buffer );
- need_swap = TRUE;
- }
-
- if ( error )
- {
- if ( error != TTO_Err_Not_Covered )
- goto End;
- }
- else
- retError = error;
-
- if ( need_swap )
- {
- error = otl_buffer_swap( buffer );
- if ( error )
- goto End;
- }
- }
- }
-
- error = retError;
-
- End:
- return error;
- }
-
-
-/* END */
diff --git a/pango/opentype/ftxgsub.h b/pango/opentype/ftxgsub.h
deleted file mode 100644
index 53409d68..00000000
--- a/pango/opentype/ftxgsub.h
+++ /dev/null
@@ -1,594 +0,0 @@
-/*******************************************************************
- *
- * ftxgsub.h
- *
- * TrueType Open GSUB table support
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#ifndef FTXOPEN_H
-#error "Don't include this file! Use ftxopen.h instead."
-#endif
-
-#ifndef FTXGSUB_H
-#define FTXGSUB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define TTO_Err_Invalid_GSUB_SubTable_Format 0x1010
-#define TTO_Err_Invalid_GSUB_SubTable 0x1011
-
-
-/* Lookup types for glyph substitution */
-
-#define GSUB_LOOKUP_SINGLE 1
-#define GSUB_LOOKUP_MULTIPLE 2
-#define GSUB_LOOKUP_ALTERNATE 3
-#define GSUB_LOOKUP_LIGATURE 4
-#define GSUB_LOOKUP_CONTEXT 5
-#define GSUB_LOOKUP_CHAIN 6
-#define GSUB_LOOKUP_EXTENSION 7
-#define GSUB_LOOKUP_REVERSE_CHAIN 8
-
-/* Use this if a feature applies to all glyphs */
-
-#define ALL_GLYPHS 0xFFFF
-
-
- /* A pointer to a function which selects the alternate glyph. `pos' is
- the position of the glyph with index `glyphID', `num_alternates'
- gives the number of alternates in the `alternates' array. `data'
- points to the user-defined structure specified during a call to
- TT_GSUB_Register_Alternate_Function(). The function must return an
- index into the `alternates' array. */
-
- typedef FT_UShort (*TTO_AltFunction)(FT_ULong pos,
- FT_UShort glyphID,
- FT_UShort num_alternates,
- FT_UShort* alternates,
- void* data );
-
-
- struct TTO_GSUBHeader_
- {
- FT_Memory memory;
-
- FT_ULong offset;
-
- FT_Fixed Version;
-
- TTO_ScriptList ScriptList;
- TTO_FeatureList FeatureList;
- TTO_LookupList LookupList;
-
- TTO_GDEFHeader* gdef;
-
- /* the next two fields are used for an alternate substitution callback
- function to select the proper alternate glyph. */
-
- TTO_AltFunction altfunc;
- void* data;
- };
-
- typedef struct TTO_GSUBHeader_ TTO_GSUBHeader;
- typedef struct TTO_GSUBHeader_* TTO_GSUB;
-
-
- /* LookupType 1 */
-
- struct TTO_SingleSubstFormat1_
- {
- FT_Short DeltaGlyphID; /* constant added to get
- substitution glyph index */
- };
-
- typedef struct TTO_SingleSubstFormat1_ TTO_SingleSubstFormat1;
-
-
- struct TTO_SingleSubstFormat2_
- {
- FT_UShort GlyphCount; /* number of glyph IDs in
- Substitute array */
- FT_UShort* Substitute; /* array of substitute glyph IDs */
- };
-
- typedef struct TTO_SingleSubstFormat2_ TTO_SingleSubstFormat2;
-
-
- struct TTO_SingleSubst_
- {
- FT_UShort SubstFormat; /* 1 or 2 */
- TTO_Coverage Coverage; /* Coverage table */
-
- union
- {
- TTO_SingleSubstFormat1 ssf1;
- TTO_SingleSubstFormat2 ssf2;
- } ssf;
- };
-
- typedef struct TTO_SingleSubst_ TTO_SingleSubst;
-
-
- /* LookupType 2 */
-
- struct TTO_Sequence_
- {
- FT_UShort GlyphCount; /* number of glyph IDs in the
- Substitute array */
- FT_UShort* Substitute; /* string of glyph IDs to
- substitute */
- };
-
- typedef struct TTO_Sequence_ TTO_Sequence;
-
-
- struct TTO_MultipleSubst_
- {
- FT_UShort SubstFormat; /* always 1 */
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort SequenceCount; /* number of Sequence tables */
- TTO_Sequence* Sequence; /* array of Sequence tables */
- };
-
- typedef struct TTO_MultipleSubst_ TTO_MultipleSubst;
-
-
- /* LookupType 3 */
-
- struct TTO_AlternateSet_
- {
- FT_UShort GlyphCount; /* number of glyph IDs in the
- Alternate array */
- FT_UShort* Alternate; /* array of alternate glyph IDs */
- };
-
- typedef struct TTO_AlternateSet_ TTO_AlternateSet;
-
-
- struct TTO_AlternateSubst_
- {
- FT_UShort SubstFormat; /* always 1 */
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort AlternateSetCount;
- /* number of AlternateSet tables */
- TTO_AlternateSet* AlternateSet; /* array of AlternateSet tables */
- };
-
- typedef struct TTO_AlternateSubst_ TTO_AlternateSubst;
-
-
- /* LookupType 4 */
-
- struct TTO_Ligature_
- {
- FT_UShort LigGlyph; /* glyphID of ligature
- to substitute */
- FT_UShort ComponentCount; /* number of components in ligature */
- FT_UShort* Component; /* array of component glyph IDs */
- };
-
- typedef struct TTO_Ligature_ TTO_Ligature;
-
-
- struct TTO_LigatureSet_
- {
- FT_UShort LigatureCount; /* number of Ligature tables */
- TTO_Ligature* Ligature; /* array of Ligature tables */
- };
-
- typedef struct TTO_LigatureSet_ TTO_LigatureSet;
-
-
- struct TTO_LigatureSubst_
- {
- FT_UShort SubstFormat; /* always 1 */
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort LigatureSetCount; /* number of LigatureSet tables */
- TTO_LigatureSet* LigatureSet; /* array of LigatureSet tables */
- };
-
- typedef struct TTO_LigatureSubst_ TTO_LigatureSubst;
-
-
- /* needed by both lookup type 5 and 6 */
-
- struct TTO_SubstLookupRecord_
- {
- FT_UShort SequenceIndex; /* index into current
- glyph sequence */
- FT_UShort LookupListIndex; /* Lookup to apply to that pos. */
- };
-
- typedef struct TTO_SubstLookupRecord_ TTO_SubstLookupRecord;
-
-
- /* LookupType 5 */
-
- struct TTO_SubRule_
- {
- FT_UShort GlyphCount; /* total number of input glyphs */
- FT_UShort SubstCount; /* number of SubstLookupRecord
- tables */
- FT_UShort* Input; /* array of input glyph IDs */
- TTO_SubstLookupRecord* SubstLookupRecord;
- /* array of SubstLookupRecord
- tables */
- };
-
- typedef struct TTO_SubRule_ TTO_SubRule;
-
-
- struct TTO_SubRuleSet_
- {
- FT_UShort SubRuleCount; /* number of SubRule tables */
- TTO_SubRule* SubRule; /* array of SubRule tables */
- };
-
- typedef struct TTO_SubRuleSet_ TTO_SubRuleSet;
-
-
- struct TTO_ContextSubstFormat1_
- {
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort SubRuleSetCount; /* number of SubRuleSet tables */
- TTO_SubRuleSet* SubRuleSet; /* array of SubRuleSet tables */
- };
-
- typedef struct TTO_ContextSubstFormat1_ TTO_ContextSubstFormat1;
-
-
- struct TTO_SubClassRule_
- {
- FT_UShort GlyphCount; /* total number of context classes */
- FT_UShort SubstCount; /* number of SubstLookupRecord
- tables */
- FT_UShort* Class; /* array of classes */
- TTO_SubstLookupRecord* SubstLookupRecord;
- /* array of SubstLookupRecord
- tables */
- };
-
- typedef struct TTO_SubClassRule_ TTO_SubClassRule;
-
-
- struct TTO_SubClassSet_
- {
- FT_UShort SubClassRuleCount;
- /* number of SubClassRule tables */
- TTO_SubClassRule* SubClassRule; /* array of SubClassRule tables */
- };
-
- typedef struct TTO_SubClassSet_ TTO_SubClassSet;
-
-
- /* The `MaxContextLength' field is not defined in the TTO specification
- but simplifies the implementation of this format. It holds the
- maximal context length used in the context rules. */
-
- struct TTO_ContextSubstFormat2_
- {
- FT_UShort MaxContextLength;
- /* maximal context length */
- TTO_Coverage Coverage; /* Coverage table */
- TTO_ClassDefinition ClassDef; /* ClassDef table */
- FT_UShort SubClassSetCount;
- /* number of SubClassSet tables */
- TTO_SubClassSet* SubClassSet; /* array of SubClassSet tables */
- };
-
- typedef struct TTO_ContextSubstFormat2_ TTO_ContextSubstFormat2;
-
-
- struct TTO_ContextSubstFormat3_
- {
- FT_UShort GlyphCount; /* number of input glyphs */
- FT_UShort SubstCount; /* number of SubstLookupRecords */
- TTO_Coverage* Coverage; /* array of Coverage tables */
- TTO_SubstLookupRecord* SubstLookupRecord;
- /* array of substitution lookups */
- };
-
- typedef struct TTO_ContextSubstFormat3_ TTO_ContextSubstFormat3;
-
-
- struct TTO_ContextSubst_
- {
- FT_UShort SubstFormat; /* 1, 2, or 3 */
-
- union
- {
- TTO_ContextSubstFormat1 csf1;
- TTO_ContextSubstFormat2 csf2;
- TTO_ContextSubstFormat3 csf3;
- } csf;
- };
-
- typedef struct TTO_ContextSubst_ TTO_ContextSubst;
-
-
- /* LookupType 6 */
-
- struct TTO_ChainSubRule_
- {
- FT_UShort BacktrackGlyphCount;
- /* total number of backtrack glyphs */
- FT_UShort* Backtrack; /* array of backtrack glyph IDs */
- FT_UShort InputGlyphCount;
- /* total number of input glyphs */
- FT_UShort* Input; /* array of input glyph IDs */
- FT_UShort LookaheadGlyphCount;
- /* total number of lookahead glyphs */
- FT_UShort* Lookahead; /* array of lookahead glyph IDs */
- FT_UShort SubstCount; /* number of SubstLookupRecords */
- TTO_SubstLookupRecord* SubstLookupRecord;
- /* array of SubstLookupRecords */
- };
-
- typedef struct TTO_ChainSubRule_ TTO_ChainSubRule;
-
-
- struct TTO_ChainSubRuleSet_
- {
- FT_UShort ChainSubRuleCount;
- /* number of ChainSubRule tables */
- TTO_ChainSubRule* ChainSubRule; /* array of ChainSubRule tables */
- };
-
- typedef struct TTO_ChainSubRuleSet_ TTO_ChainSubRuleSet;
-
-
- struct TTO_ChainContextSubstFormat1_
- {
- TTO_Coverage Coverage; /* Coverage table */
- FT_UShort ChainSubRuleSetCount;
- /* number of ChainSubRuleSet tables */
- TTO_ChainSubRuleSet* ChainSubRuleSet;
- /* array of ChainSubRuleSet tables */
- };
-
- typedef struct TTO_ChainContextSubstFormat1_ TTO_ChainContextSubstFormat1;
-
-
- struct TTO_ChainSubClassRule_
- {
- FT_UShort BacktrackGlyphCount;
- /* total number of backtrack
- classes */
- FT_UShort* Backtrack; /* array of backtrack classes */
- FT_UShort InputGlyphCount;
- /* total number of context classes */
- FT_UShort* Input; /* array of context classes */
- FT_UShort LookaheadGlyphCount;
- /* total number of lookahead
- classes */
- FT_UShort* Lookahead; /* array of lookahead classes */
- FT_UShort SubstCount; /* number of SubstLookupRecords */
- TTO_SubstLookupRecord* SubstLookupRecord;
- /* array of substitution lookups */
- };
-
- typedef struct TTO_ChainSubClassRule_ TTO_ChainSubClassRule;
-
-
- struct TTO_ChainSubClassSet_
- {
- FT_UShort ChainSubClassRuleCount;
- /* number of ChainSubClassRule
- tables */
- TTO_ChainSubClassRule* ChainSubClassRule;
- /* array of ChainSubClassRule
- tables */
- };
-
- typedef struct TTO_ChainSubClassSet_ TTO_ChainSubClassSet;
-
-
- /* The `MaxXXXLength' fields are not defined in the TTO specification
- but simplifies the implementation of this format. It holds the
- maximal context length used in the specific context rules. */
-
- struct TTO_ChainContextSubstFormat2_
- {
- TTO_Coverage Coverage; /* Coverage table */
-
- FT_UShort MaxBacktrackLength;
- /* maximal backtrack length */
- TTO_ClassDefinition BacktrackClassDef;
- /* BacktrackClassDef table */
- FT_UShort MaxInputLength;
- /* maximal input length */
- TTO_ClassDefinition InputClassDef;
- /* InputClassDef table */
- FT_UShort MaxLookaheadLength;
- /* maximal lookahead length */
- TTO_ClassDefinition LookaheadClassDef;
- /* LookaheadClassDef table */
-
- FT_UShort ChainSubClassSetCount;
- /* number of ChainSubClassSet
- tables */
- TTO_ChainSubClassSet* ChainSubClassSet;
- /* array of ChainSubClassSet
- tables */
- };
-
- typedef struct TTO_ChainContextSubstFormat2_ TTO_ChainContextSubstFormat2;
-
-
- struct TTO_ChainContextSubstFormat3_
- {
- FT_UShort BacktrackGlyphCount;
- /* number of backtrack glyphs */
- TTO_Coverage* BacktrackCoverage;
- /* array of backtrack Coverage
- tables */
- FT_UShort InputGlyphCount;
- /* number of input glyphs */
- TTO_Coverage* InputCoverage;
- /* array of input coverage
- tables */
- FT_UShort LookaheadGlyphCount;
- /* number of lookahead glyphs */
- TTO_Coverage* LookaheadCoverage;
- /* array of lookahead coverage
- tables */
- FT_UShort SubstCount; /* number of SubstLookupRecords */
- TTO_SubstLookupRecord* SubstLookupRecord;
- /* array of substitution lookups */
- };
-
- typedef struct TTO_ChainContextSubstFormat3_ TTO_ChainContextSubstFormat3;
-
-
- struct TTO_ChainContextSubst_
- {
- FT_UShort SubstFormat; /* 1, 2, or 3 */
-
- union
- {
- TTO_ChainContextSubstFormat1 ccsf1;
- TTO_ChainContextSubstFormat2 ccsf2;
- TTO_ChainContextSubstFormat3 ccsf3;
- } ccsf;
- };
-
- typedef struct TTO_ChainContextSubst_ TTO_ChainContextSubst;
-
-
- /* LookupType 8 */
- struct TTO_ReverseChainContextSubst_
- {
- FT_UShort SubstFormat; /* always 1 */
- TTO_Coverage Coverage; /* coverage table for input glyphs */
- FT_UShort BacktrackGlyphCount; /* number of backtrack glyphs */
- TTO_Coverage* BacktrackCoverage; /* array of backtrack Coverage
- tables */
- FT_UShort LookaheadGlyphCount; /* number of lookahead glyphs */
- TTO_Coverage* LookaheadCoverage; /* array of lookahead Coverage
- tables */
- FT_UShort GlyphCount; /* number of Glyph IDs */
- FT_UShort* Substitute; /* array of substitute Glyph ID */
- };
-
- typedef struct TTO_ReverseChainContextSubst_ TTO_ReverseChainContextSubst;
-
-
- union TTO_GSUB_SubTable_
- {
- TTO_SingleSubst single;
- TTO_MultipleSubst multiple;
- TTO_AlternateSubst alternate;
- TTO_LigatureSubst ligature;
- TTO_ContextSubst context;
- TTO_ChainContextSubst chain;
- TTO_ReverseChainContextSubst reverse;
- };
-
- typedef union TTO_GSUB_SubTable_ TTO_GSUB_SubTable;
-
-
- /* A simple string object. It can both `send' and `receive' data.
- In case of sending, `length' and `pos' will be used. In case of
- receiving, `pos' points to the first free slot, and `allocated'
- specifies the amount of allocated memory (and the `length' field
- will be ignored). The routine TT_Add_String() will increase the
- amount of memory if necessary. After end of receive, `length'
- should be set to the value of `pos', and `pos' will be set to zero.
-
- `properties' (which is treated as a bit field) gives the glyph's
- properties: If a certain bit is set for a glyph, the feature which
- has the same bit set in its property value is applied.
-
- `components' is an internal array which tracks components of
- ligatures. We need this for MarkToLigature Attachment Positioning
- Subtables (in GPOS) together with `ligIDs' (which is used to mark
- ligatures and the skipped glyphs during a ligature lookup).
- `max_ligID' is increased after a successful ligature lookup.
-
- NEVER modify any elements of the structure! You should rather copy
- its contents if necessary.
-
- TT_Add_String() will also handle allocation; you should use
- free() in case you want to destroy the arrays in the object. */
-
-
- /* finally, the GSUB API */
-
- /* EXPORT_DEF
- TT_Error TT_Init_GSUB_Extension( TT_Engine engine ); */
-
- EXPORT_DEF
- FT_Error TT_Load_GSUB_Table( FT_Face face,
- TTO_GSUBHeader** gsub,
- TTO_GDEFHeader* gdef );
-
- EXPORT_DEF
- FT_Error TT_Done_GSUB_Table( TTO_GSUBHeader* gsub );
-
- EXPORT_DEF
- FT_Error TT_GSUB_Select_Script( TTO_GSUBHeader* gsub,
- FT_ULong script_tag,
- FT_UShort* script_index );
- EXPORT_DEF
- FT_Error TT_GSUB_Select_Language( TTO_GSUBHeader* gsub,
- FT_ULong language_tag,
- FT_UShort script_index,
- FT_UShort* language_index,
- FT_UShort* req_feature_index );
- EXPORT_DEF
- FT_Error TT_GSUB_Select_Feature( TTO_GSUBHeader* gsub,
- FT_ULong feature_tag,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_UShort* feature_index );
-
- EXPORT_DEF
- FT_Error TT_GSUB_Query_Scripts( TTO_GSUBHeader* gsub,
- FT_ULong** script_tag_list );
- EXPORT_DEF
- FT_Error TT_GSUB_Query_Languages( TTO_GSUBHeader* gsub,
- FT_UShort script_index,
- FT_ULong** language_tag_list );
- EXPORT_DEF
- FT_Error TT_GSUB_Query_Features( TTO_GSUBHeader* gsub,
- FT_UShort script_index,
- FT_UShort language_index,
- FT_ULong** feature_tag_list );
-
- EXPORT_DEF
- FT_Error TT_GSUB_Add_Feature( TTO_GSUBHeader* gsub,
- FT_UShort feature_index,
- FT_UInt property );
- EXPORT_DEF
- FT_Error TT_GSUB_Clear_Features( TTO_GSUBHeader* gsub );
-
- EXPORT_DEF
- FT_Error TT_GSUB_Register_Alternate_Function( TTO_GSUBHeader* gsub,
- TTO_AltFunction altfunc,
- void* data );
-
- EXPORT_DEF
- FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub,
- OTL_Buffer buffer );
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* FTXGSUB_H */
-
-
-/* END */
diff --git a/pango/opentype/ftxopen.c b/pango/opentype/ftxopen.c
deleted file mode 100644
index 8afb8f2c..00000000
--- a/pango/opentype/ftxopen.c
+++ /dev/null
@@ -1,1552 +0,0 @@
-/*******************************************************************
- *
- * ftxopen.c
- *
- * TrueType Open common table support.
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#include <config.h>
-
-#include "ftxopen.h"
-#include "ftxopenf.h"
-
-#include "ftglue.h"
-
-
- /***************************
- * Script related functions
- ***************************/
-
-
- /* LangSys */
-
- static FT_Error Load_LangSys( TTO_LangSys* ls,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_UShort n, count;
- FT_UShort* fi;
-
-
- if ( ACCESS_Frame( 6L ) )
- return error;
-
- ls->LookupOrderOffset = GET_UShort(); /* should be 0 */
- ls->ReqFeatureIndex = GET_UShort();
- count = ls->FeatureCount = GET_UShort();
-
- FORGET_Frame();
-
- ls->FeatureIndex = NULL;
-
- if ( ALLOC_ARRAY( ls->FeatureIndex, count, FT_UShort ) )
- return error;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( ls->FeatureIndex );
- return error;
- }
-
- fi = ls->FeatureIndex;
-
- for ( n = 0; n < count; n++ )
- fi[n] = GET_UShort();
-
- FORGET_Frame();
-
- return TT_Err_Ok;
- }
-
-
- static void Free_LangSys( TTO_LangSys* ls,
- FT_Memory memory )
- {
- FREE( ls->FeatureIndex );
- }
-
-
- /* Script */
-
- static FT_Error Load_Script( TTO_Script* s,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_LangSysRecord* lsr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- if ( new_offset != base_offset ) /* not a NULL offset */
- {
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LangSys( &s->DefaultLangSys,
- stream ) ) != TT_Err_Ok )
- return error;
- (void)FILE_Seek( cur_offset );
- }
- else
- {
- /* we create a DefaultLangSys table with no entries */
-
- s->DefaultLangSys.LookupOrderOffset = 0;
- s->DefaultLangSys.ReqFeatureIndex = 0xFFFF;
- s->DefaultLangSys.FeatureCount = 0;
- s->DefaultLangSys.FeatureIndex = NULL;
- }
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail2;
-
- count = s->LangSysCount = GET_UShort();
-
- /* safety check; otherwise the official handling of TrueType Open
- fonts won't work */
-
- if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
- {
- error = TTO_Err_Empty_Script;
- goto Fail2;
- }
-
- FORGET_Frame();
-
- s->LangSysRecord = NULL;
-
- if ( ALLOC_ARRAY( s->LangSysRecord, count, TTO_LangSysRecord ) )
- goto Fail2;
-
- lsr = s->LangSysRecord;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 6L ) )
- goto Fail1;
-
- lsr[n].LangSysTag = GET_ULong();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_LangSys( &lsr[m].LangSys, memory );
-
- FREE( s->LangSysRecord );
-
- Fail2:
- Free_LangSys( &s->DefaultLangSys, memory );
- return error;
- }
-
-
- static void Free_Script( TTO_Script* s,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_LangSysRecord* lsr;
-
-
- Free_LangSys( &s->DefaultLangSys, memory );
-
- if ( s->LangSysRecord )
- {
- count = s->LangSysCount;
- lsr = s->LangSysRecord;
-
- for ( n = 0; n < count; n++ )
- Free_LangSys( &lsr[n].LangSys, memory );
-
- FREE( lsr );
- }
- }
-
-
- /* ScriptList */
-
- FT_Error Load_ScriptList( TTO_ScriptList* sl,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, script_count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_ScriptRecord* sr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- script_count = GET_UShort();
-
- FORGET_Frame();
-
- sl->ScriptRecord = NULL;
-
- if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, TTO_ScriptRecord ) )
- return error;
-
- sr = sl->ScriptRecord;
-
- sl->ScriptCount= 0;
- for ( n = 0; n < script_count; n++ )
- {
- if ( ACCESS_Frame( 6L ) )
- goto Fail;
-
- sr[sl->ScriptCount].ScriptTag = GET_ULong();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
-
- if ( FILE_Seek( new_offset ) )
- goto Fail;
-
- error = Load_Script( &sr[sl->ScriptCount].Script, stream );
- if ( error == TT_Err_Ok )
- sl->ScriptCount += 1;
- else if ( error != TTO_Err_Empty_Script )
- goto Fail;
-
- (void)FILE_Seek( cur_offset );
- }
-
- if ( sl->ScriptCount == 0 )
- {
- error = TTO_Err_Invalid_SubTable;
- goto Fail;
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( n = 0; n < sl->ScriptCount; n++ )
- Free_Script( &sr[n].Script, memory );
-
- FREE( sl->ScriptRecord );
- return error;
- }
-
-
- void Free_ScriptList( TTO_ScriptList* sl,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_ScriptRecord* sr;
-
-
- if ( sl->ScriptRecord )
- {
- count = sl->ScriptCount;
- sr = sl->ScriptRecord;
-
- for ( n = 0; n < count; n++ )
- Free_Script( &sr[n].Script, memory );
-
- FREE( sr );
- }
- }
-
-
-
- /*********************************
- * Feature List related functions
- *********************************/
-
-
- /* Feature */
-
- static FT_Error Load_Feature( TTO_Feature* f,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* lli;
-
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- f->FeatureParams = GET_UShort(); /* should be 0 */
- count = f->LookupListCount = GET_UShort();
-
- FORGET_Frame();
-
- f->LookupListIndex = NULL;
-
- if ( ALLOC_ARRAY( f->LookupListIndex, count, FT_UShort ) )
- return error;
-
- lli = f->LookupListIndex;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( f->LookupListIndex );
- return error;
- }
-
- for ( n = 0; n < count; n++ )
- lli[n] = GET_UShort();
-
- FORGET_Frame();
-
- return TT_Err_Ok;
- }
-
-
- static void Free_Feature( TTO_Feature* f,
- FT_Memory memory )
- {
- FREE( f->LookupListIndex );
- }
-
-
- /* FeatureList */
-
- FT_Error Load_FeatureList( TTO_FeatureList* fl,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_FeatureRecord* fr;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = fl->FeatureCount = GET_UShort();
-
- FORGET_Frame();
-
- fl->FeatureRecord = NULL;
-
- if ( ALLOC_ARRAY( fl->FeatureRecord, count, TTO_FeatureRecord ) )
- return error;
- if ( ALLOC_ARRAY( fl->ApplyOrder, count, FT_UShort ) )
- goto Fail2;
-
- fl->ApplyCount = 0;
-
- fr = fl->FeatureRecord;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 6L ) )
- goto Fail1;
-
- fr[n].FeatureTag = GET_ULong();
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Feature( &fr[n].Feature, stream ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- for ( m = 0; m < n; m++ )
- Free_Feature( &fr[m].Feature, memory );
-
- FREE( fl->ApplyOrder );
-
- Fail2:
- FREE( fl->FeatureRecord );
-
- return error;
- }
-
-
- void Free_FeatureList( TTO_FeatureList* fl,
- FT_Memory memory)
- {
- FT_UShort n, count;
-
- TTO_FeatureRecord* fr;
-
-
- if ( fl->FeatureRecord )
- {
- count = fl->FeatureCount;
- fr = fl->FeatureRecord;
-
- for ( n = 0; n < count; n++ )
- Free_Feature( &fr[n].Feature, memory );
-
- FREE( fr );
- }
-
- FREE( fl->ApplyOrder );
- }
-
-
-
- /********************************
- * Lookup List related functions
- ********************************/
-
- /* the subroutines of the following two functions are defined in
- ftxgsub.c and ftxgpos.c respectively */
-
-
- /* SubTable */
-
- static FT_Error Load_SubTable( TTO_SubTable* st,
- FT_Stream stream,
- TTO_Type table_type,
- FT_UShort lookup_type )
- {
- if ( table_type == GSUB )
- switch ( lookup_type )
- {
- case GSUB_LOOKUP_SINGLE:
- return Load_SingleSubst( &st->st.gsub.single, stream );
-
- case GSUB_LOOKUP_MULTIPLE:
- return Load_MultipleSubst( &st->st.gsub.multiple, stream );
-
- case GSUB_LOOKUP_ALTERNATE:
- return Load_AlternateSubst( &st->st.gsub.alternate, stream );
-
- case GSUB_LOOKUP_LIGATURE:
- return Load_LigatureSubst( &st->st.gsub.ligature, stream );
-
- case GSUB_LOOKUP_CONTEXT:
- return Load_ContextSubst( &st->st.gsub.context, stream );
-
- case GSUB_LOOKUP_CHAIN:
- return Load_ChainContextSubst( &st->st.gsub.chain, stream );
-
- case GSUB_LOOKUP_REVERSE_CHAIN:
- return Load_ReverseChainContextSubst( &st->st.gsub.reverse, stream );
-
- default:
- return TTO_Err_Invalid_GSUB_SubTable_Format;
- }
- else
- switch ( lookup_type )
- {
- case GPOS_LOOKUP_SINGLE:
- return Load_SinglePos( &st->st.gpos.single, stream );
-
- case GPOS_LOOKUP_PAIR:
- return Load_PairPos( &st->st.gpos.pair, stream );
-
- case GPOS_LOOKUP_CURSIVE:
- return Load_CursivePos( &st->st.gpos.cursive, stream );
-
- case GPOS_LOOKUP_MARKBASE:
- return Load_MarkBasePos( &st->st.gpos.markbase, stream );
-
- case GPOS_LOOKUP_MARKLIG:
- return Load_MarkLigPos( &st->st.gpos.marklig, stream );
-
- case GPOS_LOOKUP_MARKMARK:
- return Load_MarkMarkPos( &st->st.gpos.markmark, stream );
-
- case GPOS_LOOKUP_CONTEXT:
- return Load_ContextPos( &st->st.gpos.context, stream );
-
- case GPOS_LOOKUP_CHAIN:
- return Load_ChainContextPos( &st->st.gpos.chain, stream );
-
- default:
- return TTO_Err_Invalid_GPOS_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- static void Free_SubTable( TTO_SubTable* st,
- TTO_Type table_type,
- FT_UShort lookup_type,
- FT_Memory memory )
- {
- if ( table_type == GSUB )
- switch ( lookup_type )
- {
- case GSUB_LOOKUP_SINGLE:
- Free_SingleSubst( &st->st.gsub.single, memory );
- break;
-
- case GSUB_LOOKUP_MULTIPLE:
- Free_MultipleSubst( &st->st.gsub.multiple, memory );
- break;
-
- case GSUB_LOOKUP_ALTERNATE:
- Free_AlternateSubst( &st->st.gsub.alternate, memory );
- break;
-
- case GSUB_LOOKUP_LIGATURE:
- Free_LigatureSubst( &st->st.gsub.ligature, memory );
- break;
-
- case GSUB_LOOKUP_CONTEXT:
- Free_ContextSubst( &st->st.gsub.context, memory );
- break;
-
- case GSUB_LOOKUP_REVERSE_CHAIN:
- Free_ReverseChainContextSubst( &st->st.gsub.reverse, memory );
- break;
-
- case GSUB_LOOKUP_CHAIN:
- Free_ChainContextSubst( &st->st.gsub.chain, memory );
- break;
- }
- else
- switch ( lookup_type )
- {
- case GPOS_LOOKUP_SINGLE:
- Free_SinglePos( &st->st.gpos.single, memory );
- break;
-
- case GPOS_LOOKUP_PAIR:
- Free_PairPos( &st->st.gpos.pair, memory );
- break;
-
- case GPOS_LOOKUP_CURSIVE:
- Free_CursivePos( &st->st.gpos.cursive, memory );
- break;
-
- case GPOS_LOOKUP_MARKBASE:
- Free_MarkBasePos( &st->st.gpos.markbase, memory );
- break;
-
- case GPOS_LOOKUP_MARKLIG:
- Free_MarkLigPos( &st->st.gpos.marklig, memory );
- break;
-
- case GPOS_LOOKUP_MARKMARK:
- Free_MarkMarkPos( &st->st.gpos.markmark, memory );
- break;
-
- case GPOS_LOOKUP_CONTEXT:
- Free_ContextPos( &st->st.gpos.context, memory );
- break;
-
- case GPOS_LOOKUP_CHAIN:
- Free_ChainContextPos ( &st->st.gpos.chain, memory );
- break;
- }
- }
-
-
- /* Lookup */
-
- static FT_Error Load_Lookup( TTO_Lookup* l,
- FT_Stream stream,
- TTO_Type type )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_SubTable* st;
-
- FT_Bool is_extension = FALSE;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 6L ) )
- return error;
-
- l->LookupType = GET_UShort();
- l->LookupFlag = GET_UShort();
- count = l->SubTableCount = GET_UShort();
-
- FORGET_Frame();
-
- l->SubTable = NULL;
-
- if ( ALLOC_ARRAY( l->SubTable, count, TTO_SubTable ) )
- return error;
-
- st = l->SubTable;
-
- if ( ( type == GSUB && l->LookupType == GSUB_LOOKUP_EXTENSION ) ||
- ( type == GPOS && l->LookupType == GPOS_LOOKUP_EXTENSION ) )
- is_extension = TRUE;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
-
- if ( is_extension )
- {
- if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) )
- goto Fail;
-
- if (GET_UShort() != 1) /* format should be 1 */
- goto Fail;
-
- l->LookupType = GET_UShort();
- new_offset += GET_ULong();
-
- FORGET_Frame();
- }
-
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_SubTable( &st[n], stream,
- type, l->LookupType ) ) != TT_Err_Ok )
- goto Fail;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail:
- for ( m = 0; m < n; m++ )
- Free_SubTable( &st[m], type, l->LookupType, memory );
-
- FREE( l->SubTable );
- return error;
- }
-
-
- static void Free_Lookup( TTO_Lookup* l,
- TTO_Type type,
- FT_Memory memory)
- {
- FT_UShort n, count;
-
- TTO_SubTable* st;
-
-
- if ( l->SubTable )
- {
- count = l->SubTableCount;
- st = l->SubTable;
-
- for ( n = 0; n < count; n++ )
- Free_SubTable( &st[n], type, l->LookupType, memory );
-
- FREE( st );
- }
- }
-
-
- /* LookupList */
-
- FT_Error Load_LookupList( TTO_LookupList* ll,
- FT_Stream stream,
- TTO_Type type )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, m, count;
- FT_ULong cur_offset, new_offset, base_offset;
-
- TTO_Lookup* l;
-
-
- base_offset = FILE_Pos();
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = ll->LookupCount = GET_UShort();
-
- FORGET_Frame();
-
- ll->Lookup = NULL;
-
- if ( ALLOC_ARRAY( ll->Lookup, count, TTO_Lookup ) )
- return error;
- if ( ALLOC_ARRAY( ll->Properties, count, FT_UInt ) )
- goto Fail2;
-
- l = ll->Lookup;
-
- for ( n = 0; n < count; n++ )
- {
- if ( ACCESS_Frame( 2L ) )
- goto Fail1;
-
- new_offset = GET_UShort() + base_offset;
-
- FORGET_Frame();
-
- cur_offset = FILE_Pos();
- if ( FILE_Seek( new_offset ) ||
- ( error = Load_Lookup( &l[n], stream, type ) ) != TT_Err_Ok )
- goto Fail1;
- (void)FILE_Seek( cur_offset );
- }
-
- return TT_Err_Ok;
-
- Fail1:
- FREE( ll->Properties );
-
- for ( m = 0; m < n; m++ )
- Free_Lookup( &l[m], type, memory );
-
- Fail2:
- FREE( ll->Lookup );
- return error;
- }
-
-
- void Free_LookupList( TTO_LookupList* ll,
- TTO_Type type,
- FT_Memory memory )
- {
- FT_UShort n, count;
-
- TTO_Lookup* l;
-
-
- FREE( ll->Properties );
-
- if ( ll->Lookup )
- {
- count = ll->LookupCount;
- l = ll->Lookup;
-
- for ( n = 0; n < count; n++ )
- Free_Lookup( &l[n], type, memory );
-
- FREE( l );
- }
- }
-
-
-
- /*****************************
- * Coverage related functions
- *****************************/
-
-
- /* CoverageFormat1 */
-
- static FT_Error Load_Coverage1( TTO_CoverageFormat1* cf1,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* ga;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = cf1->GlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- cf1->GlyphArray = NULL;
-
- if ( ALLOC_ARRAY( cf1->GlyphArray, count, FT_UShort ) )
- return error;
-
- ga = cf1->GlyphArray;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( cf1->GlyphArray );
- return error;
- }
-
- for ( n = 0; n < count; n++ )
- ga[n] = GET_UShort();
-
- FORGET_Frame();
-
- return TT_Err_Ok;
- }
-
-
- static void Free_Coverage1( TTO_CoverageFormat1* cf1,
- FT_Memory memory)
- {
- FREE( cf1->GlyphArray );
- }
-
-
- /* CoverageFormat2 */
-
- static FT_Error Load_Coverage2( TTO_CoverageFormat2* cf2,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- TTO_RangeRecord* rr;
-
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = cf2->RangeCount = GET_UShort();
-
- FORGET_Frame();
-
- cf2->RangeRecord = NULL;
-
- if ( ALLOC_ARRAY( cf2->RangeRecord, count, TTO_RangeRecord ) )
- return error;
-
- rr = cf2->RangeRecord;
-
- if ( ACCESS_Frame( count * 6L ) )
- goto Fail;
-
- for ( n = 0; n < count; n++ )
- {
- rr[n].Start = GET_UShort();
- rr[n].End = GET_UShort();
- rr[n].StartCoverageIndex = GET_UShort();
-
- /* sanity check; we are limited to 16bit integers */
- if ( rr[n].Start > rr[n].End ||
- ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=
- 0x10000L )
- {
- error = TTO_Err_Invalid_SubTable;
- goto Fail;
- }
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail:
- FREE( cf2->RangeRecord );
- return error;
- }
-
-
- static void Free_Coverage2( TTO_CoverageFormat2* cf2,
- FT_Memory memory )
- {
- FREE( cf2->RangeRecord );
- }
-
-
- FT_Error Load_Coverage( TTO_Coverage* c,
- FT_Stream stream )
- {
- FT_Error error;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- c->CoverageFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( c->CoverageFormat )
- {
- case 1:
- return Load_Coverage1( &c->cf.cf1, stream );
-
- case 2:
- return Load_Coverage2( &c->cf.cf2, stream );
-
- default:
- return TTO_Err_Invalid_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
- void Free_Coverage( TTO_Coverage* c,
- FT_Memory memory )
- {
- switch ( c->CoverageFormat )
- {
- case 1:
- Free_Coverage1( &c->cf.cf1, memory );
- break;
-
- case 2:
- Free_Coverage2( &c->cf.cf2, memory );
- break;
- }
- }
-
-
- static FT_Error Coverage_Index1( TTO_CoverageFormat1* cf1,
- FT_UShort glyphID,
- FT_UShort* index )
- {
- FT_UShort min, max, new_min, new_max, middle;
-
- FT_UShort* array = cf1->GlyphArray;
-
-
- /* binary search */
-
- if ( cf1->GlyphCount == 0 )
- return TTO_Err_Not_Covered;
-
- new_min = 0;
- new_max = cf1->GlyphCount - 1;
-
- do
- {
- min = new_min;
- max = new_max;
-
- /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
- overflow and rounding errors */
-
- middle = max - ( ( max - min ) >> 1 );
-
- if ( glyphID == array[middle] )
- {
- *index = middle;
- return TT_Err_Ok;
- }
- else if ( glyphID < array[middle] )
- {
- if ( middle == min )
- break;
- new_max = middle - 1;
- }
- else
- {
- if ( middle == max )
- break;
- new_min = middle + 1;
- }
- } while ( min < max );
-
- return TTO_Err_Not_Covered;
- }
-
-
- static FT_Error Coverage_Index2( TTO_CoverageFormat2* cf2,
- FT_UShort glyphID,
- FT_UShort* index )
- {
- FT_UShort min, max, new_min, new_max, middle;
-
- TTO_RangeRecord* rr = cf2->RangeRecord;
-
-
- /* binary search */
-
- if ( cf2->RangeCount == 0 )
- return TTO_Err_Not_Covered;
-
- new_min = 0;
- new_max = cf2->RangeCount - 1;
-
- do
- {
- min = new_min;
- max = new_max;
-
- /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
- overflow and rounding errors */
-
- middle = max - ( ( max - min ) >> 1 );
-
- if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End )
- {
- *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start;
- return TT_Err_Ok;
- }
- else if ( glyphID < rr[middle].Start )
- {
- if ( middle == min )
- break;
- new_max = middle - 1;
- }
- else
- {
- if ( middle == max )
- break;
- new_min = middle + 1;
- }
- } while ( min < max );
-
- return TTO_Err_Not_Covered;
- }
-
-
- FT_Error Coverage_Index( TTO_Coverage* c,
- FT_UShort glyphID,
- FT_UShort* index )
- {
- switch ( c->CoverageFormat )
- {
- case 1:
- return Coverage_Index1( &c->cf.cf1, glyphID, index );
-
- case 2:
- return Coverage_Index2( &c->cf.cf2, glyphID, index );
-
- default:
- return TTO_Err_Invalid_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
-
- /*************************************
- * Class Definition related functions
- *************************************/
-
-
- /* ClassDefFormat1 */
-
- static FT_Error Load_ClassDef1( TTO_ClassDefinition* cd,
- FT_UShort limit,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* cva;
- FT_Bool* d;
-
- TTO_ClassDefFormat1* cdf1;
-
-
- cdf1 = &cd->cd.cd1;
-
- if ( ACCESS_Frame( 4L ) )
- return error;
-
- cdf1->StartGlyph = GET_UShort();
- count = cdf1->GlyphCount = GET_UShort();
-
- FORGET_Frame();
-
- /* sanity check; we are limited to 16bit integers */
-
- if ( cdf1->StartGlyph + (long)count >= 0x10000L )
- return TTO_Err_Invalid_SubTable;
-
- cdf1->ClassValueArray = NULL;
-
- if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, FT_UShort ) )
- return error;
-
- d = cd->Defined;
- cva = cdf1->ClassValueArray;
-
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail;
-
- for ( n = 0; n < count; n++ )
- {
- cva[n] = GET_UShort();
- if ( cva[n] >= limit )
- {
- error = TTO_Err_Invalid_SubTable;
- goto Fail;
- }
- d[cva[n]] = TRUE;
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail:
- FREE( cva );
-
- return error;
- }
-
-
- static void Free_ClassDef1( TTO_ClassDefFormat1* cdf1,
- FT_Memory memory )
- {
- FREE( cdf1->ClassValueArray );
- }
-
-
- /* ClassDefFormat2 */
-
- static FT_Error Load_ClassDef2( TTO_ClassDefinition* cd,
- FT_UShort limit,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- TTO_ClassRangeRecord* crr;
- FT_Bool* d;
-
- TTO_ClassDefFormat2* cdf2;
-
-
- cdf2 = &cd->cd.cd2;
-
- if ( ACCESS_Frame( 2L ) )
- return error;
-
- count = cdf2->ClassRangeCount = GET_UShort();
-
- FORGET_Frame();
-
- cdf2->ClassRangeRecord = NULL;
-
- if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, TTO_ClassRangeRecord ) )
- return error;
-
- d = cd->Defined;
- crr = cdf2->ClassRangeRecord;
-
- if ( ACCESS_Frame( count * 6L ) )
- goto Fail;
-
- for ( n = 0; n < count; n++ )
- {
- crr[n].Start = GET_UShort();
- crr[n].End = GET_UShort();
- crr[n].Class = GET_UShort();
-
- /* sanity check */
-
- if ( crr[n].Start > crr[n].End ||
- crr[n].Class >= limit )
- {
- error = TTO_Err_Invalid_SubTable;
- goto Fail;
- }
- d[crr[n].Class] = TRUE;
- }
-
- FORGET_Frame();
-
- return TT_Err_Ok;
-
- Fail:
- FREE( crr );
-
- return error;
- }
-
-
- static void Free_ClassDef2( TTO_ClassDefFormat2* cdf2,
- FT_Memory memory )
- {
- FREE( cdf2->ClassRangeRecord );
- }
-
-
- /* ClassDefinition */
-
- FT_Error Load_ClassDefinition( TTO_ClassDefinition* cd,
- FT_UShort limit,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
-
- if ( ALLOC_ARRAY( cd->Defined, limit, FT_Bool ) )
- return error;
-
- if ( ACCESS_Frame( 2L ) )
- goto Fail;
-
- cd->ClassFormat = GET_UShort();
-
- FORGET_Frame();
-
- switch ( cd->ClassFormat )
- {
- case 1:
- error = Load_ClassDef1( cd, limit, stream );
- break;
-
- case 2:
- error = Load_ClassDef2( cd, limit, stream );
- break;
-
- default:
- error = TTO_Err_Invalid_SubTable_Format;
- break;
- }
-
- if ( error )
- goto Fail;
-
- cd->loaded = TRUE;
-
- return TT_Err_Ok;
-
- Fail:
- FREE( cd->Defined );
- return error;
- }
-
-
- FT_Error Load_EmptyClassDefinition( TTO_ClassDefinition* cd,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
-
- if ( ALLOC_ARRAY( cd->Defined, 1, FT_Bool ) )
- return error;
-
- cd->ClassFormat = 1; /* Meaningless */
- cd->Defined[0] = FALSE;
-
- if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, FT_UShort ) )
- goto Fail;
-
- return TT_Err_Ok;
-
- Fail:
- FREE( cd->Defined );
- return error;
- }
-
- void Free_ClassDefinition( TTO_ClassDefinition* cd,
- FT_Memory memory )
- {
- if ( !cd->loaded )
- return;
-
- FREE( cd->Defined );
-
- switch ( cd->ClassFormat )
- {
- case 1:
- Free_ClassDef1( &cd->cd.cd1, memory );
- break;
-
- case 2:
- Free_ClassDef2( &cd->cd.cd2, memory );
- break;
- }
- }
-
-
- static FT_Error Get_Class1( TTO_ClassDefFormat1* cdf1,
- FT_UShort glyphID,
- FT_UShort* class,
- FT_UShort* index )
- {
- FT_UShort* cva = cdf1->ClassValueArray;
-
-
- if ( index )
- *index = 0;
-
- if ( glyphID >= cdf1->StartGlyph &&
- glyphID <= cdf1->StartGlyph + cdf1->GlyphCount )
- {
- *class = cva[glyphID - cdf1->StartGlyph];
- return TT_Err_Ok;
- }
- else
- {
- *class = 0;
- return TTO_Err_Not_Covered;
- }
- }
-
-
- /* we need the index value of the last searched class range record
- in case of failure for constructed GDEF tables */
-
- static FT_Error Get_Class2( TTO_ClassDefFormat2* cdf2,
- FT_UShort glyphID,
- FT_UShort* class,
- FT_UShort* index )
- {
- FT_Error error = TT_Err_Ok;
- FT_UShort min, max, new_min, new_max, middle;
-
- TTO_ClassRangeRecord* crr = cdf2->ClassRangeRecord;
-
-
- /* binary search */
-
- if ( cdf2->ClassRangeCount == 0 )
- {
- *class = 0;
- if ( index )
- *index = 0;
-
- return TTO_Err_Not_Covered;
- }
-
- new_min = 0;
- new_max = cdf2->ClassRangeCount - 1;
-
- do
- {
- min = new_min;
- max = new_max;
-
- /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
- overflow and rounding errors */
-
- middle = max - ( ( max - min ) >> 1 );
-
- if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )
- {
- *class = crr[middle].Class;
- error = TT_Err_Ok;
- break;
- }
- else if ( glyphID < crr[middle].Start )
- {
- if ( middle == min )
- {
- *class = 0;
- error = TTO_Err_Not_Covered;
- break;
- }
- new_max = middle - 1;
- }
- else
- {
- if ( middle == max )
- {
- *class = 0;
- error = TTO_Err_Not_Covered;
- break;
- }
- new_min = middle + 1;
- }
- } while ( min < max );
-
- if ( index )
- *index = middle;
-
- return error;
- }
-
-
- FT_Error Get_Class( TTO_ClassDefinition* cd,
- FT_UShort glyphID,
- FT_UShort* class,
- FT_UShort* index )
- {
- switch ( cd->ClassFormat )
- {
- case 1:
- return Get_Class1( &cd->cd.cd1, glyphID, class, index );
-
- case 2:
- return Get_Class2( &cd->cd.cd2, glyphID, class, index );
-
- default:
- return TTO_Err_Invalid_SubTable_Format;
- }
-
- return TT_Err_Ok; /* never reached */
- }
-
-
-
- /***************************
- * Device related functions
- ***************************/
-
-
- FT_Error Load_Device( TTO_Device* d,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
-
- FT_UShort n, count;
-
- FT_UShort* dv;
-
-
- if ( ACCESS_Frame( 6L ) )
- return error;
-
- d->StartSize = GET_UShort();
- d->EndSize = GET_UShort();
- d->DeltaFormat = GET_UShort();
-
- FORGET_Frame();
-
- if ( d->StartSize > d->EndSize ||
- d->DeltaFormat == 0 || d->DeltaFormat > 3 )
- return TTO_Err_Invalid_SubTable;
-
- d->DeltaValue = NULL;
-
- count = ( ( d->EndSize - d->StartSize + 1 ) >>
- ( 4 - d->DeltaFormat ) ) + 1;
-
- if ( ALLOC_ARRAY( d->DeltaValue, count, FT_UShort ) )
- return error;
-
- if ( ACCESS_Frame( count * 2L ) )
- {
- FREE( d->DeltaValue );
- return error;
- }
-
- dv = d->DeltaValue;
-
- for ( n = 0; n < count; n++ )
- dv[n] = GET_UShort();
-
- FORGET_Frame();
-
- return TT_Err_Ok;
- }
-
-
- void Free_Device( TTO_Device* d,
- FT_Memory memory )
- {
- FREE( d->DeltaValue );
- }
-
-
- /* Since we have the delta values stored in compressed form, we must
- uncompress it now. To simplify the interface, the function always
- returns a meaningful value in `value'; the error is just for
- information.
- | |
- format = 1: 0011223344556677|8899101112131415|...
- | |
- byte 1 byte 2
-
- 00: (byte >> 14) & mask
- 11: (byte >> 12) & mask
- ...
-
- mask = 0x0003
- | |
- format = 2: 0000111122223333|4444555566667777|...
- | |
- byte 1 byte 2
-
- 0000: (byte >> 12) & mask
- 1111: (byte >> 8) & mask
- ...
-
- mask = 0x000F
- | |
- format = 3: 0000000011111111|2222222233333333|...
- | |
- byte 1 byte 2
-
- 00000000: (byte >> 8) & mask
- 11111111: (byte >> 0) & mask
- ....
-
- mask = 0x00FF */
-
- FT_Error Get_Device( TTO_Device* d,
- FT_UShort size,
- FT_Short* value )
- {
- FT_UShort byte, bits, mask, f, s;
-
-
- f = d->DeltaFormat;
-
- if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize )
- {
- s = size - d->StartSize;
- byte = d->DeltaValue[s >> ( 4 - f )];
- bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );
- mask = 0xFFFF >> ( 16 - ( 1 << f ) );
-
- *value = (FT_Short)( bits & mask );
-
- /* conversion to a signed value */
-
- if ( *value >= ( ( mask + 1 ) >> 1 ) )
- *value -= mask + 1;
-
- return TT_Err_Ok;
- }
- else
- {
- *value = 0;
- return TTO_Err_Not_Covered;
- }
- }
-
-
-/* END */
diff --git a/pango/opentype/ftxopen.h b/pango/opentype/ftxopen.h
deleted file mode 100644
index 64d2820d..00000000
--- a/pango/opentype/ftxopen.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/*******************************************************************
- *
- * ftxopen.h
- *
- * TrueType Open support.
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- * This file should be included by the application. Nevertheless,
- * the table specific APIs (and structures) are located in files like
- * ftxgsub.h or ftxgpos.h; these header files are read by ftxopen.h .
- *
- ******************************************************************/
-
-#ifndef FTXOPEN_H
-#define FTXOPEN_H
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define EXPORT_DEF
-#define EXPORT_FUNC
-
-#define TTO_MAX_NESTING_LEVEL 100
-
-#define TTO_Err_Invalid_SubTable_Format 0x1000
-#define TTO_Err_Invalid_SubTable 0x1001
-#define TTO_Err_Not_Covered 0x1002
-#define TTO_Err_Too_Many_Nested_Contexts 0x1003
-#define TTO_Err_No_MM_Interpreter 0x1004
-#define TTO_Err_Empty_Script 0x1005
-
-
- /* Script list related structures */
-
- struct TTO_LangSys_
- {
- FT_UShort LookupOrderOffset; /* always 0 for TT Open 1.0 */
- FT_UShort ReqFeatureIndex; /* required FeatureIndex */
- FT_UShort FeatureCount; /* number of Feature indices */
- FT_UShort* FeatureIndex; /* array of Feature indices */
- };
-
- typedef struct TTO_LangSys_ TTO_LangSys;
-
-
- struct TTO_LangSysRecord_
- {
- FT_ULong LangSysTag; /* LangSysTag identifier */
- TTO_LangSys LangSys; /* LangSys table */
- };
-
- typedef struct TTO_LangSysRecord_ TTO_LangSysRecord;
-
-
- struct TTO_Script_
- {
- TTO_LangSys DefaultLangSys; /* DefaultLangSys table */
- FT_UShort LangSysCount; /* number of LangSysRecords */
- TTO_LangSysRecord* LangSysRecord; /* array of LangSysRecords */
- };
-
- typedef struct TTO_Script_ TTO_Script;
-
-
- struct TTO_ScriptRecord_
- {
- FT_ULong ScriptTag; /* ScriptTag identifier */
- TTO_Script Script; /* Script table */
- };
-
- typedef struct TTO_ScriptRecord_ TTO_ScriptRecord;
-
-
- struct TTO_ScriptList_
- {
- FT_UShort ScriptCount; /* number of ScriptRecords */
- TTO_ScriptRecord* ScriptRecord; /* array of ScriptRecords */
- };
-
- typedef struct TTO_ScriptList_ TTO_ScriptList;
-
-
- /* Feature list related structures */
-
- struct TTO_Feature_
- {
- FT_UShort FeatureParams; /* always 0 for TT Open 1.0 */
- FT_UShort LookupListCount; /* number of LookupList indices */
- FT_UShort* LookupListIndex; /* array of LookupList indices */
- };
-
- typedef struct TTO_Feature_ TTO_Feature;
-
-
- struct TTO_FeatureRecord_
- {
- FT_ULong FeatureTag; /* FeatureTag identifier */
- TTO_Feature Feature; /* Feature table */
- };
-
- typedef struct TTO_FeatureRecord_ TTO_FeatureRecord;
-
-
- struct TTO_FeatureList_
- {
- FT_UShort FeatureCount; /* number of FeatureRecords */
- TTO_FeatureRecord* FeatureRecord; /* array of FeatureRecords */
- FT_UShort* ApplyOrder; /* order to apply features */
- FT_UShort ApplyCount; /* number of elements in ApplyOrder */
- };
-
- typedef struct TTO_FeatureList_ TTO_FeatureList;
-
-
- /* Lookup list related structures */
-
- struct TTO_SubTable_; /* defined below after inclusion
- of ftxgsub.h and ftxgpos.h */
- typedef struct TTO_SubTable_ TTO_SubTable;
-
-
- struct TTO_Lookup_
- {
- FT_UShort LookupType; /* Lookup type */
- FT_UShort LookupFlag; /* Lookup qualifiers */
- FT_UShort SubTableCount; /* number of SubTables */
- TTO_SubTable* SubTable; /* array of SubTables */
- };
-
- typedef struct TTO_Lookup_ TTO_Lookup;
-
-
- /* The `Properties' field is not defined in the TTO specification but
- is needed for processing lookups. If properties[n] is > 0, the
- functions TT_GSUB_Apply_String() resp. TT_GPOS_Apply_String() will
- process Lookup[n] for glyphs which have the specific bit not set in
- the `properties' field of the input string object. */
-
- struct TTO_LookupList_
- {
- FT_UShort LookupCount; /* number of Lookups */
- TTO_Lookup* Lookup; /* array of Lookup records */
- FT_UInt* Properties; /* array of flags */
- };
-
- typedef struct TTO_LookupList_ TTO_LookupList;
-
-
- /* Possible LookupFlag bit masks. `IGNORE_SPECIAL_MARKS' comes from the
- OpenType 1.2 specification; RIGHT_TO_LEFT has been (re)introduced in
- OpenType 1.3 -- if set, the last glyph in a cursive attachment
- sequence has to be positioned on the baseline -- regardless of the
- writing direction. */
-
-#define RIGHT_TO_LEFT 0x0001
-#define IGNORE_BASE_GLYPHS 0x0002
-#define IGNORE_LIGATURES 0x0004
-#define IGNORE_MARKS 0x0008
-#define IGNORE_SPECIAL_MARKS 0xFF00
-
-
- struct TTO_CoverageFormat1_
- {
- FT_UShort GlyphCount; /* number of glyphs in GlyphArray */
- FT_UShort* GlyphArray; /* array of glyph IDs */
- };
-
- typedef struct TTO_CoverageFormat1_ TTO_CoverageFormat1;
-
-
- struct TTO_RangeRecord_
- {
- FT_UShort Start; /* first glyph ID in the range */
- FT_UShort End; /* last glyph ID in the range */
- FT_UShort StartCoverageIndex; /* coverage index of first
- glyph ID in the range */
- };
-
- typedef struct TTO_RangeRecord_ TTO_RangeRecord;
-
-
- struct TTO_CoverageFormat2_
- {
- FT_UShort RangeCount; /* number of RangeRecords */
- TTO_RangeRecord* RangeRecord; /* array of RangeRecords */
- };
-
- typedef struct TTO_CoverageFormat2_ TTO_CoverageFormat2;
-
-
- struct TTO_Coverage_
- {
- FT_UShort CoverageFormat; /* 1 or 2 */
-
- union
- {
- TTO_CoverageFormat1 cf1;
- TTO_CoverageFormat2 cf2;
- } cf;
- };
-
- typedef struct TTO_Coverage_ TTO_Coverage;
-
-
- struct TTO_ClassDefFormat1_
- {
- FT_UShort StartGlyph; /* first glyph ID of the
- ClassValueArray */
- FT_UShort GlyphCount; /* size of the ClassValueArray */
- FT_UShort* ClassValueArray; /* array of class values */
- };
-
- typedef struct TTO_ClassDefFormat1_ TTO_ClassDefFormat1;
-
-
- struct TTO_ClassRangeRecord_
- {
- FT_UShort Start; /* first glyph ID in the range */
- FT_UShort End; /* last glyph ID in the range */
- FT_UShort Class; /* applied to all glyphs in range */
- };
-
- typedef struct TTO_ClassRangeRecord_ TTO_ClassRangeRecord;
-
-
- struct TTO_ClassDefFormat2_
- {
- FT_UShort ClassRangeCount;
- /* number of ClassRangeRecords */
- TTO_ClassRangeRecord* ClassRangeRecord;
- /* array of ClassRangeRecords */
- };
-
- typedef struct TTO_ClassDefFormat2_ TTO_ClassDefFormat2;
-
-
- /* The `Defined' field is not defined in the TTO specification but
- apparently needed for processing fonts like trado.ttf: This font
- refers to a class which contains not a single element. We map such
- classes to class 0. */
-
- struct TTO_ClassDefinition_
- {
- FT_Bool loaded;
-
- FT_Bool* Defined; /* array of Booleans.
- If Defined[n] is FALSE,
- class n contains no glyphs. */
- FT_UShort ClassFormat; /* 1 or 2 */
-
- union
- {
- TTO_ClassDefFormat1 cd1;
- TTO_ClassDefFormat2 cd2;
- } cd;
- };
-
- typedef struct TTO_ClassDefinition_ TTO_ClassDefinition;
-
-
- struct TTO_Device_
- {
- FT_UShort StartSize; /* smallest size to correct */
- FT_UShort EndSize; /* largest size to correct */
- FT_UShort DeltaFormat; /* DeltaValue array data format:
- 1, 2, or 3 */
- FT_UShort* DeltaValue; /* array of compressed data */
- };
-
- typedef struct TTO_Device_ TTO_Device;
-
-
-#include "otlbuffer.h"
-#include "ftxgdef.h"
-#include "ftxgsub.h"
-#include "ftxgpos.h"
-
-
- struct TTO_SubTable_
- {
- union
- {
- TTO_GSUB_SubTable gsub;
- TTO_GPOS_SubTable gpos;
- } st;
- };
-
-
- enum TTO_Type_
- {
- GSUB,
- GPOS
- };
-
- typedef enum TTO_Type_ TTO_Type;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* FTXOPEN_H */
-
-
-/* END */
diff --git a/pango/opentype/ftxopenf.h b/pango/opentype/ftxopenf.h
deleted file mode 100644
index 2c274c35..00000000
--- a/pango/opentype/ftxopenf.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*******************************************************************
- *
- * ftxopenf.h
- *
- * internal TrueType Open functions
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#ifndef FTXOPENF_H
-#define FTXOPENF_H
-
-#include "ftxopen.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
- /* functions from ftxopen.c */
-
- FT_Error Load_ScriptList( TTO_ScriptList* sl,
- FT_Stream stream );
- FT_Error Load_FeatureList( TTO_FeatureList* fl,
- FT_Stream input );
- FT_Error Load_LookupList( TTO_LookupList* ll,
- FT_Stream input,
- TTO_Type type );
-
- FT_Error Load_Coverage( TTO_Coverage* c,
- FT_Stream input );
- FT_Error Load_ClassDefinition( TTO_ClassDefinition* cd,
- FT_UShort limit,
- FT_Stream input );
- FT_Error Load_EmptyClassDefinition( TTO_ClassDefinition* cd,
- FT_Stream input );
- FT_Error Load_Device( TTO_Device* d,
- FT_Stream input );
-
- void Free_ScriptList( TTO_ScriptList* sl,
- FT_Memory memory );
- void Free_FeatureList( TTO_FeatureList* fl,
- FT_Memory memory );
- void Free_LookupList( TTO_LookupList* ll,
- TTO_Type type,
- FT_Memory memory );
-
- void Free_Coverage( TTO_Coverage* c,
- FT_Memory memory );
- void Free_ClassDefinition( TTO_ClassDefinition* cd,
- FT_Memory memory );
- void Free_Device( TTO_Device* d,
- FT_Memory memory );
-
-
- /* functions from ftxgsub.c */
-
- FT_Error Load_SingleSubst( TTO_SingleSubst* ss,
- FT_Stream input );
- FT_Error Load_MultipleSubst( TTO_MultipleSubst* ms,
- FT_Stream input );
- FT_Error Load_AlternateSubst( TTO_AlternateSubst* as,
- FT_Stream input );
- FT_Error Load_LigatureSubst( TTO_LigatureSubst* ls,
- FT_Stream input );
- FT_Error Load_ContextSubst( TTO_ContextSubst* cs,
- FT_Stream input );
- FT_Error Load_ChainContextSubst( TTO_ChainContextSubst* ccs,
- FT_Stream input );
- FT_Error Load_ReverseChainContextSubst( TTO_ReverseChainContextSubst* rccs,
- FT_Stream input );
-
- void Free_SingleSubst( TTO_SingleSubst* ss,
- FT_Memory memory );
- void Free_MultipleSubst( TTO_MultipleSubst* ms,
- FT_Memory memory );
- void Free_AlternateSubst( TTO_AlternateSubst* as,
- FT_Memory memory );
- void Free_LigatureSubst( TTO_LigatureSubst* ls,
- FT_Memory memory );
- void Free_ContextSubst( TTO_ContextSubst* cs,
- FT_Memory memory );
- void Free_ChainContextSubst( TTO_ChainContextSubst* ccs,
- FT_Memory memory );
- void Free_ReverseChainContextSubst( TTO_ReverseChainContextSubst* rccs,
- FT_Memory memory );
-
- /* functions from ftxgpos.c */
-
- FT_Error Load_SinglePos( TTO_SinglePos* sp,
- FT_Stream input );
- FT_Error Load_PairPos( TTO_PairPos* pp,
- FT_Stream input );
- FT_Error Load_CursivePos( TTO_CursivePos* cp,
- FT_Stream input );
- FT_Error Load_MarkBasePos( TTO_MarkBasePos* mbp,
- FT_Stream input );
- FT_Error Load_MarkLigPos( TTO_MarkLigPos* mlp,
- FT_Stream input );
- FT_Error Load_MarkMarkPos( TTO_MarkMarkPos* mmp,
- FT_Stream input );
- FT_Error Load_ContextPos( TTO_ContextPos* cp,
- FT_Stream input );
- FT_Error Load_ChainContextPos( TTO_ChainContextPos* ccp,
- FT_Stream input );
-
- void Free_SinglePos( TTO_SinglePos* sp,
- FT_Memory memory );
- void Free_PairPos( TTO_PairPos* pp,
- FT_Memory memory );
- void Free_CursivePos( TTO_CursivePos* cp,
- FT_Memory memory );
- void Free_MarkBasePos( TTO_MarkBasePos* mbp,
- FT_Memory memory );
- void Free_MarkLigPos( TTO_MarkLigPos* mlp,
- FT_Memory memory );
- void Free_MarkMarkPos( TTO_MarkMarkPos* mmp,
- FT_Memory memory );
- void Free_ContextPos( TTO_ContextPos* cp,
- FT_Memory memory );
- void Free_ChainContextPos( TTO_ChainContextPos* ccp,
- FT_Memory memory );
- /* query functions */
-
- FT_Error Coverage_Index( TTO_Coverage* c,
- FT_UShort glyphID,
- FT_UShort* index );
- FT_Error Get_Class( TTO_ClassDefinition* cd,
- FT_UShort glyphID,
- FT_UShort* class,
- FT_UShort* index );
- FT_Error Get_Device( TTO_Device* d,
- FT_UShort size,
- FT_Short* value );
-
-
- /* functions from ftxgdef.c */
-
- FT_Error Add_Glyph_Property( TTO_GDEFHeader* gdef,
- FT_UShort glyphID,
- FT_UShort property );
-
- FT_Error Check_Property( TTO_GDEFHeader* gdef,
- OTL_GlyphItem item,
- FT_UShort flags,
- FT_UShort* property );
-
-#define CHECK_Property( gdef, index, flags, property ) \
- ( ( error = Check_Property( (gdef), (index), (flags), \
- (property) ) ) != TT_Err_Ok )
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* FTXOPENF_H */
-
-
-/* END */
diff --git a/pango/opentype/harfbuzz-buffer.c b/pango/opentype/harfbuzz-buffer.c
new file mode 100644
index 00000000..3d233b4a
--- /dev/null
+++ b/pango/opentype/harfbuzz-buffer.c
@@ -0,0 +1,227 @@
+/* harfbuzz-buffer.c: Buffer of glyphs for substitution/positioning
+ *
+ * Copyright 2004 Red Hat Software
+ *
+ * Portions Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ */
+
+#include "harfbuzz-impl.h"
+#include "harfbuzz-buffer.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-gpos-private.h"
+
+static FT_Error
+hb_buffer_ensure( HB_Buffer buffer,
+ FT_ULong size )
+{
+ FT_Memory memory = buffer->memory;
+ FT_ULong new_allocated = buffer->allocated;
+
+ if (size > new_allocated)
+ {
+ FT_Error error;
+
+ while (size > new_allocated)
+ new_allocated += (new_allocated >> 1) + 8;
+
+ if ( REALLOC_ARRAY( buffer->in_string, buffer->allocated, new_allocated, HB_GlyphItemRec ) )
+ return error;
+ if ( REALLOC_ARRAY( buffer->out_string, buffer->allocated, new_allocated, HB_GlyphItemRec ) )
+ return error;
+ if ( REALLOC_ARRAY( buffer->positions, buffer->allocated, new_allocated, HB_PositionRec ) )
+ return error;
+
+ buffer->allocated = new_allocated;
+ }
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_new( FT_Memory memory,
+ HB_Buffer *buffer )
+{
+ FT_Error error;
+
+ if ( ALLOC( *buffer, sizeof( HB_BufferRec ) ) )
+ return error;
+
+ (*buffer)->memory = memory;
+ (*buffer)->in_length = 0;
+ (*buffer)->out_length = 0;
+ (*buffer)->allocated = 0;
+ (*buffer)->in_pos = 0;
+ (*buffer)->out_pos = 0;
+
+ (*buffer)->in_string = NULL;
+ (*buffer)->out_string = NULL;
+ (*buffer)->positions = NULL;
+ (*buffer)->max_ligID = 0;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_swap( HB_Buffer buffer )
+{
+ HB_GlyphItem tmp_string;
+
+ tmp_string = buffer->in_string;
+ buffer->in_string = buffer->out_string;
+ buffer->out_string = tmp_string;
+
+ buffer->in_length = buffer->out_length;
+ buffer->out_length = 0;
+
+ buffer->in_pos = 0;
+ buffer->out_pos = 0;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_free( HB_Buffer buffer )
+{
+ FT_Memory memory = buffer->memory;
+
+ FREE( buffer->in_string );
+ FREE( buffer->out_string );
+ FREE( buffer->positions );
+ FREE( buffer );
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_clear( HB_Buffer buffer )
+{
+ buffer->in_length = 0;
+ buffer->out_length = 0;
+ buffer->in_pos = 0;
+ buffer->out_pos = 0;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_add_glyph( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UInt properties,
+ FT_UInt cluster )
+{
+ FT_Error error;
+ HB_GlyphItem glyph;
+
+ error = hb_buffer_ensure( buffer, buffer->in_length + 1 );
+ if ( error )
+ return error;
+
+ glyph = &buffer->in_string[buffer->in_length];
+ glyph->gindex = glyph_index;
+ glyph->properties = properties;
+ glyph->cluster = cluster;
+ glyph->component = 0;
+ glyph->ligID = 0;
+ glyph->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
+
+ buffer->in_length++;
+
+ return FT_Err_Ok;
+}
+
+/* The following function copies `num_out' elements from `glyph_data'
+ to `buffer->out_string', advancing the in array pointer in the structure
+ by `num_in' elements, and the out array pointer by `num_out' elements.
+ Finally, it sets the `length' field of `out' equal to
+ `pos' of the `out' structure.
+
+ If `component' is 0xFFFF, the component value from buffer->in_pos
+ will copied `num_out' times, otherwise `component' itself will
+ be used to fill the `component' fields.
+
+ If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
+ will copied `num_out' times, otherwise `ligID' itself will
+ be used to fill the `ligID' fields.
+
+ The properties for all replacement glyphs are taken
+ from the glyph at position `buffer->in_pos'.
+
+ The cluster value for the glyph at position buffer->in_pos is used
+ for all replacement glyphs */
+FT_Error
+hb_buffer_add_output_glyphs( HB_Buffer buffer,
+ FT_UShort num_in,
+ FT_UShort num_out,
+ FT_UShort *glyph_data,
+ FT_UShort component,
+ FT_UShort ligID )
+{
+ FT_Error error;
+ FT_UShort i;
+ FT_UInt properties;
+ FT_UInt cluster;
+
+ error = hb_buffer_ensure( buffer, buffer->out_pos + num_out );
+ if ( error )
+ return error;
+
+ properties = buffer->in_string[buffer->in_pos].properties;
+ cluster = buffer->in_string[buffer->in_pos].cluster;
+ if ( component == 0xFFFF )
+ component = buffer->in_string[buffer->in_pos].component;
+ if ( ligID == 0xFFFF )
+ ligID = buffer->in_string[buffer->in_pos].ligID;
+
+ for ( i = 0; i < num_out; i++ )
+ {
+ HB_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
+
+ item->gindex = glyph_data[i];
+ item->properties = properties;
+ item->cluster = cluster;
+ item->component = component;
+ item->ligID = ligID;
+ item->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
+ }
+
+ buffer->in_pos += num_in;
+ buffer->out_pos += num_out;
+
+ buffer->out_length = buffer->out_pos;
+
+ return FT_Err_Ok;
+}
+
+FT_Error
+hb_buffer_add_output_glyph( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UShort component,
+ FT_UShort ligID )
+{
+ FT_UShort glyph_data = glyph_index;
+
+ return hb_buffer_add_output_glyphs ( buffer, 1, 1,
+ &glyph_data, component, ligID );
+}
+
+FT_Error
+hb_buffer_copy_output_glyph ( HB_Buffer buffer )
+{
+ FT_Error error;
+
+ error = hb_buffer_ensure( buffer, buffer->out_pos + 1 );
+ if ( error )
+ return error;
+
+ buffer->out_string[buffer->out_pos++] = buffer->in_string[buffer->in_pos++];
+ buffer->out_length = buffer->out_pos;
+
+ return FT_Err_Ok;
+}
+
+FT_UShort
+hb_buffer_allocate_ligid( HB_Buffer buffer )
+{
+ return buffer->max_ligID++;
+}
diff --git a/pango/opentype/harfbuzz-buffer.h b/pango/opentype/harfbuzz-buffer.h
new file mode 100644
index 00000000..c7478e38
--- /dev/null
+++ b/pango/opentype/harfbuzz-buffer.h
@@ -0,0 +1,106 @@
+/* harfbuzz-buffer.h: Buffer of glyphs for substitution/positioning
+ *
+ * Copyrigh 2004 Red Hat Software
+ *
+ * Portions Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ */
+#ifndef HARFBUZZ_BUFFER_H
+#define HARFBUZZ_BUFFER_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_BEGIN_HEADER
+
+#define HB_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
+
+typedef struct HB_GlyphItemRec_ {
+ FT_UInt gindex;
+ FT_UInt properties;
+ FT_UInt cluster;
+ FT_UShort component;
+ FT_UShort ligID;
+ FT_UShort gproperties;
+} HB_GlyphItemRec, *HB_GlyphItem;
+
+typedef struct HB_PositionRec_ {
+ FT_Pos x_pos;
+ FT_Pos y_pos;
+ FT_Pos x_advance;
+ FT_Pos y_advance;
+ FT_UShort back; /* number of glyphs to go back
+ for drawing current glyph */
+ FT_Bool new_advance; /* if set, the advance width values are
+ absolute, i.e., they won't be
+ added to the original glyph's value
+ but rather replace them. */
+ FT_Short cursive_chain; /* character to which this connects,
+ may be positive or negative; used
+ only internally */
+} HB_PositionRec, *HB_Position;
+
+
+typedef struct HB_BufferRec_{
+ FT_Memory memory;
+ FT_ULong allocated;
+
+ FT_ULong in_length;
+ FT_ULong out_length;
+ FT_ULong in_pos;
+ FT_ULong out_pos;
+
+ HB_GlyphItem in_string;
+ HB_GlyphItem out_string;
+ HB_Position positions;
+ FT_UShort max_ligID;
+} HB_BufferRec, *HB_Buffer;
+
+FT_Error
+hb_buffer_new( FT_Memory memory,
+ HB_Buffer *buffer );
+
+FT_Error
+hb_buffer_swap( HB_Buffer buffer );
+
+FT_Error
+hb_buffer_free( HB_Buffer buffer );
+
+FT_Error
+hb_buffer_clear( HB_Buffer buffer );
+
+FT_Error
+hb_buffer_add_glyph( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UInt properties,
+ FT_UInt cluster );
+
+FT_Error
+hb_buffer_add_output_glyphs( HB_Buffer buffer,
+ FT_UShort num_in,
+ FT_UShort num_out,
+ FT_UShort *glyph_data,
+ FT_UShort component,
+ FT_UShort ligID );
+
+FT_Error
+hb_buffer_add_output_glyph ( HB_Buffer buffer,
+ FT_UInt glyph_index,
+ FT_UShort component,
+ FT_UShort ligID );
+
+FT_Error
+hb_buffer_copy_output_glyph ( HB_Buffer buffer );
+
+FT_UShort
+hb_buffer_allocate_ligid( HB_Buffer buffer );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_BUFFER_H */
diff --git a/pango/opentype/ottest.c b/pango/opentype/harfbuzz-dump-main.c
index b0f4fd6b..81fecf43 100644
--- a/pango/opentype/ottest.c
+++ b/pango/opentype/harfbuzz-dump-main.c
@@ -1,5 +1,4 @@
-/* Pango
- * otttest.c: Test program for OpenType
+/* harfbuzz-dump-main.c: Test program for OpenType
*
* Copyright (C) 2000 Red Hat Software
*
@@ -19,13 +18,12 @@
* Boston, MA 02111-1307, USA.
*/
-#include <config.h>
#include <stdio.h>
#include <stdlib.h>
-#include "ftxopen.h"
+#include "harfbuzz-open.h"
-#include "disasm.h"
+#include "harfbuzz-dump.h"
#define N_ELEMENTS(arr) (sizeof(arr)/ sizeof((arr)[0]))
@@ -56,7 +54,7 @@ print_tag (FT_ULong tag)
}
static void
-maybe_add_feature (TTO_GSUB gsub,
+maybe_add_feature (HB_GSUB gsub,
FT_UShort script_index,
FT_ULong tag,
FT_UShort property)
@@ -65,22 +63,22 @@ maybe_add_feature (TTO_GSUB gsub,
FT_UShort feature_index;
/* 0xffff == default language system */
- error = TT_GSUB_Select_Feature (gsub, tag, script_index, 0xffff, &feature_index);
+ error = HB_GSUB_Select_Feature (gsub, tag, script_index, 0xffff, &feature_index);
if (error)
{
- if (error == TTO_Err_Not_Covered)
+ if (error == HB_Err_Not_Covered)
{
print_tag (tag);
fprintf (stderr, " not covered, ignored\n");
return;
}
- croak ("TT_GSUB_Select_Feature", error);
+ croak ("HB_GSUB_Select_Feature", error);
}
- if ((error = TT_GSUB_Add_Feature (gsub, feature_index, property)))
- croak ("TT_GSUB_Add_Feature", error);
+ if ((error = HB_GSUB_Add_Feature (gsub, feature_index, property)))
+ croak ("HB_GSUB_Add_Feature", error);
}
static void
@@ -122,23 +120,23 @@ select_cmap (FT_Face face)
}
static void
-add_features (TTO_GSUB gsub)
+add_features (HB_GSUB gsub)
{
FT_Error error;
FT_ULong tag = FT_MAKE_TAG ('a', 'r', 'a', 'b');
FT_UShort script_index;
- error = TT_GSUB_Select_Script (gsub, tag, &script_index);
+ error = HB_GSUB_Select_Script (gsub, tag, &script_index);
if (error)
{
- if (error == TTO_Err_Not_Covered)
+ if (error == HB_Err_Not_Covered)
{
fprintf (stderr, "Arabic not covered, no features used\n");
return;
}
- croak ("TT_GSUB_Select_Script", error);
+ croak ("HB_GSUB_Select_Script", error);
}
maybe_add_feature (gsub, script_index, FT_MAKE_TAG ('i', 'n', 'i', 't'), I);
@@ -150,7 +148,7 @@ add_features (TTO_GSUB gsub)
#if 0
void
-dump_string (TTO_GSUB_String *str)
+dump_string (HB_GSUB_String *str)
{
FT_ULong i;
@@ -173,20 +171,20 @@ FT_UShort arabic_props[] = { I|L, M|L, M|L, M|L, M|L, F|L, I|L, M|L
void
try_string (FT_Library library,
FT_Face face,
- TTO_GSUB gsub)
+ HB_GSUB gsub)
{
FT_Error error;
- TTO_GSUB_String *in_str;
- TTO_GSUB_String *out_str;
+ HB_GSUB_String *in_str;
+ HB_GSUB_String *out_str;
FT_ULong i;
- if ((error = TT_GSUB_String_New (face->memory, &in_str)))
- croak ("TT_GSUB_String_New", error);
- if ((error = TT_GSUB_String_New (face->memory, &out_str)))
- croak ("TT_GSUB_String_New", error);
+ if ((error = HB_GSUB_String_New (face->memory, &in_str)))
+ croak ("HB_GSUB_String_New", error);
+ if ((error = HB_GSUB_String_New (face->memory, &out_str)))
+ croak ("HB_GSUB_String_New", error);
- if ((error = TT_GSUB_String_Set_Length (in_str, N_ELEMENTS (arabic_str))))
- croak ("TT_GSUB_String_Set_Length", error);
+ if ((error = HB_GSUB_String_Set_Length (in_str, N_ELEMENTS (arabic_str))))
+ croak ("HB_GSUB_String_Set_Length", error);
for (i=0; i < N_ELEMENTS (arabic_str); i++)
{
@@ -196,16 +194,16 @@ try_string (FT_Library library,
in_str->ligIDs[i] = i;
}
- if ((error = TT_GSUB_Apply_String (gsub, in_str, out_str)))
- croak ("TT_GSUB_Apply_String", error);
+ if ((error = HB_GSUB_Apply_String (gsub, in_str, out_str)))
+ croak ("HB_GSUB_Apply_String", error);
dump_string (in_str);
dump_string (out_str);
- if ((error = TT_GSUB_String_Done (in_str)))
- croak ("TT_GSUB_String_New", error);
- if ((error = TT_GSUB_String_Done (out_str)))
- croak ("TT_GSUB_String_New", error);
+ if ((error = HB_GSUB_String_Done (in_str)))
+ croak ("HB_GSUB_String_New", error);
+ if ((error = HB_GSUB_String_Done (out_str)))
+ croak ("HB_GSUB_String_New", error);
}
#endif
@@ -215,8 +213,8 @@ main (int argc, char **argv)
FT_Error error;
FT_Library library;
FT_Face face;
- TTO_GSUB gsub;
- TTO_GPOS gpos;
+ HB_GSUB gsub;
+ HB_GPOS gpos;
if (argc != 2)
{
@@ -233,25 +231,25 @@ main (int argc, char **argv)
printf ("<?xml version=\"1.0\"?>\n");
printf ("<OpenType>\n");
- if (!(error = TT_Load_GSUB_Table (face, &gsub, NULL)))
+ if (!(error = HB_Load_GSUB_Table (face, &gsub, NULL)))
{
- TT_Dump_GSUB_Table (gsub, stdout);
+ HB_Dump_GSUB_Table (gsub, stdout);
- if ((error = TT_Done_GSUB_Table (gsub)))
- croak ("FT_Done_GSUB_Table", error);
+ if ((error = HB_Done_GSUB_Table (gsub)))
+ croak ("HB_Done_GSUB_Table", error);
}
else if (error != FT_Err_Table_Missing)
- fprintf (stderr, "TT_Load_GSUB_Table %x\n", error);
+ fprintf (stderr, "HB_Load_GSUB_Table %x\n", error);
- if (!(error = TT_Load_GPOS_Table (face, &gpos, NULL)))
+ if (!(error = HB_Load_GPOS_Table (face, &gpos, NULL)))
{
- TT_Dump_GPOS_Table (gpos, stdout);
+ HB_Dump_GPOS_Table (gpos, stdout);
- if ((error = TT_Done_GPOS_Table (gpos)))
- croak ("FT_Done_GPOS_Table", error);
+ if ((error = HB_Done_GPOS_Table (gpos)))
+ croak ("HB_Done_GPOS_Table", error);
}
else if (error != FT_Err_Table_Missing)
- fprintf (stderr, "TT_Load_GPOS_Table %x\n", error);
+ fprintf (stderr, "HB_Load_GPOS_Table %x\n", error);
printf ("</OpenType>\n");
diff --git a/pango/opentype/disasm.c b/pango/opentype/harfbuzz-dump.c
index 50a07205..0500ff5e 100644
--- a/pango/opentype/disasm.c
+++ b/pango/opentype/harfbuzz-dump.c
@@ -1,5 +1,4 @@
-/* Pango
- * disasm.c: Dump OpenType layout tables
+/* harfbuzz-dump.c: Dump OpenType layout tables
*
* Copyright (C) 2000 Red Hat Software
*
@@ -19,28 +18,29 @@
* Boston, MA 02111-1307, USA.
*/
-#include <config.h>
-
-#include <glib.h> /* For G_HAVE_ISO_VARARGS */
+#include "harfbuzz-impl.h"
+#include "harfbuzz-dump.h"
+#include "harfbuzz-gdef-private.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-gpos-private.h"
+#include "harfbuzz-open-private.h"
#include <stdarg.h>
-#include "disasm.h"
+#define DUMP(format) dump (stream, indent, format)
+#define DUMP1(format, arg1) dump (stream, indent, format, arg1)
+#define DUMP2(format, arg1, arg2) dump (stream, indent, format, arg1, arg2)
+#define DUMP3(format, arg1, arg2, arg3) dump (stream, indent, format, arg1, arg2, arg3)
-#ifdef G_HAVE_ISO_VARARGS
-#define DUMP(...) dump (stream, indent, __VA_ARGS__)
-#elif defined (G_HAVE_GNUC_VARARGS)
-#define DUMP(args...) dump (stream, indent, args)
-#endif
#define DUMP_FINT(strct,fld) dump (stream, indent, "<" #fld ">%d</" #fld ">\n", (strct)->fld)
#define DUMP_FUINT(strct,fld) dump (stream, indent, "<" #fld ">%u</" #fld ">\n", (strct)->fld)
#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x</" #fld ">\n", (strct)->fld)
#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#06x</" #fld ">\n", (strct)->fld)
#define DUMP_USHORT_ARRAY(strct,fld,cnt) Dump_UShort_Array ((strct)->fld, cnt, #fld, stream, indent);
-#define DEF_DUMP(type) static void Dump_ ## type (TTO_ ## type *type, FILE *stream, int indent, FT_Bool G_GNUC_UNUSED is_gsub)
-#define RECURSE(name, type, val) do { DUMP ("<" #name ">\n"); Dump_ ## type (val, stream, indent + 1, is_gsub); DUMP ("</" #name ">\n"); } while (0)
-#define RECURSE_NUM(name, i, type, val) do { DUMP ("<" #name "> <!-- %d -->\n", i); Dump_ ## type (val, stream, indent + 1, is_gsub); DUMP ("</" #name ">\n"); } while (0)
-#define DUMP_VALUE_RECORD(val, frmt) do { DUMP ("<ValueRecord>\n"); Dump_ValueRecord (val, stream, indent + 1, is_gsub, frmt); DUMP ("</ValueRecord>\n"); } while (0)
+#define DEF_DUMP(type) static void Dump_ ## type (HB_ ## type *type, FILE *stream, int indent, HB_Type hb_type)
+#define RECURSE(name, type, val) do { DUMP ("<" #name ">\n"); Dump_ ## type (val, stream, indent + 1, hb_type); DUMP ("</" #name ">\n"); } while (0)
+#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)
+#define DUMP_VALUE_RECORD(val, frmt) do { DUMP ("<ValueRecord>\n"); Dump_ValueRecord (val, stream, indent + 1, hb_type, frmt); DUMP ("</ValueRecord>\n"); } while (0)
static void
do_indent (FILE *stream, int indent)
@@ -92,7 +92,7 @@ DEF_DUMP (LangSys)
DUMP_FUINT (LangSys, FeatureCount);
for (i=0; i < LangSys->FeatureCount; i++)
- DUMP("<FeatureIndex>%d</FeatureIndex>\n", LangSys->FeatureIndex[i]);
+ DUMP1("<FeatureIndex>%d</FeatureIndex>\n", LangSys->FeatureIndex[i]);
}
DEF_DUMP (Script)
@@ -137,13 +137,13 @@ DEF_DUMP (Feature)
DUMP_FUINT (Feature, LookupListCount);
for (i=0; i < Feature->LookupListCount; i++)
- DUMP("<LookupIndex>%d</LookupIndex>\n", Feature->LookupListIndex[i]);
+ DUMP1("<LookupIndex>%d</LookupIndex>\n", Feature->LookupListIndex[i]);
}
DEF_DUMP (MarkRecord)
{
DUMP_FUINT (MarkRecord, Class);
- DUMP("<Anchor>%d</Anchor>\n", MarkRecord->MarkAnchor.PosFormat );
+ DUMP1("<Anchor>%d</Anchor>\n", MarkRecord->MarkAnchor.PosFormat );
}
DEF_DUMP (MarkArray)
@@ -182,8 +182,8 @@ DEF_DUMP (Coverage)
DUMP_FUINT (&Coverage->cf.cf1, GlyphCount);
for (i = 0; i < Coverage->cf.cf1.GlyphCount; i++)
- DUMP("<Glyph>%#06x</Glyph> <!-- %d -->\n",
- Coverage->cf.cf1.GlyphArray[i], i);
+ DUMP2("<Glyph>%#06x</Glyph> <!-- %d -->\n",
+ Coverage->cf.cf1.GlyphArray[i], i);
}
else
{
@@ -191,9 +191,9 @@ DEF_DUMP (Coverage)
DUMP_FUINT (&Coverage->cf.cf2, RangeCount);
for ( i = 0; i < Coverage->cf.cf2.RangeCount; i++ )
- DUMP("<Glyph>%#06x - %#06x</Glyph> <!-- %d -->\n",
- Coverage->cf.cf2.RangeRecord[i].Start,
- Coverage->cf.cf2.RangeRecord[i].End);
+ DUMP3("<Glyph>%#06x - %#06x</Glyph> <!-- %d -->\n",
+ Coverage->cf.cf2.RangeRecord[i].Start,
+ Coverage->cf.cf2.RangeRecord[i].End, i);
}
}
@@ -212,18 +212,18 @@ DEF_DUMP (ClassDefinition)
if (ClassDefinition->ClassFormat == 1)
{
int i;
- TTO_ClassDefFormat1 *ClassDefFormat1 = &ClassDefinition->cd.cd1;
+ HB_ClassDefFormat1 *ClassDefFormat1 = &ClassDefinition->cd.cd1;
DUMP("<ClassDefinition>\n");
DUMP_FUINT (ClassDefFormat1, StartGlyph );
DUMP_FUINT (ClassDefFormat1, GlyphCount );
for (i = 0; i < ClassDefFormat1->GlyphCount; i++)
- DUMP(" <Class>%d</Class> <!-- %#06x -->", ClassDefFormat1->ClassValueArray[i],
- ClassDefFormat1->StartGlyph+i );
+ DUMP2(" <Class>%d</Class> <!-- %#06x -->", ClassDefFormat1->ClassValueArray[i],
+ ClassDefFormat1->StartGlyph+i );
}
else if (ClassDefinition->ClassFormat == 2)
{
int i;
- TTO_ClassDefFormat2 *ClassDefFormat2 = &ClassDefinition->cd.cd2;
+ HB_ClassDefFormat2 *ClassDefFormat2 = &ClassDefinition->cd.cd2;
DUMP_FUINT (ClassDefFormat2, ClassRangeCount);
for (i = 0; i < ClassDefFormat2->ClassRangeCount; i++)
@@ -263,9 +263,9 @@ DEF_DUMP (ChainSubClassSet)
}
static void
-Dump_GSUB_Lookup_Single (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_GSUB_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
{
- TTO_SingleSubst *SingleSubst = &subtable->st.gsub.single;
+ HB_SingleSubst *SingleSubst = &subtable->st.gsub.single;
DUMP_FUINT (SingleSubst, SubstFormat);
RECURSE (Coverage, Coverage, &SingleSubst->Coverage);
@@ -280,7 +280,7 @@ Dump_GSUB_Lookup_Single (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bo
DUMP_FINT (&SingleSubst->ssf.ssf2, GlyphCount);
for (i=0; i < SingleSubst->ssf.ssf2.GlyphCount; i++)
- DUMP("<Substitute>%#06x</Substitute> <!-- %d -->\n", SingleSubst->ssf.ssf2.Substitute[i], i);
+ DUMP2("<Substitute>%#06x</Substitute> <!-- %d -->\n", SingleSubst->ssf.ssf2.Substitute[i], i);
}
}
@@ -292,7 +292,7 @@ DEF_DUMP (Ligature)
DUMP_FUINT (Ligature, ComponentCount);
for (i=0; i < Ligature->ComponentCount - 1; i++)
- DUMP("<Component>%#06x</Component>\n", Ligature->Component[i]);
+ DUMP1("<Component>%#06x</Component>\n", Ligature->Component[i]);
}
DEF_DUMP (LigatureSet)
@@ -306,10 +306,10 @@ DEF_DUMP (LigatureSet)
}
static void
-Dump_GSUB_Lookup_Ligature (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_GSUB_Lookup_Ligature (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
{
int i;
- TTO_LigatureSubst *LigatureSubst = &subtable->st.gsub.ligature;
+ HB_LigatureSubst *LigatureSubst = &subtable->st.gsub.ligature;
DUMP_FUINT (LigatureSubst, SubstFormat);
RECURSE (Coverage, Coverage, &LigatureSubst->Coverage);
@@ -338,21 +338,21 @@ DEF_DUMP (ContextSubstFormat3)
}
static void
-Dump_GSUB_Lookup_Context (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_GSUB_Lookup_Context (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
{
- TTO_ContextSubst *ContextSubst = &subtable->st.gsub.context;
+ HB_ContextSubst *ContextSubst = &subtable->st.gsub.context;
DUMP_FUINT (ContextSubst, SubstFormat);
switch( ContextSubst->SubstFormat )
{
case 1:
- Dump_ContextSubstFormat1 (&ContextSubst->csf.csf1, stream, indent+2, is_gsub);
+ Dump_ContextSubstFormat1 (&ContextSubst->csf.csf1, stream, indent+2, hb_type);
break;
case 2:
- Dump_ContextSubstFormat2 (&ContextSubst->csf.csf2, stream, indent+2, is_gsub);
+ Dump_ContextSubstFormat2 (&ContextSubst->csf.csf2, stream, indent+2, hb_type);
break;
case 3:
- Dump_ContextSubstFormat3 (&ContextSubst->csf.csf3, stream, indent+2, is_gsub);
+ Dump_ContextSubstFormat3 (&ContextSubst->csf.csf3, stream, indent+2, hb_type);
break;
default:
fprintf(stderr, "invalid subformat!!!!!\n");
@@ -401,21 +401,21 @@ DEF_DUMP (ChainContextSubstFormat3)
}
static void
-Dump_GSUB_Lookup_Chain (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_GSUB_Lookup_Chain (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
{
- TTO_ChainContextSubst *chain = &subtable->st.gsub.chain;
+ HB_ChainContextSubst *chain = &subtable->st.gsub.chain;
DUMP_FUINT (chain, SubstFormat);
switch (chain->SubstFormat)
{
case 1:
- Dump_ChainContextSubstFormat1 (&chain->ccsf.ccsf1, stream, indent+2, is_gsub);
+ Dump_ChainContextSubstFormat1 (&chain->ccsf.ccsf1, stream, indent+2, hb_type);
break;
case 2:
- Dump_ChainContextSubstFormat2 (&chain->ccsf.ccsf2, stream, indent+2, is_gsub);
+ Dump_ChainContextSubstFormat2 (&chain->ccsf.ccsf2, stream, indent+2, hb_type);
break;
case 3:
- Dump_ChainContextSubstFormat3 (&chain->ccsf.ccsf3, stream, indent+2, is_gsub);
+ Dump_ChainContextSubstFormat3 (&chain->ccsf.ccsf3, stream, indent+2, hb_type);
break;
default:
fprintf(stderr, "invalid subformat!!!!!\n");
@@ -423,7 +423,7 @@ Dump_GSUB_Lookup_Chain (TTO_SubTable *subtable, FILE *stream, int indent, FT_Boo
}
static void
-Dump_Device (TTO_Device *Device, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_Device (HB_Device *Device, FILE *stream, int indent, HB_Type hb_type)
{
int i;
int bits = 0;
@@ -471,38 +471,38 @@ Dump_Device (TTO_Device *Device, FILE *stream, int indent, FT_Bool is_gsub)
}
static void
-Dump_ValueRecord (TTO_ValueRecord *ValueRecord, FILE *stream, int indent, FT_Bool is_gsub, FT_UShort value_format)
+Dump_ValueRecord (HB_ValueRecord *ValueRecord, FILE *stream, int indent, HB_Type hb_type, FT_UShort value_format)
{
- if (value_format & HAVE_X_PLACEMENT)
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT)
DUMP_FINT (ValueRecord, XPlacement);
- if (value_format & HAVE_Y_PLACEMENT)
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT)
DUMP_FINT (ValueRecord, YPlacement);
- if (value_format & HAVE_X_ADVANCE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE)
DUMP_FINT (ValueRecord, XAdvance);
- if (value_format & HAVE_Y_ADVANCE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE)
DUMP_FINT (ValueRecord, XAdvance);
- if (value_format & HAVE_X_PLACEMENT_DEVICE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE)
RECURSE (Device, Device, &ValueRecord->XPlacementDevice);
- if (value_format & HAVE_Y_PLACEMENT_DEVICE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE)
RECURSE (Device, Device, &ValueRecord->YPlacementDevice);
- if (value_format & HAVE_X_ADVANCE_DEVICE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE)
RECURSE (Device, Device, &ValueRecord->XAdvanceDevice);
- if (value_format & HAVE_Y_ADVANCE_DEVICE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE)
RECURSE (Device, Device, &ValueRecord->YAdvanceDevice);
- if (value_format & HAVE_X_ID_PLACEMENT)
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT)
DUMP_FUINT (ValueRecord, XIdPlacement);
- if (value_format & HAVE_Y_ID_PLACEMENT)
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT)
DUMP_FUINT (ValueRecord, YIdPlacement);
- if (value_format & HAVE_X_ID_ADVANCE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE)
DUMP_FUINT (ValueRecord, XIdAdvance);
- if (value_format & HAVE_Y_ID_ADVANCE)
+ if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE)
DUMP_FUINT (ValueRecord, XIdAdvance);
}
static void
-Dump_GPOS_Lookup_Single (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_GPOS_Lookup_Single (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
{
- TTO_SinglePos *SinglePos = &subtable->st.gpos.single;
+ HB_SinglePos *SinglePos = &subtable->st.gpos.single;
DUMP_FUINT (SinglePos, PosFormat);
RECURSE (Coverage, Coverage, &SinglePos->Coverage);
@@ -524,7 +524,7 @@ Dump_GPOS_Lookup_Single (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bo
}
static void
-Dump_PairValueRecord (TTO_PairValueRecord *PairValueRecord, FILE *stream, int indent, FT_Bool is_gsub, FT_UShort ValueFormat1, FT_UShort ValueFormat2)
+Dump_PairValueRecord (HB_PairValueRecord *PairValueRecord, FILE *stream, int indent, HB_Type hb_type, FT_UShort ValueFormat1, FT_UShort ValueFormat2)
{
DUMP_FUINT (PairValueRecord, SecondGlyph);
DUMP_VALUE_RECORD (&PairValueRecord->Value1, ValueFormat1);
@@ -532,7 +532,7 @@ Dump_PairValueRecord (TTO_PairValueRecord *PairValueRecord, FILE *stream, int in
}
static void
-Dump_PairSet (TTO_PairSet *PairSet, FILE *stream, int indent, FT_Bool is_gsub, FT_UShort ValueFormat1, FT_UShort ValueFormat2)
+Dump_PairSet (HB_PairSet *PairSet, FILE *stream, int indent, HB_Type hb_type, FT_UShort ValueFormat1, FT_UShort ValueFormat2)
{
int i;
DUMP_FUINT (PairSet, PairValueCount);
@@ -540,15 +540,15 @@ Dump_PairSet (TTO_PairSet *PairSet, FILE *stream, int indent, FT_Bool is_gsub, F
for (i = 0; i < PairSet->PairValueCount; i++)
{
DUMP ("<PairValueRecord>\n");
- Dump_PairValueRecord (&PairSet->PairValueRecord[i], stream, indent + 1, is_gsub, ValueFormat1, ValueFormat2);
+ Dump_PairValueRecord (&PairSet->PairValueRecord[i], stream, indent + 1, hb_type, ValueFormat1, ValueFormat2);
DUMP ("</PairValueRecord>\n");
}
}
static void
-Dump_GPOS_Lookup_Pair (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_GPOS_Lookup_Pair (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
{
- TTO_PairPos *PairPos = &subtable->st.gpos.pair;
+ HB_PairPos *PairPos = &subtable->st.gpos.pair;
DUMP_FUINT (PairPos, PosFormat);
RECURSE (Coverage, Coverage, &PairPos->Coverage);
@@ -564,7 +564,7 @@ Dump_GPOS_Lookup_Pair (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool
for (i = 0; i < PairPos->ppf.ppf1.PairSetCount; i++)
{
DUMP ("<PairSet>\n");
- Dump_PairSet (&PairPos->ppf.ppf1.PairSet[i], stream, indent + 1, is_gsub, PairPos->ValueFormat1, PairPos->ValueFormat2);
+ Dump_PairSet (&PairPos->ppf.ppf1.PairSet[i], stream, indent + 1, hb_type, PairPos->ValueFormat1, PairPos->ValueFormat2);
DUMP ("</PairSet>\n");
}
}
@@ -574,10 +574,10 @@ Dump_GPOS_Lookup_Pair (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool
}
static void
-Dump_GPOS_Lookup_Markbase (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+Dump_GPOS_Lookup_Markbase (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type)
{
int i;
- TTO_MarkBasePos *markbase = &subtable->st.gpos.markbase;
+ HB_MarkBasePos *markbase = &subtable->st.gpos.markbase;
DUMP_FUINT (markbase, PosFormat);
RECURSE (Coverage, Coverage, &markbase->MarkCoverage);
@@ -592,10 +592,10 @@ Dump_GPOS_Lookup_Markbase (TTO_SubTable *subtable, FILE *stream, int indent, FT_
for (i = 0; i < markbase->BaseArray.BaseCount; i++)
{
int j;
- TTO_BaseRecord *r = &markbase->BaseArray.BaseRecord[i];
- DUMP ("<BaseRecord> <!-- %d -->\n", i);
+ HB_BaseRecord *r = &markbase->BaseArray.BaseRecord[i];
+ DUMP1 ("<BaseRecord> <!-- %d -->\n", i);
for (j = 0; j < markbase->ClassCount; j++)
- DUMP (" <Anchor>%d</Anchor>\n", r->BaseAnchor->PosFormat);
+ DUMP1 (" <Anchor>%d</Anchor>\n", r->BaseAnchor->PosFormat);
DUMP ("<BaseRecord>\n");
}
@@ -607,31 +607,31 @@ DEF_DUMP (Lookup)
{
int i;
const char *lookup_name = NULL;
- void (*lookup_func) (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub) = NULL;
+ void (*lookup_func) (HB_SubTable *subtable, FILE *stream, int indent, HB_Type hb_type) = NULL;
- if (is_gsub)
+ if (hb_type == HB_Type_GSUB)
{
switch (Lookup->LookupType)
{
- case GSUB_LOOKUP_SINGLE:
+ case HB_GSUB_LOOKUP_SINGLE:
lookup_name = "SINGLE";
lookup_func = Dump_GSUB_Lookup_Single;
break;
- case GSUB_LOOKUP_MULTIPLE:
+ case HB_GSUB_LOOKUP_MULTIPLE:
lookup_name = "MULTIPLE";
break;
- case GSUB_LOOKUP_ALTERNATE:
+ case HB_GSUB_LOOKUP_ALTERNATE:
lookup_name = "ALTERNATE";
break;
- case GSUB_LOOKUP_LIGATURE:
+ case HB_GSUB_LOOKUP_LIGATURE:
lookup_name = "LIGATURE";
lookup_func = Dump_GSUB_Lookup_Ligature;
break;
- case GSUB_LOOKUP_CONTEXT:
+ case HB_GSUB_LOOKUP_CONTEXT:
lookup_name = "CONTEXT";
lookup_func = Dump_GSUB_Lookup_Context;
break;
- case GSUB_LOOKUP_CHAIN:
+ case HB_GSUB_LOOKUP_CHAIN:
lookup_name = "CHAIN";
lookup_func = Dump_GSUB_Lookup_Chain;
break;
@@ -641,44 +641,44 @@ DEF_DUMP (Lookup)
{
switch (Lookup->LookupType)
{
- case GPOS_LOOKUP_SINGLE:
+ case HB_GPOS_LOOKUP_SINGLE:
lookup_name = "SINGLE";
lookup_func = Dump_GPOS_Lookup_Single;
break;
- case GPOS_LOOKUP_PAIR:
+ case HB_GPOS_LOOKUP_PAIR:
lookup_name = "PAIR";
lookup_func = Dump_GPOS_Lookup_Pair;
break;
- case GPOS_LOOKUP_CURSIVE:
+ case HB_GPOS_LOOKUP_CURSIVE:
lookup_name = "CURSIVE";
break;
- case GPOS_LOOKUP_MARKBASE:
+ case HB_GPOS_LOOKUP_MARKBASE:
lookup_name = "MARKBASE";
lookup_func = Dump_GPOS_Lookup_Markbase;
break;
- case GPOS_LOOKUP_MARKLIG:
+ case HB_GPOS_LOOKUP_MARKLIG:
lookup_name = "MARKLIG";
break;
- case GPOS_LOOKUP_MARKMARK:
+ case HB_GPOS_LOOKUP_MARKMARK:
lookup_name = "MARKMARK";
break;
- case GPOS_LOOKUP_CONTEXT:
+ case HB_GPOS_LOOKUP_CONTEXT:
lookup_name = "CONTEXT";
break;
- case GPOS_LOOKUP_CHAIN:
+ case HB_GPOS_LOOKUP_CHAIN:
lookup_name = "CHAIN";
break;
}
}
- DUMP("<LookupType>%s</LookupType> <!-- %d -->\n", lookup_name, Lookup->LookupType);
- DUMP("<LookupFlag>%#06x</LookupFlag>\n", Lookup->LookupFlag);
+ DUMP2("<LookupType>%s</LookupType> <!-- %d -->\n", lookup_name, Lookup->LookupType);
+ DUMP1("<LookupFlag>%#06x</LookupFlag>\n", Lookup->LookupFlag);
for (i=0; i < Lookup->SubTableCount; i++)
{
DUMP ("<Subtable>\n");
if (lookup_func)
- (*lookup_func) (&Lookup->SubTable[i], stream, indent + 1, is_gsub);
+ (*lookup_func) (&Lookup->SubTable[i], stream, indent + 1, hb_type);
DUMP ("</Subtable>\n");
}
}
@@ -694,10 +694,10 @@ DEF_DUMP (LookupList)
}
void
-TT_Dump_GSUB_Table (TTO_GSUB gsub, FILE *stream)
+HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream)
{
int indent = 1;
- FT_Bool is_gsub = 1;
+ HB_Type hb_type = HB_Type_GSUB;
do_indent (stream, indent);
fprintf(stream, "<!-- GSUB -->\n");
@@ -707,10 +707,10 @@ TT_Dump_GSUB_Table (TTO_GSUB gsub, FILE *stream)
}
void
-TT_Dump_GPOS_Table (TTO_GPOS gpos, FILE *stream)
+HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream)
{
int indent = 1;
- FT_Bool is_gsub = 0;
+ HB_Type hb_type = HB_Type_GPOS;
do_indent (stream, indent);
fprintf(stream, "<!-- GPOS -->\n");
diff --git a/pango/opentype/disasm.h b/pango/opentype/harfbuzz-dump.h
index e7556d40..c41ca683 100644
--- a/pango/opentype/disasm.h
+++ b/pango/opentype/harfbuzz-dump.h
@@ -1,5 +1,4 @@
-/* Pango
- * disasm.h: Dump OpenType layout tables
+/* harfbuzz-dump.h: Dump OpenType layout tables
*
* Copyright (C) 2000 Red Hat Software
*
@@ -18,9 +17,18 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+#ifndef HARFBUZZ_DUMP_H
+#define HARFBUZZ_DUMP_H
#include <stdio.h>
-#include "ftxopen.h"
+#include "harfbuzz-gsub.h"
+#include "harfbuzz-gpos.h"
-void TT_Dump_GSUB_Table (TTO_GSUB gsub, FILE *stream);
-void TT_Dump_GPOS_Table (TTO_GPOS gpos, FILE *stream);
+FT_BEGIN_HEADER
+
+void HB_Dump_GSUB_Table (HB_GSUB gsub, FILE *stream);
+void HB_Dump_GPOS_Table (HB_GPOS gpos, FILE *stream);
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_DUMP_H */
diff --git a/pango/opentype/harfbuzz-gdef-private.h b/pango/opentype/harfbuzz-gdef-private.h
new file mode 100644
index 00000000..e07e2364
--- /dev/null
+++ b/pango/opentype/harfbuzz-gdef-private.h
@@ -0,0 +1,101 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GDEF_PRIVATE_H
+#define HARFBUZZ_GDEF_PRIVATE_H
+
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-buffer.h"
+
+FT_BEGIN_HEADER
+
+
+/* Attachment related structures */
+
+struct HB_AttachPoint_
+{
+ FT_UShort PointCount; /* size of the PointIndex array */
+ FT_UShort* PointIndex; /* array of contour points */
+};
+
+/* Ligature Caret related structures */
+
+struct HB_CaretValueFormat1_
+{
+ FT_Short Coordinate; /* x or y value (in design units) */
+};
+
+typedef struct HB_CaretValueFormat1_ HB_CaretValueFormat1;
+
+
+struct HB_CaretValueFormat2_
+{
+ FT_UShort CaretValuePoint; /* contour point index on glyph */
+};
+
+typedef struct HB_CaretValueFormat2_ HB_CaretValueFormat2;
+
+
+struct HB_CaretValueFormat3_
+{
+ FT_Short Coordinate; /* x or y value (in design units) */
+ HB_Device Device; /* Device table for x or y value */
+};
+
+typedef struct HB_CaretValueFormat3_ HB_CaretValueFormat3;
+
+
+struct HB_CaretValueFormat4_
+{
+ FT_UShort IdCaretValue; /* metric ID */
+};
+
+typedef struct HB_CaretValueFormat4_ HB_CaretValueFormat4;
+
+
+struct HB_CaretValue_
+{
+ FT_UShort CaretValueFormat; /* 1, 2, 3, or 4 */
+
+ union
+ {
+ HB_CaretValueFormat1 cvf1;
+ HB_CaretValueFormat2 cvf2;
+ HB_CaretValueFormat3 cvf3;
+ HB_CaretValueFormat4 cvf4;
+ } cvf;
+};
+
+typedef struct HB_CaretValue_ HB_CaretValue;
+
+
+struct HB_LigGlyph_
+{
+ FT_Bool loaded;
+
+ FT_UShort CaretCount; /* number of caret values */
+ HB_CaretValue* CaretValue; /* array of caret values */
+};
+
+
+FT_Error _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort property );
+
+FT_Error _HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
+ HB_GlyphItem item,
+ FT_UShort flags,
+ FT_UShort* property );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GDEF_PRIVATE_H */
diff --git a/pango/opentype/harfbuzz-gdef.c b/pango/opentype/harfbuzz-gdef.c
new file mode 100644
index 00000000..1564e88c
--- /dev/null
+++ b/pango/opentype/harfbuzz-gdef.c
@@ -0,0 +1,1228 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-gdef-private.h"
+#include "harfbuzz-open-private.h"
+
+#include FT_TRUETYPE_TAGS_H
+
+
+static FT_Error Load_AttachList( HB_AttachList* al,
+ FT_Stream stream );
+static FT_Error Load_LigCaretList( HB_LigCaretList* lcl,
+ FT_Stream stream );
+
+static void Free_AttachList( HB_AttachList* al,
+ FT_Memory memory );
+static void Free_LigCaretList( HB_LigCaretList* lcl,
+ FT_Memory memory );
+
+static void Free_NewGlyphClasses( HB_GDEFHeader* gdef,
+ FT_Memory memory );
+
+
+
+/**********************
+ * Extension Functions
+ **********************/
+
+#if 0
+#define GDEF_ID Build_Extension_ID( 'G', 'D', 'E', 'F' )
+
+
+static FT_Error GDEF_Create( void* ext,
+ PFace face )
+{
+ DEFINE_LOAD_LOCALS( face->stream );
+
+ HB_GDEFHeader* gdef = (HB_GDEFHeader*)ext;
+ Long table;
+
+
+ /* by convention */
+
+ if ( !gdef )
+ return FT_Err_Ok;
+
+ /* a null offset indicates that there is no GDEF table */
+
+ gdef->offset = 0;
+
+ /* we store the start offset and the size of the subtable */
+
+ table = HB_LookUp_Table( face, TTAG_GDEF );
+ if ( table < 0 )
+ return FT_Err_Ok; /* The table is optional */
+
+ if ( FILE_Seek( face->dirTables[table].Offset ) ||
+ ACCESS_Frame( 4L ) )
+ return error;
+
+ gdef->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */
+ gdef->Version = GET_ULong();
+
+ FORGET_Frame();
+
+ gdef->loaded = FALSE;
+
+ return FT_Err_Ok;
+}
+
+
+static FT_Error GDEF_Destroy( void* ext,
+ PFace face )
+{
+ HB_GDEFHeader* gdef = (HB_GDEFHeader*)ext;
+
+
+ /* by convention */
+
+ if ( !gdef )
+ return FT_Err_Ok;
+
+ if ( gdef->loaded )
+ {
+ Free_LigCaretList( &gdef->LigCaretList, memory );
+ Free_AttachList( &gdef->AttachList, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef, memory );
+
+ Free_NewGlyphClasses( gdef, memory );
+ }
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_Init_GDEF_Extension( HB_Engine engine )
+{
+ PEngine_Instance _engine = HANDLE_Engine( engine );
+
+
+ if ( !_engine )
+ return FT_Err_Invalid_Engine;
+
+ return HB_Register_Extension( _engine,
+ GDEF_ID,
+ sizeof ( HB_GDEFHeader ),
+ GDEF_Create,
+ GDEF_Destroy );
+}
+#endif
+/* GDEF glyph classes */
+
+#define UNCLASSIFIED_GLYPH 0
+#define SIMPLE_GLYPH 1
+#define LIGATURE_GLYPH 2
+#define MARK_GLYPH 3
+#define COMPONENT_GLYPH 4
+
+
+
+
+
+
+FT_Error HB_New_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** retptr )
+{
+ FT_Error error;
+ FT_Memory memory = face->memory;
+
+ HB_GDEFHeader* gdef;
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if ( ALLOC( gdef, sizeof( *gdef ) ) )
+ return error;
+
+ gdef->memory = face->memory;
+
+ gdef->GlyphClassDef.loaded = FALSE;
+ gdef->AttachList.loaded = FALSE;
+ gdef->LigCaretList.loaded = FALSE;
+ gdef->MarkAttachClassDef_offset = 0;
+ gdef->MarkAttachClassDef.loaded = FALSE;
+
+ gdef->LastGlyph = 0;
+ gdef->NewGlyphClasses = NULL;
+
+ *retptr = gdef;
+
+ return FT_Err_Ok;
+}
+
+
+FT_Error HB_Load_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** retptr )
+{
+ FT_Error error;
+ FT_Memory memory = face->memory;
+ FT_Stream stream = face->stream;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_GDEFHeader* gdef;
+
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if (( error = _hb_ftglue_face_goto_table( face, TTAG_GDEF, stream ) ))
+ return error;
+
+ if (( error = HB_New_GDEF_Table ( face, &gdef ) ))
+ return error;
+
+ base_offset = FILE_Pos();
+
+ /* skip version */
+
+ if ( FILE_Seek( base_offset + 4L ) ||
+ ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ /* all GDEF subtables are optional */
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ /* only classes 1-4 are allowed here */
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5,
+ stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_AttachList( &gdef->AttachList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigCaretList( &gdef->LigCaretList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We
+ first have to scan the LookupFlag values to find out whether we
+ must load it or not. Here we only store the offset of the table. */
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ gdef->MarkAttachClassDef_offset = new_offset + base_offset;
+ else
+ gdef->MarkAttachClassDef_offset = 0;
+
+ *retptr = gdef;
+
+ return FT_Err_Ok;
+
+Fail3:
+ Free_LigCaretList( &gdef->LigCaretList, memory );
+
+Fail2:
+ Free_AttachList( &gdef->AttachList, memory );
+
+Fail1:
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );
+
+Fail0:
+ FREE( gdef );
+
+ return error;
+}
+
+
+FT_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef )
+{
+ FT_Memory memory = gdef->memory;
+
+ Free_LigCaretList( &gdef->LigCaretList, memory );
+ Free_AttachList( &gdef->AttachList, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef, memory );
+
+ Free_NewGlyphClasses( gdef, memory );
+
+ FREE( gdef );
+
+ return FT_Err_Ok;
+}
+
+
+
+
+/*******************************
+ * AttachList related functions
+ *******************************/
+
+
+/* AttachPoint */
+
+static FT_Error Load_AttachPoint( HB_AttachPoint* ap,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort n, count;
+ FT_UShort* pi;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ap->PointCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ap->PointIndex = NULL;
+
+ if ( count )
+ {
+ if ( ALLOC_ARRAY( ap->PointIndex, count, FT_UShort ) )
+ return error;
+
+ pi = ap->PointIndex;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( pi );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ pi[n] = GET_UShort();
+
+ FORGET_Frame();
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_AttachPoint( HB_AttachPoint* ap,
+ FT_Memory memory )
+{
+ FREE( ap->PointIndex );
+}
+
+
+/* AttachList */
+
+static FT_Error Load_AttachList( HB_AttachList* al,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_AttachPoint* ap;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = al->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ al->AttachPoint = NULL;
+
+ if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) )
+ goto Fail2;
+
+ ap = al->AttachPoint;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_AttachPoint( &ap[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ al->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_AttachPoint( &ap[m], memory );
+
+ FREE( ap );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &al->Coverage, memory );
+ return error;
+}
+
+
+static void Free_AttachList( HB_AttachList* al,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_AttachPoint* ap;
+
+
+ if ( !al->loaded )
+ return;
+
+ if ( al->AttachPoint )
+ {
+ count = al->GlyphCount;
+ ap = al->AttachPoint;
+
+ for ( n = 0; n < count; n++ )
+ Free_AttachPoint( &ap[n], memory );
+
+ FREE( ap );
+ }
+
+ _HB_OPEN_Free_Coverage( &al->Coverage, memory );
+}
+
+
+
+/*********************************
+ * LigCaretList related functions
+ *********************************/
+
+
+/* CaretValueFormat1 */
+/* CaretValueFormat2 */
+/* CaretValueFormat3 */
+/* CaretValueFormat4 */
+
+static FT_Error Load_CaretValue( HB_CaretValue* cv,
+ FT_Stream stream )
+{
+ FT_Error error;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->CaretValueFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cv->CaretValueFormat )
+ {
+ case 1:
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->cvf.cvf1.Coordinate = GET_Short();
+
+ FORGET_Frame();
+
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->cvf.cvf2.CaretValuePoint = GET_UShort();
+
+ FORGET_Frame();
+
+ break;
+
+ case 3:
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cv->cvf.cvf3.Coordinate = GET_Short();
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ break;
+
+ case 4:
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cv->cvf.cvf4.IdCaretValue = GET_UShort();
+
+ FORGET_Frame();
+ break;
+
+ default:
+ return HB_Err_Invalid_GDEF_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_CaretValue( HB_CaretValue* cv,
+ FT_Memory memory )
+{
+ if ( cv->CaretValueFormat == 3 )
+ _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device, memory );
+}
+
+
+/* LigGlyph */
+
+static FT_Error Load_LigGlyph( HB_LigGlyph* lg,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_CaretValue* cv;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = lg->CaretCount = GET_UShort();
+
+ FORGET_Frame();
+
+ lg->CaretValue = NULL;
+
+ if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) )
+ return error;
+
+ cv = lg->CaretValue;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_CaretValue( &cv[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_CaretValue( &cv[m], memory );
+
+ FREE( cv );
+ return error;
+}
+
+
+static void Free_LigGlyph( HB_LigGlyph* lg,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_CaretValue* cv;
+
+
+ if ( lg->CaretValue )
+ {
+ count = lg->CaretCount;
+ cv = lg->CaretValue;
+
+ for ( n = 0; n < count; n++ )
+ Free_CaretValue( &cv[n], memory );
+
+ FREE( cv );
+ }
+}
+
+
+/* LigCaretList */
+
+static FT_Error Load_LigCaretList( HB_LigCaretList* lcl,
+ FT_Stream stream )
+{
+ FT_Memory memory = stream->memory;
+ FT_Error error;
+
+ FT_UShort m, n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LigGlyph* lg;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = lcl->LigGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ lcl->LigGlyph = NULL;
+
+ if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) )
+ goto Fail2;
+
+ lg = lcl->LigGlyph;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigGlyph( &lg[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ lcl->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_LigGlyph( &lg[m], memory );
+
+ FREE( lg );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &lcl->Coverage, memory );
+ return error;
+}
+
+
+static void Free_LigCaretList( HB_LigCaretList* lcl,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_LigGlyph* lg;
+
+
+ if ( !lcl->loaded )
+ return;
+
+ if ( lcl->LigGlyph )
+ {
+ count = lcl->LigGlyphCount;
+ lg = lcl->LigGlyph;
+
+ for ( n = 0; n < count; n++ )
+ Free_LigGlyph( &lg[n], memory );
+
+ FREE( lg );
+ }
+
+ _HB_OPEN_Free_Coverage( &lcl->Coverage, memory );
+}
+
+
+
+/***********
+ * GDEF API
+ ***********/
+
+
+static FT_UShort Get_New_Class( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort index )
+{
+ FT_UShort glyph_index, array_index, count;
+ FT_UShort byte, bits;
+
+ HB_ClassRangeRecord* gcrr;
+ FT_UShort** ngc;
+
+
+ if ( glyphID >= gdef->LastGlyph )
+ return 0;
+
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
+ gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
+ ngc = gdef->NewGlyphClasses;
+
+ if ( index < count && glyphID < gcrr[index].Start )
+ {
+ array_index = index;
+ if ( index == 0 )
+ glyph_index = glyphID;
+ else
+ glyph_index = glyphID - gcrr[index - 1].End - 1;
+ }
+ else
+ {
+ array_index = index + 1;
+ glyph_index = glyphID - gcrr[index].End - 1;
+ }
+
+ byte = ngc[array_index][glyph_index / 4];
+ bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
+
+ return bits & 0x000F;
+}
+
+
+
+FT_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort* property )
+{
+ FT_UShort class, index;
+
+ FT_Error error;
+
+
+ if ( !gdef || !property )
+ return FT_Err_Invalid_Argument;
+
+ /* first, we check for mark attach classes */
+
+ if ( gdef->MarkAttachClassDef.loaded )
+ {
+ error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ if ( !error )
+ {
+ *property = class << 8;
+ return FT_Err_Ok;
+ }
+ }
+
+ error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ /* if we have a constructed class table, check whether additional
+ values have been assigned */
+
+ if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses )
+ class = Get_New_Class( gdef, glyphID, index );
+
+ switch ( class )
+ {
+ case UNCLASSIFIED_GLYPH:
+ *property = 0;
+ break;
+
+ case SIMPLE_GLYPH:
+ *property = HB_GDEF_BASE_GLYPH;
+ break;
+
+ case LIGATURE_GLYPH:
+ *property = HB_GDEF_LIGATURE;
+ break;
+
+ case MARK_GLYPH:
+ *property = HB_GDEF_MARK;
+ break;
+
+ case COMPONENT_GLYPH:
+ *property = HB_GDEF_COMPONENT;
+ break;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static FT_Error Make_ClassRange( HB_ClassDefinition* cd,
+ FT_UShort start,
+ FT_UShort end,
+ FT_UShort class,
+ FT_Memory memory )
+{
+ FT_Error error;
+ FT_UShort index;
+
+ HB_ClassDefFormat2* cdf2;
+ HB_ClassRangeRecord* crr;
+
+
+ cdf2 = &cd->cd.cd2;
+
+ if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,
+ cdf2->ClassRangeCount,
+ cdf2->ClassRangeCount + 1 ,
+ HB_ClassRangeRecord ) )
+ return error;
+
+ cdf2->ClassRangeCount++;
+
+ crr = cdf2->ClassRangeRecord;
+ index = cdf2->ClassRangeCount - 1;
+
+ crr[index].Start = start;
+ crr[index].End = end;
+ crr[index].Class = class;
+
+ cd->Defined[class] = TRUE;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,
+ FT_UShort num_glyphs,
+ FT_UShort glyph_count,
+ FT_UShort* glyph_array,
+ FT_UShort* class_array )
+{
+ FT_UShort start, curr_glyph, curr_class;
+ FT_UShort n, m, count;
+ FT_Error error;
+ FT_Memory memory = gdef->memory;
+
+ HB_ClassDefinition* gcd;
+ HB_ClassRangeRecord* gcrr;
+ FT_UShort** ngc;
+
+
+ if ( !gdef || !glyph_array || !class_array )
+ return FT_Err_Invalid_Argument;
+
+ gcd = &gdef->GlyphClassDef;
+
+ /* We build a format 2 table */
+
+ gcd->ClassFormat = 2;
+
+ /* A GlyphClassDef table contains at most 5 different class values */
+
+ if ( ALLOC_ARRAY( gcd->Defined, 5, FT_Bool ) )
+ return error;
+
+ gcd->cd.cd2.ClassRangeCount = 0;
+ gcd->cd.cd2.ClassRangeRecord = NULL;
+
+ start = glyph_array[0];
+ curr_class = class_array[0];
+ curr_glyph = start;
+
+ if ( curr_class >= 5 )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail4;
+ }
+
+ glyph_count--;
+
+ for ( n = 0; n <= glyph_count; n++ )
+ {
+ if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )
+ {
+ if ( n == glyph_count )
+ {
+ if ( ( error = Make_ClassRange( gcd, start,
+ curr_glyph,
+ curr_class,
+ memory ) ) != FT_Err_Ok )
+ goto Fail3;
+ }
+ else
+ {
+ if ( curr_glyph == 0xFFFF )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+ else
+ curr_glyph++;
+ }
+ }
+ else
+ {
+ if ( ( error = Make_ClassRange( gcd, start,
+ curr_glyph - 1,
+ curr_class,
+ memory ) ) != FT_Err_Ok )
+ goto Fail3;
+
+ if ( curr_glyph > glyph_array[n] )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+
+ start = glyph_array[n];
+ curr_class = class_array[n];
+ curr_glyph = start;
+
+ if ( curr_class >= 5 )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+
+ if ( n == glyph_count )
+ {
+ if ( ( error = Make_ClassRange( gcd, start,
+ curr_glyph,
+ curr_class,
+ memory ) ) != FT_Err_Ok )
+ goto Fail3;
+ }
+ else
+ {
+ if ( curr_glyph == 0xFFFF )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Fail3;
+ }
+ else
+ curr_glyph++;
+ }
+ }
+ }
+
+ /* now prepare the arrays for class values assigned during the lookup
+ process */
+
+ if ( ALLOC_ARRAY( gdef->NewGlyphClasses,
+ gcd->cd.cd2.ClassRangeCount + 1, FT_UShort* ) )
+ goto Fail3;
+
+ count = gcd->cd.cd2.ClassRangeCount;
+ gcrr = gcd->cd.cd2.ClassRangeRecord;
+ ngc = gdef->NewGlyphClasses;
+
+ /* We allocate arrays for all glyphs not covered by the class range
+ records. Each element holds four class values. */
+
+ if ( count > 0 )
+ {
+ if ( gcrr[0].Start )
+ {
+ if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, FT_UShort ) )
+ goto Fail2;
+ }
+
+ for ( n = 1; n < count; n++ )
+ {
+ if ( gcrr[n].Start - gcrr[n - 1].End > 1 )
+ if ( ALLOC_ARRAY( ngc[n],
+ ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4,
+ FT_UShort ) )
+ goto Fail1;
+ }
+
+ if ( gcrr[count - 1].End != num_glyphs - 1 )
+ {
+ if ( ALLOC_ARRAY( ngc[count],
+ ( num_glyphs - gcrr[count - 1].End + 2 ) / 4,
+ FT_UShort ) )
+ goto Fail1;
+ }
+ }
+ else if ( num_glyphs > 0 )
+ {
+ if ( ALLOC_ARRAY( ngc[count],
+ ( num_glyphs + 3 ) / 4,
+ FT_UShort ) )
+ goto Fail2;
+ }
+
+ gdef->LastGlyph = num_glyphs - 1;
+
+ gdef->MarkAttachClassDef_offset = 0L;
+ gdef->MarkAttachClassDef.loaded = FALSE;
+
+ gcd->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ FREE( ngc[m] );
+
+Fail2:
+ FREE( gdef->NewGlyphClasses );
+
+Fail3:
+ FREE( gcd->cd.cd2.ClassRangeRecord );
+
+Fail4:
+ FREE( gcd->Defined );
+ return error;
+}
+
+
+static void Free_NewGlyphClasses( HB_GDEFHeader* gdef,
+ FT_Memory memory )
+{
+ FT_UShort** ngc;
+ FT_UShort n, count;
+
+
+ if ( gdef->NewGlyphClasses )
+ {
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1;
+ ngc = gdef->NewGlyphClasses;
+
+ for ( n = 0; n < count; n++ )
+ FREE( ngc[n] );
+
+ FREE( ngc );
+ }
+}
+
+
+FT_Error _HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort property )
+{
+ FT_Error error;
+ FT_UShort class, new_class, index;
+ FT_UShort byte, bits, mask;
+ FT_UShort array_index, glyph_index, count;
+
+ HB_ClassRangeRecord* gcrr;
+ FT_UShort** ngc;
+
+
+ error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ /* we don't accept glyphs covered in `GlyphClassDef' */
+
+ if ( !error )
+ return HB_Err_Not_Covered;
+
+ switch ( property )
+ {
+ case 0:
+ new_class = UNCLASSIFIED_GLYPH;
+ break;
+
+ case HB_GDEF_BASE_GLYPH:
+ new_class = SIMPLE_GLYPH;
+ break;
+
+ case HB_GDEF_LIGATURE:
+ new_class = LIGATURE_GLYPH;
+ break;
+
+ case HB_GDEF_MARK:
+ new_class = MARK_GLYPH;
+ break;
+
+ case HB_GDEF_COMPONENT:
+ new_class = COMPONENT_GLYPH;
+ break;
+
+ default:
+ return FT_Err_Invalid_Argument;
+ }
+
+ count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
+ gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
+ ngc = gdef->NewGlyphClasses;
+
+ if ( index < count && glyphID < gcrr[index].Start )
+ {
+ array_index = index;
+ if ( index == 0 )
+ glyph_index = glyphID;
+ else
+ glyph_index = glyphID - gcrr[index - 1].End - 1;
+ }
+ else
+ {
+ array_index = index + 1;
+ glyph_index = glyphID - gcrr[index].End - 1;
+ }
+
+ byte = ngc[array_index][glyph_index / 4];
+ bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
+ class = bits & 0x000F;
+
+ /* we don't overwrite existing entries */
+
+ if ( !class )
+ {
+ bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 );
+ mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) );
+
+ ngc[array_index][glyph_index / 4] &= mask;
+ ngc[array_index][glyph_index / 4] |= bits;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+FT_Error _HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
+ HB_GlyphItem gitem,
+ FT_UShort flags,
+ FT_UShort* property )
+{
+ FT_Error error;
+
+ if ( gdef )
+ {
+ FT_UShort basic_glyph_class;
+ FT_UShort desired_attachment_class;
+
+ if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN )
+ {
+ error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties );
+ if ( error )
+ return error;
+ }
+
+ *property = gitem->gproperties;
+
+ /* If the glyph was found in the MarkAttachmentClass table,
+ * then that class value is the high byte of the result,
+ * otherwise the low byte contains the basic type of the glyph
+ * as defined by the GlyphClassDef table.
+ */
+ if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ basic_glyph_class = HB_GDEF_MARK;
+ else
+ basic_glyph_class = *property;
+
+ /* Return Not_Covered, if, for example, basic_glyph_class
+ * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES
+ */
+ if ( flags & basic_glyph_class )
+ return HB_Err_Not_Covered;
+
+ /* The high byte of LookupFlags has the meaning
+ * "ignore marks of attachment type different than
+ * the attachment type specified."
+ */
+ desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS;
+ if ( desired_attachment_class )
+ {
+ if ( basic_glyph_class == HB_GDEF_MARK &&
+ *property != desired_attachment_class )
+ return HB_Err_Not_Covered;
+ }
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* END */
diff --git a/pango/opentype/harfbuzz-gdef.h b/pango/opentype/harfbuzz-gdef.h
new file mode 100644
index 00000000..e126e826
--- /dev/null
+++ b/pango/opentype/harfbuzz-gdef.h
@@ -0,0 +1,127 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GDEF_H
+#define HARFBUZZ_GDEF_H
+
+#include "harfbuzz-open.h"
+
+FT_BEGIN_HEADER
+
+#define HB_Err_Invalid_GDEF_SubTable_Format 0x1030
+#define HB_Err_Invalid_GDEF_SubTable 0x1031
+
+
+/* GDEF glyph properties. Note that HB_GDEF_COMPONENT has no corresponding
+ * flag in the LookupFlag field. */
+#define HB_GDEF_BASE_GLYPH 0x0002
+#define HB_GDEF_LIGATURE 0x0004
+#define HB_GDEF_MARK 0x0008
+#define HB_GDEF_COMPONENT 0x0010
+
+
+typedef struct HB_AttachPoint_ HB_AttachPoint;
+
+
+struct HB_AttachList_
+{
+ FT_Bool loaded;
+
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort GlyphCount; /* number of glyphs with
+ attachments */
+ HB_AttachPoint* AttachPoint; /* array of AttachPoint tables */
+};
+
+typedef struct HB_AttachList_ HB_AttachList;
+
+typedef struct HB_LigGlyph_ HB_LigGlyph;
+
+struct HB_LigCaretList_
+{
+ FT_Bool loaded;
+
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort LigGlyphCount; /* number of ligature glyphs */
+ HB_LigGlyph* LigGlyph; /* array of LigGlyph tables */
+};
+
+typedef struct HB_LigCaretList_ HB_LigCaretList;
+
+
+
+/* The `NewGlyphClasses' field is not defined in the TTO specification.
+ We use it for fonts with a constructed `GlyphClassDef' structure
+ (i.e., which don't have a GDEF table) to collect glyph classes
+ assigned during the lookup process. The number of arrays in this
+ pointer array is GlyphClassDef->cd.cd2.ClassRangeCount+1; the nth
+ array then contains the glyph class values of the glyphs not covered
+ by the ClassRangeRecords structures with index n-1 and n. We store
+ glyph class values for four glyphs in a single array element.
+
+ `LastGlyph' is identical to the number of glyphs minus one in the
+ font; we need it only if `NewGlyphClasses' is not NULL (to have an
+ upper bound for the last array).
+
+ Note that we first store the file offset to the `MarkAttachClassDef'
+ field (which has been introduced in OpenType 1.2) -- since the
+ `Version' field value hasn't been increased to indicate that we have
+ one more field for some obscure reason, we must parse the GSUB table
+ to find out whether class values refer to this table. Only then we
+ can finally load the MarkAttachClassDef structure if necessary. */
+
+struct HB_GDEFHeader_
+{
+ FT_Memory memory;
+ FT_ULong offset;
+
+ FT_Fixed Version;
+
+ HB_ClassDefinition GlyphClassDef;
+ HB_AttachList AttachList;
+ HB_LigCaretList LigCaretList;
+ FT_ULong MarkAttachClassDef_offset;
+ HB_ClassDefinition MarkAttachClassDef; /* new in OT 1.2 */
+
+ FT_UShort LastGlyph;
+ FT_UShort** NewGlyphClasses;
+};
+
+typedef struct HB_GDEFHeader_ HB_GDEFHeader;
+typedef struct HB_GDEFHeader_* HB_GDEF;
+
+
+FT_Error HB_New_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** retptr );
+
+
+FT_Error HB_Load_GDEF_Table( FT_Face face,
+ HB_GDEFHeader** gdef );
+
+
+FT_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef );
+
+
+FT_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef,
+ FT_UShort glyphID,
+ FT_UShort* property );
+
+FT_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef,
+ FT_UShort num_glyphs,
+ FT_UShort glyph_count,
+ FT_UShort* glyph_array,
+ FT_UShort* class_array );
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GDEF_H */
diff --git a/pango/opentype/harfbuzz-gpos-private.h b/pango/opentype/harfbuzz-gpos-private.h
new file mode 100644
index 00000000..a04416f5
--- /dev/null
+++ b/pango/opentype/harfbuzz-gpos-private.h
@@ -0,0 +1,683 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GPOS_PRIVATE_H
+#define HARFBUZZ_GPOS_PRIVATE_H
+
+#include "harfbuzz-gpos.h"
+
+FT_BEGIN_HEADER
+
+
+/* shared tables */
+
+struct HB_ValueRecord_
+{
+ FT_Short XPlacement; /* horizontal adjustment for
+ placement */
+ FT_Short YPlacement; /* vertical adjustment for
+ placement */
+ FT_Short XAdvance; /* horizontal adjustment for
+ advance */
+ FT_Short YAdvance; /* vertical adjustment for
+ advance */
+ HB_Device XPlacementDevice; /* device table for horizontal
+ placement */
+ HB_Device YPlacementDevice; /* device table for vertical
+ placement */
+ HB_Device XAdvanceDevice; /* device table for horizontal
+ advance */
+ HB_Device YAdvanceDevice; /* device table for vertical
+ advance */
+ FT_UShort XIdPlacement; /* horizontal placement metric ID */
+ FT_UShort YIdPlacement; /* vertical placement metric ID */
+ FT_UShort XIdAdvance; /* horizontal advance metric ID */
+ FT_UShort YIdAdvance; /* vertical advance metric ID */
+};
+
+typedef struct HB_ValueRecord_ HB_ValueRecord;
+
+
+/* Mask values to scan the value format of the ValueRecord structure.
+ We always expand compressed ValueRecords of the font. */
+
+#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT 0x0001
+#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT 0x0002
+#define HB_GPOS_FORMAT_HAVE_X_ADVANCE 0x0004
+#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE 0x0008
+#define HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE 0x0010
+#define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE 0x0020
+#define HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE 0x0040
+#define HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE 0x0080
+#define HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT 0x0100
+#define HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT 0x0200
+#define HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE 0x0400
+#define HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE 0x0800
+
+
+struct HB_AnchorFormat1_
+{
+ FT_Short XCoordinate; /* horizontal value */
+ FT_Short YCoordinate; /* vertical value */
+};
+
+typedef struct HB_AnchorFormat1_ HB_AnchorFormat1;
+
+
+struct HB_AnchorFormat2_
+{
+ FT_Short XCoordinate; /* horizontal value */
+ FT_Short YCoordinate; /* vertical value */
+ FT_UShort AnchorPoint; /* index to glyph contour point */
+};
+
+typedef struct HB_AnchorFormat2_ HB_AnchorFormat2;
+
+
+struct HB_AnchorFormat3_
+{
+ FT_Short XCoordinate; /* horizontal value */
+ FT_Short YCoordinate; /* vertical value */
+ HB_Device XDeviceTable; /* device table for X coordinate */
+ HB_Device YDeviceTable; /* device table for Y coordinate */
+};
+
+typedef struct HB_AnchorFormat3_ HB_AnchorFormat3;
+
+
+struct HB_AnchorFormat4_
+{
+ FT_UShort XIdAnchor; /* horizontal metric ID */
+ FT_UShort YIdAnchor; /* vertical metric ID */
+};
+
+typedef struct HB_AnchorFormat4_ HB_AnchorFormat4;
+
+
+struct HB_Anchor_
+{
+ FT_UShort PosFormat; /* 1, 2, 3, or 4 -- 0 indicates
+ that there is no Anchor table */
+
+ union
+ {
+ HB_AnchorFormat1 af1;
+ HB_AnchorFormat2 af2;
+ HB_AnchorFormat3 af3;
+ HB_AnchorFormat4 af4;
+ } af;
+};
+
+typedef struct HB_Anchor_ HB_Anchor;
+
+
+struct HB_MarkRecord_
+{
+ FT_UShort Class; /* mark class */
+ HB_Anchor MarkAnchor; /* anchor table */
+};
+
+typedef struct HB_MarkRecord_ HB_MarkRecord;
+
+
+struct HB_MarkArray_
+{
+ FT_UShort MarkCount; /* number of MarkRecord tables */
+ HB_MarkRecord* MarkRecord; /* array of MarkRecord tables */
+};
+
+typedef struct HB_MarkArray_ HB_MarkArray;
+
+
+/* LookupType 1 */
+
+struct HB_SinglePosFormat1_
+{
+ HB_ValueRecord Value; /* ValueRecord for all covered
+ glyphs */
+};
+
+typedef struct HB_SinglePosFormat1_ HB_SinglePosFormat1;
+
+
+struct HB_SinglePosFormat2_
+{
+ FT_UShort ValueCount; /* number of ValueRecord tables */
+ HB_ValueRecord* Value; /* array of ValueRecord tables */
+};
+
+typedef struct HB_SinglePosFormat2_ HB_SinglePosFormat2;
+
+
+struct HB_SinglePos_
+{
+ FT_UShort PosFormat; /* 1 or 2 */
+ HB_Coverage Coverage; /* Coverage table */
+
+ FT_UShort ValueFormat; /* format of ValueRecord table */
+
+ union
+ {
+ HB_SinglePosFormat1 spf1;
+ HB_SinglePosFormat2 spf2;
+ } spf;
+};
+
+typedef struct HB_SinglePos_ HB_SinglePos;
+
+
+/* LookupType 2 */
+
+struct HB_PairValueRecord_
+{
+ FT_UShort SecondGlyph; /* glyph ID for second glyph */
+ HB_ValueRecord Value1; /* pos. data for first glyph */
+ HB_ValueRecord Value2; /* pos. data for second glyph */
+};
+
+typedef struct HB_PairValueRecord_ HB_PairValueRecord;
+
+
+struct HB_PairSet_
+{
+ FT_UShort PairValueCount;
+ /* number of PairValueRecord tables */
+ HB_PairValueRecord* PairValueRecord;
+ /* array of PairValueRecord tables */
+};
+
+typedef struct HB_PairSet_ HB_PairSet;
+
+
+struct HB_PairPosFormat1_
+{
+ FT_UShort PairSetCount; /* number of PairSet tables */
+ HB_PairSet* PairSet; /* array of PairSet tables */
+};
+
+typedef struct HB_PairPosFormat1_ HB_PairPosFormat1;
+
+
+struct HB_Class2Record_
+{
+ HB_ValueRecord Value1; /* pos. data for first glyph */
+ HB_ValueRecord Value2; /* pos. data for second glyph */
+};
+
+typedef struct HB_Class2Record_ HB_Class2Record;
+
+
+struct HB_Class1Record_
+{
+ HB_Class2Record* Class2Record; /* array of Class2Record tables */
+};
+
+typedef struct HB_Class1Record_ HB_Class1Record;
+
+
+struct HB_PairPosFormat2_
+{
+ HB_ClassDefinition ClassDef1; /* class def. for first glyph */
+ HB_ClassDefinition ClassDef2; /* class def. for second glyph */
+ FT_UShort Class1Count; /* number of classes in ClassDef1
+ table */
+ FT_UShort Class2Count; /* number of classes in ClassDef2
+ table */
+ HB_Class1Record* Class1Record; /* array of Class1Record tables */
+};
+
+typedef struct HB_PairPosFormat2_ HB_PairPosFormat2;
+
+
+struct HB_PairPos_
+{
+ FT_UShort PosFormat; /* 1 or 2 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort ValueFormat1; /* format of ValueRecord table
+ for first glyph */
+ FT_UShort ValueFormat2; /* format of ValueRecord table
+ for second glyph */
+
+ union
+ {
+ HB_PairPosFormat1 ppf1;
+ HB_PairPosFormat2 ppf2;
+ } ppf;
+};
+
+typedef struct HB_PairPos_ HB_PairPos;
+
+
+/* LookupType 3 */
+
+struct HB_EntryExitRecord_
+{
+ HB_Anchor EntryAnchor; /* entry Anchor table */
+ HB_Anchor ExitAnchor; /* exit Anchor table */
+};
+
+
+typedef struct HB_EntryExitRecord_ HB_EntryExitRecord;
+
+struct HB_CursivePos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort EntryExitCount;
+ /* number of EntryExitRecord tables */
+ HB_EntryExitRecord* EntryExitRecord;
+ /* array of EntryExitRecord tables */
+};
+
+typedef struct HB_CursivePos_ HB_CursivePos;
+
+
+/* LookupType 4 */
+
+struct HB_BaseRecord_
+{
+ HB_Anchor* BaseAnchor; /* array of base glyph anchor
+ tables */
+};
+
+typedef struct HB_BaseRecord_ HB_BaseRecord;
+
+
+struct HB_BaseArray_
+{
+ FT_UShort BaseCount; /* number of BaseRecord tables */
+ HB_BaseRecord* BaseRecord; /* array of BaseRecord tables */
+};
+
+typedef struct HB_BaseArray_ HB_BaseArray;
+
+
+struct HB_MarkBasePos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage MarkCoverage; /* mark glyph coverage table */
+ HB_Coverage BaseCoverage; /* base glyph coverage table */
+ FT_UShort ClassCount; /* number of mark classes */
+ HB_MarkArray MarkArray; /* mark array table */
+ HB_BaseArray BaseArray; /* base array table */
+};
+
+typedef struct HB_MarkBasePos_ HB_MarkBasePos;
+
+
+/* LookupType 5 */
+
+struct HB_ComponentRecord_
+{
+ HB_Anchor* LigatureAnchor; /* array of ligature glyph anchor
+ tables */
+};
+
+typedef struct HB_ComponentRecord_ HB_ComponentRecord;
+
+
+struct HB_LigatureAttach_
+{
+ FT_UShort ComponentCount;
+ /* number of ComponentRecord tables */
+ HB_ComponentRecord* ComponentRecord;
+ /* array of ComponentRecord tables */
+};
+
+typedef struct HB_LigatureAttach_ HB_LigatureAttach;
+
+
+struct HB_LigatureArray_
+{
+ FT_UShort LigatureCount; /* number of LigatureAttach tables */
+ HB_LigatureAttach* LigatureAttach;
+ /* array of LigatureAttach tables */
+};
+
+typedef struct HB_LigatureArray_ HB_LigatureArray;
+
+
+struct HB_MarkLigPos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage MarkCoverage; /* mark glyph coverage table */
+ HB_Coverage LigatureCoverage;
+ /* ligature glyph coverage table */
+ FT_UShort ClassCount; /* number of mark classes */
+ HB_MarkArray MarkArray; /* mark array table */
+ HB_LigatureArray LigatureArray; /* ligature array table */
+};
+
+typedef struct HB_MarkLigPos_ HB_MarkLigPos;
+
+
+/* LookupType 6 */
+
+struct HB_Mark2Record_
+{
+ HB_Anchor* Mark2Anchor; /* array of mark glyph anchor
+ tables */
+};
+
+typedef struct HB_Mark2Record_ HB_Mark2Record;
+
+
+struct HB_Mark2Array_
+{
+ FT_UShort Mark2Count; /* number of Mark2Record tables */
+ HB_Mark2Record* Mark2Record; /* array of Mark2Record tables */
+};
+
+typedef struct HB_Mark2Array_ HB_Mark2Array;
+
+
+struct HB_MarkMarkPos_
+{
+ FT_UShort PosFormat; /* always 1 */
+ HB_Coverage Mark1Coverage; /* first mark glyph coverage table */
+ HB_Coverage Mark2Coverage; /* second mark glyph coverave table */
+ FT_UShort ClassCount; /* number of combining mark classes */
+ HB_MarkArray Mark1Array; /* MarkArray table for first mark */
+ HB_Mark2Array Mark2Array; /* MarkArray table for second mark */
+};
+
+typedef struct HB_MarkMarkPos_ HB_MarkMarkPos;
+
+
+/* needed by both lookup type 7 and 8 */
+
+struct HB_PosLookupRecord_
+{
+ FT_UShort SequenceIndex; /* index into current
+ glyph sequence */
+ FT_UShort LookupListIndex; /* Lookup to apply to that pos. */
+};
+
+typedef struct HB_PosLookupRecord_ HB_PosLookupRecord;
+
+
+/* LookupType 7 */
+
+struct HB_PosRule_
+{
+ FT_UShort GlyphCount; /* total number of input glyphs */
+ FT_UShort PosCount; /* number of PosLookupRecord tables */
+ FT_UShort* Input; /* array of input glyph IDs */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecord tables */
+};
+
+typedef struct HB_PosRule_ HB_PosRule;
+
+
+struct HB_PosRuleSet_
+{
+ FT_UShort PosRuleCount; /* number of PosRule tables */
+ HB_PosRule* PosRule; /* array of PosRule tables */
+};
+
+typedef struct HB_PosRuleSet_ HB_PosRuleSet;
+
+
+struct HB_ContextPosFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort PosRuleSetCount; /* number of PosRuleSet tables */
+ HB_PosRuleSet* PosRuleSet; /* array of PosRuleSet tables */
+};
+
+typedef struct HB_ContextPosFormat1_ HB_ContextPosFormat1;
+
+
+struct HB_PosClassRule_
+{
+ FT_UShort GlyphCount; /* total number of context classes */
+ FT_UShort PosCount; /* number of PosLookupRecord tables */
+ FT_UShort* Class; /* array of classes */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecord tables */
+};
+
+typedef struct HB_PosClassRule_ HB_PosClassRule;
+
+
+struct HB_PosClassSet_
+{
+ FT_UShort PosClassRuleCount;
+ /* number of PosClassRule tables */
+ HB_PosClassRule* PosClassRule; /* array of PosClassRule tables */
+};
+
+typedef struct HB_PosClassSet_ HB_PosClassSet;
+
+
+/* The `MaxContextLength' field is not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the context rules. */
+
+struct HB_ContextPosFormat2_
+{
+ FT_UShort MaxContextLength;
+ /* maximal context length */
+ HB_Coverage Coverage; /* Coverage table */
+ HB_ClassDefinition ClassDef; /* ClassDef table */
+ FT_UShort PosClassSetCount;
+ /* number of PosClassSet tables */
+ HB_PosClassSet* PosClassSet; /* array of PosClassSet tables */
+};
+
+typedef struct HB_ContextPosFormat2_ HB_ContextPosFormat2;
+
+
+struct HB_ContextPosFormat3_
+{
+ FT_UShort GlyphCount; /* number of input glyphs */
+ FT_UShort PosCount; /* number of PosLookupRecord tables */
+ HB_Coverage* Coverage; /* array of Coverage tables */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecord tables */
+};
+
+typedef struct HB_ContextPosFormat3_ HB_ContextPosFormat3;
+
+
+struct HB_ContextPos_
+{
+ FT_UShort PosFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ContextPosFormat1 cpf1;
+ HB_ContextPosFormat2 cpf2;
+ HB_ContextPosFormat3 cpf3;
+ } cpf;
+};
+
+typedef struct HB_ContextPos_ HB_ContextPos;
+
+
+/* LookupType 8 */
+
+struct HB_ChainPosRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack glyphs */
+ FT_UShort* Backtrack; /* array of backtrack glyph IDs */
+ FT_UShort InputGlyphCount;
+ /* total number of input glyphs */
+ FT_UShort* Input; /* array of input glyph IDs */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead glyphs */
+ FT_UShort* Lookahead; /* array of lookahead glyph IDs */
+ FT_UShort PosCount; /* number of PosLookupRecords */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of PosLookupRecords */
+};
+
+typedef struct HB_ChainPosRule_ HB_ChainPosRule;
+
+
+struct HB_ChainPosRuleSet_
+{
+ FT_UShort ChainPosRuleCount;
+ /* number of ChainPosRule tables */
+ HB_ChainPosRule* ChainPosRule; /* array of ChainPosRule tables */
+};
+
+typedef struct HB_ChainPosRuleSet_ HB_ChainPosRuleSet;
+
+
+struct HB_ChainContextPosFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort ChainPosRuleSetCount;
+ /* number of ChainPosRuleSet tables */
+ HB_ChainPosRuleSet* ChainPosRuleSet;
+ /* array of ChainPosRuleSet tables */
+};
+
+typedef struct HB_ChainContextPosFormat1_ HB_ChainContextPosFormat1;
+
+
+struct HB_ChainPosClassRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack
+ classes */
+ FT_UShort* Backtrack; /* array of backtrack classes */
+ FT_UShort InputGlyphCount;
+ /* total number of context classes */
+ FT_UShort* Input; /* array of context classes */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead
+ classes */
+ FT_UShort* Lookahead; /* array of lookahead classes */
+ FT_UShort PosCount; /* number of PosLookupRecords */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainPosClassRule_ HB_ChainPosClassRule;
+
+
+struct HB_ChainPosClassSet_
+{
+ FT_UShort ChainPosClassRuleCount;
+ /* number of ChainPosClassRule
+ tables */
+ HB_ChainPosClassRule* ChainPosClassRule;
+ /* array of ChainPosClassRule
+ tables */
+};
+
+typedef struct HB_ChainPosClassSet_ HB_ChainPosClassSet;
+
+
+/* The `MaxXXXLength' fields are not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the specific context rules. */
+
+struct HB_ChainContextPosFormat2_
+{
+ HB_Coverage Coverage; /* Coverage table */
+
+ FT_UShort MaxBacktrackLength;
+ /* maximal backtrack length */
+ HB_ClassDefinition BacktrackClassDef;
+ /* BacktrackClassDef table */
+ FT_UShort MaxInputLength;
+ /* maximal input length */
+ HB_ClassDefinition InputClassDef;
+ /* InputClassDef table */
+ FT_UShort MaxLookaheadLength;
+ /* maximal lookahead length */
+ HB_ClassDefinition LookaheadClassDef;
+ /* LookaheadClassDef table */
+
+ FT_UShort ChainPosClassSetCount;
+ /* number of ChainPosClassSet
+ tables */
+ HB_ChainPosClassSet* ChainPosClassSet;
+ /* array of ChainPosClassSet
+ tables */
+};
+
+typedef struct HB_ChainContextPosFormat2_ HB_ChainContextPosFormat2;
+
+
+struct HB_ChainContextPosFormat3_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* number of backtrack glyphs */
+ HB_Coverage* BacktrackCoverage;
+ /* array of backtrack Coverage
+ tables */
+ FT_UShort InputGlyphCount;
+ /* number of input glyphs */
+ HB_Coverage* InputCoverage;
+ /* array of input coverage
+ tables */
+ FT_UShort LookaheadGlyphCount;
+ /* number of lookahead glyphs */
+ HB_Coverage* LookaheadCoverage;
+ /* array of lookahead coverage
+ tables */
+ FT_UShort PosCount; /* number of PosLookupRecords */
+ HB_PosLookupRecord* PosLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainContextPosFormat3_ HB_ChainContextPosFormat3;
+
+
+struct HB_ChainContextPos_
+{
+ FT_UShort PosFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ChainContextPosFormat1 ccpf1;
+ HB_ChainContextPosFormat2 ccpf2;
+ HB_ChainContextPosFormat3 ccpf3;
+ } ccpf;
+};
+
+typedef struct HB_ChainContextPos_ HB_ChainContextPos;
+
+
+union HB_GPOS_SubTable_
+{
+ HB_SinglePos single;
+ HB_PairPos pair;
+ HB_CursivePos cursive;
+ HB_MarkBasePos markbase;
+ HB_MarkLigPos marklig;
+ HB_MarkMarkPos markmark;
+ HB_ContextPos context;
+ HB_ChainContextPos chain;
+};
+
+typedef union HB_GPOS_SubTable_ HB_GPOS_SubTable;
+
+
+
+FT_Error _HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type );
+
+void _HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GPOS_PRIVATE_H */
diff --git a/pango/opentype/harfbuzz-gpos.c b/pango/opentype/harfbuzz-gpos.c
new file mode 100644
index 00000000..8143eace
--- /dev/null
+++ b/pango/opentype/harfbuzz-gpos.c
@@ -0,0 +1,6269 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-gpos-private.h"
+#include "harfbuzz-open-private.h"
+#include "harfbuzz-gdef-private.h"
+
+#include FT_TRUETYPE_TAGS_H
+
+
+struct GPOS_Instance_
+{
+ HB_GPOSHeader* gpos;
+ FT_Face face;
+ FT_Bool dvi;
+ FT_UShort load_flags; /* how the glyph should be loaded */
+ FT_Bool r2l;
+
+ FT_UShort last; /* the last valid glyph -- used
+ with cursive positioning */
+ FT_Pos anchor_x; /* the coordinates of the anchor point */
+ FT_Pos anchor_y; /* of the last valid glyph */
+};
+
+typedef struct GPOS_Instance_ GPOS_Instance;
+
+
+static FT_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level );
+
+
+
+/* the client application must replace this with something more
+ meaningful if multiple master fonts are to be supported. */
+
+static FT_Error default_mmfunc( FT_Face face,
+ FT_UShort metric_id,
+ FT_Pos* metric_value,
+ void* data )
+{
+ return HB_Err_No_MM_Interpreter;
+}
+
+
+
+FT_Error HB_Load_GPOS_Table( FT_Face face,
+ HB_GPOSHeader** retptr,
+ HB_GDEFHeader* gdef )
+{
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ FT_UShort i, num_lookups;
+ HB_GPOSHeader* gpos;
+ HB_Lookup* lo;
+
+ FT_Stream stream = face->stream;
+ FT_Error error;
+ FT_Memory memory = face->memory;
+
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if ( !stream )
+ return FT_Err_Invalid_Face_Handle;
+
+ if (( error = _hb_ftglue_face_goto_table( face, TTAG_GPOS, stream ) ))
+ return error;
+
+ base_offset = FILE_Pos();
+
+ if ( ALLOC ( gpos, sizeof( *gpos ) ) )
+ return error;
+
+ gpos->memory = memory;
+ gpos->gfunc = FT_Load_Glyph;
+ gpos->mmfunc = default_mmfunc;
+
+ /* skip version */
+
+ if ( FILE_Seek( base_offset + 4L ) ||
+ ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_FeatureList( &gpos->FeatureList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_LookupList( &gpos->LookupList,
+ stream, HB_Type_GPOS ) ) != FT_Err_Ok )
+ goto Fail2;
+
+ gpos->gdef = gdef; /* can be NULL */
+
+ /* We now check the LookupFlags for values larger than 0xFF to find
+ out whether we need to load the `MarkAttachClassDef' field of the
+ GDEF table -- this hack is necessary for OpenType 1.2 tables since
+ the version field of the GDEF table hasn't been incremented.
+
+ For constructed GDEF tables, we only load it if
+ `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
+ a constructed mark attach table is not supported currently). */
+
+ if ( gdef &&
+ gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
+ {
+ lo = gpos->LookupList.Lookup;
+ num_lookups = gpos->LookupList.LookupCount;
+
+ for ( i = 0; i < num_lookups; i++ )
+ {
+ if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ {
+ if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
+ 256, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ break;
+ }
+ }
+ }
+
+ *retptr = gpos;
+
+ return FT_Err_Ok;
+
+Fail1:
+ _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS, memory );
+
+Fail2:
+ _HB_OPEN_Free_FeatureList( &gpos->FeatureList, memory );
+
+Fail3:
+ _HB_OPEN_Free_ScriptList( &gpos->ScriptList, memory );
+
+Fail4:
+ FREE( gpos );
+
+ return error;
+}
+
+
+FT_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
+{
+ FT_Memory memory = gpos->memory;
+
+ _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS, memory );
+ _HB_OPEN_Free_FeatureList( &gpos->FeatureList, memory );
+ _HB_OPEN_Free_ScriptList( &gpos->ScriptList, memory );
+
+ return FT_Err_Ok;
+}
+
+
+/*****************************
+ * SubTable related functions
+ *****************************/
+
+/* shared tables */
+
+/* ValueRecord */
+
+/* There is a subtle difference in the specs between a `table' and a
+ `record' -- offsets for device tables in ValueRecords are taken from
+ the parent table and not the parent record. */
+
+static FT_Error Load_ValueRecord( HB_ValueRecord* vr,
+ FT_UShort format,
+ FT_ULong base_offset,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong cur_offset, new_offset;
+
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->XPlacement = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->YPlacement = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->XAdvance = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XAdvance = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ vr->YAdvance = GET_Short();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YAdvance = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty1;
+ }
+ else
+ {
+ empty1:
+ vr->XPlacementDevice.StartSize = 0;
+ vr->XPlacementDevice.EndSize = 0;
+ vr->XPlacementDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty2;
+ }
+ else
+ {
+ empty2:
+ vr->YPlacementDevice.StartSize = 0;
+ vr->YPlacementDevice.EndSize = 0;
+ vr->YPlacementDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,
+ stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty3;
+ }
+ else
+ {
+ empty3:
+ vr->XAdvanceDevice.StartSize = 0;
+ vr->XAdvanceDevice.EndSize = 0;
+ vr->XAdvanceDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ goto empty4;
+ }
+ else
+ {
+ empty4:
+ vr->YAdvanceDevice.StartSize = 0;
+ vr->YAdvanceDevice.EndSize = 0;
+ vr->YAdvanceDevice.DeltaValue = NULL;
+ }
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->XIdPlacement = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XIdPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->YIdPlacement = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YIdPlacement = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->XIdAdvance = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->XIdAdvance = 0;
+
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ vr->YIdAdvance = GET_UShort();
+
+ FORGET_Frame();
+ }
+ else
+ vr->YIdAdvance = 0;
+
+ return FT_Err_Ok;
+
+Fail1:
+ _HB_OPEN_Free_Device( &vr->YAdvanceDevice, memory );
+
+Fail2:
+ _HB_OPEN_Free_Device( &vr->XAdvanceDevice, memory );
+
+Fail3:
+ _HB_OPEN_Free_Device( &vr->YPlacementDevice, memory );
+ return error;
+}
+
+
+static void Free_ValueRecord( HB_ValueRecord* vr,
+ FT_UShort format,
+ FT_Memory memory )
+{
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
+ _HB_OPEN_Free_Device( &vr->YAdvanceDevice, memory );
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
+ _HB_OPEN_Free_Device( &vr->XAdvanceDevice, memory );
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
+ _HB_OPEN_Free_Device( &vr->YPlacementDevice, memory );
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
+ _HB_OPEN_Free_Device( &vr->XPlacementDevice, memory );
+}
+
+
+static FT_Error Get_ValueRecord( GPOS_Instance* gpi,
+ HB_ValueRecord* vr,
+ FT_UShort format,
+ HB_Position gd )
+{
+ FT_Pos value;
+ FT_Short pixel_value;
+ FT_Error error = FT_Err_Ok;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ FT_UShort x_ppem, y_ppem;
+ FT_Fixed x_scale, y_scale;
+
+
+ if ( !format )
+ return FT_Err_Ok;
+
+ x_ppem = gpi->face->size->metrics.x_ppem;
+ y_ppem = gpi->face->size->metrics.y_ppem;
+ x_scale = gpi->face->size->metrics.x_scale;
+ y_scale = gpi->face->size->metrics.y_scale;
+
+ /* design units -> fractional pixel */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
+ gd->x_pos += x_scale * vr->XPlacement / 0x10000;
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
+ gd->y_pos += y_scale * vr->YPlacement / 0x10000;
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
+ gd->x_advance += x_scale * vr->XAdvance / 0x10000;
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
+ gd->y_advance += y_scale * vr->YAdvance / 0x10000;
+
+ if ( !gpi->dvi )
+ {
+ /* pixel -> fractional pixel */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );
+ gd->x_pos += pixel_value << 6;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );
+ gd->y_pos += pixel_value << 6;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );
+ gd->x_advance += pixel_value << 6;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
+ {
+ _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );
+ gd->y_advance += pixel_value << 6;
+ }
+ }
+
+ /* values returned from mmfunc() are already in fractional pixels */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->XIdPlacement,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->x_pos += value;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->YIdPlacement,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->y_pos += value;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->XIdAdvance,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->x_advance += value;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
+ {
+ error = (gpos->mmfunc)( gpi->face, vr->YIdAdvance,
+ &value, gpos->data );
+ if ( error )
+ return error;
+ gd->y_advance += value;
+ }
+
+ return error;
+}
+
+
+/* AnchorFormat1 */
+/* AnchorFormat2 */
+/* AnchorFormat3 */
+/* AnchorFormat4 */
+
+static FT_Error Load_Anchor( HB_Anchor* an,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ an->PosFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( an->PosFormat )
+ {
+ case 1:
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ an->af.af1.XCoordinate = GET_Short();
+ an->af.af1.YCoordinate = GET_Short();
+
+ FORGET_Frame();
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ an->af.af2.XCoordinate = GET_Short();
+ an->af.af2.YCoordinate = GET_Short();
+ an->af.af2.AnchorPoint = GET_UShort();
+
+ FORGET_Frame();
+ break;
+
+ case 3:
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ an->af.af3.XCoordinate = GET_Short();
+ an->af.af3.YCoordinate = GET_Short();
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ an->af.af3.XDeviceTable.StartSize = 0;
+ an->af.af3.XDeviceTable.EndSize = 0;
+ an->af.af3.XDeviceTable.DeltaValue = NULL;
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable,
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ an->af.af3.YDeviceTable.StartSize = 0;
+ an->af.af3.YDeviceTable.EndSize = 0;
+ an->af.af3.YDeviceTable.DeltaValue = NULL;
+ }
+ break;
+
+ case 4:
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ an->af.af4.XIdAnchor = GET_UShort();
+ an->af.af4.YIdAnchor = GET_UShort();
+
+ FORGET_Frame();
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable, memory );
+ return error;
+}
+
+
+static void Free_Anchor( HB_Anchor* an,
+ FT_Memory memory)
+{
+ if ( an->PosFormat == 3 )
+ {
+ _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable, memory );
+ _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable, memory );
+ }
+}
+
+
+static FT_Error Get_Anchor( GPOS_Instance* gpi,
+ HB_Anchor* an,
+ FT_UShort glyph_index,
+ FT_Pos* x_value,
+ FT_Pos* y_value )
+{
+ FT_Error error = FT_Err_Ok;
+
+ FT_Outline outline;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ FT_UShort ap;
+
+ FT_Short pixel_value;
+ FT_UShort load_flags;
+
+ FT_UShort x_ppem, y_ppem;
+ FT_Fixed x_scale, y_scale;
+
+
+ x_ppem = gpi->face->size->metrics.x_ppem;
+ y_ppem = gpi->face->size->metrics.y_ppem;
+ x_scale = gpi->face->size->metrics.x_scale;
+ y_scale = gpi->face->size->metrics.y_scale;
+
+ switch ( an->PosFormat )
+ {
+ case 0:
+ /* The special case of an empty AnchorTable */
+
+ return HB_Err_Not_Covered;
+
+ case 1:
+ *x_value = x_scale * an->af.af1.XCoordinate / 0x10000;
+ *y_value = y_scale * an->af.af1.YCoordinate / 0x10000;
+ break;
+
+ case 2:
+ /* glyphs must be scaled */
+
+ load_flags = gpi->load_flags & ~FT_LOAD_NO_SCALE;
+
+ if ( !gpi->dvi )
+ {
+ error = (gpos->gfunc)( gpi->face, glyph_index, load_flags );
+ if ( error )
+ return error;
+
+ if ( gpi->face->glyph->format != ft_glyph_format_outline )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ ap = an->af.af2.AnchorPoint;
+
+ outline = gpi->face->glyph->outline;
+
+ /* if outline.n_points is set to zero by gfunc(), we use the
+ design coordinate value pair. This can happen e.g. for
+ sbit glyphs */
+
+ if ( !outline.n_points )
+ goto no_contour_point;
+
+ if ( ap >= outline.n_points )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ *x_value = outline.points[ap].x;
+ *y_value = outline.points[ap].y;
+ }
+ else
+ {
+ no_contour_point:
+ *x_value = x_scale * an->af.af3.XCoordinate / 0x10000;
+ *y_value = y_scale * an->af.af3.YCoordinate / 0x10000;
+ }
+ break;
+
+ case 3:
+ if ( !gpi->dvi )
+ {
+ _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );
+ *x_value = pixel_value << 6;
+ _HB_OPEN_Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value );
+ *y_value = pixel_value << 6;
+ }
+ else
+ *x_value = *y_value = 0;
+
+ *x_value += x_scale * an->af.af3.XCoordinate / 0x10000;
+ *y_value += y_scale * an->af.af3.YCoordinate / 0x10000;
+ break;
+
+ case 4:
+ error = (gpos->mmfunc)( gpi->face, an->af.af4.XIdAnchor,
+ x_value, gpos->data );
+ if ( error )
+ return error;
+
+ error = (gpos->mmfunc)( gpi->face, an->af.af4.YIdAnchor,
+ y_value, gpos->data );
+ if ( error )
+ return error;
+ break;
+ }
+
+ return error;
+}
+
+
+/* MarkArray */
+
+static FT_Error Load_MarkArray ( HB_MarkArray* ma,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_MarkRecord* mr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ma->MarkCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ma->MarkRecord = NULL;
+
+ if ( ALLOC_ARRAY( ma->MarkRecord, count, HB_MarkRecord ) )
+ return error;
+
+ mr = ma->MarkRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail;
+
+ mr[n].Class = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_Anchor( &mr[m].MarkAnchor, memory );
+
+ FREE( mr );
+ return error;
+}
+
+
+static void Free_MarkArray( HB_MarkArray* ma,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_MarkRecord* mr;
+
+
+ if ( ma->MarkRecord )
+ {
+ count = ma->MarkCount;
+ mr = ma->MarkRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_Anchor( &mr[n].MarkAnchor, memory );
+
+ FREE( mr );
+ }
+}
+
+
+/* LookupType 1 */
+
+/* SinglePosFormat1 */
+/* SinglePosFormat2 */
+
+static FT_Error Load_SinglePos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_SinglePos* sp = &st->single;
+
+ FT_UShort n, m, count, format;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ValueRecord* vr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ sp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ format = sp->ValueFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( !format )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ switch ( sp->PosFormat )
+ {
+ case 1:
+ error = Load_ValueRecord( &sp->spf.spf1.Value, format,
+ base_offset, stream );
+ if ( error )
+ goto Fail2;
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = sp->spf.spf2.ValueCount = GET_UShort();
+
+ FORGET_Frame();
+
+ sp->spf.spf2.Value = NULL;
+
+ if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, HB_ValueRecord ) )
+ goto Fail2;
+
+ vr = sp->spf.spf2.Value;
+
+ for ( n = 0; n < count; n++ )
+ {
+ error = Load_ValueRecord( &vr[n], format, base_offset, stream );
+ if ( error )
+ goto Fail1;
+ }
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ValueRecord( &vr[m], format, memory );
+
+ FREE( vr );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &sp->Coverage, memory );
+ return error;
+}
+
+
+static void Free_SinglePos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count, format;
+ HB_SinglePos* sp = &st->single;
+
+ HB_ValueRecord* v;
+
+
+ format = sp->ValueFormat;
+
+ switch ( sp->PosFormat )
+ {
+ case 1:
+ Free_ValueRecord( &sp->spf.spf1.Value, format, memory );
+ break;
+
+ case 2:
+ if ( sp->spf.spf2.Value )
+ {
+ count = sp->spf.spf2.ValueCount;
+ v = sp->spf.spf2.Value;
+
+ for ( n = 0; n < count; n++ )
+ Free_ValueRecord( &v[n], format, memory );
+
+ FREE( v );
+ }
+ break;
+ }
+
+ _HB_OPEN_Free_Coverage( &sp->Coverage, memory );
+}
+
+static FT_Error Lookup_DefaultPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ return HB_Err_Not_Covered;
+}
+
+static FT_Error Lookup_SinglePos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_SinglePos* sp = &st->single;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ switch ( sp->PosFormat )
+ {
+ case 1:
+ error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
+ if ( error )
+ return error;
+ break;
+
+ case 2:
+ if ( index >= sp->spf.spf2.ValueCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+ error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
+ sp->ValueFormat, POSITION( buffer->in_pos ) );
+ if ( error )
+ return error;
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable;
+ }
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 2 */
+
+/* PairSet */
+
+static FT_Error Load_PairSet ( HB_PairSet* ps,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong base_offset;
+
+ HB_PairValueRecord* pvr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ps->PairValueCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ps->PairValueRecord = NULL;
+
+ if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) )
+ return error;
+
+ pvr = ps->PairValueRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ pvr[n].SecondGlyph = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( format1 )
+ {
+ error = Load_ValueRecord( &pvr[n].Value1, format1,
+ base_offset, stream );
+ if ( error )
+ goto Fail;
+ }
+ if ( format2 )
+ {
+ error = Load_ValueRecord( &pvr[n].Value2, format2,
+ base_offset, stream );
+ if ( error )
+ {
+ if ( format1 )
+ Free_ValueRecord( &pvr[n].Value1, format1, memory );
+ goto Fail;
+ }
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &pvr[m].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &pvr[m].Value2, format2, memory );
+ }
+
+ FREE( pvr );
+ return error;
+}
+
+
+static void Free_PairSet( HB_PairSet* ps,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PairValueRecord* pvr;
+
+
+ if ( ps->PairValueRecord )
+ {
+ count = ps->PairValueCount;
+ pvr = ps->PairValueRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &pvr[n].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &pvr[n].Value2, format2, memory );
+ }
+
+ FREE( pvr );
+ }
+}
+
+
+/* PairPosFormat1 */
+
+static FT_Error Load_PairPos1( HB_PairPosFormat1* ppf1,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PairSet* ps;
+
+
+ base_offset = FILE_Pos() - 8L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ppf1->PairSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ppf1->PairSet = NULL;
+
+ if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) )
+ return error;
+
+ ps = ppf1->PairSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PairSet( &ps[n], format1,
+ format2, stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_PairSet( &ps[m], format1, format2, memory );
+
+ FREE( ps );
+ return error;
+}
+
+
+static void Free_PairPos1( HB_PairPosFormat1* ppf1,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PairSet* ps;
+
+
+ if ( ppf1->PairSet )
+ {
+ count = ppf1->PairSetCount;
+ ps = ppf1->PairSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_PairSet( &ps[n], format1, format2, memory );
+
+ FREE( ps );
+ }
+}
+
+
+/* PairPosFormat2 */
+
+static FT_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort m, n, k, count1, count2;
+ FT_ULong cur_offset, new_offset1, new_offset2, base_offset;
+
+ HB_Class1Record* c1r;
+ HB_Class2Record* c2r;
+
+
+ base_offset = FILE_Pos() - 8L;
+
+ if ( ACCESS_Frame( 8L ) )
+ return error;
+
+ new_offset1 = GET_UShort() + base_offset;
+ new_offset2 = GET_UShort() + base_offset;
+
+ /* `Class1Count' and `Class2Count' are the upper limits for class
+ values, thus we read it now to make additional safety checks. */
+
+ count1 = ppf2->Class1Count = GET_UShort();
+ count2 = ppf2->Class2Count = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset1 ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ if ( FILE_Seek( new_offset2 ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ ppf2->Class1Record = NULL;
+
+ if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) )
+ goto Fail2;
+
+ c1r = ppf2->Class1Record;
+
+ for ( m = 0; m < count1; m++ )
+ {
+ c1r[m].Class2Record = NULL;
+
+ if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
+ goto Fail1;
+
+ c2r = c1r[m].Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value1, format1,
+ base_offset, stream );
+ if ( error )
+ goto Fail0;
+ }
+ if ( format2 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value2, format2,
+ base_offset, stream );
+ if ( error )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1, memory );
+ goto Fail0;
+ }
+ }
+ }
+
+ continue;
+
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[k].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &c2r[k].Value2, format2, memory );
+ }
+ goto Fail1;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( k = 0; k < m; k++ )
+ {
+ c2r = c1r[k].Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2, memory );
+ }
+
+ FREE( c2r );
+ }
+
+ FREE( c1r );
+Fail2:
+
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory );
+
+Fail3:
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory );
+ return error;
+}
+
+
+static void Free_PairPos2( HB_PairPosFormat2* ppf2,
+ FT_UShort format1,
+ FT_UShort format2,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count1, count2;
+
+ HB_Class1Record* c1r;
+ HB_Class2Record* c2r;
+
+
+ if ( ppf2->Class1Record )
+ {
+ c1r = ppf2->Class1Record;
+ count1 = ppf2->Class1Count;
+ count2 = ppf2->Class2Count;
+
+ for ( m = 0; m < count1; m++ )
+ {
+ c2r = c1r[m].Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1, memory );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2, memory );
+ }
+
+ FREE( c2r );
+ }
+
+ FREE( c1r );
+
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory );
+ _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory );
+ }
+}
+
+
+static FT_Error Load_PairPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_PairPos* pp = &st->pair;
+
+ FT_UShort format1, format2;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 8L ) )
+ return error;
+
+ pp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ format1 = pp->ValueFormat1 = GET_UShort();
+ format2 = pp->ValueFormat2 = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ switch ( pp->PosFormat )
+ {
+ case 1:
+ error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );
+ if ( error )
+ goto Fail;
+ break;
+
+ case 2:
+ error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );
+ if ( error )
+ goto Fail;
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ _HB_OPEN_Free_Coverage( &pp->Coverage, memory );
+ return error;
+}
+
+
+static void Free_PairPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort format1, format2;
+ HB_PairPos* pp = &st->pair;
+
+
+ format1 = pp->ValueFormat1;
+ format2 = pp->ValueFormat2;
+
+ switch ( pp->PosFormat )
+ {
+ case 1:
+ Free_PairPos1( &pp->ppf.ppf1, format1, format2, memory );
+ break;
+
+ case 2:
+ Free_PairPos2( &pp->ppf.ppf2, format1, format2, memory );
+ break;
+ }
+
+ _HB_OPEN_Free_Coverage( &pp->Coverage, memory );
+}
+
+
+static FT_Error Lookup_PairPos1( GPOS_Instance* gpi,
+ HB_PairPosFormat1* ppf1,
+ HB_Buffer buffer,
+ FT_UShort first_pos,
+ FT_UShort index,
+ FT_UShort format1,
+ FT_UShort format2 )
+{
+ FT_Error error;
+ FT_UShort numpvr, glyph2;
+
+ HB_PairValueRecord* pvr;
+
+
+ if ( index >= ppf1->PairSetCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ pvr = ppf1->PairSet[index].PairValueRecord;
+ if ( !pvr )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ glyph2 = IN_CURGLYPH();
+
+ for ( numpvr = ppf1->PairSet[index].PairValueCount;
+ numpvr;
+ numpvr--, pvr++ )
+ {
+ if ( glyph2 == pvr->SecondGlyph )
+ {
+ error = Get_ValueRecord( gpi, &pvr->Value1, format1,
+ POSITION( first_pos ) );
+ if ( error )
+ return error;
+ return Get_ValueRecord( gpi, &pvr->Value2, format2,
+ POSITION( buffer->in_pos ) );
+ }
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_PairPos2( GPOS_Instance* gpi,
+ HB_PairPosFormat2* ppf2,
+ HB_Buffer buffer,
+ FT_UShort first_pos,
+ FT_UShort format1,
+ FT_UShort format2 )
+{
+ FT_Error error;
+ FT_UShort cl1, cl2;
+
+ HB_Class1Record* c1r;
+ HB_Class2Record* c2r;
+
+
+ error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
+ &cl1, NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),
+ &cl2, NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ c1r = &ppf2->Class1Record[cl1];
+ if ( !c1r )
+ return HB_Err_Invalid_GPOS_SubTable;
+ c2r = &c1r->Class2Record[cl2];
+
+ error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
+ if ( error )
+ return error;
+ return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
+}
+
+
+static FT_Error Lookup_PairPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, property, first_pos;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_PairPos* pp = &st->pair;
+
+
+ if ( buffer->in_pos >= buffer->in_length - 1 )
+ return HB_Err_Not_Covered; /* Not enough glyphs in stream */
+
+ if ( context_length != 0xFFFF && context_length < 2 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ /* second glyph */
+
+ first_pos = buffer->in_pos;
+ (buffer->in_pos)++;
+
+ while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( buffer->in_pos == buffer->in_length )
+ return HB_Err_Not_Covered;
+ (buffer->in_pos)++;
+ }
+
+ switch ( pp->PosFormat )
+ {
+ case 1:
+ error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
+ first_pos, index,
+ pp->ValueFormat1, pp->ValueFormat2 );
+ break;
+
+ case 2:
+ error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
+ pp->ValueFormat1, pp->ValueFormat2 );
+ break;
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ /* adjusting the `next' glyph */
+
+ if ( pp->ValueFormat2 )
+ (buffer->in_pos)++;
+
+ return error;
+}
+
+
+/* LookupType 3 */
+
+/* CursivePosFormat1 */
+
+static FT_Error Load_CursivePos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_CursivePos* cp = &st->cursive;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_EntryExitRecord* eer;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = cp->EntryExitCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cp->EntryExitRecord = NULL;
+
+ if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) )
+ goto Fail2;
+
+ eer = cp->EntryExitRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ FT_ULong entry_offset;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ entry_offset = new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &eer[n].EntryAnchor,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ eer[n].EntryAnchor.PosFormat = 0;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &eer[n].ExitAnchor,
+ stream ) ) != FT_Err_Ok )
+ {
+ if ( entry_offset )
+ Free_Anchor( &eer[n].EntryAnchor, memory );
+ goto Fail1;
+ }
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ eer[n].ExitAnchor.PosFormat = 0;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ {
+ Free_Anchor( &eer[m].EntryAnchor, memory );
+ Free_Anchor( &eer[m].ExitAnchor, memory );
+ }
+
+ FREE( eer );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &cp->Coverage, memory );
+ return error;
+}
+
+
+static void Free_CursivePos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_CursivePos* cp = &st->cursive;
+
+ HB_EntryExitRecord* eer;
+
+
+ if ( cp->EntryExitRecord )
+ {
+ count = cp->EntryExitCount;
+ eer = cp->EntryExitRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ Free_Anchor( &eer[n].EntryAnchor, memory );
+ Free_Anchor( &eer[n].ExitAnchor, memory );
+ }
+
+ FREE( eer );
+ }
+
+ _HB_OPEN_Free_Coverage( &cp->Coverage, memory );
+}
+
+
+static FT_Error Lookup_CursivePos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_CursivePos* cp = &st->cursive;
+
+ HB_EntryExitRecord* eer;
+ FT_Pos entry_x, entry_y;
+ FT_Pos exit_x, exit_y;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ {
+ gpi->last = 0xFFFF;
+ return HB_Err_Not_Covered;
+ }
+
+ /* Glyphs not having the right GDEF properties will be ignored, i.e.,
+ gpi->last won't be reset (contrary to user defined properties). */
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* We don't handle mark glyphs here. According to Andrei, this isn't
+ possible, but who knows... */
+
+ if ( property == HB_GDEF_MARK )
+ {
+ gpi->last = 0xFFFF;
+ return HB_Err_Not_Covered;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ {
+ gpi->last = 0xFFFF;
+ return error;
+ }
+
+ if ( index >= cp->EntryExitCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ eer = &cp->EntryExitRecord[index];
+
+ /* Now comes the messiest part of the whole OpenType
+ specification. At first glance, cursive connections seem easy
+ to understand, but there are pitfalls! The reason is that
+ the specs don't mention how to compute the advance values
+ resp. glyph offsets. I was told it would be an omission, to
+ be fixed in the next OpenType version... Again many thanks to
+ Andrei Burago <andreib@microsoft.com> for clarifications.
+
+ Consider the following example:
+
+ | xadv1 |
+ +---------+
+ | |
+ +-----+--+ 1 |
+ | | .| |
+ | 0+--+------+
+ | 2 |
+ | |
+ 0+--------+
+ | xadv2 |
+
+ glyph1: advance width = 12
+ anchor point = (3,1)
+
+ glyph2: advance width = 11
+ anchor point = (9,4)
+
+ LSB is 1 for both glyphs (so the boxes drawn above are glyph
+ bboxes). Writing direction is R2L; `0' denotes the glyph's
+ coordinate origin.
+
+ Now the surprising part: The advance width of the *left* glyph
+ (resp. of the *bottom* glyph) will be modified, no matter
+ whether the writing direction is L2R or R2L (resp. T2B or
+ B2T)! This assymetry is caused by the fact that the glyph's
+ coordinate origin is always the lower left corner for all
+ writing directions.
+
+ Continuing the above example, we can compute the new
+ (horizontal) advance width of glyph2 as
+
+ 9 - 3 = 6 ,
+
+ and the new vertical offset of glyph2 as
+
+ 1 - 4 = -3 .
+
+
+ Vertical writing direction is far more complicated:
+
+ a) Assuming that we recompute the advance height of the lower glyph:
+
+ --
+ +---------+
+ -- | |
+ +-----+--+ 1 | yadv1
+ | | .| |
+ yadv2 | 0+--+------+ -- BSB1 --
+ | 2 | -- -- y_offset
+ | |
+ BSB2 -- 0+--------+ --
+ -- --
+
+ glyph1: advance height = 6
+ anchor point = (3,1)
+
+ glyph2: advance height = 7
+ anchor point = (9,4)
+
+ TSB is 1 for both glyphs; writing direction is T2B.
+
+
+ BSB1 = yadv1 - (TSB1 + ymax1)
+ BSB2 = yadv2 - (TSB2 + ymax2)
+ y_offset = y2 - y1
+
+ vertical advance width of glyph2
+ = y_offset + BSB2 - BSB1
+ = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
+ = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
+ = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
+
+
+ b) Assuming that we recompute the advance height of the upper glyph:
+
+ -- --
+ +---------+ -- TSB1
+ -- -- | |
+ TSB2 -- +-----+--+ 1 | yadv1 ymax1
+ | | .| |
+ yadv2 | 0+--+------+ -- --
+ ymax2 | 2 | -- y_offset
+ | |
+ -- 0+--------+ --
+ --
+
+ glyph1: advance height = 6
+ anchor point = (3,1)
+
+ glyph2: advance height = 7
+ anchor point = (9,4)
+
+ TSB is 1 for both glyphs; writing direction is T2B.
+
+ y_offset = y2 - y1
+
+ vertical advance width of glyph2
+ = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
+ = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
+
+
+ Comparing a) with b) shows that b) is easier to compute. I'll wait
+ for a reply from Andrei to see what should really be implemented...
+
+ Since horizontal advance widths or vertical advance heights
+ can be used alone but not together, no ambiguity occurs. */
+
+ if ( gpi->last == 0xFFFF )
+ goto end;
+
+ /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor
+ table. */
+
+ error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),
+ &entry_x, &entry_y );
+ if ( error == HB_Err_Not_Covered )
+ goto end;
+ if ( error )
+ return error;
+
+ if ( gpi->r2l )
+ {
+ POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
+ POSITION( buffer->in_pos )->new_advance = TRUE;
+ }
+ else
+ {
+ POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
+ POSITION( gpi->last )->new_advance = TRUE;
+ }
+
+ if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )
+ {
+ POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
+ POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
+ }
+ else
+ {
+ POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
+ POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
+ }
+
+end:
+ error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),
+ &exit_x, &exit_y );
+ if ( error == HB_Err_Not_Covered )
+ gpi->last = 0xFFFF;
+ else
+ {
+ gpi->last = buffer->in_pos;
+ gpi->anchor_x = exit_x;
+ gpi->anchor_y = exit_y;
+ }
+ if ( error )
+ return error;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 4 */
+
+/* BaseArray */
+
+static FT_Error Load_BaseArray( HB_BaseArray* ba,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort m, n, k, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_BaseRecord* br;
+ HB_Anchor* ban;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ba->BaseCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ba->BaseRecord = NULL;
+
+ if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) )
+ return error;
+
+ br = ba->BaseRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ br[m].BaseAnchor = NULL;
+
+ if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, HB_Anchor ) )
+ goto Fail;
+
+ ban = br[m].BaseAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if (new_offset == base_offset) {
+ /* Doulos SIL Regular is buggy and has zer offsets here. Skip */
+ ban[n].PosFormat = 0;
+ continue;
+ }
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &ban[n], stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ continue;
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ Free_Anchor( &ban[k], memory );
+ goto Fail;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( k = 0; k < m; k++ )
+ {
+ ban = br[k].BaseAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &ban[n], memory );
+
+ FREE( ban );
+ }
+
+ FREE( br );
+ return error;
+}
+
+
+static void Free_BaseArray( HB_BaseArray* ba,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count;
+
+ HB_BaseRecord* br;
+ HB_Anchor* ban;
+
+
+ if ( ba->BaseRecord )
+ {
+ count = ba->BaseCount;
+ br = ba->BaseRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ ban = br[m].BaseAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &ban[n], memory );
+
+ FREE( ban );
+ }
+
+ FREE( br );
+ }
+}
+
+
+/* MarkBasePosFormat1 */
+
+static FT_Error Load_MarkBasePos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MarkBasePos* mbp = &st->markbase;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ mbp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if (mbp->PosFormat != 1)
+ return HB_Err_Invalid_SubTable_Format;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail2;
+
+ mbp->ClassCount = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ return FT_Err_Ok;
+
+Fail1:
+ Free_MarkArray( &mbp->MarkArray, memory );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );
+ return error;
+}
+
+
+static void Free_MarkBasePos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ HB_MarkBasePos* mbp = &st->markbase;
+
+ Free_BaseArray( &mbp->BaseArray, mbp->ClassCount, memory );
+ Free_MarkArray( &mbp->MarkArray, memory );
+ _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );
+ _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );
+}
+
+
+static FT_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort i, j, mark_index, base_index, property, class;
+ FT_Pos x_mark_value, y_mark_value, x_base_value, y_base_value;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_MarkBasePos* mbp = &st->markbase;
+
+ HB_MarkArray* ma;
+ HB_BaseArray* ba;
+ HB_BaseRecord* br;
+ HB_Anchor* mark_anchor;
+ HB_Anchor* base_anchor;
+
+ HB_Position o;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),
+ &mark_index );
+ if ( error )
+ return error;
+
+ /* now we search backwards for a non-mark glyph */
+
+ i = 1;
+ j = buffer->in_pos - 1;
+
+ while ( i <= buffer->in_pos )
+ {
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
+ &property );
+ if ( error )
+ return error;
+
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
+ break;
+
+ i++;
+ j--;
+ }
+
+ /* The following assertion is too strong -- at least for mangal.ttf. */
+#if 0
+ if ( property != HB_GDEF_BASE_GLYPH )
+ return HB_Err_Not_Covered;
+#endif
+
+ if ( i > buffer->in_pos )
+ return HB_Err_Not_Covered;
+
+ error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
+ &base_index );
+ if ( error )
+ return error;
+
+ ma = &mbp->MarkArray;
+
+ if ( mark_index >= ma->MarkCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ class = ma->MarkRecord[mark_index].Class;
+ mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
+
+ if ( class >= mbp->ClassCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ ba = &mbp->BaseArray;
+
+ if ( base_index >= ba->BaseCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ br = &ba->BaseRecord[base_index];
+ base_anchor = &br->BaseAnchor[class];
+
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
+ &x_mark_value, &y_mark_value );
+ if ( error )
+ return error;
+
+ error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
+ &x_base_value, &y_base_value );
+ if ( error )
+ return error;
+
+ /* anchor points are not cumulative */
+
+ o = POSITION( buffer->in_pos );
+
+ o->x_pos = x_base_value - x_mark_value;
+ o->y_pos = y_base_value - y_mark_value;
+ o->x_advance = 0;
+ o->y_advance = 0;
+ o->back = i;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 5 */
+
+/* LigatureAttach */
+
+static FT_Error Load_LigatureAttach( HB_LigatureAttach* lat,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort m, n, k, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ComponentRecord* cr;
+ HB_Anchor* lan;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = lat->ComponentCount = GET_UShort();
+
+ FORGET_Frame();
+
+ lat->ComponentRecord = NULL;
+
+ if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) )
+ return error;
+
+ cr = lat->ComponentRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ cr[m].LigatureAnchor = NULL;
+
+ if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) )
+ goto Fail;
+
+ lan = cr[m].LigatureAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( new_offset )
+ {
+ new_offset += base_offset;
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &lan[n], stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ lan[n].PosFormat = 0;
+ }
+
+ continue;
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ Free_Anchor( &lan[k], memory );
+ goto Fail;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( k = 0; k < m; k++ )
+ {
+ lan = cr[k].LigatureAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &lan[n], memory );
+
+ FREE( lan );
+ }
+
+ FREE( cr );
+ return error;
+}
+
+
+static void Free_LigatureAttach( HB_LigatureAttach* lat,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count;
+
+ HB_ComponentRecord* cr;
+ HB_Anchor* lan;
+
+
+ if ( lat->ComponentRecord )
+ {
+ count = lat->ComponentCount;
+ cr = lat->ComponentRecord;
+
+ for ( m = 0; m < count; m++ )
+ {
+ lan = cr[m].LigatureAnchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &lan[n], memory );
+
+ FREE( lan );
+ }
+
+ FREE( cr );
+ }
+}
+
+
+/* LigatureArray */
+
+static FT_Error Load_LigatureArray( HB_LigatureArray* la,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LigatureAttach* lat;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = la->LigatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ la->LigatureAttach = NULL;
+
+ if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) )
+ return error;
+
+ lat = la->LigatureAttach;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigatureAttach( &lat[n], num_classes,
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_LigatureAttach( &lat[m], num_classes, memory );
+
+ FREE( lat );
+ return error;
+}
+
+
+static void Free_LigatureArray( HB_LigatureArray* la,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_LigatureAttach* lat;
+
+
+ if ( la->LigatureAttach )
+ {
+ count = la->LigatureCount;
+ lat = la->LigatureAttach;
+
+ for ( n = 0; n < count; n++ )
+ Free_LigatureAttach( &lat[n], num_classes, memory );
+
+ FREE( lat );
+ }
+}
+
+
+/* MarkLigPosFormat1 */
+
+static FT_Error Load_MarkLigPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MarkLigPos* mlp = &st->marklig;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ mlp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail2;
+
+ mlp->ClassCount = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ return FT_Err_Ok;
+
+Fail1:
+ Free_MarkArray( &mlp->MarkArray, memory );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory );
+ return error;
+}
+
+
+static void Free_MarkLigPos( HB_GPOS_SubTable* st,
+ FT_Memory memory)
+{
+ HB_MarkLigPos* mlp = &st->marklig;
+
+ Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, memory );
+ Free_MarkArray( &mlp->MarkArray, memory );
+ _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory );
+ _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory );
+}
+
+
+static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort i, j, mark_index, lig_index, property, class;
+ FT_UShort mark_glyph;
+ FT_Pos x_mark_value, y_mark_value, x_lig_value, y_lig_value;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_MarkLigPos* mlp = &st->marklig;
+
+ HB_MarkArray* ma;
+ HB_LigatureArray* la;
+ HB_LigatureAttach* lat;
+ HB_ComponentRecord* cr;
+ FT_UShort comp_index;
+ HB_Anchor* mark_anchor;
+ HB_Anchor* lig_anchor;
+
+ HB_Position o;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES )
+ return HB_Err_Not_Covered;
+
+ mark_glyph = IN_CURGLYPH();
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
+ if ( error )
+ return error;
+
+ /* now we search backwards for a non-mark glyph */
+
+ i = 1;
+ j = buffer->in_pos - 1;
+
+ while ( i <= buffer->in_pos )
+ {
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
+ &property );
+ if ( error )
+ return error;
+
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
+ break;
+
+ i++;
+ j--;
+ }
+
+ /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
+ too strong, thus it is commented out. */
+#if 0
+ if ( property != HB_GDEF_LIGATURE )
+ return HB_Err_Not_Covered;
+#endif
+
+ if ( i > buffer->in_pos )
+ return HB_Err_Not_Covered;
+
+ error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
+ &lig_index );
+ if ( error )
+ return error;
+
+ ma = &mlp->MarkArray;
+
+ if ( mark_index >= ma->MarkCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ class = ma->MarkRecord[mark_index].Class;
+ mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
+
+ if ( class >= mlp->ClassCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ la = &mlp->LigatureArray;
+
+ if ( lig_index >= la->LigatureCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ lat = &la->LigatureAttach[lig_index];
+
+ /* We must now check whether the ligature ID of the current mark glyph
+ is identical to the ligature ID of the found ligature. If yes, we
+ can directly use the component index. If not, we attach the mark
+ glyph to the last component of the ligature. */
+
+ if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
+ {
+ comp_index = IN_COMPONENT( buffer->in_pos );
+ if ( comp_index >= lat->ComponentCount )
+ return HB_Err_Not_Covered;
+ }
+ else
+ comp_index = lat->ComponentCount - 1;
+
+ cr = &lat->ComponentRecord[comp_index];
+ lig_anchor = &cr->LigatureAnchor[class];
+
+ error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
+ &x_mark_value, &y_mark_value );
+ if ( error )
+ return error;
+ error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
+ &x_lig_value, &y_lig_value );
+ if ( error )
+ return error;
+
+ /* anchor points are not cumulative */
+
+ o = POSITION( buffer->in_pos );
+
+ o->x_pos = x_lig_value - x_mark_value;
+ o->y_pos = y_lig_value - y_mark_value;
+ o->x_advance = 0;
+ o->y_advance = 0;
+ o->back = i;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 6 */
+
+/* Mark2Array */
+
+static FT_Error Load_Mark2Array( HB_Mark2Array* m2a,
+ FT_UShort num_classes,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort k, m, n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Mark2Record* m2r;
+ HB_Anchor* m2an;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = m2a->Mark2Count = GET_UShort();
+
+ FORGET_Frame();
+
+ m2a->Mark2Record = NULL;
+
+ if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) )
+ return error;
+
+ m2r = m2a->Mark2Record;
+
+ for ( m = 0; m < count; m++ )
+ {
+ m2r[m].Mark2Anchor = NULL;
+
+ if ( ALLOC_ARRAY( m2r[m].Mark2Anchor, num_classes, HB_Anchor ) )
+ goto Fail;
+
+ m2an = m2r[m].Mark2Anchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail0;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Anchor( &m2an[n], stream ) ) != FT_Err_Ok )
+ goto Fail0;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ continue;
+ Fail0:
+ for ( k = 0; k < n; k++ )
+ Free_Anchor( &m2an[k], memory );
+ goto Fail;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( k = 0; k < m; k++ )
+ {
+ m2an = m2r[k].Mark2Anchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &m2an[n], memory );
+
+ FREE( m2an );
+ }
+
+ FREE( m2r );
+ return error;
+}
+
+
+static void Free_Mark2Array( HB_Mark2Array* m2a,
+ FT_UShort num_classes,
+ FT_Memory memory )
+{
+ FT_UShort m, n, count;
+
+ HB_Mark2Record* m2r;
+ HB_Anchor* m2an;
+
+
+ if ( m2a->Mark2Record )
+ {
+ count = m2a->Mark2Count;
+ m2r = m2a->Mark2Record;
+
+ for ( m = 0; m < count; m++ )
+ {
+ m2an = m2r[m].Mark2Anchor;
+
+ for ( n = 0; n < num_classes; n++ )
+ Free_Anchor( &m2an[n], memory );
+
+ FREE( m2an );
+ }
+
+ FREE( m2r );
+ }
+}
+
+
+/* MarkMarkPosFormat1 */
+
+static FT_Error Load_MarkMarkPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MarkMarkPos* mmp = &st->markmark;
+
+ FT_ULong cur_offset, new_offset, base_offset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ mmp->PosFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail2;
+
+ mmp->ClassCount = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount,
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ return FT_Err_Ok;
+
+Fail1:
+ Free_MarkArray( &mmp->Mark1Array, memory );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage, memory );
+ return error;
+}
+
+
+static void Free_MarkMarkPos( HB_GPOS_SubTable* st,
+ FT_Memory memory)
+{
+ HB_MarkMarkPos* mmp = &st->markmark;
+
+ Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, memory );
+ Free_MarkArray( &mmp->Mark1Array, memory );
+ _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage, memory );
+ _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage, memory );
+}
+
+
+static FT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort j, mark1_index, mark2_index, property, class;
+ FT_Pos x_mark1_value, y_mark1_value,
+ x_mark2_value, y_mark2_value;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_MarkMarkPos* mmp = &st->markmark;
+
+ HB_MarkArray* ma1;
+ HB_Mark2Array* ma2;
+ HB_Mark2Record* m2r;
+ HB_Anchor* mark1_anchor;
+ HB_Anchor* mark2_anchor;
+
+ HB_Position o;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),
+ &mark1_index );
+ if ( error )
+ return error;
+
+ /* now we check the preceding glyph whether it is a suitable
+ mark glyph */
+
+ if ( buffer->in_pos == 0 )
+ return HB_Err_Not_Covered;
+
+ j = buffer->in_pos - 1;
+ error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
+ &property );
+ if ( error )
+ return error;
+
+ if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ {
+ if ( property != (flags & 0xFF00) )
+ return HB_Err_Not_Covered;
+ }
+ else
+ {
+ if ( property != HB_GDEF_MARK )
+ return HB_Err_Not_Covered;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
+ &mark2_index );
+ if ( error )
+ return error;
+
+ ma1 = &mmp->Mark1Array;
+
+ if ( mark1_index >= ma1->MarkCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ class = ma1->MarkRecord[mark1_index].Class;
+ mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
+
+ if ( class >= mmp->ClassCount )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ ma2 = &mmp->Mark2Array;
+
+ if ( mark2_index >= ma2->Mark2Count )
+ return HB_Err_Invalid_GPOS_SubTable;
+
+ m2r = &ma2->Mark2Record[mark2_index];
+ mark2_anchor = &m2r->Mark2Anchor[class];
+
+ error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),
+ &x_mark1_value, &y_mark1_value );
+ if ( error )
+ return error;
+ error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
+ &x_mark2_value, &y_mark2_value );
+ if ( error )
+ return error;
+
+ /* anchor points are not cumulative */
+
+ o = POSITION( buffer->in_pos );
+
+ o->x_pos = x_mark2_value - x_mark1_value;
+ o->y_pos = y_mark2_value - y_mark1_value;
+ o->x_advance = 0;
+ o->y_advance = 0;
+ o->back = 1;
+
+ (buffer->in_pos)++;
+
+ return FT_Err_Ok;
+}
+
+
+/* Do the actual positioning for a context positioning (either format
+ 7 or 8). This is only called after we've determined that the stream
+ matches the subrule. */
+
+static FT_Error Do_ContextPos( GPOS_Instance* gpi,
+ FT_UShort GlyphCount,
+ FT_UShort PosCount,
+ HB_PosLookupRecord* pos,
+ HB_Buffer buffer,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort i, old_pos;
+
+
+ i = 0;
+
+ while ( i < GlyphCount )
+ {
+ if ( PosCount && i == pos->SequenceIndex )
+ {
+ old_pos = buffer->in_pos;
+
+ /* Do a positioning */
+
+ error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
+ GlyphCount, nesting_level );
+
+ if ( error )
+ return error;
+
+ pos++;
+ PosCount--;
+ i += buffer->in_pos - old_pos;
+ }
+ else
+ {
+ i++;
+ (buffer->in_pos)++;
+ }
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 7 */
+
+/* PosRule */
+
+static FT_Error Load_PosRule( HB_PosRule* pr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* i;
+
+ HB_PosLookupRecord* plr;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ pr->GlyphCount = GET_UShort();
+ pr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ pr->Input = NULL;
+
+ count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( pr->Input, count, FT_UShort ) )
+ return error;
+
+ i = pr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ pr->PosLookupRecord = NULL;
+
+ count = pr->PosCount;
+
+ if ( ALLOC_ARRAY( pr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = pr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( i );
+ return error;
+}
+
+
+static void Free_PosRule( HB_PosRule* pr,
+ FT_Memory memory )
+{
+ FREE( pr->PosLookupRecord );
+ FREE( pr->Input );
+}
+
+
+/* PosRuleSet */
+
+static FT_Error Load_PosRuleSet( HB_PosRuleSet* prs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosRule* pr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = prs->PosRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ prs->PosRule = NULL;
+
+ if ( ALLOC_ARRAY( prs->PosRule, count, HB_PosRule ) )
+ return error;
+
+ pr = prs->PosRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosRule( &pr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_PosRule( &pr[m], memory );
+
+ FREE( pr );
+ return error;
+}
+
+
+static void Free_PosRuleSet( HB_PosRuleSet* prs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosRule* pr;
+
+
+ if ( prs->PosRule )
+ {
+ count = prs->PosRuleCount;
+ pr = prs->PosRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosRule( &pr[n], memory );
+
+ FREE( pr );
+ }
+}
+
+
+/* ContextPosFormat1 */
+
+static FT_Error Load_ContextPos1( HB_ContextPosFormat1* cpf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosRuleSet* prs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = cpf1->PosRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpf1->PosRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, HB_PosRuleSet ) )
+ goto Fail2;
+
+ prs = cpf1->PosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosRuleSet( &prs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_PosRuleSet( &prs[m], memory );
+
+ FREE( prs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &cpf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextPos1( HB_ContextPosFormat1* cpf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosRuleSet* prs;
+
+
+ if ( cpf1->PosRuleSet )
+ {
+ count = cpf1->PosRuleSetCount;
+ prs = cpf1->PosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosRuleSet( &prs[n], memory );
+
+ FREE( prs );
+ }
+
+ _HB_OPEN_Free_Coverage( &cpf1->Coverage, memory );
+}
+
+
+/* PosClassRule */
+
+static FT_Error Load_PosClassRule( HB_ContextPosFormat2* cpf2,
+ HB_PosClassRule* pcr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* c;
+ HB_PosLookupRecord* plr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ pcr->GlyphCount = GET_UShort();
+ pcr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( pcr->GlyphCount > cpf2->MaxContextLength )
+ cpf2->MaxContextLength = pcr->GlyphCount;
+
+ pcr->Class = NULL;
+
+ count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( pcr->Class, count, FT_UShort ) )
+ return error;
+
+ c = pcr->Class;
+ d = cpf2->ClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ c[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+
+ if ( !d[c[n]] )
+ c[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ pcr->PosLookupRecord = NULL;
+
+ count = pcr->PosCount;
+
+ if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = pcr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( c );
+ return error;
+}
+
+
+static void Free_PosClassRule( HB_PosClassRule* pcr,
+ FT_Memory memory )
+{
+ FREE( pcr->PosLookupRecord );
+ FREE( pcr->Class );
+}
+
+
+/* PosClassSet */
+
+static FT_Error Load_PosClassSet( HB_ContextPosFormat2* cpf2,
+ HB_PosClassSet* pcs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosClassRule* pcr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = pcs->PosClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ pcs->PosClassRule = NULL;
+
+ if ( ALLOC_ARRAY( pcs->PosClassRule, count, HB_PosClassRule ) )
+ return error;
+
+ pcr = pcs->PosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosClassRule( cpf2, &pcr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_PosClassRule( &pcr[m], memory );
+
+ FREE( pcr );
+ return error;
+}
+
+
+static void Free_PosClassSet( HB_PosClassSet* pcs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosClassRule* pcr;
+
+
+ if ( pcs->PosClassRule )
+ {
+ count = pcs->PosClassRuleCount;
+ pcr = pcs->PosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosClassRule( &pcr[n], memory );
+
+ FREE( pcr );
+ }
+}
+
+
+/* ContextPosFormat2 */
+
+static FT_Error Load_ContextPos2( HB_ContextPosFormat2* cpf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_PosClassSet* pcs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ /* `PosClassSetCount' is the upper limit for class values, thus we
+ read it now to make an additional safety check. */
+
+ count = cpf2->PosClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ cpf2->PosClassSet = NULL;
+ cpf2->MaxContextLength = 0;
+
+ if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_PosClassSet ) )
+ goto Fail2;
+
+ pcs = cpf2->PosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_PosClassSet( cpf2, &pcs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a PosClassSet table with no entries */
+
+ cpf2->PosClassSet[n].PosClassRuleCount = 0;
+ cpf2->PosClassSet[n].PosClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; n++ )
+ Free_PosClassSet( &pcs[m], memory );
+
+ FREE( pcs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &cpf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextPos2( HB_ContextPosFormat2* cpf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_PosClassSet* pcs;
+
+
+ if ( cpf2->PosClassSet )
+ {
+ count = cpf2->PosClassSetCount;
+ pcs = cpf2->PosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_PosClassSet( &pcs[n], memory );
+
+ FREE( pcs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef, memory );
+ _HB_OPEN_Free_Coverage( &cpf2->Coverage, memory );
+}
+
+
+/* ContextPosFormat3 */
+
+static FT_Error Load_ContextPos3( HB_ContextPosFormat3* cpf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* c;
+ HB_PosLookupRecord* plr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cpf3->GlyphCount = GET_UShort();
+ cpf3->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpf3->Coverage = NULL;
+
+ count = cpf3->GlyphCount;
+
+ if ( ALLOC_ARRAY( cpf3->Coverage, count, HB_Coverage ) )
+ return error;
+
+ c = cpf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ cpf3->PosLookupRecord = NULL;
+
+ count = cpf3->PosCount;
+
+ if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = cpf3->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ return error;
+}
+
+
+static void Free_ContextPos3( HB_ContextPosFormat3* cpf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( cpf3->PosLookupRecord );
+
+ if ( cpf3->Coverage )
+ {
+ count = cpf3->GlyphCount;
+ c = cpf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ContextPos */
+
+static FT_Error Load_ContextPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ContextPos* cp = &st->context;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cp->PosFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cp->PosFormat )
+ {
+ case 1:
+ return Load_ContextPos1( &cp->cpf.cpf1, stream );
+
+ case 2:
+ return Load_ContextPos2( &cp->cpf.cpf2, stream );
+
+ case 3:
+ return Load_ContextPos3( &cp->cpf.cpf3, stream );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ContextPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ContextPos* cp = &st->context;
+
+ switch ( cp->PosFormat )
+ {
+ case 1:
+ Free_ContextPos1( &cp->cpf.cpf1, memory );
+ break;
+
+ case 2:
+ Free_ContextPos2( &cp->cpf.cpf2, memory );
+ break;
+
+ case 3:
+ Free_ContextPos3( &cp->cpf.cpf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ContextPos1( GPOS_Instance* gpi,
+ HB_ContextPosFormat1* cpf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, numpr;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_PosRule* pr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ pr = cpf1->PosRuleSet[index].PosRule;
+ numpr = cpf1->PosRuleSet[index].PosRuleCount;
+
+ for ( k = 0; k < numpr; k++ )
+ {
+ if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
+ goto next_posrule;
+
+ if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
+ goto next_posrule; /* context is too long */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + pr[k].GlyphCount - i == buffer->in_length )
+ goto next_posrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
+ goto next_posrule;
+ }
+
+ return Do_ContextPos( gpi, pr[k].GlyphCount,
+ pr[k].PosCount, pr[k].PosLookupRecord,
+ buffer,
+ nesting_level );
+
+ next_posrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ContextPos2( GPOS_Instance* gpi,
+ HB_ContextPosFormat2* cpf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ FT_Memory memory = gpi->face->memory;
+ FT_UShort i, j, k, known_classes;
+
+ FT_UShort* classes;
+ FT_UShort* cl;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_PosClassSet* pcs;
+ HB_PosClassRule* pr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) )
+ return error;
+
+ error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),
+ &classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = 0;
+
+ pcs = &cpf2->PosClassSet[classes[0]];
+ if ( !pcs )
+ {
+ error = HB_Err_Invalid_GPOS_SubTable;
+ goto End;
+ }
+
+ for ( k = 0; k < pcs->PosClassRuleCount; k++ )
+ {
+ pr = &pcs->PosClassRule[k];
+
+ if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
+ goto next_posclassrule;
+
+ if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
+ goto next_posclassrule; /* context is too long */
+
+ cl = pr->Class;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+
+ if ( j + pr->GlyphCount - i == buffer->in_length )
+ goto next_posclassrule;
+ j++;
+ }
+
+ if ( i > known_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = i;
+ }
+
+ if ( cl[i - 1] != classes[i] )
+ goto next_posclassrule;
+ }
+
+ error = Do_ContextPos( gpi, pr->GlyphCount,
+ pr->PosCount, pr->PosLookupRecord,
+ buffer,
+ nesting_level );
+ goto End;
+
+ next_posclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End:
+ FREE( classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ContextPos3( GPOS_Instance* gpi,
+ HB_ContextPosFormat3* cpf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, i, j, property;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_Coverage* c;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
+ return HB_Err_Not_Covered;
+
+ if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
+ return HB_Err_Not_Covered; /* context is too long */
+
+ c = cpf3->Coverage;
+
+ for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + cpf3->GlyphCount - i == buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextPos( gpi, cpf3->GlyphCount,
+ cpf3->PosCount, cpf3->PosLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ContextPos( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ContextPos* cp = &st->context;
+
+ switch ( cp->PosFormat )
+ {
+ case 1:
+ return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
+ flags, context_length, nesting_level );
+
+ case 2:
+ return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
+ flags, context_length, nesting_level );
+
+ case 3:
+ return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
+ flags, context_length, nesting_level );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+/* LookupType 8 */
+
+/* ChainPosRule */
+
+static FT_Error Load_ChainPosRule( HB_ChainPosRule* cpr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+
+ HB_PosLookupRecord* plr;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cpr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->Backtrack = NULL;
+
+ count = cpr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( cpr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = cpr->Backtrack;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ b[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ cpr->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->Input = NULL;
+
+ count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( cpr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = cpr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ cpr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->Lookahead = NULL;
+
+ count = cpr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( cpr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = cpr->Lookahead;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ l[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ cpr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpr->PosLookupRecord = NULL;
+
+ count = cpr->PosCount;
+
+ if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = cpr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainPosRule( HB_ChainPosRule* cpr,
+ FT_Memory memory )
+{
+ FREE( cpr->PosLookupRecord );
+ FREE( cpr->Lookahead );
+ FREE( cpr->Input );
+ FREE( cpr->Backtrack );
+}
+
+
+/* ChainPosRuleSet */
+
+static FT_Error Load_ChainPosRuleSet( HB_ChainPosRuleSet* cprs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainPosRule* cpr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cprs->ChainPosRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cprs->ChainPosRule = NULL;
+
+ if ( ALLOC_ARRAY( cprs->ChainPosRule, count, HB_ChainPosRule ) )
+ return error;
+
+ cpr = cprs->ChainPosRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosRule( &cpr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosRule( &cpr[m], memory );
+
+ FREE( cpr );
+ return error;
+}
+
+
+static void Free_ChainPosRuleSet( HB_ChainPosRuleSet* cprs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosRule* cpr;
+
+
+ if ( cprs->ChainPosRule )
+ {
+ count = cprs->ChainPosRuleCount;
+ cpr = cprs->ChainPosRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosRule( &cpr[n], memory );
+
+ FREE( cpr );
+ }
+}
+
+
+/* ChainContextPosFormat1 */
+
+static FT_Error Load_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainPosRuleSet* cprs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ccpf1->ChainPosRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf1->ChainPosRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, HB_ChainPosRuleSet ) )
+ goto Fail2;
+
+ cprs = ccpf1->ChainPosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosRuleSet( &cprs[m], memory );
+
+ FREE( cprs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ccpf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosRuleSet* cprs;
+
+
+ if ( ccpf1->ChainPosRuleSet )
+ {
+ count = ccpf1->ChainPosRuleSetCount;
+ cprs = ccpf1->ChainPosRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosRuleSet( &cprs[n], memory );
+
+ FREE( cprs );
+ }
+
+ _HB_OPEN_Free_Coverage( &ccpf1->Coverage, memory );
+}
+
+
+/* ChainPosClassRule */
+
+static FT_Error Load_ChainPosClassRule(
+ HB_ChainContextPosFormat2* ccpf2,
+ HB_ChainPosClassRule* cpcr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+ HB_PosLookupRecord* plr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cpcr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength )
+ ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount;
+
+ cpcr->Backtrack = NULL;
+
+ count = cpcr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( cpcr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = cpcr->Backtrack;
+ d = ccpf2->BacktrackClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ {
+ b[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+
+ if ( !d[b[n]] )
+ b[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ cpcr->InputGlyphCount = GET_UShort();
+
+ if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength )
+ ccpf2->MaxInputLength = cpcr->InputGlyphCount;
+
+ FORGET_Frame();
+
+ cpcr->Input = NULL;
+
+ count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( cpcr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = cpcr->Input;
+ d = ccpf2->InputClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ {
+ i[n] = GET_UShort();
+
+ if ( !d[i[n]] )
+ i[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ cpcr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength )
+ ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount;
+
+ cpcr->Lookahead = NULL;
+
+ count = cpcr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( cpcr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = cpcr->Lookahead;
+ d = ccpf2->LookaheadClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ l[n] = GET_UShort();
+
+ if ( !d[l[n]] )
+ l[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ cpcr->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpcr->PosLookupRecord = NULL;
+
+ count = cpcr->PosCount;
+
+ if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = cpcr->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainPosClassRule( HB_ChainPosClassRule* cpcr,
+ FT_Memory memory )
+{
+ FREE( cpcr->PosLookupRecord );
+ FREE( cpcr->Lookahead );
+ FREE( cpcr->Input );
+ FREE( cpcr->Backtrack );
+}
+
+
+/* PosClassSet */
+
+static FT_Error Load_ChainPosClassSet(
+ HB_ChainContextPosFormat2* ccpf2,
+ HB_ChainPosClassSet* cpcs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainPosClassRule* cpcr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cpcs->ChainPosClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cpcs->ChainPosClassRule = NULL;
+
+ if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count,
+ HB_ChainPosClassRule ) )
+ return error;
+
+ cpcr = cpcs->ChainPosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosClassRule( &cpcr[m], memory );
+
+ FREE( cpcr );
+ return error;
+}
+
+
+static void Free_ChainPosClassSet( HB_ChainPosClassSet* cpcs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosClassRule* cpcr;
+
+
+ if ( cpcs->ChainPosClassRule )
+ {
+ count = cpcs->ChainPosClassRuleCount;
+ cpcr = cpcs->ChainPosClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosClassRule( &cpcr[n], memory );
+
+ FREE( cpcr );
+ }
+}
+
+
+static FT_Error GPOS_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_ULong class_offset,
+ FT_ULong base_offset,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_ULong cur_offset;
+
+ cur_offset = FILE_Pos();
+
+ if ( class_offset )
+ {
+ if ( !FILE_Seek( class_offset + base_offset ) )
+ error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
+ }
+ else
+ error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
+
+ if (error == FT_Err_Ok)
+ (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
+
+ return error;
+}
+
+/* ChainContextPosFormat2 */
+
+static FT_Error Load_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+ FT_ULong backtrack_offset, input_offset, lookahead_offset;
+
+ HB_ChainPosClassSet* cpcs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 8L ) )
+ goto Fail5;
+
+ backtrack_offset = GET_UShort();
+ input_offset = GET_UShort();
+ lookahead_offset = GET_UShort();
+
+ /* `ChainPosClassSetCount' is the upper limit for input class values,
+ thus we read it now to make an additional safety check. No limit
+ is known or needed for the other two class definitions */
+
+ count = ccpf2->ChainPosClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
+ backtrack_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail5;
+ if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
+ input_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
+ lookahead_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+
+ ccpf2->ChainPosClassSet = NULL;
+ ccpf2->MaxBacktrackLength = 0;
+ ccpf2->MaxInputLength = 0;
+ ccpf2->MaxLookaheadLength = 0;
+
+ if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_ChainPosClassSet ) )
+ goto Fail2;
+
+ cpcs = ccpf2->ChainPosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a ChainPosClassSet table with no entries */
+
+ ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0;
+ ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainPosClassSet( &cpcs[m], memory );
+
+ FREE( cpcs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef, memory );
+
+Fail4:
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
+
+Fail5:
+ _HB_OPEN_Free_Coverage( &ccpf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainPosClassSet* cpcs;
+
+
+ if ( ccpf2->ChainPosClassSet )
+ {
+ count = ccpf2->ChainPosClassSetCount;
+ cpcs = ccpf2->ChainPosClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainPosClassSet( &cpcs[n], memory );
+
+ FREE( cpcs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
+
+ _HB_OPEN_Free_Coverage( &ccpf2->Coverage, memory );
+}
+
+
+/* ChainContextPosFormat3 */
+
+static FT_Error Load_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, nb, ni, nl, m, count;
+ FT_UShort backtrack_count, input_count, lookahead_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* b;
+ HB_Coverage* i;
+ HB_Coverage* l;
+ HB_PosLookupRecord* plr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccpf3->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->BacktrackCoverage = NULL;
+
+ backtrack_count = ccpf3->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count,
+ HB_Coverage ) )
+ return error;
+
+ b = ccpf3->BacktrackCoverage;
+
+ for ( nb = 0; nb < backtrack_count; nb++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ ccpf3->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->InputCoverage = NULL;
+
+ input_count = ccpf3->InputGlyphCount;
+
+ if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, HB_Coverage ) )
+ goto Fail4;
+
+ i = ccpf3->InputCoverage;
+
+ for ( ni = 0; ni < input_count; ni++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ ccpf3->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->LookaheadCoverage = NULL;
+
+ lookahead_count = ccpf3->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count,
+ HB_Coverage ) )
+ goto Fail3;
+
+ l = ccpf3->LookaheadCoverage;
+
+ for ( nl = 0; nl < lookahead_count; nl++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ ccpf3->PosCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccpf3->PosLookupRecord = NULL;
+
+ count = ccpf3->PosCount;
+
+ if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
+ goto Fail2;
+
+ plr = ccpf3->PosLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ plr[n].SequenceIndex = GET_UShort();
+ plr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( plr );
+
+Fail2:
+ for ( m = 0; m < nl; nl++ )
+ _HB_OPEN_Free_Coverage( &l[m], memory );
+
+ FREE( l );
+
+Fail3:
+ for ( m = 0; m < ni; n++ )
+ _HB_OPEN_Free_Coverage( &i[m], memory );
+
+ FREE( i );
+
+Fail4:
+ for ( m = 0; m < nb; n++ )
+ _HB_OPEN_Free_Coverage( &b[m], memory );
+
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( ccpf3->PosLookupRecord );
+
+ if ( ccpf3->LookaheadCoverage )
+ {
+ count = ccpf3->LookaheadGlyphCount;
+ c = ccpf3->LookaheadCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccpf3->InputCoverage )
+ {
+ count = ccpf3->InputGlyphCount;
+ c = ccpf3->InputCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccpf3->BacktrackCoverage )
+ {
+ count = ccpf3->BacktrackGlyphCount;
+ c = ccpf3->BacktrackCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ChainContextPos */
+
+static FT_Error Load_ChainContextPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ChainContextPos* ccp = &st->chain;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccp->PosFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( ccp->PosFormat )
+ {
+ case 1:
+ return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );
+
+ case 2:
+ return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );
+
+ case 3:
+ return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ChainContextPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ChainContextPos* ccp = &st->chain;
+
+ switch ( ccp->PosFormat )
+ {
+ case 1:
+ Free_ChainContextPos1( &ccp->ccpf.ccpf1, memory );
+ break;
+
+ case 2:
+ Free_ChainContextPos2( &ccp->ccpf.ccpf2, memory );
+ break;
+
+ case 3:
+ Free_ChainContextPos3( &ccp->ccpf.ccpf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ChainContextPos1(
+ GPOS_Instance* gpi,
+ HB_ChainContextPosFormat1* ccpf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, num_cpr;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_ChainPosRule* cpr;
+ HB_ChainPosRule curr_cpr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule;
+ num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount;
+
+ for ( k = 0; k < num_cpr; k++ )
+ {
+ curr_cpr = cpr[k];
+ bgc = curr_cpr.BacktrackGlyphCount;
+ igc = curr_cpr.InputGlyphCount;
+ lgc = curr_cpr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainposrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainposrule;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainposrule;
+ j--;
+ }
+
+ /* In OpenType 1.3, it is undefined whether the offsets of
+ backtrack glyphs is in logical order or not. Version 1.4
+ will clarify this:
+
+ Logical order - a b c d e f g h i j
+ i
+ Input offsets - 0 1
+ Backtrack offsets - 3 2 1 0
+ Lookahead offsets - 0 1 2 3 */
+
+ if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
+ goto next_chainposrule;
+ }
+ }
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == buffer->in_length )
+ goto next_chainposrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
+ goto next_chainposrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == buffer->in_length )
+ goto next_chainposrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
+ goto next_chainposrule;
+ }
+
+ return Do_ContextPos( gpi, igc,
+ curr_cpr.PosCount,
+ curr_cpr.PosLookupRecord,
+ buffer,
+ nesting_level );
+
+ next_chainposrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ChainContextPos2(
+ GPOS_Instance* gpi,
+ HB_ChainContextPosFormat2* ccpf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Memory memory = gpi->face->memory;
+ FT_Error error;
+ FT_UShort i, j, k;
+ FT_UShort bgc, igc, lgc;
+ FT_UShort known_backtrack_classes,
+ known_input_classes,
+ known_lookahead_classes;
+
+ FT_UShort* backtrack_classes;
+ FT_UShort* input_classes;
+ FT_UShort* lookahead_classes;
+
+ FT_UShort* bc;
+ FT_UShort* ic;
+ FT_UShort* lc;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_ChainPosClassSet* cpcs;
+ HB_ChainPosClassRule cpcr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, FT_UShort ) )
+ return error;
+ known_backtrack_classes = 0;
+
+ if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, FT_UShort ) )
+ goto End3;
+ known_input_classes = 1;
+
+ if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, FT_UShort ) )
+ goto End2;
+ known_lookahead_classes = 0;
+
+ error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),
+ &input_classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
+ if ( !cpcs )
+ {
+ error = HB_Err_Invalid_GPOS_SubTable;
+ goto End1;
+ }
+
+ for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ )
+ {
+ cpcr = cpcs->ChainPosClassRule[k];
+ bgc = cpcr.BacktrackGlyphCount;
+ igc = cpcr.InputGlyphCount;
+ lgc = cpcr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainposclassrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainposclassrule;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array.
+ Note that `known_backtrack_classes' starts at index 0. */
+
+ bc = cpcr.Backtrack;
+
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainposclassrule;
+ j++;
+ }
+
+ if ( i >= known_backtrack_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
+ &backtrack_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_backtrack_classes = i;
+ }
+
+ if ( bc[i] != backtrack_classes[i] )
+ goto next_chainposclassrule;
+ }
+ }
+
+ ic = cpcr.Input;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + igc - i + lgc == buffer->in_length )
+ goto next_chainposclassrule;
+ j++;
+ }
+
+ if ( i >= known_input_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
+ &input_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_input_classes = i;
+ }
+
+ if ( ic[i - 1] != input_classes[i] )
+ goto next_chainposclassrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ lc = cpcr.Lookahead;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + lgc - i == buffer->in_length )
+ goto next_chainposclassrule;
+ j++;
+ }
+
+ if ( i >= known_lookahead_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
+ &lookahead_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_lookahead_classes = i;
+ }
+
+ if ( lc[i] != lookahead_classes[i] )
+ goto next_chainposclassrule;
+ }
+
+ error = Do_ContextPos( gpi, igc,
+ cpcr.PosCount,
+ cpcr.PosLookupRecord,
+ buffer,
+ nesting_level );
+ goto End1;
+
+ next_chainposclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End1:
+ FREE( lookahead_classes );
+
+End2:
+ FREE( input_classes );
+
+End3:
+ FREE( backtrack_classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ChainContextPos3(
+ GPOS_Instance* gpi,
+ HB_ChainContextPosFormat3* ccpf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, i, j, property;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ HB_Coverage* bc;
+ HB_Coverage* ic;
+ HB_Coverage* lc;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gpos->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ bgc = ccpf3->BacktrackGlyphCount;
+ igc = ccpf3->InputGlyphCount;
+ lgc = ccpf3->LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ return HB_Err_Not_Covered;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ return HB_Err_Not_Covered;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ bc = ccpf3->BacktrackCoverage;
+
+ for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ return HB_Err_Not_Covered;
+ j--;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+ }
+
+ ic = ccpf3->InputCoverage;
+
+ for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
+ {
+ /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
+ while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ lc = ccpf3->LookaheadCoverage;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextPos( gpi, igc,
+ ccpf3->PosCount,
+ ccpf3->PosLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ChainContextPos(
+ GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ChainContextPos* ccp = &st->chain;
+
+ switch ( ccp->PosFormat )
+ {
+ case 1:
+ return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 2:
+ return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 3:
+ return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
+ flags, context_length,
+ nesting_level );
+
+ default:
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+
+/***********
+ * GPOS API
+ ***********/
+
+
+
+FT_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,
+ FT_ULong script_tag,
+ FT_UShort* script_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gpos || !script_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ if ( script_tag == sr[n].ScriptTag )
+ {
+ *script_index = n;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+
+FT_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gpos || !language_index || !req_feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ if ( language_tag == lsr[n].LangSysTag )
+ {
+ *language_index = n;
+ *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gpos || !feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gpos->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+
+ if ( feature_tag == fr[fi[n]].FeatureTag )
+ {
+ *feature_index = fi[n];
+
+ return FT_Err_Ok;
+ }
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* The next three functions return a null-terminated list */
+
+
+FT_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,
+ FT_ULong** script_tag_list )
+{
+ FT_Error error;
+ FT_Memory memory = gpos->memory;
+ FT_UShort n;
+ FT_ULong* stl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gpos || !script_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ stl[n] = sr[n].ScriptTag;
+ stl[n] = 0;
+
+ *script_tag_list = stl;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list )
+{
+ FT_Error error;
+ FT_Memory memory = gpos->memory;
+ FT_UShort n;
+ FT_ULong* ltl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gpos || !language_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ ltl[n] = lsr[n].LangSysTag;
+ ltl[n] = 0;
+
+ *language_tag_list = ltl;
+
+ return FT_Err_Ok;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory = gpos->memory;
+ FT_ULong* ftl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gpos || !feature_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gpos->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gpos->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ {
+ FREE( ftl );
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+ }
+ ftl[n] = fr[fi[n]].FeatureTag;
+ }
+ ftl[n] = 0;
+
+ *feature_tag_list = ftl;
+
+ return FT_Err_Ok;
+}
+
+
+typedef FT_Error (*Lookup_Pos_Func_Type) ( GPOS_Instance* gpi,
+ HB_GPOS_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level );
+static const Lookup_Pos_Func_Type Lookup_Pos_Call_Table[] = {
+ Lookup_DefaultPos,
+ Lookup_SinglePos, /* HB_GPOS_LOOKUP_SINGLE 1 */
+ Lookup_PairPos, /* HB_GPOS_LOOKUP_PAIR 2 */
+ Lookup_CursivePos, /* HB_GPOS_LOOKUP_CURSIVE 3 */
+ Lookup_MarkBasePos, /* HB_GPOS_LOOKUP_MARKBASE 4 */
+ Lookup_MarkLigPos, /* HB_GPOS_LOOKUP_MARKLIG 5 */
+ Lookup_MarkMarkPos, /* HB_GPOS_LOOKUP_MARKMARK 6 */
+ Lookup_ContextPos, /* HB_GPOS_LOOKUP_CONTEXT 7 */
+ Lookup_ChainContextPos, /* HB_GPOS_LOOKUP_CHAIN 8 */
+ Lookup_DefaultPos, /* HB_GPOS_LOOKUP_EXTENSION 9 */
+};
+
+/* Do an individual subtable lookup. Returns FT_Err_Ok if positioning
+ has been done, or HB_Err_Not_Covered if not. */
+static FT_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error = HB_Err_Not_Covered;
+ FT_UShort i, flags, lookup_count;
+ HB_GPOSHeader* gpos = gpi->gpos;
+ HB_Lookup* lo;
+ int lookup_type;
+ Lookup_Pos_Func_Type Func;
+
+
+ nesting_level++;
+
+ if ( nesting_level > HB_MAX_NESTING_LEVEL )
+ return HB_Err_Too_Many_Nested_Contexts;
+
+ lookup_count = gpos->LookupList.LookupCount;
+ if (lookup_index >= lookup_count)
+ return error;
+
+ lo = &gpos->LookupList.Lookup[lookup_index];
+ flags = lo->LookupFlag;
+ lookup_type = lo->LookupType;
+ if (lookup_type >= ARRAY_LEN (Lookup_Pos_Call_Table))
+ lookup_type = 0;
+ Func = Lookup_Pos_Call_Table[lookup_type];
+
+ for ( i = 0; i < lo->SubTableCount; i++ )
+ {
+ error = Func ( gpi,
+ &lo->SubTable[i].st.gpos,
+ buffer,
+ flags, context_length,
+ nesting_level );
+
+ /* Check whether we have a successful positioning or an error other
+ than HB_Err_Not_Covered */
+
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Load_DefaultPos( HB_GPOS_SubTable* st,
+ FT_Stream stream )
+{
+ return HB_Err_Invalid_GPOS_SubTable_Format;
+}
+
+typedef FT_Error (*Load_Pos_Func_Type)( HB_GPOS_SubTable* st,
+ FT_Stream stream );
+static const Load_Pos_Func_Type Load_Pos_Call_Table[] = {
+ Load_DefaultPos,
+ Load_SinglePos, /* HB_GPOS_LOOKUP_SINGLE 1 */
+ Load_PairPos, /* HB_GPOS_LOOKUP_PAIR 2 */
+ Load_CursivePos, /* HB_GPOS_LOOKUP_CURSIVE 3 */
+ Load_MarkBasePos, /* HB_GPOS_LOOKUP_MARKBASE 4 */
+ Load_MarkLigPos, /* HB_GPOS_LOOKUP_MARKLIG 5 */
+ Load_MarkMarkPos, /* HB_GPOS_LOOKUP_MARKMARK 6 */
+ Load_ContextPos, /* HB_GPOS_LOOKUP_CONTEXT 7 */
+ Load_ChainContextPos, /* HB_GPOS_LOOKUP_CHAIN 8 */
+ Load_DefaultPos, /* HB_GPOS_LOOKUP_EXTENSION 9 */
+};
+
+FT_Error _HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type )
+{
+ Load_Pos_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Load_Pos_Call_Table))
+ lookup_type = 0;
+
+ Func = Load_Pos_Call_Table[lookup_type];
+
+ return Func ( st, stream );
+}
+
+
+static void Free_DefaultPos( HB_GPOS_SubTable* st,
+ FT_Memory memory )
+{
+}
+
+typedef void (*Free_Pos_Func_Type)( HB_GPOS_SubTable* st,
+ FT_Memory memory );
+static const Free_Pos_Func_Type Free_Pos_Call_Table[] = {
+ Free_DefaultPos,
+ Free_SinglePos, /* HB_GPOS_LOOKUP_SINGLE 1 */
+ Free_PairPos, /* HB_GPOS_LOOKUP_PAIR 2 */
+ Free_CursivePos, /* HB_GPOS_LOOKUP_CURSIVE 3 */
+ Free_MarkBasePos, /* HB_GPOS_LOOKUP_MARKBASE 4 */
+ Free_MarkLigPos, /* HB_GPOS_LOOKUP_MARKLIG 5 */
+ Free_MarkMarkPos, /* HB_GPOS_LOOKUP_MARKMARK 6 */
+ Free_ContextPos, /* HB_GPOS_LOOKUP_CONTEXT 7 */
+ Free_ChainContextPos, /* HB_GPOS_LOOKUP_CHAIN 8 */
+ Free_DefaultPos, /* HB_GPOS_LOOKUP_EXTENSION 9 */
+};
+
+void _HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type )
+{
+ Free_Pos_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Free_Pos_Call_Table))
+ lookup_type = 0;
+
+ Func = Free_Pos_Call_Table[lookup_type];
+
+ Func ( st, memory );
+}
+
+
+
+/* apply one lookup to the input string object */
+
+static FT_Error GPOS_Do_String_Lookup( GPOS_Instance* gpi,
+ FT_UShort lookup_index,
+ HB_Buffer buffer )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+ HB_GPOSHeader* gpos = gpi->gpos;
+
+ FT_UInt* properties = gpos->LookupList.Properties;
+
+ int nesting_level = 0;
+
+
+ gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */
+
+ buffer->in_pos = 0;
+
+ while ( buffer->in_pos < buffer->in_length )
+ {
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
+ {
+ /* 0xFFFF indicates that we don't have a context length yet. */
+
+ /* Note that the connection between mark and base glyphs hold
+ exactly one (string) lookup. For example, it would be possible
+ that in the first lookup, mark glyph X is attached to base
+ glyph A, and in the next lookup it is attached to base glyph B.
+ It is up to the font designer to provide meaningful lookups and
+ lookup order. */
+
+ error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer,
+ 0xFFFF, nesting_level );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ {
+ /* Contrary to properties defined in GDEF, user-defined properties
+ will always stop a possible cursive positioning. */
+ gpi->last = 0xFFFF;
+
+ error = HB_Err_Not_Covered;
+ }
+
+ if ( error == HB_Err_Not_Covered )
+ (buffer->in_pos)++;
+ else
+ retError = error;
+ }
+
+ return retError;
+}
+
+
+static FT_Error Position_CursiveChain ( HB_Buffer buffer )
+{
+ FT_ULong i, j;
+ HB_Position positions = buffer->positions;
+
+ /* First handle all left-to-right connections */
+ for (j = 0; j < buffer->in_length; j--)
+ {
+ if (positions[j].cursive_chain > 0)
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
+ }
+
+ /* Then handle all right-to-left connections */
+ for (i = buffer->in_length; i > 0; i--)
+ {
+ j = i - 1;
+
+ if (positions[j].cursive_chain < 0)
+ positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+FT_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,
+ FT_UShort feature_index,
+ FT_UInt property )
+{
+ FT_UShort i;
+
+ HB_Feature feature;
+ FT_UInt* properties;
+ FT_UShort* index;
+ FT_UShort lookup_count;
+
+ /* Each feature can only be added once */
+
+ if ( !gpos ||
+ feature_index >= gpos->FeatureList.FeatureCount ||
+ gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
+ return FT_Err_Invalid_Argument;
+
+ gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
+
+ properties = gpos->LookupList.Properties;
+
+ feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
+ index = feature.LookupListIndex;
+ lookup_count = gpos->LookupList.LookupCount;
+
+ for ( i = 0; i < feature.LookupListCount; i++ )
+ {
+ FT_UShort lookup_index = index[i];
+ if (lookup_index < lookup_count)
+ properties[lookup_index] |= property;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos )
+{
+ FT_UShort i;
+
+ FT_UInt* properties;
+
+
+ if ( !gpos )
+ return FT_Err_Invalid_Argument;
+
+ gpos->FeatureList.ApplyCount = 0;
+
+ properties = gpos->LookupList.Properties;
+
+ for ( i = 0; i < gpos->LookupList.LookupCount; i++ )
+ properties[i] = 0;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Register_Glyph_Function( HB_GPOSHeader* gpos,
+ HB_GlyphFunction gfunc )
+{
+ if ( !gpos )
+ return FT_Err_Invalid_Argument;
+
+ gpos->gfunc = gfunc;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,
+ HB_MMFunction mmfunc,
+ void* data )
+{
+ if ( !gpos )
+ return FT_Err_Invalid_Argument;
+
+ gpos->mmfunc = mmfunc;
+ gpos->data = data;
+
+ return FT_Err_Ok;
+}
+
+/* If `dvi' is TRUE, glyph contour points for anchor points and device
+ tables are ignored -- you will get device independent values. */
+
+
+FT_Error HB_GPOS_Apply_String( FT_Face face,
+ HB_GPOSHeader* gpos,
+ FT_UShort load_flags,
+ HB_Buffer buffer,
+ FT_Bool dvi,
+ FT_Bool r2l )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+ GPOS_Instance gpi;
+ FT_UShort i, j, feature_index, lookup_count;
+ HB_Feature feature;
+
+ if ( !face || !gpos ||
+ !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
+ return FT_Err_Invalid_Argument;
+
+ gpi.face = face;
+ gpi.gpos = gpos;
+ gpi.load_flags = load_flags;
+ gpi.r2l = r2l;
+ gpi.dvi = dvi;
+
+ lookup_count = gpos->LookupList.LookupCount;
+
+ for ( i = 0; i < gpos->FeatureList.ApplyCount; i++ )
+ {
+ /* index of i'th feature */
+ feature_index = gpos->FeatureList.ApplyOrder[i];
+ feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
+
+ for ( j = 0; j < feature.LookupListCount; j++ )
+ {
+ FT_UShort lookup_index = feature.LookupListIndex[j];
+
+ /* Skip nonexistant lookups */
+ if (lookup_index >= lookup_count)
+ continue;
+
+ error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer );
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ retError = error;
+ }
+ }
+
+ error = Position_CursiveChain ( buffer );
+ if ( error )
+ return error;
+
+ return retError;
+}
+
+/* END */
diff --git a/pango/opentype/harfbuzz-gpos.h b/pango/opentype/harfbuzz-gpos.h
new file mode 100644
index 00000000..1c670279
--- /dev/null
+++ b/pango/opentype/harfbuzz-gpos.h
@@ -0,0 +1,168 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GPOS_H
+#define HARFBUZZ_GPOS_H
+
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-buffer.h"
+
+FT_BEGIN_HEADER
+
+#define HB_Err_Invalid_GPOS_SubTable_Format 0x1020
+#define HB_Err_Invalid_GPOS_SubTable 0x1021
+
+
+/* Lookup types for glyph positioning */
+
+#define HB_GPOS_LOOKUP_SINGLE 1
+#define HB_GPOS_LOOKUP_PAIR 2
+#define HB_GPOS_LOOKUP_CURSIVE 3
+#define HB_GPOS_LOOKUP_MARKBASE 4
+#define HB_GPOS_LOOKUP_MARKLIG 5
+#define HB_GPOS_LOOKUP_MARKMARK 6
+#define HB_GPOS_LOOKUP_CONTEXT 7
+#define HB_GPOS_LOOKUP_CHAIN 8
+#define HB_GPOS_LOOKUP_EXTENSION 9
+
+
+/* A pointer to a function which loads a glyph. Its parameters are
+ the same as in a call to Load_Glyph() -- if no glyph loading
+ function will be registered with HB_GPOS_Register_Glyph_Function(),
+ Load_Glyph() will be called indeed. The purpose of this function
+ pointer is to provide a hook for caching glyph outlines and sbits
+ (using the instance's generic pointer to hold the data).
+
+ If for some reason no outline data is available (e.g. for an
+ embedded bitmap glyph), _glyph->outline.n_points should be set to
+ zero. _glyph can be computed with
+
+ _glyph = HANDLE_Glyph( glyph ) */
+
+typedef FT_Error (*HB_GlyphFunction)(FT_Face face,
+ FT_UInt glyphIndex,
+ FT_Int loadFlags );
+
+
+/* A pointer to a function which accesses the PostScript interpreter.
+ Multiple Master fonts need this interface to convert a metric ID
+ (as stored in an OpenType font version 1.2 or higher) `metric_id'
+ into a metric value (returned in `metric_value').
+
+ `data' points to the user-defined structure specified during a
+ call to HB_GPOS_Register_MM_Function().
+
+ `metric_value' must be returned as a scaled value (but shouldn't
+ be rounded). */
+
+typedef FT_Error (*HB_MMFunction)(FT_Face face,
+ FT_UShort metric_id,
+ FT_Pos* metric_value,
+ void* data );
+
+
+struct HB_GPOSHeader_
+{
+ FT_Memory memory;
+
+ FT_Fixed Version;
+
+ HB_ScriptList ScriptList;
+ HB_FeatureList FeatureList;
+ HB_LookupList LookupList;
+
+ HB_GDEFHeader* gdef;
+
+ /* the next field is used for a callback function to get the
+ glyph outline. */
+
+ HB_GlyphFunction gfunc;
+
+ /* this is OpenType 1.2 -- Multiple Master fonts need this
+ callback function to get various metric values from the
+ PostScript interpreter. */
+
+ HB_MMFunction mmfunc;
+ void* data;
+};
+
+typedef struct HB_GPOSHeader_ HB_GPOSHeader;
+typedef HB_GPOSHeader* HB_GPOS;
+
+
+FT_Error HB_Load_GPOS_Table( FT_Face face,
+ HB_GPOSHeader** gpos,
+ HB_GDEFHeader* gdef );
+
+
+FT_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos );
+
+
+FT_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,
+ FT_ULong script_tag,
+ FT_UShort* script_index );
+
+FT_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index );
+
+FT_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index );
+
+
+FT_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,
+ FT_ULong** script_tag_list );
+
+FT_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list );
+
+FT_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list );
+
+
+FT_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,
+ FT_UShort feature_index,
+ FT_UInt property );
+
+FT_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos );
+
+
+FT_Error HB_GPOS_Register_Glyph_Function( HB_GPOSHeader* gpos,
+ HB_GlyphFunction gfunc );
+
+
+FT_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,
+ HB_MMFunction mmfunc,
+ void* data );
+
+/* If `dvi' is TRUE, glyph contour points for anchor points and device
+ tables are ignored -- you will get device independent values. */
+
+
+FT_Error HB_GPOS_Apply_String( FT_Face face,
+ HB_GPOSHeader* gpos,
+ FT_UShort load_flags,
+ HB_Buffer buffer,
+ FT_Bool dvi,
+ FT_Bool r2l );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GPOS_H */
diff --git a/pango/opentype/harfbuzz-gsub-private.h b/pango/opentype/harfbuzz-gsub-private.h
new file mode 100644
index 00000000..84c08df5
--- /dev/null
+++ b/pango/opentype/harfbuzz-gsub-private.h
@@ -0,0 +1,448 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GSUB_PRIVATE_H
+#define HARFBUZZ_GSUB_PRIVATE_H
+
+#include "harfbuzz-gsub.h"
+
+FT_BEGIN_HEADER
+
+
+typedef union HB_GSUB_SubTable_ HB_GSUB_SubTable;
+
+/* LookupType 1 */
+
+struct HB_SingleSubstFormat1_
+{
+ FT_Short DeltaGlyphID; /* constant added to get
+ substitution glyph index */
+};
+
+typedef struct HB_SingleSubstFormat1_ HB_SingleSubstFormat1;
+
+
+struct HB_SingleSubstFormat2_
+{
+ FT_UShort GlyphCount; /* number of glyph IDs in
+ Substitute array */
+ FT_UShort* Substitute; /* array of substitute glyph IDs */
+};
+
+typedef struct HB_SingleSubstFormat2_ HB_SingleSubstFormat2;
+
+
+struct HB_SingleSubst_
+{
+ FT_UShort SubstFormat; /* 1 or 2 */
+ HB_Coverage Coverage; /* Coverage table */
+
+ union
+ {
+ HB_SingleSubstFormat1 ssf1;
+ HB_SingleSubstFormat2 ssf2;
+ } ssf;
+};
+
+typedef struct HB_SingleSubst_ HB_SingleSubst;
+
+
+/* LookupType 2 */
+
+struct HB_Sequence_
+{
+ FT_UShort GlyphCount; /* number of glyph IDs in the
+ Substitute array */
+ FT_UShort* Substitute; /* string of glyph IDs to
+ substitute */
+};
+
+typedef struct HB_Sequence_ HB_Sequence;
+
+
+struct HB_MultipleSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort SequenceCount; /* number of Sequence tables */
+ HB_Sequence* Sequence; /* array of Sequence tables */
+};
+
+typedef struct HB_MultipleSubst_ HB_MultipleSubst;
+
+
+/* LookupType 3 */
+
+struct HB_AlternateSet_
+{
+ FT_UShort GlyphCount; /* number of glyph IDs in the
+ Alternate array */
+ FT_UShort* Alternate; /* array of alternate glyph IDs */
+};
+
+typedef struct HB_AlternateSet_ HB_AlternateSet;
+
+
+struct HB_AlternateSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort AlternateSetCount;
+ /* number of AlternateSet tables */
+ HB_AlternateSet* AlternateSet; /* array of AlternateSet tables */
+};
+
+typedef struct HB_AlternateSubst_ HB_AlternateSubst;
+
+
+/* LookupType 4 */
+
+struct HB_Ligature_
+{
+ FT_UShort LigGlyph; /* glyphID of ligature
+ to substitute */
+ FT_UShort ComponentCount; /* number of components in ligature */
+ FT_UShort* Component; /* array of component glyph IDs */
+};
+
+typedef struct HB_Ligature_ HB_Ligature;
+
+
+struct HB_LigatureSet_
+{
+ FT_UShort LigatureCount; /* number of Ligature tables */
+ HB_Ligature* Ligature; /* array of Ligature tables */
+};
+
+typedef struct HB_LigatureSet_ HB_LigatureSet;
+
+
+struct HB_LigatureSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort LigatureSetCount; /* number of LigatureSet tables */
+ HB_LigatureSet* LigatureSet; /* array of LigatureSet tables */
+};
+
+typedef struct HB_LigatureSubst_ HB_LigatureSubst;
+
+
+/* needed by both lookup type 5 and 6 */
+
+struct HB_SubstLookupRecord_
+{
+ FT_UShort SequenceIndex; /* index into current
+ glyph sequence */
+ FT_UShort LookupListIndex; /* Lookup to apply to that pos. */
+};
+
+typedef struct HB_SubstLookupRecord_ HB_SubstLookupRecord;
+
+
+/* LookupType 5 */
+
+struct HB_SubRule_
+{
+ FT_UShort GlyphCount; /* total number of input glyphs */
+ FT_UShort SubstCount; /* number of SubstLookupRecord
+ tables */
+ FT_UShort* Input; /* array of input glyph IDs */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of SubstLookupRecord
+ tables */
+};
+
+typedef struct HB_SubRule_ HB_SubRule;
+
+
+struct HB_SubRuleSet_
+{
+ FT_UShort SubRuleCount; /* number of SubRule tables */
+ HB_SubRule* SubRule; /* array of SubRule tables */
+};
+
+typedef struct HB_SubRuleSet_ HB_SubRuleSet;
+
+
+struct HB_ContextSubstFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort SubRuleSetCount; /* number of SubRuleSet tables */
+ HB_SubRuleSet* SubRuleSet; /* array of SubRuleSet tables */
+};
+
+typedef struct HB_ContextSubstFormat1_ HB_ContextSubstFormat1;
+
+
+struct HB_SubClassRule_
+{
+ FT_UShort GlyphCount; /* total number of context classes */
+ FT_UShort SubstCount; /* number of SubstLookupRecord
+ tables */
+ FT_UShort* Class; /* array of classes */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of SubstLookupRecord
+ tables */
+};
+
+typedef struct HB_SubClassRule_ HB_SubClassRule;
+
+
+struct HB_SubClassSet_
+{
+ FT_UShort SubClassRuleCount;
+ /* number of SubClassRule tables */
+ HB_SubClassRule* SubClassRule; /* array of SubClassRule tables */
+};
+
+typedef struct HB_SubClassSet_ HB_SubClassSet;
+
+
+/* The `MaxContextLength' field is not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the context rules. */
+
+struct HB_ContextSubstFormat2_
+{
+ FT_UShort MaxContextLength;
+ /* maximal context length */
+ HB_Coverage Coverage; /* Coverage table */
+ HB_ClassDefinition ClassDef; /* ClassDef table */
+ FT_UShort SubClassSetCount;
+ /* number of SubClassSet tables */
+ HB_SubClassSet* SubClassSet; /* array of SubClassSet tables */
+};
+
+typedef struct HB_ContextSubstFormat2_ HB_ContextSubstFormat2;
+
+
+struct HB_ContextSubstFormat3_
+{
+ FT_UShort GlyphCount; /* number of input glyphs */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_Coverage* Coverage; /* array of Coverage tables */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ContextSubstFormat3_ HB_ContextSubstFormat3;
+
+
+struct HB_ContextSubst_
+{
+ FT_UShort SubstFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ContextSubstFormat1 csf1;
+ HB_ContextSubstFormat2 csf2;
+ HB_ContextSubstFormat3 csf3;
+ } csf;
+};
+
+typedef struct HB_ContextSubst_ HB_ContextSubst;
+
+
+/* LookupType 6 */
+
+struct HB_ChainSubRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack glyphs */
+ FT_UShort* Backtrack; /* array of backtrack glyph IDs */
+ FT_UShort InputGlyphCount;
+ /* total number of input glyphs */
+ FT_UShort* Input; /* array of input glyph IDs */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead glyphs */
+ FT_UShort* Lookahead; /* array of lookahead glyph IDs */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of SubstLookupRecords */
+};
+
+typedef struct HB_ChainSubRule_ HB_ChainSubRule;
+
+
+struct HB_ChainSubRuleSet_
+{
+ FT_UShort ChainSubRuleCount;
+ /* number of ChainSubRule tables */
+ HB_ChainSubRule* ChainSubRule; /* array of ChainSubRule tables */
+};
+
+typedef struct HB_ChainSubRuleSet_ HB_ChainSubRuleSet;
+
+
+struct HB_ChainContextSubstFormat1_
+{
+ HB_Coverage Coverage; /* Coverage table */
+ FT_UShort ChainSubRuleSetCount;
+ /* number of ChainSubRuleSet tables */
+ HB_ChainSubRuleSet* ChainSubRuleSet;
+ /* array of ChainSubRuleSet tables */
+};
+
+typedef struct HB_ChainContextSubstFormat1_ HB_ChainContextSubstFormat1;
+
+
+struct HB_ChainSubClassRule_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* total number of backtrack
+ classes */
+ FT_UShort* Backtrack; /* array of backtrack classes */
+ FT_UShort InputGlyphCount;
+ /* total number of context classes */
+ FT_UShort* Input; /* array of context classes */
+ FT_UShort LookaheadGlyphCount;
+ /* total number of lookahead
+ classes */
+ FT_UShort* Lookahead; /* array of lookahead classes */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainSubClassRule_ HB_ChainSubClassRule;
+
+
+struct HB_ChainSubClassSet_
+{
+ FT_UShort ChainSubClassRuleCount;
+ /* number of ChainSubClassRule
+ tables */
+ HB_ChainSubClassRule* ChainSubClassRule;
+ /* array of ChainSubClassRule
+ tables */
+};
+
+typedef struct HB_ChainSubClassSet_ HB_ChainSubClassSet;
+
+
+/* The `MaxXXXLength' fields are not defined in the TTO specification
+ but simplifies the implementation of this format. It holds the
+ maximal context length used in the specific context rules. */
+
+struct HB_ChainContextSubstFormat2_
+{
+ HB_Coverage Coverage; /* Coverage table */
+
+ FT_UShort MaxBacktrackLength;
+ /* maximal backtrack length */
+ HB_ClassDefinition BacktrackClassDef;
+ /* BacktrackClassDef table */
+ FT_UShort MaxInputLength;
+ /* maximal input length */
+ HB_ClassDefinition InputClassDef;
+ /* InputClassDef table */
+ FT_UShort MaxLookaheadLength;
+ /* maximal lookahead length */
+ HB_ClassDefinition LookaheadClassDef;
+ /* LookaheadClassDef table */
+
+ FT_UShort ChainSubClassSetCount;
+ /* number of ChainSubClassSet
+ tables */
+ HB_ChainSubClassSet* ChainSubClassSet;
+ /* array of ChainSubClassSet
+ tables */
+};
+
+typedef struct HB_ChainContextSubstFormat2_ HB_ChainContextSubstFormat2;
+
+
+struct HB_ChainContextSubstFormat3_
+{
+ FT_UShort BacktrackGlyphCount;
+ /* number of backtrack glyphs */
+ HB_Coverage* BacktrackCoverage;
+ /* array of backtrack Coverage
+ tables */
+ FT_UShort InputGlyphCount;
+ /* number of input glyphs */
+ HB_Coverage* InputCoverage;
+ /* array of input coverage
+ tables */
+ FT_UShort LookaheadGlyphCount;
+ /* number of lookahead glyphs */
+ HB_Coverage* LookaheadCoverage;
+ /* array of lookahead coverage
+ tables */
+ FT_UShort SubstCount; /* number of SubstLookupRecords */
+ HB_SubstLookupRecord* SubstLookupRecord;
+ /* array of substitution lookups */
+};
+
+typedef struct HB_ChainContextSubstFormat3_ HB_ChainContextSubstFormat3;
+
+
+struct HB_ChainContextSubst_
+{
+ FT_UShort SubstFormat; /* 1, 2, or 3 */
+
+ union
+ {
+ HB_ChainContextSubstFormat1 ccsf1;
+ HB_ChainContextSubstFormat2 ccsf2;
+ HB_ChainContextSubstFormat3 ccsf3;
+ } ccsf;
+};
+
+typedef struct HB_ChainContextSubst_ HB_ChainContextSubst;
+
+
+/* LookupType 8 */
+struct HB_ReverseChainContextSubst_
+{
+ FT_UShort SubstFormat; /* always 1 */
+ HB_Coverage Coverage; /* coverage table for input glyphs */
+ FT_UShort BacktrackGlyphCount; /* number of backtrack glyphs */
+ HB_Coverage* BacktrackCoverage; /* array of backtrack Coverage
+ tables */
+ FT_UShort LookaheadGlyphCount; /* number of lookahead glyphs */
+ HB_Coverage* LookaheadCoverage; /* array of lookahead Coverage
+ tables */
+ FT_UShort GlyphCount; /* number of Glyph IDs */
+ FT_UShort* Substitute; /* array of substitute Glyph ID */
+};
+
+typedef struct HB_ReverseChainContextSubst_ HB_ReverseChainContextSubst;
+
+
+union HB_GSUB_SubTable_
+{
+ HB_SingleSubst single;
+ HB_MultipleSubst multiple;
+ HB_AlternateSubst alternate;
+ HB_LigatureSubst ligature;
+ HB_ContextSubst context;
+ HB_ChainContextSubst chain;
+ HB_ReverseChainContextSubst reverse;
+};
+
+
+
+
+
+FT_Error _HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type );
+
+void _HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GSUB_PRIVATE_H */
diff --git a/pango/opentype/harfbuzz-gsub.c b/pango/opentype/harfbuzz-gsub.c
new file mode 100644
index 00000000..0a69fa6d
--- /dev/null
+++ b/pango/opentype/harfbuzz-gsub.c
@@ -0,0 +1,4581 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-open-private.h"
+#include "harfbuzz-gdef-private.h"
+
+#include FT_TRUETYPE_TAGS_H
+
+
+static FT_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level );
+
+
+
+/**********************
+ * Auxiliary functions
+ **********************/
+
+
+
+FT_Error HB_Load_GSUB_Table( FT_Face face,
+ HB_GSUBHeader** retptr,
+ HB_GDEFHeader* gdef )
+{
+ FT_Stream stream = face->stream;
+ FT_Memory memory = face->memory;
+ FT_Error error;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ FT_UShort i, num_lookups;
+ HB_GSUBHeader* gsub;
+ HB_Lookup* lo;
+
+ if ( !retptr )
+ return FT_Err_Invalid_Argument;
+
+ if (( error = _hb_ftglue_face_goto_table( face, TTAG_GSUB, stream ) ))
+ return error;
+
+ base_offset = FILE_Pos();
+
+ if ( ALLOC ( gsub, sizeof( *gsub ) ) )
+ return error;
+
+ gsub->memory = memory;
+
+ /* skip version */
+
+ if ( FILE_Seek( base_offset + 4L ) ||
+ ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList,
+ stream, HB_Type_GSUB ) ) != FT_Err_Ok )
+ goto Fail2;
+
+ gsub->gdef = gdef; /* can be NULL */
+
+ /* We now check the LookupFlags for values larger than 0xFF to find
+ out whether we need to load the `MarkAttachClassDef' field of the
+ GDEF table -- this hack is necessary for OpenType 1.2 tables since
+ the version field of the GDEF table hasn't been incremented.
+
+ For constructed GDEF tables, we only load it if
+ `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
+ a constructed mark attach table is not supported currently). */
+
+ if ( gdef &&
+ gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
+ {
+ lo = gsub->LookupList.Lookup;
+ num_lookups = gsub->LookupList.LookupCount;
+
+ for ( i = 0; i < num_lookups; i++ )
+ {
+
+ if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ {
+ if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
+ 256, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+
+ break;
+ }
+ }
+ }
+
+ *retptr = gsub;
+
+ return FT_Err_Ok;
+
+Fail1:
+ _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB, memory );
+
+Fail2:
+ _HB_OPEN_Free_FeatureList( &gsub->FeatureList, memory );
+
+Fail3:
+ _HB_OPEN_Free_ScriptList( &gsub->ScriptList, memory );
+
+Fail4:
+ FREE ( gsub );
+
+
+ return error;
+}
+
+
+FT_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub )
+{
+ FT_Memory memory = gsub->memory;
+
+ _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB, memory );
+ _HB_OPEN_Free_FeatureList( &gsub->FeatureList, memory );
+ _HB_OPEN_Free_ScriptList( &gsub->ScriptList, memory );
+
+ FREE( gsub );
+
+ return FT_Err_Ok;
+}
+
+/*****************************
+ * SubTable related functions
+ *****************************/
+
+static FT_Error Lookup_DefaultSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ return HB_Err_Not_Covered;
+}
+
+
+/* LookupType 1 */
+
+/* SingleSubstFormat1 */
+/* SingleSubstFormat2 */
+
+static FT_Error Load_SingleSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_SingleSubst* ss = &st->single;
+
+ FT_UShort n, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ FT_UShort* s;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ ss->SubstFormat = GET_UShort();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ switch ( ss->SubstFormat )
+ {
+ case 1:
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ ss->ssf.ssf1.DeltaGlyphID = GET_UShort();
+
+ FORGET_Frame();
+
+ break;
+
+ case 2:
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ss->ssf.ssf2.GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ss->ssf.ssf2.Substitute = NULL;
+
+ if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, FT_UShort ) )
+ goto Fail2;
+
+ s = ss->ssf.ssf2.Substitute;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ s[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ break;
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( s );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ss->Coverage, memory );
+ return error;
+}
+
+
+static void Free_SingleSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ HB_SingleSubst* ss = &st->single;
+
+ switch ( ss->SubstFormat )
+ {
+ case 1:
+ break;
+
+ case 2:
+ FREE( ss->ssf.ssf2.Substitute );
+ break;
+ }
+
+ _HB_OPEN_Free_Coverage( &ss->Coverage, memory );
+}
+
+
+static FT_Error Lookup_SingleSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, value, property;
+ FT_Error error;
+ HB_SingleSubst* ss = &st->single;
+ HB_GDEFHeader* gdef = gsub->gdef;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ switch ( ss->SubstFormat )
+ {
+ case 1:
+ value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
+ return error;
+ break;
+
+ case 2:
+ if ( index >= ss->ssf.ssf2.GlyphCount )
+ return HB_Err_Invalid_GSUB_SubTable;
+ value = ss->ssf.ssf2.Substitute[index];
+ if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )
+ return error;
+ break;
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable;
+ }
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* we inherit the old glyph class to the substituted glyph */
+
+ error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 2 */
+
+/* Sequence */
+
+static FT_Error Load_Sequence( HB_Sequence* s,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* sub;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = s->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ s->Substitute = NULL;
+
+ if ( count )
+ {
+ if ( ALLOC_ARRAY( s->Substitute, count, FT_UShort ) )
+ return error;
+
+ sub = s->Substitute;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( sub );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ sub[n] = GET_UShort();
+
+ FORGET_Frame();
+ }
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Sequence( HB_Sequence* s,
+ FT_Memory memory )
+{
+ FREE( s->Substitute );
+}
+
+
+/* MultipleSubstFormat1 */
+
+static FT_Error Load_MultipleSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_MultipleSubst* ms = &st->multiple;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Sequence* s;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ ms->SubstFormat = GET_UShort(); /* should be 1 */
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ms->SequenceCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ms->Sequence = NULL;
+
+ if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) )
+ goto Fail2;
+
+ s = ms->Sequence;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Sequence( &s[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_Sequence( &s[m], memory );
+
+ FREE( s );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ms->Coverage, memory );
+ return error;
+}
+
+
+static void Free_MultipleSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_MultipleSubst* ms = &st->multiple;
+
+ HB_Sequence* s;
+
+
+ if ( ms->Sequence )
+ {
+ count = ms->SequenceCount;
+ s = ms->Sequence;
+
+ for ( n = 0; n < count; n++ )
+ Free_Sequence( &s[n], memory );
+
+ FREE( s );
+ }
+
+ _HB_OPEN_Free_Coverage( &ms->Coverage, memory );
+}
+
+
+static FT_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, property, n, count;
+ FT_UShort*s;
+ HB_MultipleSubst* ms = &st->multiple;
+ HB_GDEFHeader* gdef = gsub->gdef;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( index >= ms->SequenceCount )
+ return HB_Err_Invalid_GSUB_SubTable;
+
+ count = ms->Sequence[index].GlyphCount;
+ s = ms->Sequence[index].Substitute;
+
+ if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
+ return error;
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* this is a guess only ... */
+
+ if ( property == HB_GDEF_LIGATURE )
+ property = HB_GDEF_BASE_GLYPH;
+
+ for ( n = 0; n < count; n++ )
+ {
+ error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 3 */
+
+/* AlternateSet */
+
+static FT_Error Load_AlternateSet( HB_AlternateSet* as,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* a;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = as->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ as->Alternate = NULL;
+
+ if ( ALLOC_ARRAY( as->Alternate, count, FT_UShort ) )
+ return error;
+
+ a = as->Alternate;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( a );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ a[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_AlternateSet( HB_AlternateSet* as,
+ FT_Memory memory )
+{
+ FREE( as->Alternate );
+}
+
+
+/* AlternateSubstFormat1 */
+
+static FT_Error Load_AlternateSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_AlternateSubst* as = &st->alternate;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_AlternateSet* aset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ as->SubstFormat = GET_UShort(); /* should be 1 */
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = as->AlternateSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ as->AlternateSet = NULL;
+
+ if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) )
+ goto Fail2;
+
+ aset = as->AlternateSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_AlternateSet( &aset[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_AlternateSet( &aset[m], memory );
+
+ FREE( aset );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &as->Coverage, memory );
+ return error;
+}
+
+
+static void Free_AlternateSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_AlternateSubst* as = &st->alternate;
+
+ HB_AlternateSet* aset;
+
+
+ if ( as->AlternateSet )
+ {
+ count = as->AlternateSetCount;
+ aset = as->AlternateSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_AlternateSet( &aset[n], memory );
+
+ FREE( aset );
+ }
+
+ _HB_OPEN_Free_Coverage( &as->Coverage, memory );
+}
+
+
+static FT_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, alt_index, property;
+ HB_AlternateSubst* as = &st->alternate;
+ HB_GDEFHeader* gdef = gsub->gdef;
+
+
+ HB_AlternateSet aset;
+
+
+ if ( context_length != 0xFFFF && context_length < 1 )
+ return HB_Err_Not_Covered;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ aset = as->AlternateSet[index];
+
+ /* we use a user-defined callback function to get the alternate index */
+
+ if ( gsub->altfunc )
+ alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(),
+ aset.GlyphCount, aset.Alternate,
+ gsub->data );
+ else
+ alt_index = 0;
+
+ if ( ADD_Glyph( buffer, aset.Alternate[alt_index],
+ 0xFFFF, 0xFFFF ) )
+ return error;
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* we inherit the old glyph class to the substituted glyph */
+
+ error = _HB_GDEF_Add_Glyph_Property( gdef, aset.Alternate[alt_index],
+ property );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 4 */
+
+/* Ligature */
+
+static FT_Error Load_Ligature( HB_Ligature* l,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* c;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ l->LigGlyph = GET_UShort();
+ l->ComponentCount = GET_UShort();
+
+ FORGET_Frame();
+
+ l->Component = NULL;
+
+ count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */
+
+ if ( ALLOC_ARRAY( l->Component, count, FT_UShort ) )
+ return error;
+
+ c = l->Component;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( c );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ c[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Ligature( HB_Ligature* l,
+ FT_Memory memory )
+{
+ FREE( l->Component );
+}
+
+
+/* LigatureSet */
+
+static FT_Error Load_LigatureSet( HB_LigatureSet* ls,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Ligature* l;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ls->LigatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ls->Ligature = NULL;
+
+ if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) )
+ return error;
+
+ l = ls->Ligature;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Ligature( &l[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_Ligature( &l[m], memory );
+
+ FREE( l );
+ return error;
+}
+
+
+static void Free_LigatureSet( HB_LigatureSet* ls,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Ligature* l;
+
+
+ if ( ls->Ligature )
+ {
+ count = ls->LigatureCount;
+ l = ls->Ligature;
+
+ for ( n = 0; n < count; n++ )
+ Free_Ligature( &l[n], memory );
+
+ FREE( l );
+ }
+}
+
+
+/* LigatureSubstFormat1 */
+
+static FT_Error Load_LigatureSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_LigatureSubst* ls = &st->ligature;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LigatureSet* lset;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ ls->SubstFormat = GET_UShort(); /* should be 1 */
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ls->LigatureSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ls->LigatureSet = NULL;
+
+ if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) )
+ goto Fail2;
+
+ lset = ls->LigatureSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LigatureSet( &lset[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_LigatureSet( &lset[m], memory );
+
+ FREE( lset );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ls->Coverage, memory );
+ return error;
+}
+
+
+static void Free_LigatureSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_LigatureSubst* ls = &st->ligature;
+
+ HB_LigatureSet* lset;
+
+
+ if ( ls->LigatureSet )
+ {
+ count = ls->LigatureSetCount;
+ lset = ls->LigatureSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_LigatureSet( &lset[n], memory );
+
+ FREE( lset );
+ }
+
+ _HB_OPEN_Free_Coverage( &ls->Coverage, memory );
+}
+
+
+static FT_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
+ FT_UShort* c;
+ HB_LigatureSubst* ls = &st->ligature;
+ HB_GDEFHeader* gdef = gsub->gdef;
+
+ HB_Ligature* lig;
+
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
+ first_is_mark = TRUE;
+
+ error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( index >= ls->LigatureSetCount )
+ return HB_Err_Invalid_GSUB_SubTable;
+
+ lig = ls->LigatureSet[index].Ligature;
+
+ for ( numlig = ls->LigatureSet[index].LigatureCount;
+ numlig;
+ numlig--, lig++ )
+ {
+ if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
+ goto next_ligature; /* Not enough glyphs in input */
+
+ c = lig->Component;
+
+ is_mark = first_is_mark;
+
+ if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
+ break;
+
+ for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lig->ComponentCount - i == buffer->in_length )
+ goto next_ligature;
+ j++;
+ }
+
+ if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
+ is_mark = FALSE;
+
+ if ( IN_GLYPH( j ) != c[i - 1] )
+ goto next_ligature;
+ }
+
+ if ( gdef && gdef->NewGlyphClasses )
+ {
+ /* this is just a guess ... */
+
+ error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph,
+ is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE );
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
+ {
+ /* We don't use a new ligature ID if there are no skipped
+ glyphs and the ligature already has an ID. */
+
+ if ( IN_LIGID( buffer->in_pos ) )
+ {
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, 0xFFFF ) )
+ return error;
+ }
+ else
+ {
+ FT_UShort ligID = hb_buffer_allocate_ligid( buffer );
+ if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
+ 0xFFFF, ligID ) )
+ return error;
+ }
+ }
+ else
+ {
+ FT_UShort ligID = hb_buffer_allocate_ligid( buffer );
+ if ( ADD_Glyph( buffer, lig->LigGlyph,
+ 0xFFFF, ligID ) )
+ return error;
+
+ /* Now we must do a second loop to copy the skipped glyphs to
+ `out' and assign component values to it. We start with the
+ glyph after the first component. Glyphs between component
+ i and i+1 belong to component i. Together with the ligID
+ value it is later possible to check whether a specific
+ component value really belongs to a given ligature. */
+
+ for ( i = 0; i < lig->ComponentCount - 1; i++ )
+ {
+ while ( CHECK_Property( gdef, IN_CURITEM(),
+ flags, &property ) )
+ if ( ADD_Glyph( buffer, IN_CURGLYPH(),
+ i, ligID ) )
+ return error;
+
+ (buffer->in_pos)++;
+ }
+ }
+
+ return FT_Err_Ok;
+
+ next_ligature:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* Do the actual substitution for a context substitution (either format
+ 5 or 6). This is only called after we've determined that the input
+ matches the subrule. */
+
+static FT_Error Do_ContextSubst( HB_GSUBHeader* gsub,
+ FT_UShort GlyphCount,
+ FT_UShort SubstCount,
+ HB_SubstLookupRecord* subst,
+ HB_Buffer buffer,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort i, old_pos;
+
+
+ i = 0;
+
+ while ( i < GlyphCount )
+ {
+ if ( SubstCount && i == subst->SequenceIndex )
+ {
+ old_pos = buffer->in_pos;
+
+ /* Do a substitution */
+
+ error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
+ GlyphCount, nesting_level );
+
+ subst++;
+ SubstCount--;
+ i += buffer->in_pos - old_pos;
+
+ if ( error == HB_Err_Not_Covered )
+ {
+ /* XXX "can't happen" -- but don't count on it */
+
+ if ( ADD_Glyph( buffer, IN_CURGLYPH(),
+ 0xFFFF, 0xFFFF ) )
+ return error;
+ i++;
+ }
+ else if ( error )
+ return error;
+ }
+ else
+ {
+ /* No substitution for this index */
+
+ if ( ADD_Glyph( buffer, IN_CURGLYPH(),
+ 0xFFFF, 0xFFFF ) )
+ return error;
+ i++;
+ }
+ }
+
+ return FT_Err_Ok;
+}
+
+
+/* LookupType 5 */
+
+/* SubRule */
+
+static FT_Error Load_SubRule( HB_SubRule* sr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* i;
+
+ HB_SubstLookupRecord* slr;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ sr->GlyphCount = GET_UShort();
+ sr->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ sr->Input = NULL;
+
+ count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( sr->Input, count, FT_UShort ) )
+ return error;
+
+ i = sr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ sr->SubstLookupRecord = NULL;
+
+ count = sr->SubstCount;
+
+ if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = sr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( i );
+ return error;
+}
+
+
+static void Free_SubRule( HB_SubRule* sr,
+ FT_Memory memory )
+{
+ FREE( sr->SubstLookupRecord );
+ FREE( sr->Input );
+}
+
+
+/* SubRuleSet */
+
+static FT_Error Load_SubRuleSet( HB_SubRuleSet* srs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubRule* sr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = srs->SubRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ srs->SubRule = NULL;
+
+ if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) )
+ return error;
+
+ sr = srs->SubRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubRule( &sr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_SubRule( &sr[m], memory );
+
+ FREE( sr );
+ return error;
+}
+
+
+static void Free_SubRuleSet( HB_SubRuleSet* srs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubRule* sr;
+
+
+ if ( srs->SubRule )
+ {
+ count = srs->SubRuleCount;
+ sr = srs->SubRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubRule( &sr[n], memory );
+
+ FREE( sr );
+ }
+}
+
+
+/* ContextSubstFormat1 */
+
+static FT_Error Load_ContextSubst1( HB_ContextSubstFormat1* csf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubRuleSet* srs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = csf1->SubRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csf1->SubRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) )
+ goto Fail2;
+
+ srs = csf1->SubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubRuleSet( &srs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_SubRuleSet( &srs[m], memory );
+
+ FREE( srs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &csf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextSubst1( HB_ContextSubstFormat1* csf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubRuleSet* srs;
+
+
+ if ( csf1->SubRuleSet )
+ {
+ count = csf1->SubRuleSetCount;
+ srs = csf1->SubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubRuleSet( &srs[n], memory );
+
+ FREE( srs );
+ }
+
+ _HB_OPEN_Free_Coverage( &csf1->Coverage, memory );
+}
+
+
+/* SubClassRule */
+
+static FT_Error Load_SubClassRule( HB_ContextSubstFormat2* csf2,
+ HB_SubClassRule* scr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* c;
+ HB_SubstLookupRecord* slr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ scr->GlyphCount = GET_UShort();
+ scr->SubstCount = GET_UShort();
+
+ if ( scr->GlyphCount > csf2->MaxContextLength )
+ csf2->MaxContextLength = scr->GlyphCount;
+
+ FORGET_Frame();
+
+ scr->Class = NULL;
+
+ count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( scr->Class, count, FT_UShort ) )
+ return error;
+
+ c = scr->Class;
+ d = csf2->ClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ c[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+ if ( !d[c[n]] )
+ c[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ scr->SubstLookupRecord = NULL;
+
+ count = scr->SubstCount;
+
+ if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = scr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( c );
+ return error;
+}
+
+
+static void Free_SubClassRule( HB_SubClassRule* scr,
+ FT_Memory memory )
+{
+ FREE( scr->SubstLookupRecord );
+ FREE( scr->Class );
+}
+
+
+/* SubClassSet */
+
+static FT_Error Load_SubClassSet( HB_ContextSubstFormat2* csf2,
+ HB_SubClassSet* scs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubClassRule* scr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = scs->SubClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ scs->SubClassRule = NULL;
+
+ if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) )
+ return error;
+
+ scr = scs->SubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubClassRule( csf2, &scr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_SubClassRule( &scr[m], memory );
+
+ FREE( scr );
+ return error;
+}
+
+
+static void Free_SubClassSet( HB_SubClassSet* scs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubClassRule* scr;
+
+
+ if ( scs->SubClassRule )
+ {
+ count = scs->SubClassRuleCount;
+ scr = scs->SubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubClassRule( &scr[n], memory );
+
+ FREE( scr );
+ }
+}
+
+
+/* ContextSubstFormat2 */
+
+static FT_Error Load_ContextSubst2( HB_ContextSubstFormat2* csf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubClassSet* scs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 4L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ /* `SubClassSetCount' is the upper limit for class values, thus we
+ read it now to make an additional safety check. */
+
+ count = csf2->SubClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+
+ csf2->SubClassSet = NULL;
+ csf2->MaxContextLength = 0;
+
+ if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) )
+ goto Fail2;
+
+ scs = csf2->SubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubClassSet( csf2, &scs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a SubClassSet table with no entries */
+
+ csf2->SubClassSet[n].SubClassRuleCount = 0;
+ csf2->SubClassSet[n].SubClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_SubClassSet( &scs[m], memory );
+
+ FREE( scs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_Coverage( &csf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ContextSubst2( HB_ContextSubstFormat2* csf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_SubClassSet* scs;
+
+
+ if ( csf2->SubClassSet )
+ {
+ count = csf2->SubClassSetCount;
+ scs = csf2->SubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubClassSet( &scs[n], memory );
+
+ FREE( scs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef, memory );
+ _HB_OPEN_Free_Coverage( &csf2->Coverage, memory );
+}
+
+
+/* ContextSubstFormat3 */
+
+static FT_Error Load_ContextSubst3( HB_ContextSubstFormat3* csf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* c;
+ HB_SubstLookupRecord* slr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ csf3->GlyphCount = GET_UShort();
+ csf3->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csf3->Coverage = NULL;
+
+ count = csf3->GlyphCount;
+
+ if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) )
+ return error;
+
+ c = csf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ csf3->SubstLookupRecord = NULL;
+
+ count = csf3->SubstCount;
+
+ if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
+ HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = csf3->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ for ( m = 0; m < n; m++ )
+ _HB_OPEN_Free_Coverage( &c[m], memory );
+
+ FREE( c );
+ return error;
+}
+
+
+static void Free_ContextSubst3( HB_ContextSubstFormat3* csf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( csf3->SubstLookupRecord );
+
+ if ( csf3->Coverage )
+ {
+ count = csf3->GlyphCount;
+ c = csf3->Coverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ContextSubst */
+
+static FT_Error Load_ContextSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ContextSubst* cs = &st->context;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cs->SubstFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cs->SubstFormat )
+ {
+ case 1:
+ return Load_ContextSubst1( &cs->csf.csf1, stream );
+
+ case 2:
+ return Load_ContextSubst2( &cs->csf.csf2, stream );
+
+ case 3:
+ return Load_ContextSubst3( &cs->csf.csf3, stream );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ContextSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ContextSubst* cs = &st->context;
+
+ switch ( cs->SubstFormat )
+ {
+ case 1:
+ Free_ContextSubst1( &cs->csf.csf1, memory );
+ break;
+
+ case 2:
+ Free_ContextSubst2( &cs->csf.csf2, memory );
+ break;
+
+ case 3:
+ Free_ContextSubst3( &cs->csf.csf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,
+ HB_ContextSubstFormat1* csf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, numsr;
+ FT_Error error;
+
+ HB_SubRule* sr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ sr = csf1->SubRuleSet[index].SubRule;
+ numsr = csf1->SubRuleSet[index].SubRuleCount;
+
+ for ( k = 0; k < numsr; k++ )
+ {
+ if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
+ goto next_subrule;
+
+ if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
+ goto next_subrule; /* context is too long */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + sr[k].GlyphCount - i == buffer->in_length )
+ goto next_subrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
+ goto next_subrule;
+ }
+
+ return Do_ContextSubst( gsub, sr[k].GlyphCount,
+ sr[k].SubstCount, sr[k].SubstLookupRecord,
+ buffer,
+ nesting_level );
+ next_subrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,
+ HB_ContextSubstFormat2* csf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Error error;
+ FT_Memory memory = gsub->memory;
+ FT_UShort i, j, k, known_classes;
+
+ FT_UShort* classes;
+ FT_UShort* cl;
+
+ HB_SubClassSet* scs;
+ HB_SubClassRule* sr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) )
+ return error;
+
+ error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(),
+ &classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = 0;
+
+ scs = &csf2->SubClassSet[classes[0]];
+ if ( !scs )
+ {
+ error = HB_Err_Invalid_GSUB_SubTable;
+ goto End;
+ }
+
+ for ( k = 0; k < scs->SubClassRuleCount; k++ )
+ {
+ sr = &scs->SubClassRule[k];
+
+ if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
+ goto next_subclassrule;
+
+ if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
+ goto next_subclassrule; /* context is too long */
+
+ cl = sr->Class;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+
+ if ( j + sr->GlyphCount - i < buffer->in_length )
+ goto next_subclassrule;
+ j++;
+ }
+
+ if ( i > known_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End;
+ known_classes = i;
+ }
+
+ if ( cl[i - 1] != classes[i] )
+ goto next_subclassrule;
+ }
+
+ error = Do_ContextSubst( gsub, sr->GlyphCount,
+ sr->SubstCount, sr->SubstLookupRecord,
+ buffer,
+ nesting_level );
+ goto End;
+
+ next_subclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End:
+ FREE( classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,
+ HB_ContextSubstFormat3* csf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error;
+ FT_UShort index, i, j, property;
+
+ HB_Coverage* c;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
+ return HB_Err_Not_Covered;
+
+ if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
+ return HB_Err_Not_Covered; /* context is too long */
+
+ c = csf3->Coverage;
+
+ for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + csf3->GlyphCount - i == buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextSubst( gsub, csf3->GlyphCount,
+ csf3->SubstCount, csf3->SubstLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ContextSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ContextSubst* cs = &st->context;
+
+ switch ( cs->SubstFormat )
+ {
+ case 1:
+ return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer,
+ flags, context_length, nesting_level );
+
+ case 2:
+ return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer,
+ flags, context_length, nesting_level );
+
+ case 3:
+ return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer,
+ flags, context_length, nesting_level );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+/* LookupType 6 */
+
+/* ChainSubRule */
+
+static FT_Error Load_ChainSubRule( HB_ChainSubRule* csr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+
+ HB_SubstLookupRecord* slr;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ csr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->Backtrack = NULL;
+
+ count = csr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( csr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = csr->Backtrack;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ b[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ csr->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->Input = NULL;
+
+ count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( csr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = csr->Input;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ i[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ csr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->Lookahead = NULL;
+
+ count = csr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( csr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = csr->Lookahead;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ l[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ csr->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csr->SubstLookupRecord = NULL;
+
+ count = csr->SubstCount;
+
+ if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = csr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainSubRule( HB_ChainSubRule* csr,
+ FT_Memory memory )
+{
+ FREE( csr->SubstLookupRecord );
+ FREE( csr->Lookahead );
+ FREE( csr->Input );
+ FREE( csr->Backtrack );
+}
+
+
+/* ChainSubRuleSet */
+
+static FT_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainSubRule* csr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = csrs->ChainSubRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ csrs->ChainSubRule = NULL;
+
+ if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) )
+ return error;
+
+ csr = csrs->ChainSubRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubRule( &csr[n], stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubRule( &csr[m], memory );
+
+ FREE( csr );
+ return error;
+}
+
+
+static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubRule* csr;
+
+
+ if ( csrs->ChainSubRule )
+ {
+ count = csrs->ChainSubRuleCount;
+ csr = csrs->ChainSubRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubRule( &csr[n], memory );
+
+ FREE( csr );
+ }
+}
+
+
+/* ChainContextSubstFormat1 */
+
+static FT_Error Load_ChainContextSubst1(
+ HB_ChainContextSubstFormat1* ccsf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainSubRuleSet* csrs;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = ccsf1->ChainSubRuleSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf1->ChainSubRuleSet = NULL;
+
+ if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) )
+ goto Fail2;
+
+ csrs = ccsf1->ChainSubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubRuleSet( &csrs[m], memory );
+
+ FREE( csrs );
+
+Fail2:
+ _HB_OPEN_Free_Coverage( &ccsf1->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubRuleSet* csrs;
+
+
+ if ( ccsf1->ChainSubRuleSet )
+ {
+ count = ccsf1->ChainSubRuleSetCount;
+ csrs = ccsf1->ChainSubRuleSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubRuleSet( &csrs[n], memory );
+
+ FREE( csrs );
+ }
+
+ _HB_OPEN_Free_Coverage( &ccsf1->Coverage, memory );
+}
+
+
+/* ChainSubClassRule */
+
+static FT_Error Load_ChainSubClassRule(
+ HB_ChainContextSubstFormat2* ccsf2,
+ HB_ChainSubClassRule* cscr,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* b;
+ FT_UShort* i;
+ FT_UShort* l;
+ HB_SubstLookupRecord* slr;
+ FT_Bool* d;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ cscr->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
+ ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
+
+ cscr->Backtrack = NULL;
+
+ count = cscr->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( cscr->Backtrack, count, FT_UShort ) )
+ return error;
+
+ b = cscr->Backtrack;
+ d = ccsf2->BacktrackClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail4;
+
+ for ( n = 0; n < count; n++ )
+ {
+ b[n] = GET_UShort();
+
+ /* We check whether the specific class is used at all. If not,
+ class 0 is used instead. */
+
+ if ( !d[b[n]] )
+ b[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ cscr->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
+ ccsf2->MaxInputLength = cscr->InputGlyphCount;
+
+ cscr->Input = NULL;
+
+ count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
+
+ if ( ALLOC_ARRAY( cscr->Input, count, FT_UShort ) )
+ goto Fail4;
+
+ i = cscr->Input;
+ d = ccsf2->InputClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail3;
+
+ for ( n = 0; n < count; n++ )
+ {
+ i[n] = GET_UShort();
+
+ if ( !d[i[n]] )
+ i[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ cscr->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )
+ ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;
+
+ cscr->Lookahead = NULL;
+
+ count = cscr->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( cscr->Lookahead, count, FT_UShort ) )
+ goto Fail3;
+
+ l = cscr->Lookahead;
+ d = ccsf2->LookaheadClassDef.Defined;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail2;
+
+ for ( n = 0; n < count; n++ )
+ {
+ l[n] = GET_UShort();
+
+ if ( !d[l[n]] )
+ l[n] = 0;
+ }
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ cscr->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cscr->SubstLookupRecord = NULL;
+
+ count = cscr->SubstCount;
+
+ if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,
+ HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = cscr->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ FREE( l );
+
+Fail3:
+ FREE( i );
+
+Fail4:
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr,
+ FT_Memory memory )
+{
+ FREE( cscr->SubstLookupRecord );
+ FREE( cscr->Lookahead );
+ FREE( cscr->Input );
+ FREE( cscr->Backtrack );
+}
+
+
+/* SubClassSet */
+
+static FT_Error Load_ChainSubClassSet(
+ HB_ChainContextSubstFormat2* ccsf2,
+ HB_ChainSubClassSet* cscs,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ChainSubClassRule* cscr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cscs->ChainSubClassRuleCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cscs->ChainSubClassRule = NULL;
+
+ if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,
+ HB_ChainSubClassRule ) )
+ return error;
+
+ cscr = cscs->ChainSubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubClassRule( &cscr[m], memory );
+
+ FREE( cscr );
+ return error;
+}
+
+
+static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubClassRule* cscr;
+
+
+ if ( cscs->ChainSubClassRule )
+ {
+ count = cscs->ChainSubClassRuleCount;
+ cscr = cscs->ChainSubClassRule;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubClassRule( &cscr[n], memory );
+
+ FREE( cscr );
+ }
+}
+
+static FT_Error GSUB_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_ULong class_offset,
+ FT_ULong base_offset,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_ULong cur_offset;
+
+ cur_offset = FILE_Pos();
+
+ if ( class_offset )
+ {
+ if ( !FILE_Seek( class_offset + base_offset ) )
+ error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
+ }
+ else
+ error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
+
+ if (error == FT_Err_Ok)
+ (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
+
+ return error;
+}
+
+
+/* ChainContextSubstFormat2 */
+
+static FT_Error Load_ChainContextSubst2(
+ HB_ChainContextSubstFormat2* ccsf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n = 0, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+ FT_ULong backtrack_offset, input_offset, lookahead_offset;
+
+ HB_ChainSubClassSet* cscs;
+
+
+ base_offset = FILE_Pos() - 2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+ if ( ACCESS_Frame( 8L ) )
+ goto Fail5;
+
+ backtrack_offset = GET_UShort();
+ input_offset = GET_UShort();
+ lookahead_offset = GET_UShort();
+
+ /* `ChainSubClassSetCount' is the upper limit for input class values,
+ thus we read it now to make an additional safety check. No limit
+ is known or needed for the other two class definitions */
+
+ count = ccsf2->ChainSubClassSetCount = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
+ backtrack_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail5;
+
+ if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
+ input_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ if ( ( error = GSUB_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
+ lookahead_offset, base_offset,
+ stream ) ) != FT_Err_Ok )
+ goto Fail3;
+
+ ccsf2->ChainSubClassSet = NULL;
+ ccsf2->MaxBacktrackLength = 0;
+ ccsf2->MaxInputLength = 0;
+ ccsf2->MaxLookaheadLength = 0;
+
+ if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) )
+ goto Fail2;
+
+ cscs = ccsf2->ChainSubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],
+ stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a ChainSubClassSet table with no entries */
+
+ ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;
+ ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL;
+ }
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_ChainSubClassSet( &cscs[m], memory );
+
+ FREE( cscs );
+
+Fail2:
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory );
+
+Fail3:
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef, memory );
+
+Fail4:
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory );
+
+Fail5:
+ _HB_OPEN_Free_Coverage( &ccsf2->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ChainSubClassSet* cscs;
+
+
+ if ( ccsf2->ChainSubClassSet )
+ {
+ count = ccsf2->ChainSubClassSetCount;
+ cscs = ccsf2->ChainSubClassSet;
+
+ for ( n = 0; n < count; n++ )
+ Free_ChainSubClassSet( &cscs[n], memory );
+
+ FREE( cscs );
+ }
+
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef, memory );
+ _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory );
+
+ _HB_OPEN_Free_Coverage( &ccsf2->Coverage, memory );
+}
+
+
+/* ChainContextSubstFormat3 */
+
+static FT_Error Load_ChainContextSubst3(
+ HB_ChainContextSubstFormat3* ccsf3,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, nb = 0, ni =0, nl = 0, m, count;
+ FT_UShort backtrack_count, input_count, lookahead_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* b;
+ HB_Coverage* i;
+ HB_Coverage* l;
+ HB_SubstLookupRecord* slr;
+
+
+ base_offset = FILE_Pos() - 2L;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccsf3->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->BacktrackCoverage = NULL;
+
+ backtrack_count = ccsf3->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,
+ HB_Coverage ) )
+ return error;
+
+ b = ccsf3->BacktrackCoverage;
+
+ for ( nb = 0; nb < backtrack_count; nb++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != FT_Err_Ok )
+ goto Fail4;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ ccsf3->InputGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->InputCoverage = NULL;
+
+ input_count = ccsf3->InputGlyphCount;
+
+ if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) )
+ goto Fail4;
+
+ i = ccsf3->InputCoverage;
+
+ for ( ni = 0; ni < input_count; ni++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ ccsf3->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->LookaheadCoverage = NULL;
+
+ lookahead_count = ccsf3->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,
+ HB_Coverage ) )
+ goto Fail3;
+
+ l = ccsf3->LookaheadCoverage;
+
+ for ( nl = 0; nl < lookahead_count; nl++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ ccsf3->SubstCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ccsf3->SubstLookupRecord = NULL;
+
+ count = ccsf3->SubstCount;
+
+ if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,
+ HB_SubstLookupRecord ) )
+ goto Fail2;
+
+ slr = ccsf3->SubstLookupRecord;
+
+ if ( ACCESS_Frame( count * 4L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ {
+ slr[n].SequenceIndex = GET_UShort();
+ slr[n].LookupListIndex = GET_UShort();
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( slr );
+
+Fail2:
+ for ( m = 0; m < nl; m++ )
+ _HB_OPEN_Free_Coverage( &l[m], memory );
+
+ FREE( l );
+
+Fail3:
+ for ( m = 0; m < ni; m++ )
+ _HB_OPEN_Free_Coverage( &i[m], memory );
+
+ FREE( i );
+
+Fail4:
+ for ( m = 0; m < nb; m++ )
+ _HB_OPEN_Free_Coverage( &b[m], memory );
+
+ FREE( b );
+ return error;
+}
+
+
+static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Coverage* c;
+
+
+ FREE( ccsf3->SubstLookupRecord );
+
+ if ( ccsf3->LookaheadCoverage )
+ {
+ count = ccsf3->LookaheadGlyphCount;
+ c = ccsf3->LookaheadCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccsf3->InputCoverage )
+ {
+ count = ccsf3->InputGlyphCount;
+ c = ccsf3->InputCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( ccsf3->BacktrackCoverage )
+ {
+ count = ccsf3->BacktrackGlyphCount;
+ c = ccsf3->BacktrackCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+}
+
+
+/* ChainContextSubst */
+
+static FT_Error Load_ChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ HB_ChainContextSubst* ccs = &st->chain;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ ccs->SubstFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( ccs->SubstFormat )
+ {
+ case 1:
+ return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
+
+ case 2:
+ return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
+
+ case 3:
+ return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static void Free_ChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ HB_ChainContextSubst* ccs = &st->chain;
+
+ switch ( ccs->SubstFormat )
+ {
+ case 1:
+ Free_ChainContextSubst1( &ccs->ccsf.ccsf1, memory );
+ break;
+
+ case 2:
+ Free_ChainContextSubst2( &ccs->ccsf.ccsf2, memory );
+ break;
+
+ case 3:
+ Free_ChainContextSubst3( &ccs->ccsf.ccsf3, memory );
+ break;
+ }
+}
+
+
+static FT_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
+ HB_ChainContextSubstFormat1* ccsf1,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_UShort i, j, k, num_csr;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+
+ HB_ChainSubRule* csr;
+ HB_ChainSubRule curr_csr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ csr = ccsf1->ChainSubRuleSet[index].ChainSubRule;
+ num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;
+
+ for ( k = 0; k < num_csr; k++ )
+ {
+ curr_csr = csr[k];
+ bgc = curr_csr.BacktrackGlyphCount;
+ igc = curr_csr.InputGlyphCount;
+ lgc = curr_csr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainsubrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainsubrule;
+
+ if ( bgc )
+ {
+ /* since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainsubrule;
+ j--;
+ }
+
+ /* In OpenType 1.3, it is undefined whether the offsets of
+ backtrack glyphs is in logical order or not. Version 1.4
+ will clarify this:
+
+ Logical order - a b c d e f g h i j
+ i
+ Input offsets - 0 1
+ Backtrack offsets - 3 2 1 0
+ Lookahead offsets - 0 1 2 3 */
+
+ if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )
+ goto next_chainsubrule;
+ }
+ }
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == buffer->in_length )
+ goto next_chainsubrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
+ goto next_chainsubrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == buffer->in_length )
+ goto next_chainsubrule;
+ j++;
+ }
+
+ if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
+ goto next_chainsubrule;
+ }
+
+ return Do_ContextSubst( gsub, igc,
+ curr_csr.SubstCount,
+ curr_csr.SubstLookupRecord,
+ buffer,
+ nesting_level );
+
+ next_chainsubrule:
+ ;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
+ HB_ChainContextSubstFormat2* ccsf2,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, property;
+ FT_Memory memory;
+ FT_Error error;
+ FT_UShort i, j, k;
+ FT_UShort bgc, igc, lgc;
+ FT_UShort known_backtrack_classes,
+ known_input_classes,
+ known_lookahead_classes;
+
+ FT_UShort* backtrack_classes;
+ FT_UShort* input_classes;
+ FT_UShort* lookahead_classes;
+
+ FT_UShort* bc;
+ FT_UShort* ic;
+ FT_UShort* lc;
+
+ HB_ChainSubClassSet* cscs;
+ HB_ChainSubClassRule ccsr;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+ memory = gsub->memory;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ /* Note: The coverage table in format 2 doesn't give an index into
+ anything. It just lets us know whether or not we need to
+ do any lookup at all. */
+
+ error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index );
+ if ( error )
+ return error;
+
+ if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, FT_UShort ) )
+ return error;
+ known_backtrack_classes = 0;
+
+ if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, FT_UShort ) )
+ goto End3;
+ known_input_classes = 1;
+
+ if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, FT_UShort ) )
+ goto End2;
+ known_lookahead_classes = 0;
+
+ error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(),
+ &input_classes[0], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ cscs = &ccsf2->ChainSubClassSet[input_classes[0]];
+ if ( !cscs )
+ {
+ error = HB_Err_Invalid_GSUB_SubTable;
+ goto End1;
+ }
+
+ for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ )
+ {
+ ccsr = cscs->ChainSubClassRule[k];
+ bgc = ccsr.BacktrackGlyphCount;
+ igc = ccsr.InputGlyphCount;
+ lgc = ccsr.LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ goto next_chainsubclassrule;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ goto next_chainsubclassrule;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array.
+ Note that `known_backtrack_classes' starts at index 0. */
+
+ bc = ccsr.Backtrack;
+
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + 1 == bgc - i )
+ goto next_chainsubclassrule;
+ j--;
+ }
+
+ if ( i >= known_backtrack_classes )
+ {
+ /* Keeps us from having to do this for each rule */
+
+ error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ),
+ &backtrack_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_backtrack_classes = i;
+ }
+
+ if ( bc[i] != backtrack_classes[i] )
+ goto next_chainsubclassrule;
+ }
+ }
+
+ ic = ccsr.Input;
+
+ /* Start at 1 because [0] is implied */
+
+ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + igc - i + lgc == buffer->in_length )
+ goto next_chainsubclassrule;
+ j++;
+ }
+
+ if ( i >= known_input_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),
+ &input_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_input_classes = i;
+ }
+
+ if ( ic[i - 1] != input_classes[i] )
+ goto next_chainsubclassrule;
+ }
+
+ /* we are starting to check for lookahead glyphs right after the
+ last context glyph */
+
+ lc = ccsr.Lookahead;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+
+ if ( j + lgc - i == buffer->in_length )
+ goto next_chainsubclassrule;
+ j++;
+ }
+
+ if ( i >= known_lookahead_classes )
+ {
+ error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),
+ &lookahead_classes[i], NULL );
+ if ( error && error != HB_Err_Not_Covered )
+ goto End1;
+ known_lookahead_classes = i;
+ }
+
+ if ( lc[i] != lookahead_classes[i] )
+ goto next_chainsubclassrule;
+ }
+
+ error = Do_ContextSubst( gsub, igc,
+ ccsr.SubstCount,
+ ccsr.SubstLookupRecord,
+ buffer,
+ nesting_level );
+ goto End1;
+
+ next_chainsubclassrule:
+ ;
+ }
+
+ error = HB_Err_Not_Covered;
+
+End1:
+ FREE( lookahead_classes );
+
+End2:
+ FREE( input_classes );
+
+End3:
+ FREE( backtrack_classes );
+ return error;
+}
+
+
+static FT_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
+ HB_ChainContextSubstFormat3* ccsf3,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_UShort index, i, j, property;
+ FT_UShort bgc, igc, lgc;
+ FT_Error error;
+
+ HB_Coverage* bc;
+ HB_Coverage* ic;
+ HB_Coverage* lc;
+ HB_GDEFHeader* gdef;
+
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ return error;
+
+ bgc = ccsf3->BacktrackGlyphCount;
+ igc = ccsf3->InputGlyphCount;
+ lgc = ccsf3->LookaheadGlyphCount;
+
+ if ( context_length != 0xFFFF && context_length < igc )
+ return HB_Err_Not_Covered;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
+ return HB_Err_Not_Covered;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ bc = ccsf3->BacktrackCoverage;
+
+ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ return HB_Err_Not_Covered;
+ j--;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+ }
+
+ ic = ccsf3->InputCoverage;
+
+ for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
+ {
+ /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
+ while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + igc - i + lgc == buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ /* we are starting for lookahead glyphs right after the last context
+ glyph */
+
+ lc = ccsf3->LookaheadCoverage;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ return Do_ContextSubst( gsub, igc,
+ ccsf3->SubstCount,
+ ccsf3->SubstLookupRecord,
+ buffer,
+ nesting_level );
+}
+
+
+static FT_Error Lookup_ChainContextSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ HB_ChainContextSubst* ccs = &st->chain;
+
+ switch ( ccs->SubstFormat )
+ {
+ case 1:
+ return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 2:
+ return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer,
+ flags, context_length,
+ nesting_level );
+
+ case 3:
+ return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer,
+ flags, context_length,
+ nesting_level );
+
+ default:
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+static FT_Error Load_ReverseChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ HB_ReverseChainContextSubst* rccs = &st->reverse;
+
+ FT_UShort m, count;
+
+ FT_UShort nb = 0, nl = 0, n;
+ FT_UShort backtrack_count, lookahead_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Coverage* b;
+ HB_Coverage* l;
+ FT_UShort* sub;
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ rccs->SubstFormat = GET_UShort();
+
+ if ( rccs->SubstFormat != 1 )
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+
+ FORGET_Frame();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail4;
+
+ rccs->BacktrackGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ rccs->BacktrackCoverage = NULL;
+
+ backtrack_count = rccs->BacktrackGlyphCount;
+
+ if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count,
+ HB_Coverage ) )
+ goto Fail4;
+
+ b = rccs->BacktrackCoverage;
+
+ for ( nb = 0; nb < backtrack_count; nb++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != FT_Err_Ok )
+ goto Fail3;
+ (void)FILE_Seek( cur_offset );
+ }
+
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail3;
+
+ rccs->LookaheadGlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ rccs->LookaheadCoverage = NULL;
+
+ lookahead_count = rccs->LookaheadGlyphCount;
+
+ if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count,
+ HB_Coverage ) )
+ goto Fail3;
+
+ l = rccs->LookaheadCoverage;
+
+ for ( nl = 0; nl < lookahead_count; nl++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != FT_Err_Ok )
+ goto Fail2;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ rccs->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ rccs->Substitute = NULL;
+
+ count = rccs->GlyphCount;
+
+ if ( ALLOC_ARRAY( rccs->Substitute, count,
+ FT_UShort ) )
+ goto Fail2;
+
+ sub = rccs->Substitute;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail1;
+
+ for ( n = 0; n < count; n++ )
+ sub[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( sub );
+
+Fail2:
+ for ( m = 0; m < nl; m++ )
+ _HB_OPEN_Free_Coverage( &l[m], memory );
+
+ FREE( l );
+
+Fail3:
+ for ( m = 0; m < nb; m++ )
+ _HB_OPEN_Free_Coverage( &b[m], memory );
+
+ FREE( b );
+
+Fail4:
+ _HB_OPEN_Free_Coverage( &rccs->Coverage, memory );
+ return error;
+}
+
+
+static void Free_ReverseChainContextSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+ HB_ReverseChainContextSubst* rccs = &st->reverse;
+
+ HB_Coverage* c;
+
+ _HB_OPEN_Free_Coverage( &rccs->Coverage, memory );
+
+ if ( rccs->LookaheadCoverage )
+ {
+ count = rccs->LookaheadGlyphCount;
+ c = rccs->LookaheadCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ if ( rccs->BacktrackCoverage )
+ {
+ count = rccs->BacktrackGlyphCount;
+ c = rccs->BacktrackCoverage;
+
+ for ( n = 0; n < count; n++ )
+ _HB_OPEN_Free_Coverage( &c[n], memory );
+
+ FREE( c );
+ }
+
+ FREE ( rccs->Substitute );
+}
+
+
+static FT_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ /* note different signature here: */ FT_ULong string_index )
+{
+ FT_UShort index, input_index, i, j, property;
+ FT_UShort bgc, lgc;
+ FT_Error error;
+
+ HB_ReverseChainContextSubst* rccs = &st->reverse;
+ HB_Coverage* bc;
+ HB_Coverage* lc;
+ HB_GDEFHeader* gdef;
+
+ gdef = gsub->gdef;
+
+ if ( CHECK_Property( gdef, IN_ITEM( string_index ), flags, &property ) )
+ return error;
+
+ bgc = rccs->BacktrackGlyphCount;
+ lgc = rccs->LookaheadGlyphCount;
+
+ /* check whether context is too long; it is a first guess only */
+
+ if ( bgc > string_index || string_index + 1 + lgc > buffer->in_length )
+ return HB_Err_Not_Covered;
+
+ if ( bgc )
+ {
+ /* Since we don't know in advance the number of glyphs to inspect,
+ we search backwards for matches in the backtrack glyph array */
+
+ bc = rccs->BacktrackCoverage;
+
+ for ( i = 0, j = string_index - 1; i < bgc; i++, j-- )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + 1 == bgc - i )
+ return HB_Err_Not_Covered;
+ j--;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+ }
+
+ j = string_index;
+
+ error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );
+ if ( error )
+ return error;
+
+ /* we are starting for lookahead glyphs right after the last context
+ glyph */
+
+ j += 1;
+
+ lc = rccs->LookaheadCoverage;
+
+ for ( i = 0; i < lgc; i++, j++ )
+ {
+ while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
+ {
+ if ( error && error != HB_Err_Not_Covered )
+ return error;
+
+ if ( j + lgc - i == buffer->in_length )
+ return HB_Err_Not_Covered;
+ j++;
+ }
+
+ error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
+ if ( error )
+ return error;
+ }
+
+ IN_GLYPH( string_index ) = rccs->Substitute[input_index];
+
+ return error;
+}
+
+
+
+/***********
+ * GSUB API
+ ***********/
+
+
+
+FT_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,
+ FT_ULong script_tag,
+ FT_UShort* script_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gsub || !script_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ if ( script_tag == sr[n].ScriptTag )
+ {
+ *script_index = n;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+
+FT_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gsub || !language_index || !req_feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ if ( language_tag == lsr[n].LangSysTag )
+ {
+ *language_index = n;
+ *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
+
+ return FT_Err_Ok;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index )
+{
+ FT_UShort n;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gsub || !feature_index )
+ return FT_Err_Invalid_Argument;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gsub->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+
+ if ( feature_tag == fr[fi[n]].FeatureTag )
+ {
+ *feature_index = fi[n];
+
+ return FT_Err_Ok;
+ }
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+/* The next three functions return a null-terminated list */
+
+
+FT_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,
+ FT_ULong** script_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory;
+ FT_ULong* stl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+
+
+ if ( !gsub || !script_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gsub->memory;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ stl[n] = sr[n].ScriptTag;
+ stl[n] = 0;
+
+ *script_tag_list = stl;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory;
+ FT_ULong* ltl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+
+
+ if ( !gsub || !language_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gsub->memory;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < s->LangSysCount; n++ )
+ ltl[n] = lsr[n].LangSysTag;
+ ltl[n] = 0;
+
+ *language_tag_list = ltl;
+
+ return FT_Err_Ok;
+}
+
+
+/* selecting 0xFFFF for language_index asks for the values of the
+ default language (DefaultLangSys) */
+
+
+FT_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list )
+{
+ FT_UShort n;
+ FT_Error error;
+ FT_Memory memory;
+ FT_ULong* ftl;
+
+ HB_ScriptList* sl;
+ HB_ScriptRecord* sr;
+ HB_Script* s;
+ HB_LangSysRecord* lsr;
+ HB_LangSys* ls;
+ FT_UShort* fi;
+
+ HB_FeatureList* fl;
+ HB_FeatureRecord* fr;
+
+
+ if ( !gsub || !feature_tag_list )
+ return FT_Err_Invalid_Argument;
+
+ memory = gsub->memory;
+
+ sl = &gsub->ScriptList;
+ sr = sl->ScriptRecord;
+
+ fl = &gsub->FeatureList;
+ fr = fl->FeatureRecord;
+
+ if ( script_index >= sl->ScriptCount )
+ return FT_Err_Invalid_Argument;
+
+ s = &sr[script_index].Script;
+ lsr = s->LangSysRecord;
+
+ if ( language_index == 0xFFFF )
+ ls = &s->DefaultLangSys;
+ else
+ {
+ if ( language_index >= s->LangSysCount )
+ return FT_Err_Invalid_Argument;
+
+ ls = &lsr[language_index].LangSys;
+ }
+
+ fi = ls->FeatureIndex;
+
+ if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) )
+ return error;
+
+ for ( n = 0; n < ls->FeatureCount; n++ )
+ {
+ if ( fi[n] >= fl->FeatureCount )
+ {
+ FREE( ftl );
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+ }
+ ftl[n] = fr[fi[n]].FeatureTag;
+ }
+ ftl[n] = 0;
+
+ *feature_tag_list = ftl;
+
+ return FT_Err_Ok;
+}
+
+
+typedef FT_Error (*Lookup_Subst_Func_Type)( HB_GSUBHeader* gsub,
+ HB_GSUB_SubTable* st,
+ HB_Buffer buffer,
+ FT_UShort flags,
+ FT_UShort context_length,
+ int nesting_level );
+static const Lookup_Subst_Func_Type Lookup_Subst_Call_Table[] = {
+ Lookup_DefaultSubst,
+ Lookup_SingleSubst, /* HB_GSUB_LOOKUP_SINGLE 1 */
+ Lookup_MultipleSubst, /* HB_GSUB_LOOKUP_MULTIPLE 2 */
+ Lookup_AlternateSubst, /* HB_GSUB_LOOKUP_ALTERNATE 3 */
+ Lookup_LigatureSubst, /* HB_GSUB_LOOKUP_LIGATURE 4 */
+ Lookup_ContextSubst, /* HB_GSUB_LOOKUP_CONTEXT 5 */
+ Lookup_ChainContextSubst, /* HB_GSUB_LOOKUP_CHAIN 6 */
+ Lookup_DefaultSubst /* HB_GSUB_LOOKUP_EXTENSION 7 */
+};
+/* Note that the following lookup does not belong to the table above:
+ * Lookup_ReverseChainContextSubst, HB_GSUB_LOOKUP_REVERSE_CHAIN 8
+ * because it's invalid to happen where this table is used. It's
+ * signature is different too...
+ */
+
+/* Do an individual subtable lookup. Returns FT_Err_Ok if substitution
+ has been done, or HB_Err_Not_Covered if not. */
+static FT_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer,
+ FT_UShort context_length,
+ int nesting_level )
+{
+ FT_Error error = HB_Err_Not_Covered;
+ FT_UShort i, flags, lookup_count;
+ HB_Lookup* lo;
+ int lookup_type;
+ Lookup_Subst_Func_Type Func;
+
+
+ nesting_level++;
+
+ if ( nesting_level > HB_MAX_NESTING_LEVEL )
+ return HB_Err_Too_Many_Nested_Contexts;
+
+ lookup_count = gsub->LookupList.LookupCount;
+ if (lookup_index >= lookup_count)
+ return error;
+
+ lo = &gsub->LookupList.Lookup[lookup_index];
+ flags = lo->LookupFlag;
+ lookup_type = lo->LookupType;
+
+ if (lookup_type >= ARRAY_LEN (Lookup_Subst_Call_Table))
+ lookup_type = 0;
+ Func = Lookup_Subst_Call_Table[lookup_type];
+
+ for ( i = 0; i < lo->SubTableCount; i++ )
+ {
+ error = Func ( gsub,
+ &lo->SubTable[i].st.gsub,
+ buffer,
+ flags, context_length,
+ nesting_level );
+
+ /* Check whether we have a successful substitution or an error other
+ than HB_Err_Not_Covered */
+
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Load_DefaultSubst( HB_GSUB_SubTable* st,
+ FT_Stream stream )
+{
+ return HB_Err_Invalid_GSUB_SubTable_Format;
+}
+
+typedef FT_Error (*Load_Subst_Func_Type)( HB_GSUB_SubTable* st,
+ FT_Stream stream );
+static const Load_Subst_Func_Type Load_Subst_Call_Table[] = {
+ Load_DefaultSubst,
+ Load_SingleSubst, /* HB_GSUB_LOOKUP_SINGLE 1 */
+ Load_MultipleSubst, /* HB_GSUB_LOOKUP_MULTIPLE 2 */
+ Load_AlternateSubst, /* HB_GSUB_LOOKUP_ALTERNATE 3 */
+ Load_LigatureSubst, /* HB_GSUB_LOOKUP_LIGATURE 4 */
+ Load_ContextSubst, /* HB_GSUB_LOOKUP_CONTEXT 5 */
+ Load_ChainContextSubst, /* HB_GSUB_LOOKUP_CHAIN 6 */
+ Load_DefaultSubst, /* HB_GSUB_LOOKUP_EXTENSION 7 */
+ Load_ReverseChainContextSubst /* HB_GSUB_LOOKUP_REVERSE_CHAIN 8 */
+};
+
+FT_Error _HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
+ FT_Stream stream,
+ FT_UShort lookup_type )
+{
+ Load_Subst_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Load_Subst_Call_Table))
+ lookup_type = 0;
+
+ Func = Load_Subst_Call_Table[lookup_type];
+
+ return Func ( st, stream );
+}
+
+
+static void Free_DefaultSubst( HB_GSUB_SubTable* st,
+ FT_Memory memory )
+{
+}
+
+typedef void (*Free_Subst_Func_Type)( HB_GSUB_SubTable* st,
+ FT_Memory memory );
+static const Free_Subst_Func_Type Free_Subst_Call_Table[] = {
+ Free_DefaultSubst,
+ Free_SingleSubst, /* HB_GSUB_LOOKUP_SINGLE 1 */
+ Free_MultipleSubst, /* HB_GSUB_LOOKUP_MULTIPLE 2 */
+ Free_AlternateSubst, /* HB_GSUB_LOOKUP_ALTERNATE 3 */
+ Free_LigatureSubst, /* HB_GSUB_LOOKUP_LIGATURE 4 */
+ Free_ContextSubst, /* HB_GSUB_LOOKUP_CONTEXT 5 */
+ Free_ChainContextSubst, /* HB_GSUB_LOOKUP_CHAIN 6 */
+ Free_DefaultSubst, /* HB_GSUB_LOOKUP_EXTENSION 7 */
+ Free_ReverseChainContextSubst /* HB_GSUB_LOOKUP_REVERSE_CHAIN 8 */
+};
+
+void _HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
+ FT_Memory memory,
+ FT_UShort lookup_type )
+{
+ Free_Subst_Func_Type Func;
+
+ if (lookup_type >= ARRAY_LEN (Free_Subst_Call_Table))
+ lookup_type = 0;
+
+ Func = Free_Subst_Call_Table[lookup_type];
+
+ Func ( st, memory );
+}
+
+
+
+/* apply one lookup to the input string object */
+
+static FT_Error GSUB_Do_String_Lookup( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+
+ FT_UInt* properties = gsub->LookupList.Properties;
+
+ int nesting_level = 0;
+
+
+ while ( buffer->in_pos < buffer->in_length )
+ {
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
+ {
+ /* 0xFFFF indicates that we don't have a context length yet */
+ error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer,
+ 0xFFFF, nesting_level );
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ retError = error;
+ }
+ else
+ error = HB_Err_Not_Covered;
+
+ if ( error == HB_Err_Not_Covered )
+ if ( hb_buffer_copy_output_glyph ( buffer ) )
+ return error;
+ }
+
+ return retError;
+}
+
+
+static FT_Error Apply_ReverseChainContextSubst( HB_GSUBHeader* gsub,
+ FT_UShort lookup_index,
+ HB_Buffer buffer )
+{
+ FT_UInt* properties = gsub->LookupList.Properties;
+ FT_Error error, retError = HB_Err_Not_Covered;
+ FT_ULong subtable_Count, string_index;
+ FT_UShort flags;
+ HB_Lookup* lo;
+
+ if ( buffer->in_length == 0 )
+ return HB_Err_Not_Covered;
+
+ lo = &gsub->LookupList.Lookup[lookup_index];
+ flags = lo->LookupFlag;
+
+ for ( subtable_Count = 0; subtable_Count < lo->SubTableCount; subtable_Count++ )
+ {
+ string_index = buffer->in_length - 1;
+ do
+ {
+ if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
+ {
+ error = Lookup_ReverseChainContextSubst( gsub, &lo->SubTable[subtable_Count].st.gsub,
+ buffer, flags, string_index );
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ return error;
+ }
+ else
+ retError = error;
+ }
+ }
+ while (string_index--);
+ }
+
+ return retError;
+}
+
+
+FT_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,
+ FT_UShort feature_index,
+ FT_UInt property )
+{
+ FT_UShort i;
+
+ HB_Feature feature;
+ FT_UInt* properties;
+ FT_UShort* index;
+ FT_UShort lookup_count;
+
+ /* Each feature can only be added once */
+
+ if ( !gsub ||
+ feature_index >= gsub->FeatureList.FeatureCount ||
+ gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )
+ return FT_Err_Invalid_Argument;
+
+ gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;
+
+ properties = gsub->LookupList.Properties;
+
+ feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
+ index = feature.LookupListIndex;
+ lookup_count = gsub->LookupList.LookupCount;
+
+ for ( i = 0; i < feature.LookupListCount; i++ )
+ {
+ FT_UShort lookup_index = index[i];
+ if (lookup_index < lookup_count)
+ properties[lookup_index] |= property;
+ }
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub )
+{
+ FT_UShort i;
+
+ FT_UInt* properties;
+
+
+ if ( !gsub )
+ return FT_Err_Invalid_Argument;
+
+ gsub->FeatureList.ApplyCount = 0;
+
+ properties = gsub->LookupList.Properties;
+
+ for ( i = 0; i < gsub->LookupList.LookupCount; i++ )
+ properties[i] = 0;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,
+ HB_AltFunction altfunc,
+ void* data )
+{
+ if ( !gsub )
+ return FT_Err_Invalid_Argument;
+
+ gsub->altfunc = altfunc;
+ gsub->data = data;
+
+ return FT_Err_Ok;
+}
+
+
+
+FT_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,
+ HB_Buffer buffer )
+{
+ FT_Error error, retError = HB_Err_Not_Covered;
+ FT_UShort i, j, lookup_count;
+
+ if ( !gsub ||
+ !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
+ return FT_Err_Invalid_Argument;
+
+ lookup_count = gsub->LookupList.LookupCount;
+
+ for ( i = 0; i < gsub->FeatureList.ApplyCount; i++)
+ {
+ FT_UShort feature_index;
+ HB_Feature feature;
+
+ feature_index = gsub->FeatureList.ApplyOrder[i];
+ feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
+
+ for ( j = 0; j < feature.LookupListCount; j++ )
+ {
+ FT_UShort lookup_index;
+ HB_Lookup* lookup;
+ FT_Bool need_swap;
+
+ lookup_index = feature.LookupListIndex[j];
+
+ /* Skip nonexistant lookups */
+ if (lookup_index >= lookup_count)
+ continue;
+
+ lookup = &gsub->LookupList.Lookup[lookup_index];
+
+ if ( lookup->LookupType == HB_GSUB_LOOKUP_REVERSE_CHAIN )
+ {
+ error = Apply_ReverseChainContextSubst( gsub, lookup_index, buffer);
+ need_swap = FALSE; /* We do ReverseChainContextSubst in-place */
+ }
+ else
+ {
+ error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer );
+ need_swap = TRUE;
+ }
+
+ if ( error )
+ {
+ if ( error != HB_Err_Not_Covered )
+ goto End;
+ }
+ else
+ retError = error;
+
+ if ( need_swap )
+ {
+ error = hb_buffer_swap( buffer );
+ if ( error )
+ goto End;
+ }
+ }
+ }
+
+ error = retError;
+
+End:
+ return error;
+}
+
+
+/* END */
diff --git a/pango/opentype/harfbuzz-gsub.h b/pango/opentype/harfbuzz-gsub.h
new file mode 100644
index 00000000..09145bad
--- /dev/null
+++ b/pango/opentype/harfbuzz-gsub.h
@@ -0,0 +1,132 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_GSUB_H
+#define HARFBUZZ_GSUB_H
+
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-buffer.h"
+
+FT_BEGIN_HEADER
+
+#define HB_Err_Invalid_GSUB_SubTable_Format 0x1010
+#define HB_Err_Invalid_GSUB_SubTable 0x1011
+
+
+/* Lookup types for glyph substitution */
+
+#define HB_GSUB_LOOKUP_SINGLE 1
+#define HB_GSUB_LOOKUP_MULTIPLE 2
+#define HB_GSUB_LOOKUP_ALTERNATE 3
+#define HB_GSUB_LOOKUP_LIGATURE 4
+#define HB_GSUB_LOOKUP_CONTEXT 5
+#define HB_GSUB_LOOKUP_CHAIN 6
+#define HB_GSUB_LOOKUP_EXTENSION 7
+#define HB_GSUB_LOOKUP_REVERSE_CHAIN 8
+
+
+/* A pointer to a function which selects the alternate glyph. `pos' is
+ the position of the glyph with index `glyphID', `num_alternates'
+ gives the number of alternates in the `alternates' array. `data'
+ points to the user-defined structure specified during a call to
+ HB_GSUB_Register_Alternate_Function(). The function must return an
+ index into the `alternates' array. */
+
+typedef FT_UShort (*HB_AltFunction)(FT_ULong pos,
+ FT_UShort glyphID,
+ FT_UShort num_alternates,
+ FT_UShort* alternates,
+ void* data );
+
+
+struct HB_GSUBHeader_
+{
+ FT_Memory memory;
+
+ FT_ULong offset;
+
+ FT_Fixed Version;
+
+ HB_ScriptList ScriptList;
+ HB_FeatureList FeatureList;
+ HB_LookupList LookupList;
+
+ HB_GDEFHeader* gdef;
+
+ /* the next two fields are used for an alternate substitution callback
+ function to select the proper alternate glyph. */
+
+ HB_AltFunction altfunc;
+ void* data;
+};
+
+typedef struct HB_GSUBHeader_ HB_GSUBHeader;
+typedef HB_GSUBHeader* HB_GSUB;
+
+
+FT_Error HB_Load_GSUB_Table( FT_Face face,
+ HB_GSUBHeader** gsub,
+ HB_GDEFHeader* gdef );
+
+
+FT_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub );
+
+
+FT_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub,
+ FT_ULong script_tag,
+ FT_UShort* script_index );
+
+FT_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub,
+ FT_ULong language_tag,
+ FT_UShort script_index,
+ FT_UShort* language_index,
+ FT_UShort* req_feature_index );
+
+FT_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub,
+ FT_ULong feature_tag,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_UShort* feature_index );
+
+
+FT_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub,
+ FT_ULong** script_tag_list );
+
+FT_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_ULong** language_tag_list );
+
+FT_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub,
+ FT_UShort script_index,
+ FT_UShort language_index,
+ FT_ULong** feature_tag_list );
+
+
+FT_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub,
+ FT_UShort feature_index,
+ FT_UInt property );
+
+FT_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub );
+
+
+FT_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub,
+ HB_AltFunction altfunc,
+ void* data );
+
+
+FT_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub,
+ HB_Buffer buffer );
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_GSUB_H */
diff --git a/pango/opentype/harfbuzz-impl.h b/pango/opentype/harfbuzz-impl.h
new file mode 100644
index 00000000..25310141
--- /dev/null
+++ b/pango/opentype/harfbuzz-impl.h
@@ -0,0 +1,64 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_IMPL_H
+#define HARFBUZZ_IMPL_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_BEGIN_HEADER
+
+#include "ftglue.h"
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#define ARRAY_LEN(Array) ((int)(sizeof (Array) / sizeof (Array)[0]))
+
+
+
+
+#define IN_GLYPH( pos ) (buffer->in_string[(pos)].gindex)
+#define IN_ITEM( pos ) (&buffer->in_string[(pos)])
+#define IN_CURGLYPH() (buffer->in_string[buffer->in_pos].gindex)
+#define IN_CURITEM() (&buffer->in_string[buffer->in_pos])
+#define IN_PROPERTIES( pos ) (buffer->in_string[(pos)].properties)
+#define IN_LIGID( pos ) (buffer->in_string[(pos)].ligID)
+#define IN_COMPONENT( pos ) (buffer->in_string[(pos)].component)
+#define POSITION( pos ) (&buffer->positions[(pos)])
+#define OUT_GLYPH( pos ) (buffer->out_string[(pos)].gindex)
+#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])
+
+#define CHECK_Property( gdef, index, flags, property ) \
+ ( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags), \
+ (property) ) ) != FT_Err_Ok )
+
+#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
+ ( ( error = hb_buffer_add_output_glyphs( (buffer), \
+ (num_in), (num_out), \
+ (glyph_data), (component), (ligID) \
+ ) ) != FT_Err_Ok )
+#define ADD_Glyph( buffer, glyph_index, component, ligID ) \
+ ( ( error = hb_buffer_add_output_glyph( (buffer), \
+ (glyph_index), (component), (ligID) \
+ ) ) != FT_Err_Ok )
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_IMPL_H */
diff --git a/pango/opentype/harfbuzz-open-private.h b/pango/opentype/harfbuzz-open-private.h
new file mode 100644
index 00000000..be265af2
--- /dev/null
+++ b/pango/opentype/harfbuzz-open-private.h
@@ -0,0 +1,81 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_OPEN_PRIVATE_H
+#define HARFBUZZ_OPEN_PRIVATE_H
+
+#include "harfbuzz-open.h"
+#include "harfbuzz-gsub-private.h"
+#include "harfbuzz-gpos-private.h"
+
+FT_BEGIN_HEADER
+
+
+struct HB_SubTable_
+{
+ union
+ {
+ HB_GSUB_SubTable gsub;
+ HB_GPOS_SubTable gpos;
+ } st;
+};
+
+
+FT_Error _HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
+ FT_Stream stream );
+FT_Error _HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_LookupList( HB_LookupList* ll,
+ FT_Stream input,
+ HB_Type type );
+
+FT_Error _HB_OPEN_Load_Coverage( HB_Coverage* c,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd,
+ FT_Stream input );
+FT_Error _HB_OPEN_Load_Device( HB_Device* d,
+ FT_Stream input );
+
+void _HB_OPEN_Free_ScriptList( HB_ScriptList* sl,
+ FT_Memory memory );
+void _HB_OPEN_Free_FeatureList( HB_FeatureList* fl,
+ FT_Memory memory );
+void _HB_OPEN_Free_LookupList( HB_LookupList* ll,
+ HB_Type type,
+ FT_Memory memory );
+
+void _HB_OPEN_Free_Coverage( HB_Coverage* c,
+ FT_Memory memory );
+void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd,
+ FT_Memory memory );
+void _HB_OPEN_Free_Device( HB_Device* d,
+ FT_Memory memory );
+
+
+
+FT_Error _HB_OPEN_Coverage_Index( HB_Coverage* c,
+ FT_UShort glyphID,
+ FT_UShort* index );
+FT_Error _HB_OPEN_Get_Class( HB_ClassDefinition* cd,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index );
+FT_Error _HB_OPEN_Get_Device( HB_Device* d,
+ FT_UShort size,
+ FT_Short* value );
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_OPEN_PRIVATE_H */
diff --git a/pango/opentype/harfbuzz-open.c b/pango/opentype/harfbuzz-open.c
new file mode 100644
index 00000000..b3c1bcb0
--- /dev/null
+++ b/pango/opentype/harfbuzz-open.c
@@ -0,0 +1,1426 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "harfbuzz-impl.h"
+#include "harfbuzz-open-private.h"
+
+
+/***************************
+ * Script related functions
+ ***************************/
+
+
+/* LangSys */
+
+static FT_Error Load_LangSys( HB_LangSys* ls,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UShort n, count;
+ FT_UShort* fi;
+
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ ls->LookupOrderOffset = GET_UShort(); /* should be 0 */
+ ls->ReqFeatureIndex = GET_UShort();
+ count = ls->FeatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ls->FeatureIndex = NULL;
+
+ if ( ALLOC_ARRAY( ls->FeatureIndex, count, FT_UShort ) )
+ return error;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( ls->FeatureIndex );
+ return error;
+ }
+
+ fi = ls->FeatureIndex;
+
+ for ( n = 0; n < count; n++ )
+ fi[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_LangSys( HB_LangSys* ls,
+ FT_Memory memory )
+{
+ FREE( ls->FeatureIndex );
+}
+
+
+/* Script */
+
+static FT_Error Load_Script( HB_Script* s,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_LangSysRecord* lsr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ if ( new_offset != base_offset ) /* not a NULL offset */
+ {
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LangSys( &s->DefaultLangSys,
+ stream ) ) != FT_Err_Ok )
+ return error;
+ (void)FILE_Seek( cur_offset );
+ }
+ else
+ {
+ /* we create a DefaultLangSys table with no entries */
+
+ s->DefaultLangSys.LookupOrderOffset = 0;
+ s->DefaultLangSys.ReqFeatureIndex = 0xFFFF;
+ s->DefaultLangSys.FeatureCount = 0;
+ s->DefaultLangSys.FeatureIndex = NULL;
+ }
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail2;
+
+ count = s->LangSysCount = GET_UShort();
+
+ /* safety check; otherwise the official handling of TrueType Open
+ fonts won't work */
+
+ if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
+ {
+ error = HB_Err_Empty_Script;
+ goto Fail2;
+ }
+
+ FORGET_Frame();
+
+ s->LangSysRecord = NULL;
+
+ if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) )
+ goto Fail2;
+
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 6L ) )
+ goto Fail1;
+
+ lsr[n].LangSysTag = GET_ULong();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_LangSys( &lsr[m].LangSys, memory );
+
+ FREE( s->LangSysRecord );
+
+Fail2:
+ Free_LangSys( &s->DefaultLangSys, memory );
+ return error;
+}
+
+
+static void Free_Script( HB_Script* s,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_LangSysRecord* lsr;
+
+
+ Free_LangSys( &s->DefaultLangSys, memory );
+
+ if ( s->LangSysRecord )
+ {
+ count = s->LangSysCount;
+ lsr = s->LangSysRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_LangSys( &lsr[n].LangSys, memory );
+
+ FREE( lsr );
+ }
+}
+
+
+/* ScriptList */
+
+FT_Error _HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, script_count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_ScriptRecord* sr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ script_count = GET_UShort();
+
+ FORGET_Frame();
+
+ sl->ScriptRecord = NULL;
+
+ if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) )
+ return error;
+
+ sr = sl->ScriptRecord;
+
+ sl->ScriptCount= 0;
+ for ( n = 0; n < script_count; n++ )
+ {
+ if ( ACCESS_Frame( 6L ) )
+ goto Fail;
+
+ sr[sl->ScriptCount].ScriptTag = GET_ULong();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+
+ if ( FILE_Seek( new_offset ) )
+ goto Fail;
+
+ error = Load_Script( &sr[sl->ScriptCount].Script, stream );
+ if ( error == FT_Err_Ok )
+ sl->ScriptCount += 1;
+ else if ( error != HB_Err_Empty_Script )
+ goto Fail;
+
+ (void)FILE_Seek( cur_offset );
+ }
+
+ if ( sl->ScriptCount == 0 )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( n = 0; n < sl->ScriptCount; n++ )
+ Free_Script( &sr[n].Script, memory );
+
+ FREE( sl->ScriptRecord );
+ return error;
+}
+
+
+void _HB_OPEN_Free_ScriptList( HB_ScriptList* sl,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_ScriptRecord* sr;
+
+
+ if ( sl->ScriptRecord )
+ {
+ count = sl->ScriptCount;
+ sr = sl->ScriptRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_Script( &sr[n].Script, memory );
+
+ FREE( sr );
+ }
+}
+
+
+
+/*********************************
+ * Feature List related functions
+ *********************************/
+
+
+/* Feature */
+
+static FT_Error Load_Feature( HB_Feature* f,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* lli;
+
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ f->FeatureParams = GET_UShort(); /* should be 0 */
+ count = f->LookupListCount = GET_UShort();
+
+ FORGET_Frame();
+
+ f->LookupListIndex = NULL;
+
+ if ( ALLOC_ARRAY( f->LookupListIndex, count, FT_UShort ) )
+ return error;
+
+ lli = f->LookupListIndex;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( f->LookupListIndex );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ lli[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Feature( HB_Feature* f,
+ FT_Memory memory )
+{
+ FREE( f->LookupListIndex );
+}
+
+
+/* FeatureList */
+
+FT_Error _HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_FeatureRecord* fr;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = fl->FeatureCount = GET_UShort();
+
+ FORGET_Frame();
+
+ fl->FeatureRecord = NULL;
+
+ if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) )
+ return error;
+ if ( ALLOC_ARRAY( fl->ApplyOrder, count, FT_UShort ) )
+ goto Fail2;
+
+ fl->ApplyCount = 0;
+
+ fr = fl->FeatureRecord;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 6L ) )
+ goto Fail1;
+
+ fr[n].FeatureTag = GET_ULong();
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Feature( &fr[n].Feature, stream ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ for ( m = 0; m < n; m++ )
+ Free_Feature( &fr[m].Feature, memory );
+
+ FREE( fl->ApplyOrder );
+
+Fail2:
+ FREE( fl->FeatureRecord );
+
+ return error;
+}
+
+
+void _HB_OPEN_Free_FeatureList( HB_FeatureList* fl,
+ FT_Memory memory)
+{
+ FT_UShort n, count;
+
+ HB_FeatureRecord* fr;
+
+
+ if ( fl->FeatureRecord )
+ {
+ count = fl->FeatureCount;
+ fr = fl->FeatureRecord;
+
+ for ( n = 0; n < count; n++ )
+ Free_Feature( &fr[n].Feature, memory );
+
+ FREE( fr );
+ }
+
+ FREE( fl->ApplyOrder );
+}
+
+
+
+/********************************
+ * Lookup List related functions
+ ********************************/
+
+/* the subroutines of the following two functions are defined in
+ ftxgsub.c and ftxgpos.c respectively */
+
+
+/* SubTable */
+
+static FT_Error Load_SubTable( HB_SubTable* st,
+ FT_Stream stream,
+ HB_Type table_type,
+ FT_UShort lookup_type )
+{
+ if ( table_type == HB_Type_GSUB )
+ return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type );
+ else
+ return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type );
+}
+
+
+static void Free_SubTable( HB_SubTable* st,
+ HB_Type table_type,
+ FT_UShort lookup_type,
+ FT_Memory memory )
+{
+ if ( table_type == HB_Type_GSUB )
+ _HB_GSUB_Free_SubTable ( &st->st.gsub, memory, lookup_type );
+ else
+ _HB_GPOS_Free_SubTable ( &st->st.gpos, memory, lookup_type );
+}
+
+
+/* Lookup */
+
+static FT_Error Load_Lookup( HB_Lookup* l,
+ FT_Stream stream,
+ HB_Type type )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_SubTable* st;
+
+ FT_Bool is_extension = FALSE;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ l->LookupType = GET_UShort();
+ l->LookupFlag = GET_UShort();
+ count = l->SubTableCount = GET_UShort();
+
+ FORGET_Frame();
+
+ l->SubTable = NULL;
+
+ if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) )
+ return error;
+
+ st = l->SubTable;
+
+ if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) ||
+ ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) )
+ is_extension = TRUE;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+
+ if ( is_extension )
+ {
+ if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) )
+ goto Fail;
+
+ if (GET_UShort() != 1) /* format should be 1 */
+ goto Fail;
+
+ l->LookupType = GET_UShort();
+ new_offset += GET_ULong();
+
+ FORGET_Frame();
+ }
+
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_SubTable( &st[n], stream,
+ type, l->LookupType ) ) != FT_Err_Ok )
+ goto Fail;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail:
+ for ( m = 0; m < n; m++ )
+ Free_SubTable( &st[m], type, l->LookupType, memory );
+
+ FREE( l->SubTable );
+ return error;
+}
+
+
+static void Free_Lookup( HB_Lookup* l,
+ HB_Type type,
+ FT_Memory memory)
+{
+ FT_UShort n, count;
+
+ HB_SubTable* st;
+
+
+ if ( l->SubTable )
+ {
+ count = l->SubTableCount;
+ st = l->SubTable;
+
+ for ( n = 0; n < count; n++ )
+ Free_SubTable( &st[n], type, l->LookupType, memory );
+
+ FREE( st );
+ }
+}
+
+
+/* LookupList */
+
+FT_Error _HB_OPEN_Load_LookupList( HB_LookupList* ll,
+ FT_Stream stream,
+ HB_Type type )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, m, count;
+ FT_ULong cur_offset, new_offset, base_offset;
+
+ HB_Lookup* l;
+
+
+ base_offset = FILE_Pos();
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = ll->LookupCount = GET_UShort();
+
+ FORGET_Frame();
+
+ ll->Lookup = NULL;
+
+ if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) )
+ return error;
+ if ( ALLOC_ARRAY( ll->Properties, count, FT_UInt ) )
+ goto Fail2;
+
+ l = ll->Lookup;
+
+ for ( n = 0; n < count; n++ )
+ {
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail1;
+
+ new_offset = GET_UShort() + base_offset;
+
+ FORGET_Frame();
+
+ cur_offset = FILE_Pos();
+ if ( FILE_Seek( new_offset ) ||
+ ( error = Load_Lookup( &l[n], stream, type ) ) != FT_Err_Ok )
+ goto Fail1;
+ (void)FILE_Seek( cur_offset );
+ }
+
+ return FT_Err_Ok;
+
+Fail1:
+ FREE( ll->Properties );
+
+ for ( m = 0; m < n; m++ )
+ Free_Lookup( &l[m], type, memory );
+
+Fail2:
+ FREE( ll->Lookup );
+ return error;
+}
+
+
+void _HB_OPEN_Free_LookupList( HB_LookupList* ll,
+ HB_Type type,
+ FT_Memory memory )
+{
+ FT_UShort n, count;
+
+ HB_Lookup* l;
+
+
+ FREE( ll->Properties );
+
+ if ( ll->Lookup )
+ {
+ count = ll->LookupCount;
+ l = ll->Lookup;
+
+ for ( n = 0; n < count; n++ )
+ Free_Lookup( &l[n], type, memory );
+
+ FREE( l );
+ }
+}
+
+
+
+/*****************************
+ * Coverage related functions
+ *****************************/
+
+
+/* CoverageFormat1 */
+
+static FT_Error Load_Coverage1( HB_CoverageFormat1* cf1,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* ga;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cf1->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cf1->GlyphArray = NULL;
+
+ if ( ALLOC_ARRAY( cf1->GlyphArray, count, FT_UShort ) )
+ return error;
+
+ ga = cf1->GlyphArray;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( cf1->GlyphArray );
+ return error;
+ }
+
+ for ( n = 0; n < count; n++ )
+ ga[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+static void Free_Coverage1( HB_CoverageFormat1* cf1,
+ FT_Memory memory)
+{
+ FREE( cf1->GlyphArray );
+}
+
+
+/* CoverageFormat2 */
+
+static FT_Error Load_Coverage2( HB_CoverageFormat2* cf2,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ HB_RangeRecord* rr;
+
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cf2->RangeCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cf2->RangeRecord = NULL;
+
+ if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) )
+ return error;
+
+ rr = cf2->RangeRecord;
+
+ if ( ACCESS_Frame( count * 6L ) )
+ goto Fail;
+
+ for ( n = 0; n < count; n++ )
+ {
+ rr[n].Start = GET_UShort();
+ rr[n].End = GET_UShort();
+ rr[n].StartCoverageIndex = GET_UShort();
+
+ /* sanity check; we are limited to 16bit integers */
+ if ( rr[n].Start > rr[n].End ||
+ ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=
+ 0x10000L )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cf2->RangeRecord );
+ return error;
+}
+
+
+static void Free_Coverage2( HB_CoverageFormat2* cf2,
+ FT_Memory memory )
+{
+ FREE( cf2->RangeRecord );
+}
+
+
+FT_Error _HB_OPEN_Load_Coverage( HB_Coverage* c,
+ FT_Stream stream )
+{
+ FT_Error error;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ c->CoverageFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( c->CoverageFormat )
+ {
+ case 1:
+ return Load_Coverage1( &c->cf.cf1, stream );
+
+ case 2:
+ return Load_Coverage2( &c->cf.cf2, stream );
+
+ default:
+ return HB_Err_Invalid_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+void _HB_OPEN_Free_Coverage( HB_Coverage* c,
+ FT_Memory memory )
+{
+ switch ( c->CoverageFormat )
+ {
+ case 1:
+ Free_Coverage1( &c->cf.cf1, memory );
+ break;
+
+ case 2:
+ Free_Coverage2( &c->cf.cf2, memory );
+ break;
+ }
+}
+
+
+static FT_Error Coverage_Index1( HB_CoverageFormat1* cf1,
+ FT_UShort glyphID,
+ FT_UShort* index )
+{
+ FT_UShort min, max, new_min, new_max, middle;
+
+ FT_UShort* array = cf1->GlyphArray;
+
+
+ /* binary search */
+
+ if ( cf1->GlyphCount == 0 )
+ return HB_Err_Not_Covered;
+
+ new_min = 0;
+ new_max = cf1->GlyphCount - 1;
+
+ do
+ {
+ min = new_min;
+ max = new_max;
+
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
+ overflow and rounding errors */
+
+ middle = max - ( ( max - min ) >> 1 );
+
+ if ( glyphID == array[middle] )
+ {
+ *index = middle;
+ return FT_Err_Ok;
+ }
+ else if ( glyphID < array[middle] )
+ {
+ if ( middle == min )
+ break;
+ new_max = middle - 1;
+ }
+ else
+ {
+ if ( middle == max )
+ break;
+ new_min = middle + 1;
+ }
+ } while ( min < max );
+
+ return HB_Err_Not_Covered;
+}
+
+
+static FT_Error Coverage_Index2( HB_CoverageFormat2* cf2,
+ FT_UShort glyphID,
+ FT_UShort* index )
+{
+ FT_UShort min, max, new_min, new_max, middle;
+
+ HB_RangeRecord* rr = cf2->RangeRecord;
+
+
+ /* binary search */
+
+ if ( cf2->RangeCount == 0 )
+ return HB_Err_Not_Covered;
+
+ new_min = 0;
+ new_max = cf2->RangeCount - 1;
+
+ do
+ {
+ min = new_min;
+ max = new_max;
+
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
+ overflow and rounding errors */
+
+ middle = max - ( ( max - min ) >> 1 );
+
+ if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End )
+ {
+ *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start;
+ return FT_Err_Ok;
+ }
+ else if ( glyphID < rr[middle].Start )
+ {
+ if ( middle == min )
+ break;
+ new_max = middle - 1;
+ }
+ else
+ {
+ if ( middle == max )
+ break;
+ new_min = middle + 1;
+ }
+ } while ( min < max );
+
+ return HB_Err_Not_Covered;
+}
+
+
+FT_Error _HB_OPEN_Coverage_Index( HB_Coverage* c,
+ FT_UShort glyphID,
+ FT_UShort* index )
+{
+ switch ( c->CoverageFormat )
+ {
+ case 1:
+ return Coverage_Index1( &c->cf.cf1, glyphID, index );
+
+ case 2:
+ return Coverage_Index2( &c->cf.cf2, glyphID, index );
+
+ default:
+ return HB_Err_Invalid_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+
+/*************************************
+ * Class Definition related functions
+ *************************************/
+
+
+/* ClassDefFormat1 */
+
+static FT_Error Load_ClassDef1( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* cva;
+ FT_Bool* d;
+
+ HB_ClassDefFormat1* cdf1;
+
+
+ cdf1 = &cd->cd.cd1;
+
+ if ( ACCESS_Frame( 4L ) )
+ return error;
+
+ cdf1->StartGlyph = GET_UShort();
+ count = cdf1->GlyphCount = GET_UShort();
+
+ FORGET_Frame();
+
+ /* sanity check; we are limited to 16bit integers */
+
+ if ( cdf1->StartGlyph + (long)count >= 0x10000L )
+ return HB_Err_Invalid_SubTable;
+
+ cdf1->ClassValueArray = NULL;
+
+ if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, FT_UShort ) )
+ return error;
+
+ d = cd->Defined;
+ cva = cdf1->ClassValueArray;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ goto Fail;
+
+ for ( n = 0; n < count; n++ )
+ {
+ cva[n] = GET_UShort();
+ if ( cva[n] >= limit )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+ d[cva[n]] = TRUE;
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cva );
+
+ return error;
+}
+
+
+static void Free_ClassDef1( HB_ClassDefFormat1* cdf1,
+ FT_Memory memory )
+{
+ FREE( cdf1->ClassValueArray );
+}
+
+
+/* ClassDefFormat2 */
+
+static FT_Error Load_ClassDef2( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ HB_ClassRangeRecord* crr;
+ FT_Bool* d;
+
+ HB_ClassDefFormat2* cdf2;
+
+
+ cdf2 = &cd->cd.cd2;
+
+ if ( ACCESS_Frame( 2L ) )
+ return error;
+
+ count = cdf2->ClassRangeCount = GET_UShort();
+
+ FORGET_Frame();
+
+ cdf2->ClassRangeRecord = NULL;
+
+ if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) )
+ return error;
+
+ d = cd->Defined;
+ crr = cdf2->ClassRangeRecord;
+
+ if ( ACCESS_Frame( count * 6L ) )
+ goto Fail;
+
+ for ( n = 0; n < count; n++ )
+ {
+ crr[n].Start = GET_UShort();
+ crr[n].End = GET_UShort();
+ crr[n].Class = GET_UShort();
+
+ /* sanity check */
+
+ if ( crr[n].Start > crr[n].End ||
+ crr[n].Class >= limit )
+ {
+ error = HB_Err_Invalid_SubTable;
+ goto Fail;
+ }
+ d[crr[n].Class] = TRUE;
+ }
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( crr );
+
+ return error;
+}
+
+
+static void Free_ClassDef2( HB_ClassDefFormat2* cdf2,
+ FT_Memory memory )
+{
+ FREE( cdf2->ClassRangeRecord );
+}
+
+
+/* ClassDefinition */
+
+FT_Error _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
+ FT_UShort limit,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+
+ if ( ALLOC_ARRAY( cd->Defined, limit, FT_Bool ) )
+ return error;
+
+ if ( ACCESS_Frame( 2L ) )
+ goto Fail;
+
+ cd->ClassFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ switch ( cd->ClassFormat )
+ {
+ case 1:
+ error = Load_ClassDef1( cd, limit, stream );
+ break;
+
+ case 2:
+ error = Load_ClassDef2( cd, limit, stream );
+ break;
+
+ default:
+ error = HB_Err_Invalid_SubTable_Format;
+ break;
+ }
+
+ if ( error )
+ goto Fail;
+
+ cd->loaded = TRUE;
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cd->Defined );
+ return error;
+}
+
+
+FT_Error _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+
+ if ( ALLOC_ARRAY( cd->Defined, 1, FT_Bool ) )
+ return error;
+
+ cd->ClassFormat = 1; /* Meaningless */
+ cd->Defined[0] = FALSE;
+
+ if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, FT_UShort ) )
+ goto Fail;
+
+ return FT_Err_Ok;
+
+Fail:
+ FREE( cd->Defined );
+ return error;
+}
+
+void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd,
+ FT_Memory memory )
+{
+ if ( !cd->loaded )
+ return;
+
+ FREE( cd->Defined );
+
+ switch ( cd->ClassFormat )
+ {
+ case 1:
+ Free_ClassDef1( &cd->cd.cd1, memory );
+ break;
+
+ case 2:
+ Free_ClassDef2( &cd->cd.cd2, memory );
+ break;
+ }
+}
+
+
+static FT_Error Get_Class1( HB_ClassDefFormat1* cdf1,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index )
+{
+ FT_UShort* cva = cdf1->ClassValueArray;
+
+
+ if ( index )
+ *index = 0;
+
+ if ( glyphID >= cdf1->StartGlyph &&
+ glyphID <= cdf1->StartGlyph + cdf1->GlyphCount )
+ {
+ *class = cva[glyphID - cdf1->StartGlyph];
+ return FT_Err_Ok;
+ }
+ else
+ {
+ *class = 0;
+ return HB_Err_Not_Covered;
+ }
+}
+
+
+/* we need the index value of the last searched class range record
+ in case of failure for constructed GDEF tables */
+
+static FT_Error Get_Class2( HB_ClassDefFormat2* cdf2,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index )
+{
+ FT_Error error = FT_Err_Ok;
+ FT_UShort min, max, new_min, new_max, middle;
+
+ HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord;
+
+
+ /* binary search */
+
+ if ( cdf2->ClassRangeCount == 0 )
+ {
+ *class = 0;
+ if ( index )
+ *index = 0;
+
+ return HB_Err_Not_Covered;
+ }
+
+ new_min = 0;
+ new_max = cdf2->ClassRangeCount - 1;
+
+ do
+ {
+ min = new_min;
+ max = new_max;
+
+ /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
+ overflow and rounding errors */
+
+ middle = max - ( ( max - min ) >> 1 );
+
+ if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )
+ {
+ *class = crr[middle].Class;
+ error = FT_Err_Ok;
+ break;
+ }
+ else if ( glyphID < crr[middle].Start )
+ {
+ if ( middle == min )
+ {
+ *class = 0;
+ error = HB_Err_Not_Covered;
+ break;
+ }
+ new_max = middle - 1;
+ }
+ else
+ {
+ if ( middle == max )
+ {
+ *class = 0;
+ error = HB_Err_Not_Covered;
+ break;
+ }
+ new_min = middle + 1;
+ }
+ } while ( min < max );
+
+ if ( index )
+ *index = middle;
+
+ return error;
+}
+
+
+FT_Error _HB_OPEN_Get_Class( HB_ClassDefinition* cd,
+ FT_UShort glyphID,
+ FT_UShort* class,
+ FT_UShort* index )
+{
+ switch ( cd->ClassFormat )
+ {
+ case 1:
+ return Get_Class1( &cd->cd.cd1, glyphID, class, index );
+
+ case 2:
+ return Get_Class2( &cd->cd.cd2, glyphID, class, index );
+
+ default:
+ return HB_Err_Invalid_SubTable_Format;
+ }
+
+ return FT_Err_Ok; /* never reached */
+}
+
+
+
+/***************************
+ * Device related functions
+ ***************************/
+
+
+FT_Error _HB_OPEN_Load_Device( HB_Device* d,
+ FT_Stream stream )
+{
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+
+ FT_UShort n, count;
+
+ FT_UShort* dv;
+
+
+ if ( ACCESS_Frame( 6L ) )
+ return error;
+
+ d->StartSize = GET_UShort();
+ d->EndSize = GET_UShort();
+ d->DeltaFormat = GET_UShort();
+
+ FORGET_Frame();
+
+ if ( d->StartSize > d->EndSize ||
+ d->DeltaFormat == 0 || d->DeltaFormat > 3 )
+ return HB_Err_Invalid_SubTable;
+
+ d->DeltaValue = NULL;
+
+ count = ( ( d->EndSize - d->StartSize + 1 ) >>
+ ( 4 - d->DeltaFormat ) ) + 1;
+
+ if ( ALLOC_ARRAY( d->DeltaValue, count, FT_UShort ) )
+ return error;
+
+ if ( ACCESS_Frame( count * 2L ) )
+ {
+ FREE( d->DeltaValue );
+ return error;
+ }
+
+ dv = d->DeltaValue;
+
+ for ( n = 0; n < count; n++ )
+ dv[n] = GET_UShort();
+
+ FORGET_Frame();
+
+ return FT_Err_Ok;
+}
+
+
+void _HB_OPEN_Free_Device( HB_Device* d,
+ FT_Memory memory )
+{
+ FREE( d->DeltaValue );
+}
+
+
+/* Since we have the delta values stored in compressed form, we must
+ uncompress it now. To simplify the interface, the function always
+ returns a meaningful value in `value'; the error is just for
+ information.
+ | |
+ format = 1: 0011223344556677|8899101112131415|...
+ | |
+ byte 1 byte 2
+
+ 00: (byte >> 14) & mask
+ 11: (byte >> 12) & mask
+ ...
+
+ mask = 0x0003
+ | |
+ format = 2: 0000111122223333|4444555566667777|...
+ | |
+ byte 1 byte 2
+
+ 0000: (byte >> 12) & mask
+ 1111: (byte >> 8) & mask
+ ...
+
+ mask = 0x000F
+ | |
+ format = 3: 0000000011111111|2222222233333333|...
+ | |
+ byte 1 byte 2
+
+ 00000000: (byte >> 8) & mask
+ 11111111: (byte >> 0) & mask
+ ....
+
+ mask = 0x00FF */
+
+FT_Error _HB_OPEN_Get_Device( HB_Device* d,
+ FT_UShort size,
+ FT_Short* value )
+{
+ FT_UShort byte, bits, mask, f, s;
+
+
+ f = d->DeltaFormat;
+
+ if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize )
+ {
+ s = size - d->StartSize;
+ byte = d->DeltaValue[s >> ( 4 - f )];
+ bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );
+ mask = 0xFFFF >> ( 16 - ( 1 << f ) );
+
+ *value = (FT_Short)( bits & mask );
+
+ /* conversion to a signed value */
+
+ if ( *value >= ( ( mask + 1 ) >> 1 ) )
+ *value -= mask + 1;
+
+ return FT_Err_Ok;
+ }
+ else
+ {
+ *value = 0;
+ return HB_Err_Not_Covered;
+ }
+}
+
+
+/* END */
diff --git a/pango/opentype/harfbuzz-open.h b/pango/opentype/harfbuzz-open.h
new file mode 100644
index 00000000..17e1f29b
--- /dev/null
+++ b/pango/opentype/harfbuzz-open.h
@@ -0,0 +1,285 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_OPEN_H
+#define HARFBUZZ_OPEN_H
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_BEGIN_HEADER
+
+/* Use this if a feature applies to all glyphs */
+#define HB_ALL_GLYPHS 0xFFFF
+
+#define HB_DEFAULT_LANGUAGE 0xFFFF
+
+#define HB_MAX_NESTING_LEVEL 100
+
+#define HB_Err_Invalid_SubTable_Format 0x1000
+#define HB_Err_Invalid_SubTable 0x1001
+#define HB_Err_Not_Covered 0x1002
+#define HB_Err_Too_Many_Nested_Contexts 0x1003
+#define HB_Err_No_MM_Interpreter 0x1004
+#define HB_Err_Empty_Script 0x1005
+
+
+/* Script list related structures */
+
+struct HB_LangSys_
+{
+ FT_UShort LookupOrderOffset; /* always 0 for TT Open 1.0 */
+ FT_UShort ReqFeatureIndex; /* required FeatureIndex */
+ FT_UShort FeatureCount; /* number of Feature indices */
+ FT_UShort* FeatureIndex; /* array of Feature indices */
+};
+
+typedef struct HB_LangSys_ HB_LangSys;
+
+
+struct HB_LangSysRecord_
+{
+ FT_ULong LangSysTag; /* LangSysTag identifier */
+ HB_LangSys LangSys; /* LangSys table */
+};
+
+typedef struct HB_LangSysRecord_ HB_LangSysRecord;
+
+
+struct HB_Script_
+{
+ HB_LangSys DefaultLangSys; /* DefaultLangSys table */
+ FT_UShort LangSysCount; /* number of LangSysRecords */
+ HB_LangSysRecord* LangSysRecord; /* array of LangSysRecords */
+};
+
+typedef struct HB_Script_ HB_Script;
+
+
+struct HB_ScriptRecord_
+{
+ FT_ULong ScriptTag; /* ScriptTag identifier */
+ HB_Script Script; /* Script table */
+};
+
+typedef struct HB_ScriptRecord_ HB_ScriptRecord;
+
+
+struct HB_ScriptList_
+{
+ FT_UShort ScriptCount; /* number of ScriptRecords */
+ HB_ScriptRecord* ScriptRecord; /* array of ScriptRecords */
+};
+
+typedef struct HB_ScriptList_ HB_ScriptList;
+
+
+/* Feature list related structures */
+
+struct HB_Feature_
+{
+ FT_UShort FeatureParams; /* always 0 for TT Open 1.0 */
+ FT_UShort LookupListCount; /* number of LookupList indices */
+ FT_UShort* LookupListIndex; /* array of LookupList indices */
+};
+
+typedef struct HB_Feature_ HB_Feature;
+
+
+struct HB_FeatureRecord_
+{
+ FT_ULong FeatureTag; /* FeatureTag identifier */
+ HB_Feature Feature; /* Feature table */
+};
+
+typedef struct HB_FeatureRecord_ HB_FeatureRecord;
+
+
+struct HB_FeatureList_
+{
+ FT_UShort FeatureCount; /* number of FeatureRecords */
+ HB_FeatureRecord* FeatureRecord; /* array of FeatureRecords */
+ FT_UShort* ApplyOrder; /* order to apply features */
+ FT_UShort ApplyCount; /* number of elements in ApplyOrder */
+};
+
+typedef struct HB_FeatureList_ HB_FeatureList;
+
+
+/* Lookup list related structures */
+
+typedef struct HB_SubTable_ HB_SubTable;
+
+
+struct HB_Lookup_
+{
+ FT_UShort LookupType; /* Lookup type */
+ FT_UShort LookupFlag; /* Lookup qualifiers */
+ FT_UShort SubTableCount; /* number of SubTables */
+ HB_SubTable* SubTable; /* array of SubTables */
+};
+
+typedef struct HB_Lookup_ HB_Lookup;
+
+
+/* The `Properties' field is not defined in the OpenType specification but
+ is needed for processing lookups. If properties[n] is > 0, the
+ functions HB_GSUB_Apply_String() resp. HB_GPOS_Apply_String() will
+ process Lookup[n] for glyphs which have the specific bit not set in
+ the `properties' field of the input string object. */
+
+struct HB_LookupList_
+{
+ FT_UShort LookupCount; /* number of Lookups */
+ HB_Lookup* Lookup; /* array of Lookup records */
+ FT_UInt* Properties; /* array of flags */
+};
+
+typedef struct HB_LookupList_ HB_LookupList;
+
+
+/* Possible LookupFlag bit masks. `HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS' comes from the
+ OpenType 1.2 specification; HB_LOOKUP_FLAG_RIGHT_TO_LEFT has been (re)introduced in
+ OpenType 1.3 -- if set, the last glyph in a cursive attachment
+ sequence has to be positioned on the baseline -- regardless of the
+ writing direction. */
+
+#define HB_LOOKUP_FLAG_RIGHT_TO_LEFT 0x0001
+#define HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS 0x0002
+#define HB_LOOKUP_FLAG_IGNORE_LIGATURES 0x0004
+#define HB_LOOKUP_FLAG_IGNORE_MARKS 0x0008
+#define HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS 0xFF00
+
+
+struct HB_CoverageFormat1_
+{
+ FT_UShort GlyphCount; /* number of glyphs in GlyphArray */
+ FT_UShort* GlyphArray; /* array of glyph IDs */
+};
+
+typedef struct HB_CoverageFormat1_ HB_CoverageFormat1;
+
+
+struct HB_RangeRecord_
+{
+ FT_UShort Start; /* first glyph ID in the range */
+ FT_UShort End; /* last glyph ID in the range */
+ FT_UShort StartCoverageIndex; /* coverage index of first
+ glyph ID in the range */
+};
+
+typedef struct HB_RangeRecord_ HB_RangeRecord;
+
+
+struct HB_CoverageFormat2_
+{
+ FT_UShort RangeCount; /* number of RangeRecords */
+ HB_RangeRecord* RangeRecord; /* array of RangeRecords */
+};
+
+typedef struct HB_CoverageFormat2_ HB_CoverageFormat2;
+
+
+struct HB_Coverage_
+{
+ FT_UShort CoverageFormat; /* 1 or 2 */
+
+ union
+ {
+ HB_CoverageFormat1 cf1;
+ HB_CoverageFormat2 cf2;
+ } cf;
+};
+
+typedef struct HB_Coverage_ HB_Coverage;
+
+
+struct HB_ClassDefFormat1_
+{
+ FT_UShort StartGlyph; /* first glyph ID of the
+ ClassValueArray */
+ FT_UShort GlyphCount; /* size of the ClassValueArray */
+ FT_UShort* ClassValueArray; /* array of class values */
+};
+
+typedef struct HB_ClassDefFormat1_ HB_ClassDefFormat1;
+
+
+struct HB_ClassRangeRecord_
+{
+ FT_UShort Start; /* first glyph ID in the range */
+ FT_UShort End; /* last glyph ID in the range */
+ FT_UShort Class; /* applied to all glyphs in range */
+};
+
+typedef struct HB_ClassRangeRecord_ HB_ClassRangeRecord;
+
+
+struct HB_ClassDefFormat2_
+{
+ FT_UShort ClassRangeCount;
+ /* number of ClassRangeRecords */
+ HB_ClassRangeRecord* ClassRangeRecord;
+ /* array of ClassRangeRecords */
+};
+
+typedef struct HB_ClassDefFormat2_ HB_ClassDefFormat2;
+
+
+/* The `Defined' field is not defined in the OpenType specification but
+ apparently needed for processing fonts like trado.ttf: This font
+ refers to a class which contains not a single element. We map such
+ classes to class 0. */
+
+struct HB_ClassDefinition_
+{
+ FT_Bool loaded;
+
+ FT_Bool* Defined; /* array of Booleans.
+ If Defined[n] is FALSE,
+ class n contains no glyphs. */
+ FT_UShort ClassFormat; /* 1 or 2 */
+
+ union
+ {
+ HB_ClassDefFormat1 cd1;
+ HB_ClassDefFormat2 cd2;
+ } cd;
+};
+
+typedef struct HB_ClassDefinition_ HB_ClassDefinition;
+
+
+struct HB_Device_
+{
+ FT_UShort StartSize; /* smallest size to correct */
+ FT_UShort EndSize; /* largest size to correct */
+ FT_UShort DeltaFormat; /* DeltaValue array data format:
+ 1, 2, or 3 */
+ FT_UShort* DeltaValue; /* array of compressed data */
+};
+
+typedef struct HB_Device_ HB_Device;
+
+
+enum HB_Type_
+{
+ HB_Type_GSUB,
+ HB_Type_GPOS
+};
+
+typedef enum HB_Type_ HB_Type;
+
+
+FT_END_HEADER
+
+#endif /* HARFBUZZ_OPEN_H */
diff --git a/pango/opentype/harfbuzz.c b/pango/opentype/harfbuzz.c
new file mode 100644
index 00000000..4fd8bf9f
--- /dev/null
+++ b/pango/opentype/harfbuzz.c
@@ -0,0 +1,19 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#include "ftglue.c"
+#include "harfbuzz-open.c"
+#include "harfbuzz-buffer.c"
+#include "harfbuzz-gdef.c"
+#include "harfbuzz-gsub.c"
+#include "harfbuzz-gpos.c"
+#include "harfbuzz-dump.c"
diff --git a/pango/opentype/harfbuzz.h b/pango/opentype/harfbuzz.h
new file mode 100644
index 00000000..e8e08a2a
--- /dev/null
+++ b/pango/opentype/harfbuzz.h
@@ -0,0 +1,23 @@
+/*******************************************************************
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Copyright 2006 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * See the file name COPYING for licensing information.
+ *
+ ******************************************************************/
+#ifndef HARFBUZZ_H
+#define HARFBUZZ_H
+
+#include "harfbuzz-open.h"
+#include "harfbuzz-buffer.h"
+#include "harfbuzz-gdef.h"
+#include "harfbuzz-gsub.h"
+#include "harfbuzz-gpos.h"
+#include "harfbuzz-dump.h"
+
+#endif /* HARFBUZZ_OPEN_H */
diff --git a/pango/opentype/otlbuffer.c b/pango/opentype/otlbuffer.c
deleted file mode 100644
index 5578f8ee..00000000
--- a/pango/opentype/otlbuffer.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* otlbuffer.c: Buffer of glyphs for substitution/positioning
- *
- * Copyright 2004 Red Hat Software
- *
- * Portions Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- */
-
-#include <config.h>
-
-#include <otlbuffer.h>
-
-/* To get the gcc-3.3 strict-aliasing compatible versions
- * FREE/REALLOC_ARRAY/etc. rather than the FT_* versions
- * that
- */
-#include "ftglue.h"
-
- static FT_Error
- otl_buffer_ensure( OTL_Buffer buffer,
- FT_ULong size )
- {
- FT_Memory memory = buffer->memory;
- FT_ULong new_allocated = buffer->allocated;
-
- if (size > new_allocated)
- {
- FT_Error error;
-
- while (size > new_allocated)
- new_allocated += (new_allocated >> 1) + 8;
-
- if ( REALLOC_ARRAY( buffer->in_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
- return error;
- if ( REALLOC_ARRAY( buffer->out_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
- return error;
- if ( REALLOC_ARRAY( buffer->positions, buffer->allocated, new_allocated, OTL_PositionRec ) )
- return error;
-
- buffer->allocated = new_allocated;
- }
-
- return FT_Err_Ok;
- }
-
- FT_Error
- otl_buffer_new( FT_Memory memory,
- OTL_Buffer *buffer )
- {
- FT_Error error;
-
- if ( ALLOC( *buffer, sizeof( OTL_BufferRec ) ) )
- return error;
-
- (*buffer)->memory = memory;
- (*buffer)->in_length = 0;
- (*buffer)->out_length = 0;
- (*buffer)->allocated = 0;
- (*buffer)->in_pos = 0;
- (*buffer)->out_pos = 0;
-
- (*buffer)->in_string = NULL;
- (*buffer)->out_string = NULL;
- (*buffer)->positions = NULL;
- (*buffer)->max_ligID = 0;
-
- return FT_Err_Ok;
- }
-
- FT_Error
- otl_buffer_swap( OTL_Buffer buffer )
- {
- OTL_GlyphItem tmp_string;
-
- tmp_string = buffer->in_string;
- buffer->in_string = buffer->out_string;
- buffer->out_string = tmp_string;
-
- buffer->in_length = buffer->out_length;
- buffer->out_length = 0;
-
- buffer->in_pos = 0;
- buffer->out_pos = 0;
-
- return FT_Err_Ok;
- }
-
- FT_Error
- otl_buffer_free( OTL_Buffer buffer )
- {
- FT_Memory memory = buffer->memory;
-
- FREE( buffer->in_string );
- FREE( buffer->out_string );
- FREE( buffer->positions );
- FREE( buffer );
-
- return FT_Err_Ok;
- }
-
- FT_Error
- otl_buffer_clear( OTL_Buffer buffer )
- {
- buffer->in_length = 0;
- buffer->out_length = 0;
- buffer->in_pos = 0;
- buffer->out_pos = 0;
-
- return FT_Err_Ok;
- }
-
- FT_Error
- otl_buffer_add_glyph( OTL_Buffer buffer,
- FT_UInt glyph_index,
- FT_UInt properties,
- FT_UInt cluster )
- {
- FT_Error error;
- OTL_GlyphItem glyph;
-
- error = otl_buffer_ensure( buffer, buffer->in_length + 1 );
- if ( error )
- return error;
-
- glyph = &buffer->in_string[buffer->in_length];
- glyph->gindex = glyph_index;
- glyph->properties = properties;
- glyph->cluster = cluster;
- glyph->component = 0;
- glyph->ligID = 0;
- glyph->gproperties = OTL_GLYPH_PROPERTIES_UNKNOWN;
-
- buffer->in_length++;
-
- return FT_Err_Ok;
- }
-
- /* The following function copies `num_out' elements from `glyph_data'
- to `buffer->out_string', advancing the in array pointer in the structure
- by `num_in' elements, and the out array pointer by `num_out' elements.
- Finally, it sets the `length' field of `out' equal to
- `pos' of the `out' structure.
-
- If `component' is 0xFFFF, the component value from buffer->in_pos
- will copied `num_out' times, otherwise `component' itself will
- be used to fill the `component' fields.
-
- If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
- will copied `num_out' times, otherwise `ligID' itself will
- be used to fill the `ligID' fields.
-
- The properties for all replacement glyphs are taken
- from the glyph at position `buffer->in_pos'.
-
- The cluster value for the glyph at position buffer->in_pos is used
- for all replacement glyphs */
- FT_Error
- otl_buffer_add_output_glyphs( OTL_Buffer buffer,
- FT_UShort num_in,
- FT_UShort num_out,
- FT_UShort *glyph_data,
- FT_UShort component,
- FT_UShort ligID )
- {
- FT_Error error;
- FT_UShort i;
- FT_UInt properties;
- FT_UInt cluster;
-
- error = otl_buffer_ensure( buffer, buffer->out_pos + num_out );
- if ( error )
- return error;
-
- properties = buffer->in_string[buffer->in_pos].properties;
- cluster = buffer->in_string[buffer->in_pos].cluster;
- if ( component == 0xFFFF )
- component = buffer->in_string[buffer->in_pos].component;
- if ( ligID == 0xFFFF )
- ligID = buffer->in_string[buffer->in_pos].ligID;
-
- for ( i = 0; i < num_out; i++ )
- {
- OTL_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
-
- item->gindex = glyph_data[i];
- item->properties = properties;
- item->cluster = cluster;
- item->component = component;
- item->ligID = ligID;
- item->gproperties = OTL_GLYPH_PROPERTIES_UNKNOWN;
- }
-
- buffer->in_pos += num_in;
- buffer->out_pos += num_out;
-
- buffer->out_length = buffer->out_pos;
-
- return FT_Err_Ok;
- }
-
- FT_Error
- otl_buffer_add_output_glyph( OTL_Buffer buffer,
- FT_UInt glyph_index,
- FT_UShort component,
- FT_UShort ligID )
- {
- FT_UShort glyph_data = glyph_index;
-
- return otl_buffer_add_output_glyphs ( buffer, 1, 1,
- &glyph_data, component, ligID );
- }
-
- FT_Error
- otl_buffer_copy_output_glyph ( OTL_Buffer buffer )
- {
- FT_Error error;
-
- error = otl_buffer_ensure( buffer, buffer->out_pos + 1 );
- if ( error )
- return error;
-
- buffer->out_string[buffer->out_pos++] = buffer->in_string[buffer->in_pos++];
- buffer->out_length = buffer->out_pos;
-
- return FT_Err_Ok;
- }
-
- FT_UShort
- otl_buffer_allocate_ligid( OTL_Buffer buffer )
- {
- return buffer->max_ligID++;
- }
diff --git a/pango/opentype/otlbuffer.h b/pango/opentype/otlbuffer.h
deleted file mode 100644
index bcb4e3e1..00000000
--- a/pango/opentype/otlbuffer.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* otlbuffer.h: Buffer of glyphs for substitution/positioning
- *
- * Copyrigh 2004 Red Hat Software
- *
- * Portions Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- */
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-#define OTL_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
-
- typedef struct OTL_GlyphItemRec_ {
- FT_UInt gindex;
- FT_UInt properties;
- FT_UInt cluster;
- FT_UShort component;
- FT_UShort ligID;
- FT_UShort gproperties;
- } OTL_GlyphItemRec, *OTL_GlyphItem;
-
- typedef struct OTL_PositionRec_ {
- FT_Pos x_pos;
- FT_Pos y_pos;
- FT_Pos x_advance;
- FT_Pos y_advance;
- FT_UShort back; /* number of glyphs to go back
- for drawing current glyph */
- FT_Bool new_advance; /* if set, the advance width values are
- absolute, i.e., they won't be
- added to the original glyph's value
- but rather replace them. */
- FT_Short cursive_chain; /* character to which this connects,
- may be positive or negative; used
- only internally */
- } OTL_PositionRec, *OTL_Position;
-
-
- typedef struct OTL_BufferRec_{
- FT_Memory memory;
- FT_ULong allocated;
-
- FT_ULong in_length;
- FT_ULong out_length;
- FT_ULong in_pos;
- FT_ULong out_pos;
-
- OTL_GlyphItem in_string;
- OTL_GlyphItem out_string;
- OTL_Position positions;
- FT_UShort max_ligID;
- } OTL_BufferRec, *OTL_Buffer;
-
- FT_Error
- otl_buffer_new( FT_Memory memory,
- OTL_Buffer *buffer );
-
- FT_Error
- otl_buffer_swap( OTL_Buffer buffer );
-
- FT_Error
- otl_buffer_free( OTL_Buffer buffer );
-
- FT_Error
- otl_buffer_clear( OTL_Buffer buffer );
-
- FT_Error
- otl_buffer_add_glyph( OTL_Buffer buffer,
- FT_UInt glyph_index,
- FT_UInt properties,
- FT_UInt cluster );
-
- FT_Error
- otl_buffer_add_output_glyphs( OTL_Buffer buffer,
- FT_UShort num_in,
- FT_UShort num_out,
- FT_UShort *glyph_data,
- FT_UShort component,
- FT_UShort ligID );
-
- FT_Error
- otl_buffer_add_output_glyph ( OTL_Buffer buffer,
- FT_UInt glyph_index,
- FT_UShort component,
- FT_UShort ligID );
-
- FT_Error
- otl_buffer_copy_output_glyph ( OTL_Buffer buffer );
-
- FT_UShort
- otl_buffer_allocate_ligid( OTL_Buffer buffer );
-
-G_END_DECLS
diff --git a/pango/pango-ot-buffer.c b/pango/pango-ot-buffer.c
index bfe10d37..00fc4686 100644
--- a/pango/pango-ot-buffer.c
+++ b/pango/pango-ot-buffer.c
@@ -49,8 +49,8 @@ pango_ot_buffer_new (PangoFcFont *font)
PangoOTBuffer *buffer = g_slice_new (PangoOTBuffer);
FT_Face face = pango_fc_font_lock_face (font);
- if (otl_buffer_new (face->memory, &buffer->buffer) != FT_Err_Ok)
- g_warning ("Allocation of OTLBuffer failed"); /* this doesn't happen */
+ if (hb_buffer_new (face->memory, &buffer->buffer) != FT_Err_Ok)
+ g_warning ("Allocation of HB_Buffer failed"); /* this doesn't happen */
buffer->font = g_object_ref (font);
buffer->applied_gpos = FALSE;
@@ -73,7 +73,7 @@ pango_ot_buffer_new (PangoFcFont *font)
void
pango_ot_buffer_destroy (PangoOTBuffer *buffer)
{
- otl_buffer_free (buffer->buffer);
+ hb_buffer_free (buffer->buffer);
g_object_unref (buffer->font);
g_slice_free (PangoOTBuffer, buffer);
}
@@ -89,7 +89,7 @@ pango_ot_buffer_destroy (PangoOTBuffer *buffer)
void
pango_ot_buffer_clear (PangoOTBuffer *buffer)
{
- otl_buffer_clear (buffer->buffer);
+ hb_buffer_clear (buffer->buffer);
buffer->applied_gpos = FALSE;
}
@@ -111,7 +111,7 @@ pango_ot_buffer_add_glyph (PangoOTBuffer *buffer,
guint properties,
guint cluster)
{
- otl_buffer_add_glyph (buffer->buffer,
+ hb_buffer_add_glyph (buffer->buffer,
glyph, properties, cluster);
}
@@ -198,7 +198,7 @@ swap_range (PangoGlyphString *glyphs, int start, int end)
static void
apply_gpos_ltr (PangoGlyphString *glyphs,
- OTL_Position positions)
+ HB_Position positions)
{
int i;
@@ -231,7 +231,7 @@ apply_gpos_ltr (PangoGlyphString *glyphs,
static void
apply_gpos_rtl (PangoGlyphString *glyphs,
- OTL_Position positions)
+ HB_Position positions)
{
int i;
@@ -283,7 +283,7 @@ pango_ot_buffer_output (PangoOTBuffer *buffer,
{
FT_Face face;
PangoOTInfo *info;
- TTO_GDEF gdef = NULL;
+ HB_GDEF gdef = NULL;
unsigned int i;
int last_cluster;
@@ -296,7 +296,7 @@ pango_ot_buffer_output (PangoOTBuffer *buffer,
last_cluster = -1;
for (i = 0; i < buffer->buffer->in_length; i++)
{
- OTL_GlyphItem item = &buffer->buffer->in_string[i];
+ HB_GlyphItem item = &buffer->buffer->in_string[i];
glyphs->glyphs[i].glyph = item->gindex;
@@ -323,8 +323,8 @@ pango_ot_buffer_output (PangoOTBuffer *buffer,
if (buffer->zero_width_marks &&
gdef &&
- TT_GDEF_Get_Glyph_Property (gdef, glyphs->glyphs[i].glyph, &property) == FT_Err_Ok &&
- (property == TTO_MARK || (property & IGNORE_SPECIAL_MARKS) != 0))
+ HB_GDEF_Get_Glyph_Property (gdef, glyphs->glyphs[i].glyph, &property) == FT_Err_Ok &&
+ (property == HB_GDEF_MARK || (property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS) != 0))
{
glyphs->glyphs[i].geometry.width = 0;
}
diff --git a/pango/pango-ot-info.c b/pango/pango-ot-info.c
index d17ed569..2eebc5f1 100644
--- a/pango/pango-ot-info.c
+++ b/pango/pango-ot-info.c
@@ -81,17 +81,17 @@ pango_ot_info_finalize (GObject *object)
if (info->gdef)
{
- TT_Done_GDEF_Table (info->gdef);
+ HB_Done_GDEF_Table (info->gdef);
info->gdef = NULL;
}
if (info->gsub)
{
- TT_Done_GSUB_Table (info->gsub);
+ HB_Done_GSUB_Table (info->gsub);
info->gsub = NULL;
}
if (info->gpos)
{
- TT_Done_GPOS_Table (info->gpos);
+ HB_Done_GPOS_Table (info->gpos);
info->gpos = NULL;
}
@@ -272,7 +272,7 @@ synthesize_class_def (PangoOTInfo *info)
g_array_free (glyph_infos, TRUE);
- TT_GDEF_Build_ClassDefinition (info->gdef, info->face->num_glyphs, j,
+ HB_GDEF_Build_ClassDefinition (info->gdef, info->face->num_glyphs, j,
glyph_indices, classes);
g_free (glyph_indices);
@@ -282,7 +282,7 @@ synthesize_class_def (PangoOTInfo *info)
FT_Set_Charmap (info->face, old_charmap);
}
-TTO_GDEF
+HB_GDEF
pango_ot_info_get_gdef (PangoOTInfo *info)
{
g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
@@ -295,13 +295,13 @@ pango_ot_info_get_gdef (PangoOTInfo *info)
if (is_truetype (info->face))
{
- error = TT_Load_GDEF_Table (info->face, &info->gdef);
+ error = HB_Load_GDEF_Table (info->face, &info->gdef);
- if (error && error != TT_Err_Table_Missing)
+ if (error && error != FT_Err_Table_Missing)
g_warning ("Error loading GDEF table %d", error);
if (!info->gdef)
- error = TT_New_GDEF_Table (info->face, &info->gdef);
+ error = HB_New_GDEF_Table (info->face, &info->gdef);
if (info->gdef && !info->gdef->GlyphClassDef.loaded)
synthesize_class_def (info);
@@ -311,7 +311,7 @@ pango_ot_info_get_gdef (PangoOTInfo *info)
return info->gdef;
}
-TTO_GSUB
+HB_GSUB
pango_ot_info_get_gsub (PangoOTInfo *info)
{
g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
@@ -319,15 +319,15 @@ pango_ot_info_get_gsub (PangoOTInfo *info)
if (!(info->loaded & INFO_LOADED_GSUB))
{
FT_Error error;
- TTO_GDEF gdef = pango_ot_info_get_gdef (info);
+ HB_GDEF gdef = pango_ot_info_get_gdef (info);
info->loaded |= INFO_LOADED_GSUB;
if (is_truetype (info->face))
{
- error = TT_Load_GSUB_Table (info->face, &info->gsub, gdef);
+ error = HB_Load_GSUB_Table (info->face, &info->gsub, gdef);
- if (error && error != TT_Err_Table_Missing)
+ if (error && error != FT_Err_Table_Missing)
g_warning ("Error loading GSUB table %d", error);
}
}
@@ -335,7 +335,7 @@ pango_ot_info_get_gsub (PangoOTInfo *info)
return info->gsub;
}
-TTO_GPOS
+HB_GPOS
pango_ot_info_get_gpos (PangoOTInfo *info)
{
g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
@@ -343,15 +343,15 @@ pango_ot_info_get_gpos (PangoOTInfo *info)
if (!(info->loaded & INFO_LOADED_GPOS))
{
FT_Error error;
- TTO_GDEF gdef = pango_ot_info_get_gdef (info);
+ HB_GDEF gdef = pango_ot_info_get_gdef (info);
info->loaded |= INFO_LOADED_GPOS;
if (is_truetype (info->face))
{
- error = TT_Load_GPOS_Table (info->face, &info->gpos, gdef);
+ error = HB_Load_GPOS_Table (info->face, &info->gpos, gdef);
- if (error && error != TT_Err_Table_Missing)
+ if (error && error != FT_Err_Table_Missing)
g_warning ("Error loading GPOS table %d", error);
}
}
@@ -362,12 +362,12 @@ pango_ot_info_get_gpos (PangoOTInfo *info)
static gboolean
get_tables (PangoOTInfo *info,
PangoOTTableType table_type,
- TTO_ScriptList **script_list,
- TTO_FeatureList **feature_list)
+ HB_ScriptList **script_list,
+ HB_FeatureList **feature_list)
{
if (table_type == PANGO_OT_TABLE_GSUB)
{
- TTO_GSUB gsub = pango_ot_info_get_gsub (info);
+ HB_GSUB gsub = pango_ot_info_get_gsub (info);
if (!gsub)
return FALSE;
@@ -382,7 +382,7 @@ get_tables (PangoOTInfo *info,
}
else
{
- TTO_GPOS gpos = pango_ot_info_get_gpos (info);
+ HB_GPOS gpos = pango_ot_info_get_gpos (info);
if (!gpos)
return FALSE;
@@ -414,7 +414,7 @@ pango_ot_info_find_script (PangoOTInfo *info,
PangoOTTag script_tag,
guint *script_index)
{
- TTO_ScriptList *script_list;
+ HB_ScriptList *script_list;
int i;
g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE);
@@ -458,8 +458,8 @@ pango_ot_info_find_language (PangoOTInfo *info,
guint *language_index,
guint *required_feature_index)
{
- TTO_ScriptList *script_list;
- TTO_Script *script;
+ HB_ScriptList *script_list;
+ HB_Script *script;
int i;
g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE);
@@ -493,7 +493,7 @@ pango_ot_info_find_language (PangoOTInfo *info,
* @feature_tag: the tag of the feature to find.
* @script_index: the index of the script.
* @language_index: the index of the language whose features are searched,
- * or 0xffff to use the default language of the script.
+ * or %PANGO_OT_DEFAULT_LANGUAGE to use the default language of the script.
* @feature_index: location to store the index of the feature, or %NULL.
*
* Finds the index of a feature.
@@ -508,10 +508,10 @@ pango_ot_info_find_feature (PangoOTInfo *info,
guint language_index,
guint *feature_index)
{
- TTO_ScriptList *script_list;
- TTO_FeatureList *feature_list;
- TTO_Script *script;
- TTO_LangSys *lang_sys;
+ HB_ScriptList *script_list;
+ HB_FeatureList *feature_list;
+ HB_Script *script;
+ HB_LangSys *lang_sys;
int i;
@@ -524,7 +524,7 @@ pango_ot_info_find_feature (PangoOTInfo *info,
script = &script_list->ScriptRecord[script_index].Script;
- if (language_index == 0xffff)
+ if (language_index == PANGO_OT_DEFAULT_LANGUAGE)
lang_sys = &script->DefaultLangSys;
else
{
@@ -563,7 +563,7 @@ pango_ot_info_list_scripts (PangoOTInfo *info,
PangoOTTableType table_type)
{
PangoOTTag *result;
- TTO_ScriptList *script_list;
+ HB_ScriptList *script_list;
int i;
g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
@@ -597,11 +597,11 @@ PangoOTTag *
pango_ot_info_list_languages (PangoOTInfo *info,
PangoOTTableType table_type,
guint script_index,
- PangoOTTag language_tag)
+ PangoOTTag language_tag G_GNUC_UNUSED)
{
PangoOTTag *result;
- TTO_ScriptList *script_list;
- TTO_Script *script;
+ HB_ScriptList *script_list;
+ HB_Script *script;
int i;
g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL);
@@ -630,7 +630,8 @@ pango_ot_info_list_languages (PangoOTInfo *info,
* @tag: unused parameter.
* @script_index: the index of the script to obtain information about.
* @language_index: the indes of the language to list features for, or
- * 0xffff, to list features for the default language of the script.
+ * %PANGO_OT_DEFAULT_LANGUAGE, to list features for the default
+ * language of the script.
*
* Obtains the list of features for the given language of the given script.
*
@@ -640,16 +641,16 @@ pango_ot_info_list_languages (PangoOTInfo *info,
PangoOTTag *
pango_ot_info_list_features (PangoOTInfo *info,
PangoOTTableType table_type,
- PangoOTTag tag,
+ PangoOTTag tag G_GNUC_UNUSED,
guint script_index,
guint language_index)
{
PangoOTTag *result;
- TTO_ScriptList *script_list;
- TTO_FeatureList *feature_list;
- TTO_Script *script;
- TTO_LangSys *lang_sys;
+ HB_ScriptList *script_list;
+ HB_FeatureList *feature_list;
+ HB_Script *script;
+ HB_LangSys *lang_sys;
int i;
@@ -662,7 +663,7 @@ pango_ot_info_list_features (PangoOTInfo *info,
script = &script_list->ScriptRecord[script_index].Script;
- if (language_index == 0xffff)
+ if (language_index == PANGO_OT_DEFAULT_LANGUAGE)
lang_sys = &script->DefaultLangSys;
else
{
diff --git a/pango/pango-ot-private.h b/pango/pango-ot-private.h
index 91bc3393..5e5e7023 100644
--- a/pango/pango-ot-private.h
+++ b/pango/pango-ot-private.h
@@ -25,12 +25,9 @@
#include <glib-object.h>
#include <pango/pango-ot.h>
-#include "opentype/ftglue.h"
-#include "opentype/ftxopen.h"
+#include "opentype/harfbuzz.h"
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
#define PANGO_TYPE_OT_INFO (pango_ot_info_get_type ())
#define PANGO_OT_INFO(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_OT_INFO, PangoOTInfo))
@@ -49,9 +46,9 @@ struct _PangoOTInfo
FT_Face face;
- TTO_GSUB gsub;
- TTO_GDEF gdef;
- TTO_GPOS gpos;
+ HB_GSUB gsub;
+ HB_GDEF gdef;
+ HB_GPOS gpos;
};
struct _PangoOTInfoClass
@@ -83,7 +80,7 @@ struct _PangoOTRulesetClass
struct _PangoOTBuffer
{
- OTL_Buffer buffer;
+ HB_Buffer buffer;
PangoFcFont *font;
guint rtl : 1;
guint zero_width_marks : 1;
@@ -92,15 +89,12 @@ struct _PangoOTBuffer
GType pango_ot_info_get_type (void);
-TTO_GDEF pango_ot_info_get_gdef (PangoOTInfo *info);
-TTO_GSUB pango_ot_info_get_gsub (PangoOTInfo *info);
-TTO_GPOS pango_ot_info_get_gpos (PangoOTInfo *info);
+HB_GDEF pango_ot_info_get_gdef (PangoOTInfo *info);
+HB_GSUB pango_ot_info_get_gsub (PangoOTInfo *info);
+HB_GPOS pango_ot_info_get_gpos (PangoOTInfo *info);
GType pango_ot_ruleset_get_type (void);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
+G_END_DECLS
#endif /* __PANGO_OT_PRIVATE_H__ */
diff --git a/pango/pango-ot-ruleset.c b/pango/pango-ot-ruleset.c
index 03bcaf56..da876e35 100644
--- a/pango/pango-ot-ruleset.c
+++ b/pango/pango-ot-ruleset.c
@@ -120,7 +120,8 @@ pango_ot_ruleset_new (PangoOTInfo *info)
* @table_type: the table type to add a feature to.
* @feature_index: the index of the feature to add.
* @property_bit: the property bit to use for this feature. Used to identify
- * the glyphs that this feature should be applied to.
+ * the glyphs that this feature should be applied to, or
+ * %PANGO_OT_ALL_GLYPHS if it should be applied to all glyphs.
*
* Adds a feature to the ruleset.
**/
@@ -157,7 +158,7 @@ pango_ot_ruleset_substitute (PangoOTRuleset *ruleset,
{
unsigned int i;
- TTO_GSUB gsub = NULL;
+ HB_GSUB gsub = NULL;
g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
@@ -173,15 +174,15 @@ pango_ot_ruleset_substitute (PangoOTRuleset *ruleset,
gsub = pango_ot_info_get_gsub (ruleset->info);
if (gsub)
- TT_GSUB_Clear_Features (gsub);
+ HB_GSUB_Clear_Features (gsub);
else
return;
}
- TT_GSUB_Add_Feature (gsub, rule->feature_index, rule->property_bit);
+ HB_GSUB_Add_Feature (gsub, rule->feature_index, rule->property_bit);
}
- TT_GSUB_Apply_String (gsub, buffer->buffer);
+ HB_GSUB_Apply_String (gsub, buffer->buffer);
}
/**
@@ -200,7 +201,7 @@ pango_ot_ruleset_position (PangoOTRuleset *ruleset,
{
unsigned int i;
- TTO_GPOS gpos = NULL;
+ HB_GPOS gpos = NULL;
g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
@@ -216,15 +217,15 @@ pango_ot_ruleset_position (PangoOTRuleset *ruleset,
gpos = pango_ot_info_get_gpos (ruleset->info);
if (gpos)
- TT_GPOS_Clear_Features (gpos);
+ HB_GPOS_Clear_Features (gpos);
else
return;
}
- TT_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
+ HB_GPOS_Add_Feature (gpos, rule->feature_index, rule->property_bit);
}
- if (TT_GPOS_Apply_String (ruleset->info->face, gpos, 0, buffer->buffer,
+ if (HB_GPOS_Apply_String (ruleset->info->face, gpos, 0, buffer->buffer,
FALSE /* enable device-dependant values */,
buffer->rtl) == FT_Err_Ok)
buffer->applied_gpos = TRUE;
diff --git a/pango/pango-ot.h b/pango/pango-ot.h
index a0f2efa9..0d223f72 100644
--- a/pango/pango-ot.h
+++ b/pango/pango-ot.h
@@ -43,7 +43,11 @@ typedef enum
PANGO_OT_TABLE_GPOS
} PangoOTTableType;
-/* Note that this must match OTLGlyphItem */
+
+#define PANGO_OT_ALL_GLYPHS ((guint)0xFFFF)
+#define PANGO_OT_DEFAULT_LANGUAGE ((guint)0xFFFF)
+
+/* Note that this must match HB_GlyphItem */
struct _PangoOTGlyph
{
guint glyph;