]> git.saurik.com Git - wxWidgets.git/commitdiff
Added FreeType II beta 8.
authorRobert Roebling <robert@roebling.de>
Sun, 3 Sep 2000 16:51:07 +0000 (16:51 +0000)
committerRobert Roebling <robert@roebling.de>
Sun, 3 Sep 2000 16:51:07 +0000 (16:51 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8247 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

192 files changed:
src/freetype/autohint/CatharonLicense.txt [new file with mode: 0644]
src/freetype/autohint/ahangles.c [new file with mode: 0644]
src/freetype/autohint/ahangles.h [new file with mode: 0644]
src/freetype/autohint/ahglobal.c [new file with mode: 0644]
src/freetype/autohint/ahglobal.h [new file with mode: 0644]
src/freetype/autohint/ahglyph.c [new file with mode: 0644]
src/freetype/autohint/ahglyph.h [new file with mode: 0644]
src/freetype/autohint/ahhint.c [new file with mode: 0644]
src/freetype/autohint/ahhint.h [new file with mode: 0644]
src/freetype/autohint/ahloader.h [new file with mode: 0644]
src/freetype/autohint/ahmodule.c [new file with mode: 0644]
src/freetype/autohint/ahmodule.h [new file with mode: 0644]
src/freetype/autohint/ahoptim.c [new file with mode: 0644]
src/freetype/autohint/ahoptim.h [new file with mode: 0644]
src/freetype/autohint/ahtypes.h [new file with mode: 0644]
src/freetype/autohint/autohint.c [new file with mode: 0644]
src/freetype/autohint/mather.py [new file with mode: 0644]
src/freetype/autohint/module.mk [new file with mode: 0644]
src/freetype/autohint/rules.mk [new file with mode: 0644]
src/freetype/base/ftbase.c [new file with mode: 0644]
src/freetype/base/ftcalc.c [new file with mode: 0644]
src/freetype/base/ftdebug.c [new file with mode: 0644]
src/freetype/base/ftextend.c [new file with mode: 0644]
src/freetype/base/ftglyph.c [new file with mode: 0644]
src/freetype/base/ftinit.c [new file with mode: 0644]
src/freetype/base/ftlist.c [new file with mode: 0644]
src/freetype/base/ftmm.c [new file with mode: 0644]
src/freetype/base/ftnames.c [new file with mode: 0644]
src/freetype/base/ftobjs.c [new file with mode: 0644]
src/freetype/base/ftoutln.c [new file with mode: 0644]
src/freetype/base/ftstream.c [new file with mode: 0644]
src/freetype/base/ftsystem.c [new file with mode: 0644]
src/freetype/base/rules.mk [new file with mode: 0644]
src/freetype/cff/cff.c [new file with mode: 0644]
src/freetype/cff/module.mk [new file with mode: 0644]
src/freetype/cff/rules.mk [new file with mode: 0644]
src/freetype/cff/t2driver.c [new file with mode: 0644]
src/freetype/cff/t2driver.h [new file with mode: 0644]
src/freetype/cff/t2gload.c [new file with mode: 0644]
src/freetype/cff/t2gload.h [new file with mode: 0644]
src/freetype/cff/t2load.c [new file with mode: 0644]
src/freetype/cff/t2load.h [new file with mode: 0644]
src/freetype/cff/t2objs.c [new file with mode: 0644]
src/freetype/cff/t2objs.h [new file with mode: 0644]
src/freetype/cff/t2parse.c [new file with mode: 0644]
src/freetype/cff/t2parse.h [new file with mode: 0644]
src/freetype/cff/t2tokens.h [new file with mode: 0644]
src/freetype/cid/cidafm.c [new file with mode: 0644]
src/freetype/cid/cidafm.h [new file with mode: 0644]
src/freetype/cid/cidgload.c [new file with mode: 0644]
src/freetype/cid/cidgload.h [new file with mode: 0644]
src/freetype/cid/cidload.c [new file with mode: 0644]
src/freetype/cid/cidload.h [new file with mode: 0644]
src/freetype/cid/cidobjs.c [new file with mode: 0644]
src/freetype/cid/cidobjs.h [new file with mode: 0644]
src/freetype/cid/cidparse.c [new file with mode: 0644]
src/freetype/cid/cidparse.h [new file with mode: 0644]
src/freetype/cid/cidriver.c [new file with mode: 0644]
src/freetype/cid/cidriver.h [new file with mode: 0644]
src/freetype/cid/cidtokens.h [new file with mode: 0644]
src/freetype/cid/module.mk [new file with mode: 0644]
src/freetype/cid/rules.mk [new file with mode: 0644]
src/freetype/cid/type1cid.c [new file with mode: 0644]
src/freetype/freetype/config/ftconfig.h [new file with mode: 0644]
src/freetype/freetype/config/ftmodule.h [new file with mode: 0644]
src/freetype/freetype/config/ftoption.h [new file with mode: 0644]
src/freetype/freetype/freetype.h [new file with mode: 0644]
src/freetype/freetype/ftbbox.h [new file with mode: 0644]
src/freetype/freetype/fterrors.h [new file with mode: 0644]
src/freetype/freetype/ftglyph.h [new file with mode: 0644]
src/freetype/freetype/ftimage.h [new file with mode: 0644]
src/freetype/freetype/ftmm.h [new file with mode: 0644]
src/freetype/freetype/ftmodule.h [new file with mode: 0644]
src/freetype/freetype/ftnames.h [new file with mode: 0644]
src/freetype/freetype/ftoutln.h [new file with mode: 0644]
src/freetype/freetype/ftrender.h [new file with mode: 0644]
src/freetype/freetype/ftsystem.h [new file with mode: 0644]
src/freetype/freetype/fttypes.h [new file with mode: 0644]
src/freetype/freetype/internal/autohint.h [new file with mode: 0644]
src/freetype/freetype/internal/ftcalc.h [new file with mode: 0644]
src/freetype/freetype/internal/ftdebug.h [new file with mode: 0644]
src/freetype/freetype/internal/ftdriver.h [new file with mode: 0644]
src/freetype/freetype/internal/ftextend.h [new file with mode: 0644]
src/freetype/freetype/internal/ftlist.h [new file with mode: 0644]
src/freetype/freetype/internal/ftmemory.h [new file with mode: 0644]
src/freetype/freetype/internal/ftobjs.h [new file with mode: 0644]
src/freetype/freetype/internal/ftstream.h [new file with mode: 0644]
src/freetype/freetype/internal/psnames.h [new file with mode: 0644]
src/freetype/freetype/internal/sfnt.h [new file with mode: 0644]
src/freetype/freetype/internal/t1errors.h [new file with mode: 0644]
src/freetype/freetype/internal/t1types.h [new file with mode: 0644]
src/freetype/freetype/internal/t2errors.h [new file with mode: 0644]
src/freetype/freetype/internal/t2types.h [new file with mode: 0644]
src/freetype/freetype/internal/tterrors.h [new file with mode: 0644]
src/freetype/freetype/internal/tttypes.h [new file with mode: 0644]
src/freetype/freetype/t1tables.h [new file with mode: 0644]
src/freetype/freetype/ttnameid.h [new file with mode: 0644]
src/freetype/freetype/tttables.h [new file with mode: 0644]
src/freetype/freetype/tttags.h [new file with mode: 0644]
src/freetype/ftconfig.h [new file with mode: 0644]
src/freetype/macfond/fonddrvr.c [new file with mode: 0644]
src/freetype/otlayout/oltypes.c [new file with mode: 0644]
src/freetype/otlayout/oltypes.h [new file with mode: 0644]
src/freetype/psnames/module.mk [new file with mode: 0644]
src/freetype/psnames/psmodule.c [new file with mode: 0644]
src/freetype/psnames/psmodule.h [new file with mode: 0644]
src/freetype/psnames/psnames.c [new file with mode: 0644]
src/freetype/psnames/pstables.h [new file with mode: 0644]
src/freetype/psnames/rules.mk [new file with mode: 0644]
src/freetype/raster1/ftraster.c [new file with mode: 0644]
src/freetype/raster1/ftraster.h [new file with mode: 0644]
src/freetype/raster1/ftrend1.c [new file with mode: 0644]
src/freetype/raster1/ftrend1.h [new file with mode: 0644]
src/freetype/raster1/module.mk [new file with mode: 0644]
src/freetype/raster1/raster1.c [new file with mode: 0644]
src/freetype/raster1/rules.mk [new file with mode: 0644]
src/freetype/sfnt/module.mk [new file with mode: 0644]
src/freetype/sfnt/rules.mk [new file with mode: 0644]
src/freetype/sfnt/sfdriver.c [new file with mode: 0644]
src/freetype/sfnt/sfdriver.h [new file with mode: 0644]
src/freetype/sfnt/sfnt.c [new file with mode: 0644]
src/freetype/sfnt/sfobjs.c [new file with mode: 0644]
src/freetype/sfnt/sfobjs.h [new file with mode: 0644]
src/freetype/sfnt/ttcmap.c [new file with mode: 0644]
src/freetype/sfnt/ttcmap.h [new file with mode: 0644]
src/freetype/sfnt/ttload.c [new file with mode: 0644]
src/freetype/sfnt/ttload.h [new file with mode: 0644]
src/freetype/sfnt/ttpost.c [new file with mode: 0644]
src/freetype/sfnt/ttpost.h [new file with mode: 0644]
src/freetype/sfnt/ttsbit.c [new file with mode: 0644]
src/freetype/sfnt/ttsbit.h [new file with mode: 0644]
src/freetype/smooth/ftgrays.c [new file with mode: 0644]
src/freetype/smooth/ftgrays.h [new file with mode: 0644]
src/freetype/smooth/ftsmooth.c [new file with mode: 0644]
src/freetype/smooth/ftsmooth.h [new file with mode: 0644]
src/freetype/smooth/module.mk [new file with mode: 0644]
src/freetype/smooth/rules.mk [new file with mode: 0644]
src/freetype/smooth/smooth.c [new file with mode: 0644]
src/freetype/truetype/module.mk [new file with mode: 0644]
src/freetype/truetype/rules.mk [new file with mode: 0644]
src/freetype/truetype/truetype.c [new file with mode: 0644]
src/freetype/truetype/ttdriver.c [new file with mode: 0644]
src/freetype/truetype/ttdriver.h [new file with mode: 0644]
src/freetype/truetype/ttgload.c [new file with mode: 0644]
src/freetype/truetype/ttgload.h [new file with mode: 0644]
src/freetype/truetype/ttinterp.c [new file with mode: 0644]
src/freetype/truetype/ttinterp.h [new file with mode: 0644]
src/freetype/truetype/ttobjs.c [new file with mode: 0644]
src/freetype/truetype/ttobjs.h [new file with mode: 0644]
src/freetype/truetype/ttpload.c [new file with mode: 0644]
src/freetype/truetype/ttpload.h [new file with mode: 0644]
src/freetype/type1/module.mk0 [new file with mode: 0644]
src/freetype/type1/rules.mk0 [new file with mode: 0644]
src/freetype/type1/t1afm.c [new file with mode: 0644]
src/freetype/type1/t1afm.h [new file with mode: 0644]
src/freetype/type1/t1driver.c [new file with mode: 0644]
src/freetype/type1/t1driver.h [new file with mode: 0644]
src/freetype/type1/t1gload.c [new file with mode: 0644]
src/freetype/type1/t1gload.h [new file with mode: 0644]
src/freetype/type1/t1hinter.c [new file with mode: 0644]
src/freetype/type1/t1hinter.h [new file with mode: 0644]
src/freetype/type1/t1load.c [new file with mode: 0644]
src/freetype/type1/t1load.h [new file with mode: 0644]
src/freetype/type1/t1objs.c [new file with mode: 0644]
src/freetype/type1/t1objs.h [new file with mode: 0644]
src/freetype/type1/t1parse.c [new file with mode: 0644]
src/freetype/type1/t1parse.h [new file with mode: 0644]
src/freetype/type1/t1tokens.c [new file with mode: 0644]
src/freetype/type1/t1tokens.h [new file with mode: 0644]
src/freetype/type1/type1.c [new file with mode: 0644]
src/freetype/type1z/Readme.txt [new file with mode: 0644]
src/freetype/type1z/module.mk [new file with mode: 0644]
src/freetype/type1z/rules.mk [new file with mode: 0644]
src/freetype/type1z/type1z.c [new file with mode: 0644]
src/freetype/type1z/z1afm.c [new file with mode: 0644]
src/freetype/type1z/z1afm.h [new file with mode: 0644]
src/freetype/type1z/z1driver.c [new file with mode: 0644]
src/freetype/type1z/z1driver.h [new file with mode: 0644]
src/freetype/type1z/z1gload.c [new file with mode: 0644]
src/freetype/type1z/z1gload.h [new file with mode: 0644]
src/freetype/type1z/z1load.c [new file with mode: 0644]
src/freetype/type1z/z1load.h [new file with mode: 0644]
src/freetype/type1z/z1objs.c [new file with mode: 0644]
src/freetype/type1z/z1objs.h [new file with mode: 0644]
src/freetype/type1z/z1parse.c [new file with mode: 0644]
src/freetype/type1z/z1parse.h [new file with mode: 0644]
src/freetype/type1z/z1tokens.h [new file with mode: 0644]
src/freetype/unix/ftsystem.c [new file with mode: 0644]
src/freetype/winfonts/module.mk [new file with mode: 0644]
src/freetype/winfonts/rules.mk [new file with mode: 0644]
src/freetype/winfonts/winfnt.c [new file with mode: 0644]
src/freetype/winfonts/winfnt.h [new file with mode: 0644]

diff --git a/src/freetype/autohint/CatharonLicense.txt b/src/freetype/autohint/CatharonLicense.txt
new file mode 100644 (file)
index 0000000..e68bc23
--- /dev/null
@@ -0,0 +1,123 @@
+                  The Catharon Open Source LICENSE
+                    ----------------------------
+
+                            2000-Jul-04
+
+          Copyright (C) 2000 by Catharon Productions, Inc.
+
+
+Introduction
+============
+
+  This  license  applies to  source  files  distributed by  Catharon
+  Productions,  Inc.  in  several  archive packages.   This  license
+  applies  to all files  found in  such packages  which do  not fall
+  under their own explicit license.
+
+  This  license   was  inspired  by  the  BSD,   Artistic,  and  IJG
+  (Independent JPEG  Group) licenses, which  all encourage inclusion
+  and  use of  free  software in  commercial  and freeware  products
+  alike.  As a consequence, its main points are that:
+
+    o We  don't promise that  this software works.  However,  we are
+      interested in any kind of bug reports. (`as is' distribution)
+
+    o You can  use this software for whatever you  want, in parts or
+      full form, without having to pay us. (`royalty-free' usage)
+
+    o You may not pretend that  you wrote this software.  If you use
+      it, or  only parts of it,  in a program,  you must acknowledge
+      somewhere  in  your  documentation  that  you  have  used  the
+      Catharon Code. (`credits')
+
+  We  specifically  permit  and  encourage  the  inclusion  of  this
+  software, with  or without modifications,  in commercial products.
+  We disclaim  all warranties  covering the packages  distributed by
+  Catharon  Productions, Inc.  and  assume no  liability related  to
+  their use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+  Throughout this license,  the terms `Catharon Package', `package',
+  and  `Catharon  Code'  refer   to  the  set  of  files  originally
+  distributed by Catharon Productions, Inc.
+
+  `You' refers to  the licensee, or person using  the project, where
+  `using' is a generic term including compiling the project's source
+  code as  well as linking it  to form a  `program' or `executable'.
+  This  program  is referred  to  as `a  program  using  one of  the
+  Catharon Packages'.
+
+  This  license applies  to all  files distributed  in  the original
+  Catharon  Package(s),  including  all  source code,  binaries  and
+  documentation,  unless  otherwise  stated   in  the  file  in  its
+  original, unmodified form as  distributed in the original archive.
+  If you are  unsure whether or not a particular  file is covered by
+  this license, you must contact us to verify this.
+
+  The  Catharon   Packages  are  copyright  (C)   2000  by  Catharon
+  Productions, Inc.  All rights reserved except as specified below.
+
+1. No Warranty
+--------------
+
+  THE CATHARON PACKAGES ARE PROVIDED `AS IS' WITHOUT WARRANTY OF ANY
+  KIND, EITHER  EXPRESS OR IMPLIED,  INCLUDING, BUT NOT  LIMITED TO,
+  WARRANTIES  OF  MERCHANTABILITY   AND  FITNESS  FOR  A  PARTICULAR
+  PURPOSE.  IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OF OR THE INABILITY TO
+  USE THE CATHARON PACKAGE.
+
+2. Redistribution
+-----------------
+
+  This  license  grants  a  worldwide, royalty-free,  perpetual  and
+  irrevocable right  and license to use,  execute, perform, compile,
+  display,  copy,   create  derivative  works   of,  distribute  and
+  sublicense the  Catharon Packages (in both source  and object code
+  forms)  and  derivative works  thereof  for  any  purpose; and  to
+  authorize others  to exercise  some or all  of the  rights granted
+  herein, subject to the following conditions:
+
+    o Redistribution  of source code  must retain this  license file
+      (`license.txt') unaltered; any additions, deletions or changes
+      to   the  original   files  must   be  clearly   indicated  in
+      accompanying  documentation.   The  copyright notices  of  the
+      unaltered, original  files must be preserved in  all copies of
+      source files.
+
+    o Redistribution  in binary form must provide  a disclaimer that
+      states  that the  software is  based in  part on  the  work of
+      Catharon Productions, Inc. in the distribution documentation.
+
+  These conditions  apply to any  software derived from or  based on
+  the Catharon Packages, not just  the unmodified files.  If you use
+  our work, you  must acknowledge us.  However, no  fee need be paid
+  to us.
+
+3. Advertising
+--------------
+
+  Neither Catharon Productions, Inc.  and contributors nor you shall
+  use  the  name  of  the  other  for  commercial,  advertising,  or
+  promotional purposes without specific prior written permission.
+
+  We suggest, but do not  require, that you use the following phrase
+  to refer to this software in your documentation: 'this software is
+  based in part on the Catharon Typography Project'.
+
+  As  you have  not signed  this license,  you are  not  required to
+  accept  it.  However,  as  the Catharon  Packages are  copyrighted
+  material, only  this license, or  another one contracted  with the
+  authors, grants you  the right to use, distribute,  and modify it.
+  Therefore,  by  using,  distributing,  or modifying  the  Catharon
+  Packages,  you indicate  that you  understand and  accept  all the
+  terms of this license.
+
+--- end of license.txt ---
diff --git a/src/freetype/autohint/ahangles.c b/src/freetype/autohint/ahangles.c
new file mode 100644 (file)
index 0000000..2f759ed
--- /dev/null
@@ -0,0 +1,137 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahangles.h                                                             */
+/*                                                                         */
+/*    A routine used to compute vector angles with limited accuracy        */
+/*    and very high speed (body).                                          */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahangles.h"
+
+#else
+
+#include <autohint/ahangles.h>
+
+#endif
+
+
+  /* the following table has been automatically generated with */
+  /* the `mather.py' Python script                             */
+
+  const AH_Angle  ah_arctan[1L << AH_ATAN_BITS] =
+  {
+     0,  0,  1,  1,  1,  2,  2,  2,
+     3,  3,  3,  3,  4,  4,  4,  5,
+     5,  5,  6,  6,  6,  7,  7,  7,
+     8,  8,  8,  9,  9,  9, 10, 10,
+    10, 10, 11, 11, 11, 12, 12, 12,
+    13, 13, 13, 14, 14, 14, 14, 15,
+    15, 15, 16, 16, 16, 17, 17, 17,
+    18, 18, 18, 18, 19, 19, 19, 20,
+    20, 20, 21, 21, 21, 21, 22, 22,
+    22, 23, 23, 23, 24, 24, 24, 24,
+    25, 25, 25, 26, 26, 26, 26, 27,
+    27, 27, 28, 28, 28, 28, 29, 29,
+    29, 30, 30, 30, 30, 31, 31, 31,
+    31, 32, 32, 32, 33, 33, 33, 33,
+    34, 34, 34, 34, 35, 35, 35, 35,
+    36, 36, 36, 36, 37, 37, 37, 38,
+    38, 38, 38, 39, 39, 39, 39, 40,
+    40, 40, 40, 41, 41, 41, 41, 42,
+    42, 42, 42, 42, 43, 43, 43, 43,
+    44, 44, 44, 44, 45, 45, 45, 45,
+    46, 46, 46, 46, 46, 47, 47, 47,
+    47, 48, 48, 48, 48, 48, 49, 49,
+    49, 49, 50, 50, 50, 50, 50, 51,
+    51, 51, 51, 51, 52, 52, 52, 52,
+    52, 53, 53, 53, 53, 53, 54, 54,
+    54, 54, 54, 55, 55, 55, 55, 55,
+    56, 56, 56, 56, 56, 57, 57, 57,
+    57, 57, 57, 58, 58, 58, 58, 58,
+    59, 59, 59, 59, 59, 59, 60, 60,
+    60, 60, 60, 61, 61, 61, 61, 61,
+    61, 62, 62, 62, 62, 62, 62, 63,
+    63, 63, 63, 63, 63, 64, 64, 64
+  };
+
+
+  LOCAL_FUNC
+  AH_Angle  ah_angle( FT_Vector*  v )
+  {
+    FT_Pos    dx, dy;
+    AH_Angle  angle;
+
+
+    dx = v->x;
+    dy = v->y;
+
+    /* check trivial cases */
+    if ( dy == 0 )
+    {
+      angle = 0;
+      if ( dx < 0 )
+        angle = AH_PI;
+      return angle;
+    }
+    else if ( dx == 0 )
+    {
+      angle = AH_HALF_PI;
+      if ( dy < 0 )
+        angle = -AH_HALF_PI;
+      return angle;
+    }
+
+    angle = 0;
+    if ( dx < 0 )
+    {
+      dx = -v->x;
+      dy = -v->y;
+      angle = AH_PI;
+    }
+
+    if ( dy < 0 )
+    {
+      FT_Pos  tmp;
+
+
+      tmp = dx;
+      dx  = -dy;
+      dy  = tmp;
+      angle -= AH_HALF_PI;
+    }
+
+    if ( dx == 0 && dy == 0 )
+      return 0;
+
+    if ( dx == dy )
+      angle += AH_PI / 4;
+    else if ( dx > dy )
+      angle += ah_arctan[FT_DivFix( dy, dx ) >> ( 16 - AH_ATAN_BITS )];
+    else
+      angle += AH_HALF_PI -
+               ah_arctan[FT_DivFix( dx, dy ) >> ( 16 - AH_ATAN_BITS )];
+
+    if ( angle > AH_PI )
+      angle -= AH_2PI;
+
+    return angle;
+  }
+
+
+/* END */
diff --git a/src/freetype/autohint/ahangles.h b/src/freetype/autohint/ahangles.h
new file mode 100644 (file)
index 0000000..4eb36bf
--- /dev/null
@@ -0,0 +1,63 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahangles.h                                                             */
+/*                                                                         */
+/*    A routine used to compute vector angles with limited accuracy        */
+/*    and very high speed (specification).                                 */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef AHANGLES_H
+#define AHANGLES_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+#include <freetype/internal/ftobjs.h>
+
+
+  /* PI expressed in ah_angles -- we don't really need an important */
+  /* precision, so 256 should be enough                             */
+#define AH_PI       256
+#define AH_2PI      ( AH_PI * 2 )
+#define AH_HALF_PI  ( AH_PI / 2 )
+#define AH_2PIMASK  ( AH_2PI - 1 )
+
+  /* the number of bits used to express an arc tangent; */
+  /* see the structure of the lookup table              */
+#define AH_ATAN_BITS  8
+
+  extern
+  const AH_Angle  ah_arctan[1L << AH_ATAN_BITS];
+
+
+  LOCAL_DEF
+  AH_Angle  ah_angle( FT_Vector*  v );
+
+
+#endif /* AHANGLES_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahglobal.c b/src/freetype/autohint/ahglobal.c
new file mode 100644 (file)
index 0000000..892ca86
--- /dev/null
@@ -0,0 +1,402 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglobal.c                                                             */
+/*                                                                         */
+/*    Routines used to compute global metrics automatically (body).        */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahglobal.h"
+#include "ahglyph.h"
+
+#else
+
+#include <autohint/ahglobal.h>
+#include <autohint/ahglyph.h>
+
+#endif
+
+
+#define MAX_TEST_CHARACTERS  12
+
+  static
+  const char*  blue_chars[ah_blue_max] =
+  {
+    "THEZOCQS",
+    "HEZLOCUS",
+    "xzroesc",
+    "xzroesc",
+    "pqgjy"
+  };
+
+
+  /* simple insertion sort */
+  static
+  void  sort_values( FT_Int   count,
+                     FT_Pos*  table )
+  {
+    FT_Int  i, j, swap;
+
+
+    for ( i = 1; i < count; i++ )
+    {
+      for ( j = i; j > 1; j-- )
+      {
+        if ( table[j] > table[j - 1] )
+          break;
+
+        swap         = table[j];
+        table[j]     = table[j - 1];
+        table[j - 1] = swap;
+      }
+    }
+  }
+
+
+  static
+  FT_Error  ah_hinter_compute_blues( AH_Hinter*  hinter )
+  {
+    AH_Blue       blue;
+    AH_Globals*   globals = &hinter->globals->design;
+    FT_Pos        flats [MAX_TEST_CHARACTERS];
+    FT_Pos        rounds[MAX_TEST_CHARACTERS];
+    FT_Int        num_flats;
+    FT_Int        num_rounds;
+
+    FT_Face       face;
+    FT_GlyphSlot  glyph;
+    FT_Error      error;
+    FT_CharMap    charmap;
+
+
+    face  = hinter->face;
+    glyph = face->glyph;
+
+    /* save current charmap */
+    charmap = face->charmap;
+
+    /* do we have a Unicode charmap in there? */
+    error = FT_Select_Charmap( face, ft_encoding_unicode );
+    if ( error )
+      goto Exit;
+
+    /* we compute the blues simply by loading each character from the */
+    /* 'blue_chars[blues]' string, then compute its top-most and      */
+    /* bottom-most points                                             */
+
+    AH_LOG(( "blue zones computation\n" ));
+    AH_LOG(( "------------------------------------------------\n" ));
+
+    for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )
+    {
+      const char*  p     = blue_chars[blue];
+      const char*  limit = p + MAX_TEST_CHARACTERS;
+      FT_Pos       *blue_ref, *blue_shoot;
+
+
+      AH_LOG(( "blue %3d: ", blue ));
+
+      num_flats  = 0;
+      num_rounds = 0;
+
+      for ( ; p < limit; p++ )
+      {
+        FT_UInt     glyph_index;
+        FT_Vector*  extremum;
+        FT_Vector*  points;
+        FT_Vector*  point_limit;
+        FT_Vector*  point;
+        FT_Bool     round;
+
+
+        /* exit if we reach the end of the string */
+        if ( !*p )
+          break;
+
+        AH_LOG(( "`%c'", *p ));
+
+        /* load the character in the face -- skip unknown or empty ones */
+        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
+        if ( glyph_index == 0 )
+          continue;
+
+        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+        if ( error || glyph->outline.n_points <= 0 )
+          continue;
+
+        /* now compute min or max point indices and coordinates */
+        points      = glyph->outline.points;
+        point_limit = points + glyph->outline.n_points;
+        point       = points;
+        extremum    = point;
+        point++;
+
+        if ( AH_IS_TOP_BLUE( blue ) )
+        {
+          for ( ; point < point_limit; point++ )
+            if ( point->y > extremum->y )
+              extremum = point;
+        }
+        else
+        {
+          for ( ; point < point_limit; point++ )
+            if ( point->y < extremum->y )
+              extremum = point;
+        }
+
+        AH_LOG(( "%5d", (int)extremum->y ));
+
+        /* now, check whether the point belongs to a straight or round  */
+        /* segment; we first need to find in which contour the extremum */
+        /* lies, then see its previous and next points                  */
+        {
+          FT_Int  index = extremum - points;
+          FT_Int  n;
+          FT_Int  first, last, prev, next, end;
+          FT_Pos  dist;
+
+
+          last  = -1;
+          first = 0;
+
+          for ( n = 0; n < glyph->outline.n_contours; n++ )
+          {
+            end = glyph->outline.contours[n];
+            if ( end >= index )
+            {
+              last = end;
+              break;
+            }
+            first = end + 1;
+          }
+
+          /* XXX: should never happen! */
+          if ( last < 0 )
+            continue;
+
+          /* now look for the previous and next points that are not on the */
+          /* same Y coordinate.  Threshold the `closeness'...              */
+
+          prev = index;
+          next = prev;
+
+          do
+          {
+            if ( prev > first )
+              prev--;
+            else
+              prev = last;
+
+            dist = points[prev].y - extremum->y;
+            if ( dist < -5 || dist > 5 )
+              break;
+
+          } while ( prev != index );
+
+          do
+          {
+            if ( next < last )
+              next++;
+            else
+              next = first;
+
+            dist = points[next].y - extremum->y;
+            if ( dist < -5 || dist > 5 )
+              break;
+
+          } while ( next != index );
+
+          /* now, set the `round' flag depending on the segment's kind */
+          round =
+            FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_Curve_Tag_On ||
+            FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_Curve_Tag_On ;
+
+          AH_LOG(( "%c ", round ? 'r' : 'f' ));
+        }
+
+        if ( round )
+          rounds[num_rounds++] = extremum->y;
+        else
+          flats[num_flats++] = extremum->y;
+      }
+
+      AH_LOG(( "\n" ));
+
+      /* we have computed the contents of the `rounds' and `flats' tables, */
+      /* now determine the reference and overshoot position of the blue;   */
+      /* we simply take the median value after a simple short              */
+      sort_values( num_rounds, rounds );
+      sort_values( num_flats,  flats  );
+
+      blue_ref   = globals->blue_refs + blue;
+      blue_shoot = globals->blue_shoots + blue;
+      if ( num_flats == 0 && num_rounds == 0 )
+      {
+        *blue_ref   = -10000;
+        *blue_shoot = -10000;
+      }
+      else if ( num_flats == 0 )
+      {
+        *blue_ref   =
+        *blue_shoot = rounds[num_rounds / 2];
+      }
+      else if ( num_rounds == 0 )
+      {
+        *blue_ref   =
+        *blue_shoot = flats[num_flats / 2];
+      }
+      else
+      {
+        *blue_ref   = flats[num_flats / 2];
+        *blue_shoot = rounds[num_rounds / 2];
+      }
+
+      /* there are sometimes problems: if the overshoot position of top     */
+      /* zones is under its reference position, or the opposite for bottom  */
+      /* zones.  We must thus check everything there and correct the errors */
+      if ( *blue_shoot != *blue_ref )
+      {
+        FT_Pos   ref      = *blue_ref;
+        FT_Pos   shoot    = *blue_shoot;
+        FT_Bool  over_ref = ( shoot > ref );
+
+
+        if ( AH_IS_TOP_BLUE( blue ) ^ over_ref )
+          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+      }
+
+      AH_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+    }
+
+    /* reset original face charmap */
+    FT_Set_Charmap( face, charmap );
+    error = 0;
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error  ah_hinter_compute_widths( AH_Hinter*  hinter )
+  {
+    /* scan the array of segments in each direction */
+    AH_Outline*  outline = hinter->glyph;
+    AH_Segment*  segments;
+    AH_Segment*  limit;
+    AH_Globals*  globals = &hinter->globals->design;
+    FT_Pos*      widths;
+    FT_Int       dimension;
+    FT_Int*      p_num_widths;
+    FT_Error     error = 0;
+    FT_Pos       edge_distance_threshold = 32000;
+
+
+    globals->num_widths  = 0;
+    globals->num_heights = 0;
+
+    /* For now, compute the standard width and height from the `o'       */
+    /* character.  I started computing the stem width of the `i' and the */
+    /* stem height of the "-", but it wasn't too good.  Moreover, we now */
+    /* have a single character that gives us standard width and height.  */
+    {
+      FT_UInt   glyph_index;
+
+
+      glyph_index = FT_Get_Char_Index( hinter->face, 'o' );
+      if ( glyph_index == 0 )
+        return 0;
+
+      error = FT_Load_Glyph( hinter->face, glyph_index, FT_LOAD_NO_SCALE );
+      if ( error )
+        goto Exit;
+
+      error = ah_outline_load( hinter->glyph, hinter->face );
+      if ( error )
+        goto Exit;
+
+      ah_outline_compute_segments( hinter->glyph );
+      ah_outline_link_segments( hinter->glyph );
+    }
+
+    segments     = outline->horz_segments;
+    limit        = segments + outline->num_hsegments;
+    widths       = globals->heights;
+    p_num_widths = &globals->num_heights;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Segment*  seg = segments;
+      AH_Segment*  link;
+      FT_Int       num_widths = 0;
+
+
+      for ( ; seg < limit; seg++ )
+      {
+        link = seg->link;
+        /* we only consider stem segments there! */
+        if ( link && link->link == seg && link > seg )
+        {
+          FT_Int  dist;
+
+
+          dist = seg->pos - link->pos;
+          if ( dist < 0 )
+            dist = -dist;
+
+          if ( num_widths < 12 )
+            widths[num_widths++] = dist;
+        }
+      }
+
+      sort_values( num_widths, widths );
+      *p_num_widths = num_widths;
+
+      /* we will now try to find the smallest width */
+      if ( num_widths > 0 && widths[0] < edge_distance_threshold )
+        edge_distance_threshold = widths[0];
+
+      segments     = outline->vert_segments;
+      limit        = segments + outline->num_vsegments;
+      widths       = globals->widths;
+      p_num_widths = &globals->num_widths;
+
+    }
+
+    /* Now, compute the edge distance threshold as a fraction of the */
+    /* smallest width in the font. Set it in `hinter.glyph' too!     */
+    if ( edge_distance_threshold == 32000 )
+      edge_distance_threshold = 50;
+
+    /* let's try 20% */
+    hinter->glyph->edge_distance_threshold = edge_distance_threshold / 5;
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  ah_hinter_compute_globals( AH_Hinter*  hinter )
+  {
+    return ah_hinter_compute_widths( hinter ) ||
+           ah_hinter_compute_blues ( hinter );
+  }
+
+
+/* END */
diff --git a/src/freetype/autohint/ahglobal.h b/src/freetype/autohint/ahglobal.h
new file mode 100644 (file)
index 0000000..79e7358
--- /dev/null
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglobal.h                                                             */
+/*                                                                         */
+/*    Routines used to compute global metrics automatically                */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef AHGLOBAL_H
+#define AHGLOBAL_H
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+#include <freetype/internal/ftobjs.h>  /* for LOCAL_DEF/LOCAL_FUNC */
+
+
+#define AH_IS_TOP_BLUE( b )  ( (b) == ah_blue_capital_top || \
+                               (b) == ah_blue_small_top   )
+
+
+  /* compute global metrics automatically */
+  LOCAL_DEF
+  FT_Error  ah_hinter_compute_globals( AH_Hinter*  hinter );
+
+
+#endif /* AHGLOBAL_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahglyph.c b/src/freetype/autohint/ahglyph.c
new file mode 100644 (file)
index 0000000..348ee8e
--- /dev/null
@@ -0,0 +1,1299 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglyph.c                                                              */
+/*                                                                         */
+/*    Routines used to load and analyze a given glyph before hinting       */
+/*    (body).                                                              */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahglyph.h"
+#include "ahangles.h"
+#include "ahglobal.h"
+
+#else
+
+#include <autohint/ahglyph.h>
+#include <autohint/ahangles.h>
+#include <autohint/ahglobal.h>
+
+#endif
+
+
+#include <stdio.h>
+
+
+#define xxxAH_DEBUG_GLYPH
+
+
+  /* compute the direction value of a given vector.. */
+  static
+  AH_Direction  ah_compute_direction( FT_Pos  dx,
+                                      FT_Pos  dy )
+  {
+    AH_Direction  dir;
+    FT_Pos        ax = ABS( dx );
+    FT_Pos        ay = ABS( dy );
+
+
+    dir = ah_dir_none;
+
+    /* test for vertical direction */
+    if ( ax * 12 < ay )
+    {
+      dir = dy > 0 ? ah_dir_up : ah_dir_down;
+    }
+    /* test for horizontal direction */
+    else if ( ay * 12 < ax )
+    {
+      dir = dx > 0 ? ah_dir_right : ah_dir_left;
+    }
+
+    return dir;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_new                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new and empty AH_Outline object.                         */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  ah_outline_new( FT_Memory     memory,
+                            AH_Outline**  aoutline )
+  {
+    FT_Error     error;
+    AH_Outline*  outline;
+
+
+    if ( !ALLOC( outline, sizeof ( *outline ) ) )
+    {
+      outline->memory = memory;
+      *aoutline = outline;
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_done                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given AH_Outline object.                                */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  ah_outline_done( AH_Outline*  outline )
+  {
+    FT_Memory memory = outline->memory;
+
+
+    FREE( outline->horz_edges );
+    FREE( outline->horz_segments );
+    FREE( outline->contours );
+    FREE( outline->points );
+
+    FREE( outline );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_save                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Saves the content of a given AH_Outline object into a face's glyph */
+  /*    slot.                                                              */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  ah_outline_save( AH_Outline*  outline,
+                         AH_Loader*   gloader )
+  {
+    AH_Point*   point = outline->points;
+    AH_Point*   limit = point + outline->num_points;
+    FT_Vector*  vec   = gloader->current.outline.points;
+    char*       tag   = gloader->current.outline.tags;
+
+
+    /* we assume that the glyph loader has already been checked for storage */
+    for ( ; point < limit; point++, vec++, tag++ )
+    {
+      vec->x = point->x;
+      vec->y = point->y;
+
+      if ( point->flags & ah_flah_conic )
+        tag[0] = FT_Curve_Tag_Conic;
+      else if ( point->flags & ah_flah_cubic )
+        tag[0] = FT_Curve_Tag_Cubic;
+      else
+        tag[0] = FT_Curve_Tag_On;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_load                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads an unscaled outline from a glyph slot into an AH_Outline     */
+  /*    object.                                                            */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  ah_outline_load( AH_Outline*  outline,
+                             FT_Face      face )
+  {
+    FT_Memory   memory       = outline->memory;
+    FT_Error    error        = FT_Err_Ok;
+    FT_Outline* source       = &face->glyph->outline;
+    FT_Int      num_points   = source->n_points;
+    FT_Int      num_contours = source->n_contours;
+    AH_Point*   points;
+
+
+    /* check arguments */
+    if ( !face                                          ||
+         !face->size                                    ||
+         face->glyph->format != ft_glyph_format_outline )
+      return FT_Err_Invalid_Argument;
+
+    /* first of all, reallocate the contours array if necessary */
+    if ( num_contours > outline->max_contours )
+    {
+      FT_Int  new_contours = ( num_contours + 3 ) & -4;
+
+
+      if ( REALLOC_ARRAY( outline->contours, outline->max_contours,
+                          new_contours, AH_Point* ) )
+        goto Exit;
+
+      outline->max_contours = new_contours;
+    }
+
+    /* then, realloc the points, segments & edges arrays if needed */
+    if ( num_points > outline->max_points )
+    {
+      FT_Int  news = ( num_points + 7 ) & -8;
+      FT_Int  max  = outline->max_points;
+
+
+      if ( REALLOC_ARRAY( outline->points, max, news, AH_Point )          ||
+           REALLOC_ARRAY( outline->horz_edges, max, news, AH_Edge )       ||
+           REALLOC_ARRAY( outline->horz_segments, max, news, AH_Segment ) )
+        goto Exit;
+
+      /* readjust some pointers */
+      outline->vert_edges    = outline->horz_edges + ( news >> 1 );
+      outline->vert_segments = outline->horz_segments + ( news >> 1 );
+      outline->max_points    = news;
+    }
+
+    outline->num_points   = num_points;
+    outline->num_contours = num_contours;
+
+    outline->num_hedges    = 0;
+    outline->num_vedges    = 0;
+    outline->num_hsegments = 0;
+    outline->num_vsegments = 0;
+
+    /* Compute the vertical and horizontal major directions; this is     */
+    /* currently done by inspecting the `ft_outline_reverse_fill' flag.  */
+    /* However, some fonts have improper glyphs, and it'd be a good idea */
+    /* to be able to re-compute these values on the fly.                 */
+    outline->vert_major_dir = ah_dir_up;
+    outline->horz_major_dir = ah_dir_left;
+
+    if ( source->flags & ft_outline_reverse_fill )
+    {
+      outline->vert_major_dir = ah_dir_down;
+      outline->horz_major_dir = ah_dir_right;
+    }
+
+    outline->x_scale = face->size->metrics.x_scale;
+    outline->y_scale = face->size->metrics.y_scale;
+
+    points = outline->points;
+
+    {
+      /* do one thing at a time -- it is easier to understand, and */
+      /* the code is clearer                                       */
+      AH_Point*  point = points;
+      AH_Point*  limit = point + outline->num_points;
+
+
+      /* compute coordinates */
+      {
+        FT_Vector*  vec     = source->points;
+        FT_Fixed    x_scale = outline->x_scale;
+        FT_Fixed    y_scale = outline->y_scale;
+
+
+        for (; point < limit; vec++, point++ )
+        {
+          point->fx = vec->x;
+          point->fy = vec->y;
+          point->ox = point->x = FT_MulFix( vec->x, x_scale );
+          point->oy = point->y = FT_MulFix( vec->y, y_scale );
+
+          point->flags = 0;
+        }
+      }
+
+      /* compute Bezier flags */
+      {
+        char*  tag = source->tags;
+
+
+        for ( point = points; point < limit; point++, tag++ )
+        {
+          switch ( FT_CURVE_TAG( *tag ) )
+          {
+          case FT_Curve_Tag_Conic:
+            point->flags = ah_flah_conic; break;
+          case FT_Curve_Tag_Cubic:
+            point->flags = ah_flah_cubic; break;
+          default:
+            ;
+          }
+        }
+      }
+
+      /* compute `next' and `prev' */
+      {
+        FT_Int     contour_index;
+        AH_Point*  prev;
+        AH_Point*  first;
+        AH_Point*  end;
+
+
+        contour_index = 0;
+
+        first = points;
+        end   = points + source->contours[0];
+        prev  = end;
+
+        for ( point = points; point < limit; point++ )
+        {
+          point->prev = prev;
+          if ( point < end )
+          {
+            point->next = point + 1;
+            prev        = point;
+          }
+          else
+          {
+            point->next = first;
+            contour_index++;
+            if ( point + 1 < limit )
+            {
+              end   = points + source->contours[contour_index];
+              first = point + 1;
+              prev  = end;
+            }
+          }
+        }
+      }
+
+      /* set-up the contours array */
+      {
+        AH_Point**  contour  = outline->contours;
+        AH_Point**  limit    = contour + outline->num_contours;
+        short*      end      = source->contours;
+        short       index    = 0;
+
+
+        for ( ; contour < limit; contour++, end++ )
+        {
+          contour[0] = points + index;
+          index      = end[0] + 1;
+        }
+      }
+
+      /* compute directions of in & out vectors */
+      {
+        for ( point = points; point < limit; point++ )
+        {
+          AH_Point*  prev;
+          AH_Point*  next;
+          FT_Vector  vec;
+
+
+          prev  = point->prev;
+          vec.x = point->fx - prev->fx;
+          vec.y = point->fy - prev->fy;
+
+          point->in_dir = ah_compute_direction( vec.x, vec.y );
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+          point->in_angle = ah_angle( &vec );
+#endif
+
+          next  = point->next;
+          vec.x = next->fx - point->fx;
+          vec.y = next->fy - point->fy;
+
+          point->out_dir = ah_compute_direction( vec.x, vec.y );
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+          point->out_angle = ah_angle( &vec );
+
+          {
+            AH_Angle  delta = point->in_angle - point->out_angle;
+
+
+            if ( delta < 0 )
+              delta = -delta;
+            if ( delta < 2 )
+              point->flags |= ah_flah_weak_interpolation;
+          }
+
+#if 0
+          if ( point->flags & ( ah_flah_conic | ah_flah_cubic ) )
+            point->flags |= ah_flah_weak_interpolation;
+#endif
+
+#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
+
+#ifdef AH_OPTION_NO_STRONG_INTERPOLATION
+          point->flags |= ah_flah_weak_interpolation;
+#endif
+        }
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  ah_setup_uv( AH_Outline*  outline,
+                     AH_UV        source )
+  {
+    AH_Point*  point = outline->points;
+    AH_Point*  limit = point + outline->num_points;
+
+
+    for ( ; point < limit; point++ )
+    {
+      FT_Pos  u, v;
+
+
+      switch ( source )
+      {
+      case ah_uv_fxy:
+        u = point->fx;
+        v = point->fy;
+        break;
+      case ah_uv_fyx:
+        u = point->fy;
+        v = point->fx;
+        break;
+      case ah_uv_oxy:
+        u = point->ox;
+        v = point->oy;
+        break;
+      case ah_uv_oyx:
+        u = point->oy;
+        v = point->ox;
+        break;
+      case ah_uv_yx:
+        u = point->y;
+        v = point->x;
+        break;
+      case ah_uv_ox:
+        u = point->x;
+        v = point->ox;
+        break;
+      case ah_uv_oy:
+        u = point->y;
+        v = point->oy;
+        break;
+      default:
+        u = point->x;
+        v = point->y;
+        break;
+      }
+      point->u = u;
+      point->v = v;
+    }
+  }
+
+
+  LOCAL_FUNC
+  void  ah_outline_compute_segments( AH_Outline*  outline )
+  {
+    int           dimension;
+    AH_Segment*   segments;
+    FT_Int*       p_num_segments;
+    AH_Direction  segment_dir;
+    AH_Direction  major_dir;
+
+
+    segments       = outline->horz_segments;
+    p_num_segments = &outline->num_hsegments;
+    major_dir      = ah_dir_right;      /* This value must be positive! */
+    segment_dir    = major_dir;
+
+    /* set up (u,v) in each point */
+    ah_setup_uv( outline, ah_uv_fyx );
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Point**   contour       = outline->contours;
+      AH_Point**   contour_limit = contour + outline->num_contours;
+      AH_Segment*  segment       = segments;
+      FT_Int       num_segments  = 0;
+
+#ifdef AH_HINT_METRICS
+      AH_Point*    min_point = 0;
+      AH_Point*    max_point = 0;
+      FT_Pos       min_coord = 32000;
+      FT_Pos       max_coord = -32000;
+#endif
+
+
+      /* do each contour separately */
+      for ( ; contour < contour_limit; contour++ )
+      {
+        AH_Point*  point   = contour[0];
+        AH_Point*  last    = point->prev;
+        int        on_edge = 0;
+        FT_Pos     min_pos = +32000;  /* minimum segment pos != min_coord */
+        FT_Pos     max_pos = -32000;  /* maximum segment pos != max_coord */
+        FT_Bool    passed;
+
+
+#ifdef AH_HINT_METRICS
+        if ( point->u < min_coord )
+        {
+          min_coord = point->u;
+          min_point = point;
+        }
+        if ( point->u > max_coord )
+        {
+          max_coord = point->u;
+          max_point = point;
+        }
+#endif
+
+        if ( point == last )  /* skip singletons -- just in case? */
+          continue;
+
+        if ( ABS( last->out_dir )  == major_dir &&
+             ABS( point->out_dir ) == major_dir )
+        {
+          /* we are already on an edge, try to locate its start */
+          last = point;
+
+          for (;;)
+          {
+            point = point->prev;
+            if ( ABS( point->out_dir ) != major_dir )
+            {
+              point = point->next;
+              break;
+            }
+            if ( point == last )
+              break;
+          }
+
+        }
+
+        last   = point;
+        passed = 0;
+
+        for (;;)
+        {
+          FT_Pos  u, v;
+
+
+          if ( on_edge )
+          {
+            u = point->u;
+            if ( u < min_pos )
+              min_pos = u;
+            if ( u > max_pos )
+              max_pos = u;
+
+            if ( point->out_dir != segment_dir || point == last )
+            {
+              /* we are just leaving an edge; record a new segment! */
+              segment->last = point;
+              segment->pos  = ( min_pos + max_pos ) >> 1;
+
+              /* a segment is round if either its first or last point */
+              /* is a control point                                   */
+              if ( ( segment->first->flags | point->flags ) &
+                     ah_flah_control                        )
+                segment->flags |= ah_edge_round;
+
+              /* compute segment size */
+              min_pos = max_pos = point->v;
+
+              v = segment->first->v;
+              if ( v < min_pos )
+                min_pos = v;
+              if ( v > max_pos )
+                max_pos = v;
+
+              segment->min_coord = min_pos;
+              segment->max_coord = max_pos;
+
+              on_edge = 0;
+              num_segments++;
+              segment++;
+              /* fallthrough */
+            }
+          }
+
+          /* now exit if we are at the start/end point */
+          if ( point == last )
+          {
+            if ( passed )
+              break;
+            passed = 1;
+          }
+
+          if ( !on_edge && ABS( point->out_dir ) == major_dir )
+          {
+            /* this is the start of a new segment! */
+            segment_dir = point->out_dir;
+
+            /* clear all segment fields */
+            memset( segment, 0, sizeof ( *segment ) );
+
+            segment->dir      = segment_dir;
+            segment->flags    = ah_edge_normal;
+            min_pos = max_pos = point->u;
+            segment->first    = point;
+            segment->last     = point;
+            segment->contour  = contour;
+            on_edge           = 1;
+
+            if ( point == max_point )
+              max_point = 0;
+
+            if ( point == min_point )
+              min_point = 0;
+          }
+
+          point = point->next;
+        }
+
+      } /* contours */
+
+#ifdef AH_HINT_METRICS
+      /* we need to ensure that there are edges on the left-most and  */
+      /* right-most points of the glyph in order to hint the metrics; */
+      /* we do this by inserting fake segments when needed            */
+      if ( dimension == 0 )
+      {
+        AH_Point*  point = outline->points;
+        AH_Point*  limit = point + outline->num_points;
+
+        AH_Point*  min_point = 0;
+        AH_Point*  max_point = 0;
+        FT_Pos     min_pos = 32000;
+        FT_Pos     max_pos = -32000;
+
+
+        /* compute minimum and maximum points */
+        for ( ; point < limit; point++ )
+        {
+          FT_Pos  x = point->fx;
+
+
+          if ( x < min_pos )
+          {
+            min_pos   = x;
+            min_point = point;
+          }
+          if ( x > max_pos )
+          {
+            max_pos   = x;
+            max_point = point;
+          }
+        }
+
+        /* insert minimum segment */
+        if ( min_point )
+        {
+          /* clear all segment fields */
+          memset( segment, 0, sizeof ( *segment ) );
+
+          segment->dir   = segment_dir;
+          segment->flags = ah_edge_normal;
+          segment->first = min_point;
+          segment->last  = min_point;
+          segment->pos   = min_pos;
+
+          num_segments++;
+          segment++;
+        }
+
+        /* insert maximum segment */
+        if ( max_point )
+        {
+          /* clear all segment fields */
+          memset( segment, 0, sizeof ( *segment ) );
+
+          segment->dir   = segment_dir;
+          segment->flags = ah_edge_normal;
+          segment->first = max_point;
+          segment->last  = max_point;
+          segment->pos   = max_pos;
+
+          num_segments++;
+          segment++;
+        }
+      }
+#endif /* AH_HINT_METRICS */
+
+      *p_num_segments = num_segments;
+
+      segments       = outline->vert_segments;
+      major_dir      = ah_dir_up;
+      p_num_segments = &outline->num_vsegments;
+      ah_setup_uv( outline, ah_uv_fxy );
+    }
+  }
+
+
+  LOCAL_FUNC
+  void  ah_outline_link_segments( AH_Outline*  outline )
+  {
+    AH_Segment*  segments;
+    AH_Segment*  limit;
+    int          dimension;
+
+
+    ah_setup_uv( outline, ah_uv_fyx );
+
+    segments = outline->horz_segments;
+    limit    = segments + outline->num_hsegments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Segment*  seg1;
+      AH_Segment*  seg2;
+
+
+      /* now compare each segment to the others */
+      for ( seg1 = segments; seg1 < limit; seg1++ )
+      {
+        FT_Pos       best_score   = 32000;
+        AH_Segment*  best_segment = 0;
+
+
+        /* the fake segments are introduced to hint the metrics -- */
+        /* we must never link them to anything                     */
+        if ( seg1->first == seg1->last )
+          continue;
+
+        for ( seg2 = segments; seg2 < limit; seg2++ )
+          if ( seg1 != seg2 && seg1->dir + seg2->dir == 0 )
+          {
+            FT_Pos   pos1 = seg1->pos;
+            FT_Pos   pos2 = seg2->pos;
+            FT_Bool  is_dir;
+            FT_Bool  is_pos;
+
+
+            /* check that the segments are correctly oriented and */
+            /* positioned to form a black distance                */
+
+            is_dir = ( seg1->dir == outline->horz_major_dir ||
+                       seg1->dir == outline->vert_major_dir );
+            is_pos = pos1 > pos2;
+
+            if ( pos1 == pos2 || !(is_dir ^ is_pos) )
+              continue;
+
+            /* Check the two segments.  We now have a better algorithm */
+            /* that doesn't rely on the segment points themselves but  */
+            /* on their relative position.  This gets rids of many     */
+            /* unpleasant artefacts and incorrect stem/serifs          */
+            /* computations.                                           */
+
+            /* first of all, compute the size of the `common' height */
+            {
+              FT_Pos  min = seg1->min_coord;
+              FT_Pos  max = seg1->max_coord;
+              FT_Pos  len, score;
+              FT_Pos  size1, size2;
+
+
+              size1 = max - min;
+              size2 = seg2->max_coord - seg2->min_coord;
+
+              if ( min < seg2->min_coord )
+                min = seg2->min_coord;
+
+              if ( max < seg2->max_coord )
+                max = seg2->max_coord;
+
+              len   = max - min;
+              score = seg2->pos - seg1->pos;
+              if ( score < 0 )
+                score = -score;
+
+              /* before comparing the scores, take care that the segments */
+              /* are really facing each other (often not for italics..)   */
+              if ( 4 * len >= size1 && 4 * len >= size2 )
+                if ( score < best_score )
+                {
+                  best_score   = score;
+                  best_segment = seg2;
+                }
+            }
+          }
+
+        if ( best_segment )
+        {
+          seg1->link  = best_segment;
+          seg1->score = best_score;
+
+          best_segment->num_linked++;
+        }
+
+
+      } /* edges 1 */
+
+      /* now, compute the `serif' segments */
+      for ( seg1 = segments; seg1 < limit; seg1++ )
+      {
+        seg2 = seg1->link;
+
+        if ( seg2 && seg2->link != seg1 )
+        {
+          seg1->link  = 0;
+          seg1->serif = seg2->link;
+        }
+      }
+
+      ah_setup_uv( outline, ah_uv_fxy );
+
+      segments = outline->vert_segments;
+      limit    = segments + outline->num_vsegments;
+    }
+  }
+
+
+#ifdef AH_DEBUG_GLYPH
+
+  /* A function used to dump the array of linked segments */
+  void  ah_dump_segments( AH_Outline*  outline )
+  {
+    AH_Segment*  segments;
+    AH_Segment*  limit;
+    AH_Point*    points;
+    FT_Int       dimension;
+
+
+    points   = outline->points;
+    segments = outline->horz_segments;
+    limit    = segments + outline->num_hsegments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Segment*  seg;
+
+
+      printf ( "Table of %s segments:\n",
+               !dimension ? "vertical" : "horizontal" );
+      printf ( "  [ index |  pos |  dir  | link | serif |"
+               " numl | first | start ]\n" );
+
+      for ( seg = segments; seg < limit; seg++ )
+      {
+        printf ( "  [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
+                 seg - segments,
+                 (int)seg->pos,
+                 seg->dir == ah_dir_up
+                   ? "up"
+                   : ( seg->dir == ah_dir_down
+                         ? "down"
+                         : ( seg->dir == ah_dir_left
+                               ? "left"
+                               : ( seg->dir == ah_dir_right
+                                     ? "right"
+                                     : "none" ) ) ),
+                 seg->link ? (seg->link-segments) : -1,
+                 seg->serif ? (seg->serif-segments) : -1,
+                 (int)seg->num_linked,
+                 seg->first - points,
+                 seg->last - points );
+      }
+
+      segments = outline->vert_segments;
+      limit    = segments + outline->num_vsegments;
+    }
+  }
+
+#endif /* AH_DEBUG_GLYPH */
+
+
+  static
+  void  ah_outline_compute_edges( AH_Outline*  outline )
+  {
+    AH_Edge*      edges;
+    AH_Segment*   segments;
+    AH_Segment*   segment_limit;
+    AH_Direction  up_dir;
+    FT_Int*       p_num_edges;
+    FT_Int        dimension;
+    FT_Fixed      scale;
+    FT_Pos        edge_distance_threshold;
+
+
+    edges         = outline->horz_edges;
+    segments      = outline->horz_segments;
+    segment_limit = segments + outline->num_hsegments;
+    p_num_edges   = &outline->num_hedges;
+    up_dir        = ah_dir_right;
+    scale         = outline->y_scale;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*     edge;
+      AH_Edge*     edge_limit;  /* really == edge + num_edges */
+      AH_Segment*  seg;
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* We will begin by generating a sorted table of edges for the       */
+      /* current direction.  To do so, we simply scan each segment and try */
+      /* to find an edge in our table that corresponds to its position.    */
+      /*                                                                   */
+      /* If no edge is found, we create and insert a new edge in the       */
+      /* sorted table.  Otherwise, we simply add the segment to the edge's */
+      /* list which will be processed in the second step to compute the    */
+      /* edge's properties.                                                */
+      /*                                                                   */
+      /* Note that the edges table is sorted along the segment/edge        */
+      /* position.                                                         */
+      /*                                                                   */
+      /*********************************************************************/
+
+      edge_distance_threshold = FT_MulFix( outline->edge_distance_threshold,
+                                           scale );
+      if ( edge_distance_threshold > 64 / 4 )
+        edge_distance_threshold = 64 / 4;
+
+      edge_limit = edges;
+      for ( seg = segments; seg < segment_limit; seg++ )
+      {
+        AH_Edge*  found = 0;
+
+
+        /* look for an edge corresponding to the segment */
+        for ( edge = edges; edge < edge_limit; edge++ )
+        {
+          FT_Pos  dist;
+
+
+          dist = seg->pos - edge->fpos;
+          if ( dist < 0 )
+            dist = -dist;
+
+          dist = FT_MulFix( dist, scale );
+          if ( dist < edge_distance_threshold )
+          {
+            found = edge;
+            break;
+          }
+        }
+
+        if ( !found )
+        {
+          /* insert a new edge in the list and */
+          /* sort according to the position    */
+          while ( edge > edges && edge[-1].fpos > seg->pos )
+          {
+            edge[0] = edge[-1];
+            edge--;
+          }
+          edge_limit++;
+
+          /* clear all edge fields */
+          memset( edge, 0, sizeof ( *edge ) );
+
+          /* add the segment to the new edge's list */
+          edge->first    = seg;
+          edge->last     = seg;
+          edge->fpos     = seg->pos;
+          edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
+          seg->edge_next = seg;
+        }
+        else
+        {
+          /* if an edge was found, simply add the segment to the edge's */
+          /* list                                                       */
+          seg->edge_next        = edge->first;
+          edge->last->edge_next = seg;
+          edge->last            = seg;
+        }
+      }
+
+      *p_num_edges = edge_limit - edges;
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Good, we will now compute each edge's properties according to     */
+      /* segments found on its position.  Basically, these are:            */
+      /*                                                                   */
+      /*  - edge's main direction                                          */
+      /*  - stem edge, serif edge or both (which defaults to stem then)    */
+      /*  - rounded edge, straigth or both (which defaults to straight)    */
+      /*  - link for edge                                                  */
+      /*                                                                   */
+      /*********************************************************************/
+
+      /* first of all, set the `edge' field in each segment -- this is */
+      /* required in order to compute edge links                       */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        seg = edge->first;
+        if ( seg )
+          do
+          {
+            seg->edge = edge;
+            seg       = seg->edge_next;
+          }
+          while ( seg != edge->first );
+      }
+
+      /* now, compute each edge properties */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        int  is_round    = 0;  /* does it contain round segments?    */
+        int  is_straight = 0;  /* does it contain straight segments? */
+        int  ups         = 0;  /* number of upwards segments         */
+        int  downs       = 0;  /* number of downwards segments       */
+
+
+        seg = edge->first;
+
+        do
+        {
+          FT_Bool  is_serif;
+
+
+          /* check for roundness of segment */
+          if ( seg->flags & ah_edge_round )
+            is_round++;
+          else
+            is_straight++;
+
+          /* check for segment direction */
+          if ( seg->dir == up_dir )
+            ups   += seg->max_coord-seg->min_coord;
+          else
+            downs += seg->max_coord-seg->min_coord;
+
+          /* check for links -- if seg->serif is set, then seg->link must */
+          /* be ignored                                                   */
+          is_serif = seg->serif && seg->serif->edge != edge;
+
+          if ( seg->link || is_serif )
+          {
+            AH_Edge*     edge2;
+            AH_Segment*  seg2;
+
+
+            edge2 = edge->link;
+            seg2  = seg->link;
+
+            if ( is_serif )
+            {
+              seg2  = seg->serif;
+              edge2 = edge->serif;
+            }
+
+            if ( edge2 )
+            {
+              FT_Pos  edge_delta;
+              FT_Pos  seg_delta;
+
+
+              edge_delta = edge->fpos - edge2->fpos;
+              if ( edge_delta < 0 )
+                edge_delta = -edge_delta;
+
+              seg_delta = seg->pos - seg2->pos;
+              if ( seg_delta < 0 )
+                seg_delta = -seg_delta;
+
+              if ( seg_delta < edge_delta )
+                edge2 = seg2->edge;
+            }
+            else
+              edge2 = seg2->edge;
+
+            if ( is_serif )
+              edge->serif = edge2;
+            else
+              edge->link  = edge2;
+          }
+
+          seg = seg->edge_next;
+
+        } while ( seg != edge->first );
+
+        /* set the round/straight flags */
+        edge->flags = ah_edge_normal;
+
+        if ( is_straight == 0 && is_round )
+          edge->flags |= ah_edge_round;
+
+        /* set the edge's main direction */
+        edge->dir = ah_dir_none;
+
+        if ( ups > downs )
+          edge->dir = up_dir;
+
+        else if ( ups < downs )
+          edge->dir = - up_dir;
+
+        else if ( ups == downs )
+          edge->dir = 0;  /* both up and down !! */
+
+        /* gets rid of serifs if link is set                */
+        /* XXX: This gets rid of many unpleasant artefacts! */
+        /*      Example: the `c' in cour.pfa at size 13     */
+
+        if ( edge->serif && edge->link )
+          edge->serif = 0;
+      }
+
+      edges         = outline->vert_edges;
+      segments      = outline->vert_segments;
+      segment_limit = segments + outline->num_vsegments;
+      p_num_edges   = &outline->num_vedges;
+      up_dir        = ah_dir_up;
+      scale         = outline->x_scale;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_detect_features                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs feature detection on a given AH_Outline object.           */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  ah_outline_detect_features( AH_Outline*  outline )
+  {
+    ah_outline_compute_segments( outline );
+    ah_outline_link_segments   ( outline );
+    ah_outline_compute_edges   ( outline );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_compute_blue_edges                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the `blue edges' in a given outline (i.e. those that must */
+  /*    be snapped to a blue zone edge (top or bottom).                    */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  ah_outline_compute_blue_edges( AH_Outline*       outline,
+                                       AH_Face_Globals*  face_globals )
+  {
+    AH_Edge*     edge    = outline->horz_edges;
+    AH_Edge*     limit   = edge + outline->num_hedges;
+    AH_Globals*  globals = &face_globals->design;
+    FT_Fixed     y_scale = outline->y_scale;
+
+
+    /* compute for each horizontal edge, which blue zone is closer */
+    for ( ; edge < limit; edge++ )
+    {
+      AH_Blue  blue;
+      FT_Pos*  best_blue = 0;
+      FT_Pos   best_dist;  /* initial threshold */
+
+
+      /* compute the initial threshold as a fraction of the EM size */
+      best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale );
+      if ( best_dist > 64 / 4 )
+        best_dist = 64 / 4;
+
+      for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )
+      {
+        /* if it is a top zone, check for right edges -- if it is a bottom */
+        /* zone, check for left edges                                      */
+        /*                                                                 */
+        /* of course, that's for TrueType XXX                              */
+        FT_Bool  is_top_blue  = AH_IS_TOP_BLUE( blue );
+        FT_Bool  is_major_dir = edge->dir == outline->horz_major_dir;
+
+
+        /* if it is a top zone, the edge must be against the major    */
+        /* direction; if it is a bottom zone, it must be in the major */
+        /* direction                                                  */
+        if ( is_top_blue ^ is_major_dir )
+        {
+          FT_Pos   dist;
+          FT_Pos*  blue_pos = globals->blue_refs + blue;
+
+
+          /* first of all, compare it to the reference position */
+          dist = edge->fpos - *blue_pos;
+          if ( dist < 0 )
+            dist = -dist;
+
+          dist = FT_MulFix( dist, y_scale );
+          if ( dist < best_dist )
+          {
+            best_dist = dist;
+            best_blue = blue_pos;
+          }
+
+          /* now, compare it to the overshoot position if the edge is     */
+          /* rounded, and if the edge is over the reference position of a */
+          /* top zone, or under the reference position of a bottom zone   */
+          if ( edge->flags & ah_edge_round && dist != 0 )
+          {
+            FT_Bool  is_under_ref = edge->fpos < *blue_pos;
+
+
+            if ( is_top_blue ^ is_under_ref )
+            {
+              blue_pos = globals->blue_shoots + blue;
+              dist = edge->fpos - *blue_pos;
+              if ( dist < 0 )
+                dist = -dist;
+
+              dist = FT_MulFix( dist, y_scale );
+              if ( dist < best_dist )
+              {
+                best_dist = dist;
+                best_blue = blue_pos;
+              }
+            }
+          }
+        }
+      }
+
+      if ( best_blue )
+        edge->blue_edge = best_blue;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_scale_blue_edges                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This functions must be called before hinting in order to re-adjust */
+  /*    the contents of the detected edges (basically change the `blue     */
+  /*    edge' pointer from `design units' to `scaled ones').               */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  ah_outline_scale_blue_edges( AH_Outline*       outline,
+                                     AH_Face_Globals*  globals )
+  {
+    AH_Edge*  edge  = outline->horz_edges;
+    AH_Edge*  limit = edge + outline->num_hedges;
+    FT_Int    delta;
+
+
+    delta = globals->scaled.blue_refs - globals->design.blue_refs;
+
+    for ( ; edge < limit; edge++ )
+    {
+      if ( edge->blue_edge )
+        edge->blue_edge += delta;
+    }
+  }
+
+
+#ifdef AH_DEBUG_GLYPH
+
+  void  ah_dump_edges( AH_Outline*  outline )
+  {
+    AH_Edge*     edges;
+    AH_Edge*     limit;
+    AH_Segment*  segments;
+    FT_Int       dimension;
+
+
+    edges    = outline->horz_edges;
+    limit    = edges + outline->num_hedges;
+    segments = outline->horz_segments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*  edge;
+
+
+      printf ( "Table of %s edges:\n",
+               !dimension ? "vertical" : "horizontal" );
+      printf ( "  [ index |  pos |  dir  | link |"
+               " serif | blue | opos  |  pos  ]\n" );
+
+      for ( edge = edges; edge < limit; edge++ )
+      {
+        printf ( "  [ %5d | %4d | %5s | %4d | %5d |  %c  | %5.2f | %5.2f ]\n",
+                 edge - edges,
+                 (int)edge->fpos,
+                 edge->dir == ah_dir_up
+                   ? "up"
+                   : ( edge->dir == ah_dir_down
+                         ? "down"
+                         : ( edge->dir == ah_dir_left
+                               ? "left"
+                               : ( edge->dir == ah_dir_right
+                                     ? "right"
+                                     : "none" ) ) ),
+                 edge->link ? ( edge->link - edges ) : -1,
+                 edge->serif ? ( edge->serif - edges ) : -1,
+                 edge->blue_edge ? 'y' : 'n',
+                 edge->opos / 64.0,
+                 edge->pos / 64.0 );
+      }
+
+      edges = outline->vert_edges;
+      limit = edges + outline->num_vedges;
+      segments = outline->vert_segments;
+    }
+  }
+
+#endif /* AH_DEBUG_GLYPH */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahglyph.h b/src/freetype/autohint/ahglyph.h
new file mode 100644 (file)
index 0000000..66fd5e3
--- /dev/null
@@ -0,0 +1,93 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglyph.h                                                              */
+/*                                                                         */
+/*    Routines used to load and analyze a given glyph before hinting       */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef AHGLYPH_H
+#define AHGLYPH_H
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+  typedef enum  AH_UV_
+  {
+    ah_uv_fxy,
+    ah_uv_fyx,
+    ah_uv_oxy,
+    ah_uv_oyx,
+    ah_uv_ox,
+    ah_uv_oy,
+    ah_uv_yx,
+    ah_uv_xy  /* should always be last! */
+
+  } AH_UV;
+
+
+  LOCAL_DEF
+  void  ah_setup_uv( AH_Outline*  outline,
+                     AH_UV        source );
+
+
+  /* AH_Outline functions - they should be typically called in this order */
+
+  LOCAL_DEF
+  FT_Error  ah_outline_new( FT_Memory     memory,
+                            AH_Outline**  aoutline );
+
+  LOCAL_DEF
+  FT_Error  ah_outline_load( AH_Outline*  outline,
+                             FT_Face      face );
+
+  LOCAL_DEF
+  void  ah_outline_compute_segments( AH_Outline*  outline );
+
+  LOCAL_DEF
+  void  ah_outline_link_segments( AH_Outline*  outline );
+
+  LOCAL_DEF
+  void  ah_outline_detect_features( AH_Outline*  outline );
+
+  LOCAL_DEF
+  void  ah_outline_compute_blue_edges( AH_Outline*       outline,
+                                       AH_Face_Globals*  globals );
+
+  LOCAL_DEF
+  void  ah_outline_scale_blue_edges( AH_Outline*       outline,
+                                     AH_Face_Globals*  globals );
+
+  LOCAL_DEF
+  void  ah_outline_save( AH_Outline*  outline, AH_Loader*  loader );
+
+  LOCAL_DEF
+  void  ah_outline_done( AH_Outline*  outline );
+
+
+#endif /* AHGLYPH_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahhint.c b/src/freetype/autohint/ahhint.c
new file mode 100644 (file)
index 0000000..f50f883
--- /dev/null
@@ -0,0 +1,1398 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahhint.c                                                               */
+/*                                                                         */
+/*    Glyph hinter (body).                                                 */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahhint.h"
+#include "ahglyph.h"
+#include "ahangles.h"
+
+#else
+
+#include <autohint/ahhint.h>
+#include <autohint/ahglyph.h>
+#include <autohint/ahangles.h>
+
+#endif
+
+#include <freetype/ftoutln.h>
+
+
+#define FACE_GLOBALS( face )  ((AH_Face_Globals*)(face)->autohint.data)
+
+#define AH_USE_IUP
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   Hinting routines                                              ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static int  disable_horz_edges = 0;
+  static int  disable_vert_edges = 0;
+
+
+  /* snap a given width in scaled coordinates to one of the */
+  /* current standard widths                                */
+  static
+  FT_Pos  ah_snap_width( FT_Pos*  widths,
+                         FT_Int   count,
+                         FT_Pos   width )
+  {
+    int     n;
+    FT_Pos  best      = 64 + 32 + 2;
+    FT_Pos  reference = width;
+
+
+    for ( n = 0; n < count; n++ )
+    {
+      FT_Pos  w;
+      FT_Pos  dist;
+
+
+      w = widths[n];
+      dist = width - w;
+      if ( dist < 0 )
+        dist = -dist;
+      if ( dist < best )
+      {
+        best      = dist;
+        reference = w;
+      }
+    }
+
+    if ( width >= reference )
+    {
+      width -= 0x21;
+      if ( width < reference )
+        width = reference;
+    }
+    else
+    {
+      width += 0x21;
+      if ( width > reference )
+        width = reference;
+    }
+
+    return width;
+  }
+
+
+  /* align one stem edge relative to the previous stem edge */
+  static
+  void  ah_align_linked_edge( AH_Hinter*  hinter,
+                              AH_Edge*    base_edge,
+                              AH_Edge*    stem_edge,
+                              int         vertical )
+  {
+    FT_Pos       dist    = stem_edge->opos - base_edge->opos;
+    AH_Globals*  globals = &hinter->globals->scaled;
+    FT_Pos       sign    = 1;
+
+
+    if ( dist < 0 )
+    {
+      dist = -dist;
+      sign = -1;
+    }
+
+    if ( vertical )
+    {
+      dist = ah_snap_width( globals->heights, globals->num_heights, dist );
+
+      /* in the case of vertical hinting, always round */
+      /* the stem heights to integer pixels            */
+      if ( dist >= 64 )
+        dist = ( dist + 16 ) & -64;
+      else
+        dist = 64;
+    }
+    else
+    {
+      dist = ah_snap_width( globals->widths,  globals->num_widths, dist );
+
+      if ( hinter->flags & ah_hinter_monochrome )
+      {
+        /* monochrome horizontal hinting: snap widths to integer pixels */
+        /* with a different threshold                                   */
+        if ( dist < 64 )
+          dist = 64;
+        else
+          dist = ( dist + 32 ) & -64;
+      }
+      else
+      {
+        /* for horizontal anti-aliased hinting, we adopt a more subtle */
+        /* approach: we strengthen small stems, round stems whose size */
+        /* is between 1 and 2 pixels to an integer, otherwise nothing  */
+        if ( dist < 48 )
+          dist = ( dist + 64 ) >> 1;
+
+        else if ( dist < 128 )
+          dist = ( dist + 42 ) & -64;
+      }
+    }
+
+    stem_edge->pos = base_edge->pos + sign * dist;
+  }
+
+
+  static
+  void  ah_align_serif_edge( AH_Hinter*  hinter,
+                             AH_Edge*    base,
+                             AH_Edge*    serif )
+  {
+    FT_Pos  dist;
+    FT_Pos  sign = 1;
+
+    UNUSED( hinter );
+
+
+    dist = serif->opos - base->opos;
+    if ( dist < 0 )
+    {
+      dist = -dist;
+      sign = -1;
+    }
+
+    /* do not strengthen serifs */
+    if ( base->flags & ah_edge_done )
+    {
+      if ( dist > 64 )
+        dist = ( dist + 16 ) & -64;
+
+      else if ( dist <= 32 )
+        dist = ( dist + 33 ) >> 1;
+    }
+
+    serif->pos = base->pos + sign * dist;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****       E D G E   H I N T I N G                                   ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* Another alternative edge hinting algorithm */
+  static
+  void  ah_hint_edges_3( AH_Hinter*  hinter )
+  {
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Outline*  outline = hinter->glyph;
+    FT_Int       dimension;
+
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*  edge;
+      AH_Edge*  before = 0;
+      AH_Edge*  after  = 0;
+      AH_Edge*  anchor = 0;
+      int       has_serifs = 0;
+
+
+      if ( disable_vert_edges && !dimension )
+        goto Next_Dimension;
+
+      if ( disable_horz_edges && dimension )
+        goto Next_Dimension;
+
+      /* we begin by aligning all stems relative to the blue zone */
+      /* if needed -- that's only for horizontal edges            */
+      if ( dimension )
+      {
+        for ( edge = edges; edge < edge_limit; edge++ )
+        {
+          FT_Pos*  blue;
+          AH_Edge  *edge1, *edge2;
+
+
+          if ( edge->flags & ah_edge_done )
+            continue;
+
+          blue  = edge->blue_edge;
+          edge1 = 0;
+          edge2 = edge->link;
+
+          if ( blue )
+          {
+            edge1 = edge;
+          }
+          else if (edge2 && edge2->blue_edge)
+          {
+            blue  = edge2->blue_edge;
+            edge1 = edge2;
+            edge2 = edge;
+          }
+
+          if ( !edge1 )
+            continue;
+
+          edge1->pos    = blue[0];
+          edge1->flags |= ah_edge_done;
+
+          if ( edge2 && !edge2->blue_edge )
+          {
+            ah_align_linked_edge( hinter, edge1, edge2, dimension );
+            edge2->flags |= ah_edge_done;
+          }
+
+          if ( !anchor )
+            anchor = edge;
+         }
+       }
+
+      /* now, we will align all stem edges, trying to maintain the */
+      /* relative order of stems in the glyph..                    */
+      before = 0;
+      after  = 0;
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        AH_Edge  *edge2;
+
+
+        if ( edge->flags & ah_edge_done )
+          continue;
+
+        /* skip all non-stem edges */
+        edge2 = edge->link;
+        if ( !edge2 )
+        {
+          has_serifs++;
+          continue;
+        }
+
+        /* now, align the stem */
+
+        /* this should not happen, but it's better to be safe.. */
+        if ( edge2->blue_edge || edge2 < edge )
+        {
+
+#if 0
+          printf( "strange blue alignement, edge %d to %d\n",
+                  edge - edges, edge2 - edges );
+#endif
+
+          ah_align_linked_edge( hinter, edge2, edge, dimension );
+          edge->flags |= ah_edge_done;
+          continue;
+        }
+
+        {
+          FT_Bool  min = 0;
+          FT_Pos   delta;
+
+          if ( !anchor )
+          {
+            edge->pos = ( edge->opos + 32 ) & -64;
+            anchor    = edge;
+          }
+          else
+            edge->pos = anchor->pos +
+                        ( ( edge->opos - anchor->opos + 32 ) & -64 );
+
+          edge->flags |= ah_edge_done;
+
+          if ( edge > edges && edge->pos < edge[-1].pos )
+          {
+            edge->pos = edge[-1].pos;
+            min       = 1;
+          }
+
+          ah_align_linked_edge( hinter, edge, edge2, dimension );
+          delta = 0;
+          if ( edge2 + 1 < edge_limit        &&
+               edge2[1].flags & ah_edge_done )
+            delta = edge2[1].pos - edge2->pos;
+
+          if ( delta < 0 )
+          {
+            edge2->pos += delta;
+            if ( !min )
+              edge->pos += delta;
+          }
+          edge2->flags |= ah_edge_done;
+        }
+      }
+
+      if ( !has_serifs )
+        goto Next_Dimension;
+
+      /* now, hint the remaining edges (serifs and single) in order */
+      /* to complete our processing                                 */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        if ( edge->flags & ah_edge_done )
+          continue;
+
+        if ( edge->serif )
+        {
+          ah_align_serif_edge( hinter, edge->serif, edge );
+        }
+        else if ( !anchor )
+        {
+          edge->pos = ( edge->opos + 32 ) & -64;
+          anchor    = edge;
+        }
+        else
+          edge->pos = anchor->pos +
+                      ( ( edge->opos-anchor->opos + 32 ) & -64 );
+
+        edge->flags |= ah_edge_done;
+
+        if ( edge > edges && edge->pos < edge[-1].pos )
+          edge->pos = edge[-1].pos;
+
+        if ( edge + 1 < edge_limit        &&
+             edge[1].flags & ah_edge_done &&
+             edge->pos > edge[1].pos      )
+          edge->pos = edge[1].pos;
+      }
+
+    Next_Dimension:
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+    }
+  }
+
+
+  LOCAL_FUNC
+  void  ah_hinter_hint_edges( AH_Hinter*  hinter,
+                              int         no_horz_edges,
+                              int         no_vert_edges )
+  {
+    disable_horz_edges = no_horz_edges;
+    disable_vert_edges = no_vert_edges;
+
+    /* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help      */
+    /* reduce the problem of the disappearing eye in the `e' of Times... */
+    /* also, creates some artifacts near the blue zones?                 */
+    {
+      ah_hint_edges_3( hinter );
+
+#if 0
+      /* outline optimizer removed temporarily */
+      if ( hinter->flags & ah_hinter_optimize )
+      {
+        AH_Optimizer  opt;
+
+
+        if ( !AH_Optimizer_Init( &opt, hinter->glyph, hinter->memory ) )
+        {
+          AH_Optimizer_Compute( &opt );
+          AH_Optimizer_Done( &opt );
+        }
+      }
+#endif
+
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****       P O I N T   H I N T I N G                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static
+  void  ah_hinter_align_edge_points( AH_Hinter*  hinter )
+  {
+    AH_Outline*  outline = hinter->glyph;
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    FT_Int       dimension;
+
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*   edge;
+      AH_Edge*   before;
+      AH_Edge*   after;
+
+
+      before = 0;
+      after  = 0;
+
+      edge = edges;
+      for ( ; edge < edge_limit; edge++ )
+      {
+        /* move the points of each segment     */
+        /* in each edge to the edge's position */
+        AH_Segment*  seg = edge->first;
+
+
+        do
+        {
+          AH_Point*  point = seg->first;
+
+
+          for (;;)
+          {
+            if ( dimension )
+            {
+              point->y      = edge->pos;
+              point->flags |= ah_flah_touch_y;
+            }
+            else
+            {
+              point->x      = edge->pos;
+              point->flags |= ah_flah_touch_x;
+            }
+
+            if ( point == seg->last )
+              break;
+
+            point = point->next;
+          }
+
+          seg = seg->edge_next;
+
+        } while ( seg != edge->first );
+      }
+
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+    }
+  }
+
+
+  /* hint the strong points -- this is equivalent to the TrueType `IP' */
+  static
+  void  ah_hinter_align_strong_points( AH_Hinter*  hinter )
+  {
+    AH_Outline*  outline = hinter->glyph;
+    FT_Int       dimension;
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Point*    points;
+    AH_Point*    point_limit;
+    AH_Flags     touch_flag;
+
+
+    points      = outline->points;
+    point_limit = points + outline->num_points;
+
+    edges       = outline->horz_edges;
+    edge_limit  = edges + outline->num_hedges;
+    touch_flag  = ah_flah_touch_y;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Point*  point;
+      AH_Edge*   edge;
+      AH_Edge*   before;
+      AH_Edge*   after;
+
+
+      before = 0;
+      after  = 0;
+
+      if ( edges < edge_limit )
+        for ( point = points; point < point_limit; point++ )
+        {
+          FT_Pos  u, ou, fu;  /* point position */
+          FT_Pos  delta;
+
+
+          if ( point->flags & touch_flag )
+            continue;
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+          /* if this point is candidate to weak interpolation, we will  */
+          /* interpolate it after all strong points have been processed */
+          if ( point->flags & ah_flah_weak_interpolation )
+            continue;
+#endif
+
+          if ( dimension )
+          {
+            u  = point->fy;
+            ou = point->oy;
+          }
+          else
+          {
+            u  = point->fx;
+            ou = point->ox;
+          }
+
+          fu = u;
+
+          /* is the point before the first edge? */
+          edge  = edges;
+          delta = edge->fpos - u;
+          if ( delta >= 0 )
+          {
+            u = edge->pos - ( edge->opos - ou );
+            goto Store_Point;
+          }
+
+          /* is the point after the last edge ? */
+          edge  = edge_limit - 1;
+          delta = u - edge->fpos;
+          if ( delta >= 0 )
+          {
+            u = edge->pos + ( ou - edge->opos );
+            goto Store_Point;
+          }
+
+          /* otherwise, interpolate the point in between */
+          {
+            AH_Edge*  before = 0;
+            AH_Edge*  after  = 0;
+
+
+            for ( edge = edges; edge < edge_limit; edge++ )
+            {
+              if ( u == edge->fpos )
+              {
+                u = edge->pos;
+                goto Store_Point;
+              }
+              if ( u < edge->fpos )
+                break;
+              before = edge;
+            }
+
+            for ( edge = edge_limit - 1; edge >= edges; edge-- )
+            {
+              if ( u == edge->fpos )
+              {
+                u = edge->pos;
+                goto Store_Point;
+              }
+              if ( u > edge->fpos )
+                break;
+              after = edge;
+            }
+
+            /* assert( before && after && before != after ) */
+            u = before->pos + FT_MulDiv( fu - before->fpos,
+                                         after->pos - before->pos,
+                                         after->fpos - before->fpos );
+          }
+
+        Store_Point:
+
+          /* save the point position */
+          if ( dimension )
+            point->y = u;
+          else
+            point->x = u;
+
+          point->flags |= touch_flag;
+        }
+
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+      touch_flag = ah_flah_touch_x;
+    }
+  }
+
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+
+  static
+  void  ah_iup_shift( AH_Point*  p1,
+                      AH_Point*  p2,
+                      AH_Point*  ref )
+  {
+    AH_Point*  p;
+    FT_Pos     delta = ref->u - ref->v;
+
+
+    for ( p = p1; p < ref; p++ )
+      p->u = p->v + delta;
+
+    for ( p = ref + 1; p <= p2; p++ )
+      p->u = p->v + delta;
+  }
+
+
+  static
+  void  ah_iup_interp( AH_Point*  p1,
+                       AH_Point*  p2,
+                       AH_Point*  ref1,
+                       AH_Point*  ref2 )
+  {
+    AH_Point*  p;
+    FT_Pos     u;
+    FT_Pos     v1 = ref1->v;
+    FT_Pos     v2 = ref2->v;
+    FT_Pos     d1 = ref1->u - v1;
+    FT_Pos     d2 = ref2->u - v2;
+
+
+    if ( p1 > p2 )
+      return;
+
+    if ( v1 == v2 )
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        FT_Pos  u = p->v;
+
+
+        if ( u <= v1 )
+          u += d1;
+        else
+          u += d2;
+
+        p->u = u;
+      }
+      return;
+    }
+
+    if ( v1 < v2 )
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v1 )
+          u += d1;
+        else if ( u >= v2 )
+          u += d2;
+        else
+          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+        p->u = u;
+      }
+    }
+    else
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v2 )
+          u += d2;
+        else if ( u >= v1 )
+          u += d1;
+        else
+          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+        p->u = u;
+      }
+    }
+  }
+
+
+  /* interpolate weak points -- this is equivalent to the TrueType `IUP' */
+  static
+  void  ah_hinter_align_weak_points( AH_Hinter*  hinter )
+  {
+    AH_Outline*  outline = hinter->glyph;
+    FT_Int       dimension;
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Point*    points;
+    AH_Point*    point_limit;
+    AH_Point**   contour_limit;
+    AH_Flags     touch_flag;
+
+
+    points      = outline->points;
+    point_limit = points + outline->num_points;
+
+    /* PASS 1: Move segment points to edge positions */
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+    touch_flag = ah_flah_touch_y;
+
+    contour_limit = outline->contours + outline->num_contours;
+
+    ah_setup_uv( outline, ah_uv_oy );
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Point*   point;
+      AH_Point*   end_point;
+      AH_Point*   first_point;
+      AH_Point**  contour;
+
+
+      point   = points;
+      contour = outline->contours;
+
+      for ( ; contour < contour_limit; contour++ )
+      {
+        point       = *contour;
+        end_point   = point->prev;
+        first_point = point;
+
+        while ( point <= end_point && !( point->flags & touch_flag ) )
+          point++;
+
+        if ( point <= end_point )
+        {
+          AH_Point*  first_touched = point;
+          AH_Point*  cur_touched   = point;
+
+
+          point++;
+          while ( point <= end_point )
+          {
+            if ( point->flags & touch_flag )
+            {
+              /* we found two successive touched points; we interpolate */
+              /* all contour points between them                        */
+              ah_iup_interp( cur_touched + 1, point - 1,
+                             cur_touched, point );
+              cur_touched = point;
+            }
+            point++;
+          }
+
+          if ( cur_touched == first_touched )
+          {
+            /* this is a special case: only one point was touched in the */
+            /* contour; we thus simply shift the whole contour           */
+            ah_iup_shift( first_point, end_point, cur_touched );
+          }
+          else
+          {
+            /* now interpolate after the last touched point to the end */
+            /* of the contour                                          */
+            ah_iup_interp( cur_touched + 1, end_point,
+                           cur_touched, first_touched );
+
+            /* if the first contour point isn't touched, interpolate */
+            /* from the contour start to the first touched point     */
+            if ( first_touched > points )
+              ah_iup_interp( first_point, first_touched - 1,
+                             cur_touched, first_touched );
+          }
+        }
+      }
+
+      /* now save the interpolated values back to x/y */
+      if ( dimension )
+      {
+        for ( point = points; point < point_limit; point++ )
+          point->y = point->u;
+
+        touch_flag = ah_flah_touch_x;
+        ah_setup_uv( outline, ah_uv_ox );
+      }
+      else
+      {
+        for ( point = points; point < point_limit; point++ )
+          point->x = point->u;
+
+        break;  /* exit loop */
+      }
+    }
+  }
+
+#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
+
+
+  LOCAL_FUNC
+  void  ah_hinter_align_points( AH_Hinter*  hinter )
+  {
+    ah_hinter_align_edge_points( hinter );
+
+#ifndef AH_OPTION_NO_STRONG_INTERPOLATION
+    ah_hinter_align_strong_points( hinter );
+#endif
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+    ah_hinter_align_weak_points( hinter );
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****       H I N T E R   O B J E C T   M E T H O D S                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* scale and fit the global metrics */
+  static
+  void  ah_hinter_scale_globals( AH_Hinter*  hinter,
+                                 FT_Fixed    x_scale,
+                                 FT_Fixed    y_scale )
+  {
+    FT_Int            n;
+    AH_Face_Globals*  globals = hinter->globals;
+    AH_Globals*       design = &globals->design;
+    AH_Globals*       scaled = &globals->scaled;
+
+
+    /* copy content */
+    *scaled = *design;
+
+    /* scale the standard widths & heights */
+    for ( n = 0; n < design->num_widths; n++ )
+      scaled->widths[n] = FT_MulFix( design->widths[n], x_scale );
+
+    for ( n = 0; n < design->num_heights; n++ )
+      scaled->heights[n] = FT_MulFix( design->heights[n], y_scale );
+
+    /* scale the blue zones */
+    for ( n = 0; n < ah_blue_max; n++ )
+    {
+      FT_Pos  delta, delta2;
+
+
+      delta = design->blue_shoots[n] - design->blue_refs[n];
+      delta2 = delta;
+      if ( delta < 0 )
+        delta2 = -delta2;
+      delta2 = FT_MulFix( delta2, y_scale );
+
+      if ( delta2 < 32 )
+        delta2 = 0;
+      else if ( delta2 < 64 )
+        delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & -32 );
+      else
+        delta2 = ( delta2 + 32 ) & -64;
+
+      if ( delta < 0 )
+        delta2 = -delta2;
+
+      scaled->blue_refs[n] =
+        ( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64;
+      scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2;
+    }
+
+    globals->x_scale = x_scale;
+    globals->y_scale = y_scale;
+  }
+
+
+  static
+  void  ah_hinter_align( AH_Hinter*  hinter )
+  {
+    ah_hinter_align_edge_points( hinter );
+    ah_hinter_align_points( hinter );
+  }
+
+
+  /* finalize a hinter object */
+  void ah_hinter_done( AH_Hinter*  hinter )
+  {
+    if ( hinter )
+    {
+      FT_Memory  memory = hinter->memory;
+
+
+      ah_loader_done( hinter->loader );
+      ah_outline_done( hinter->glyph );
+
+      /* note: the `globals' pointer is _not_ owned by the hinter */
+      /*       but by the current face object, we don't need to   */
+      /*       release it                                         */
+      hinter->globals = 0;
+      hinter->face    = 0;
+
+      FREE( hinter );
+    }
+  }
+
+
+  /* create a new empty hinter object */
+  FT_Error  ah_hinter_new( FT_Library   library,
+                           AH_Hinter**  ahinter )
+  {
+    AH_Hinter*  hinter = 0;
+    FT_Memory   memory = library->memory;
+    FT_Error    error;
+
+
+    *ahinter = 0;
+
+    /* allocate object */
+    if ( ALLOC( hinter, sizeof ( *hinter ) ) )
+      goto Exit;
+
+    hinter->memory = memory;
+    hinter->flags  = 0;
+
+    /* allocate outline and loader */
+    error = ah_outline_new( memory, &hinter->glyph )  ||
+            ah_loader_new ( memory, &hinter->loader ) ||
+            ah_loader_create_extra( hinter->loader );
+    if ( error )
+      goto Exit;
+
+    *ahinter = hinter;
+
+  Exit:
+    if ( error )
+      ah_hinter_done( hinter );
+
+    return error;
+  }
+
+
+  /* create a face's autohint globals */
+  FT_Error  ah_hinter_new_face_globals( AH_Hinter*   hinter,
+                                        FT_Face      face,
+                                        AH_Globals*  globals )
+  {
+    FT_Error          error;
+    FT_Memory         memory = hinter->memory;
+    AH_Face_Globals*  face_globals;
+
+
+    if ( ALLOC( face_globals, sizeof ( *face_globals ) ) )
+      goto Exit;
+
+    hinter->face    = face;
+    hinter->globals = face_globals;
+
+    if ( globals )
+      face_globals->design = *globals;
+    else
+      ah_hinter_compute_globals( hinter );
+
+    face->autohint.data      = face_globals;
+    face->autohint.finalizer = (FT_Generic_Finalizer)
+                                 ah_hinter_done_face_globals;
+    face_globals->face       = face;
+
+  Exit:
+    return error;
+  }
+
+
+  /* discard a face's autohint globals */
+  void  ah_hinter_done_face_globals( AH_Face_Globals*  globals )
+  {
+    FT_Face    face   = globals->face;
+    FT_Memory  memory = face->memory;
+
+
+    FREE( globals );
+  }
+
+
+  static
+  FT_Error  ah_hinter_load( AH_Hinter*  hinter,
+                            FT_UInt     glyph_index,
+                            FT_UInt     load_flags,
+                            FT_UInt     depth )
+  {
+    FT_Face           face    = hinter->face;
+    FT_GlyphSlot      slot    = face->glyph;
+    FT_Fixed          x_scale = face->size->metrics.x_scale;
+    FT_Fixed          y_scale = face->size->metrics.y_scale;
+    FT_Glyph_Metrics  metrics;  /* temporary metrics */
+    FT_Error          error;
+    AH_Outline*       outline = hinter->glyph;
+    AH_Loader*        gloader = hinter->loader;
+    FT_Bool           no_horz_hints =
+                        ( load_flags & AH_HINT_NO_HORZ_EDGES ) != 0;
+    FT_Bool           no_vert_hints =
+                        ( load_flags & AH_HINT_NO_VERT_EDGES ) != 0;
+
+
+    /* load the glyph */
+    error = FT_Load_Glyph( face, glyph_index, load_flags );
+    if ( error )
+      goto Exit;
+
+    /* save current glyph metrics */
+    metrics = slot->metrics;
+
+    switch ( slot->format )
+    {
+    case ft_glyph_format_outline:
+      /* first of all, copy the outline points in the loader's current  */
+      /* extra points, which is used to keep original glyph coordinates */
+      error = ah_loader_check_points( gloader, slot->outline.n_points + 2,
+                                      slot->outline.n_contours );
+      if ( error )
+        goto Exit;
+
+      MEM_Copy( gloader->current.extra_points, slot->outline.points,
+                slot->outline.n_points * sizeof ( FT_Vector ) );
+
+      MEM_Copy( gloader->current.outline.contours, slot->outline.contours,
+                slot->outline.n_contours * sizeof ( short ) );
+
+      MEM_Copy( gloader->current.outline.tags, slot->outline.tags,
+                slot->outline.n_points * sizeof ( char ) );
+
+      gloader->current.outline.n_points   = slot->outline.n_points;
+      gloader->current.outline.n_contours = slot->outline.n_contours;
+
+      /* compute original phantom points */
+      hinter->pp1.x = 0;
+      hinter->pp1.y = 0;
+      hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale );
+      hinter->pp2.y = 0;
+
+      /* be sure to check for spacing glyphs */
+      if ( slot->outline.n_points == 0 )
+        goto Hint_Metrics;
+
+      /* now, load the slot image into the auto-outline, and run the */
+      /* automatic hinting process                                   */
+      error = ah_outline_load( outline, face );   /* XXX: change to slot */
+      if ( error )
+        goto Exit;
+
+      /* perform feature detection */
+      ah_outline_detect_features( outline );
+
+      if ( !no_horz_hints )
+      {
+        ah_outline_compute_blue_edges( outline, hinter->globals );
+        ah_outline_scale_blue_edges( outline, hinter->globals );
+      }
+
+      /* perform alignment control */
+      ah_hinter_hint_edges( hinter, no_horz_hints, no_vert_hints );
+      ah_hinter_align( hinter );
+
+      /* now save the current outline into the loader's current table */
+      ah_outline_save( outline, gloader );
+
+      /* we now need to hint the metrics according to the change in */
+      /* width/positioning that occured during the hinting process  */
+      {
+        FT_Pos    old_width, new_width;
+        FT_Pos    old_advance, new_advance;
+        FT_Pos    old_lsb, new_lsb;
+        AH_Edge*  edge1 = outline->vert_edges;     /* leftmost edge  */
+        AH_Edge*  edge2 = edge1 +
+                          outline->num_vedges - 1; /* rightmost edge */
+
+
+        old_width = edge2->opos - edge1->opos;
+        new_width = edge2->pos  - edge1->pos;
+
+        old_advance = hinter->pp2.x;
+        old_lsb     = edge1->opos;
+        new_lsb     = edge1->pos;
+
+        new_advance = old_advance +
+                      ( new_width + new_lsb - old_width - old_lsb );
+
+        hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64;
+        hinter->pp2.x = ( ( edge2->pos + 
+                            ( old_advance - edge2->opos ) ) + 32 ) & -64;
+      }
+
+      /* good, we simply add the glyph to our loader's base */
+      ah_loader_add( gloader );
+      break;
+
+    case ft_glyph_format_composite:
+      {
+        FT_UInt       nn, num_subglyphs = slot->num_subglyphs;
+        FT_UInt       num_base_subgs, start_point, start_contour;
+        FT_SubGlyph*  subglyph;
+
+
+        start_point   = gloader->base.outline.n_points;
+        start_contour = gloader->base.outline.n_contours;
+
+        /* first of all, copy the subglyph descriptors in the glyph loader */
+        error = ah_loader_check_subglyphs( gloader, num_subglyphs );
+        if ( error )
+          goto Exit;
+
+        MEM_Copy( gloader->current.subglyphs, slot->subglyphs,
+                  num_subglyphs * sizeof ( FT_SubGlyph ) );
+
+        gloader->current.num_subglyphs = num_subglyphs;
+        num_base_subgs = gloader->base.num_subglyphs;
+
+        /* now, read each subglyph independently */
+        for ( nn = 0; nn < num_subglyphs; nn++ )
+        {
+          FT_Vector  pp1, pp2;
+          FT_Pos     x, y;
+          FT_UInt    num_points, num_new_points, num_base_points;
+
+
+          /* gloader.current.subglyphs can change during glyph loading due */
+          /* to re-allocation -- we must recompute the current subglyph on */
+          /* each iteration                                                */
+          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+          pp1 = hinter->pp1;
+          pp2 = hinter->pp2;
+
+          num_base_points = gloader->base.outline.n_points;
+
+          error = ah_hinter_load( hinter, subglyph->index,
+                                  load_flags, depth + 1 );
+          if ( error )
+            goto Exit;
+
+          /* recompute subglyph pointer */
+          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+          if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
+          {
+            pp1 = hinter->pp1;
+            pp2 = hinter->pp2;
+          }
+          else
+          {
+            hinter->pp1 = pp1;
+            hinter->pp2 = pp2;
+          }
+
+          num_points     = gloader->base.outline.n_points;
+          num_new_points = num_points - num_base_points;
+
+          /* now perform the transform required for this subglyph */
+
+          if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
+                                   FT_SUBGLYPH_FLAG_XY_SCALE |
+                                   FT_SUBGLYPH_FLAG_2X2      ) )
+          {
+            FT_Vector*  cur   = gloader->base.outline.points +
+                                num_base_points;
+            FT_Vector*  org   = gloader->base.extra_points +
+                                num_base_points;
+            FT_Vector*  limit = cur + num_new_points;
+
+
+            for ( ; cur < limit; cur++, org++ )
+            {
+              FT_Vector_Transform( cur, &subglyph->transform );
+              FT_Vector_Transform( org, &subglyph->transform );
+            }
+          }
+
+          /* apply offset */
+
+          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
+          {
+            FT_Int      k = subglyph->arg1;
+            FT_UInt     l = subglyph->arg2;
+            FT_Vector*  p1;
+            FT_Vector*  p2;
+
+
+            if ( start_point + k >= num_base_points          ||
+                               l >= (FT_UInt)num_new_points  )
+            {
+              error = FT_Err_Invalid_Composite;
+              goto Exit;
+            }
+
+            l += num_base_points;
+
+            /* for now, only use the current point coordinates     */
+            /* we may consider another approach in the near future */
+            p1 = gloader->base.outline.points + start_point + k;
+            p2 = gloader->base.outline.points + start_point + l;
+
+            x = p1->x - p2->x;
+            y = p1->y - p2->y;
+          }
+          else
+          {
+            x = FT_MulFix( subglyph->arg1, x_scale );
+            y = FT_MulFix( subglyph->arg2, y_scale );
+
+            x = ( x + 32 ) & -64;
+            y = ( y + 32 ) & -64;
+          }
+
+          {
+            FT_Outline  dummy = gloader->base.outline;
+
+
+            dummy.points  += num_base_points;
+            dummy.n_points = num_new_points;
+
+            FT_Outline_Translate( &dummy, x, y );
+          }
+        }
+      }
+      break;
+
+    default:
+      /* we don't support other formats (yet?) */
+      error = FT_Err_Unimplemented_Feature;
+    }
+
+  Hint_Metrics:
+    if ( depth == 0 )
+    {
+      FT_BBox  bbox;
+
+
+      /* we must translate our final outline by -pp1.x, and compute */
+      /* the new metrics                                            */
+      if ( hinter->pp1.x )
+        FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 );
+
+      FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
+      bbox.xMin &= -64;
+      bbox.yMin &= -64;
+      bbox.xMax  = ( bbox.xMax + 63 ) & -64;
+      bbox.yMax  = ( bbox.yMax + 63 ) & -64;
+
+      slot->metrics.width        = bbox.xMax - bbox.xMin;
+      slot->metrics.height       = bbox.yMax - bbox.yMin;
+      slot->metrics.horiBearingX = bbox.xMin;
+      slot->metrics.horiBearingY = bbox.yMax;
+      slot->metrics.horiAdvance  = hinter->pp2.x - hinter->pp1.x;
+      /* XXX: TO DO - slot->linearHoriAdvance */
+
+      /* now copy outline into glyph slot */
+      ah_loader_rewind( slot->loader );
+      error = ah_loader_copy_points( slot->loader, gloader );
+      if ( error )
+        goto Exit;
+
+      slot->outline = slot->loader->base.outline;
+      slot->format  = ft_glyph_format_outline;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* load and hint a given glyph */
+  FT_Error  ah_hinter_load_glyph( AH_Hinter*    hinter,
+                                  FT_GlyphSlot  slot,
+                                  FT_Size       size,
+                                  FT_UInt       glyph_index,
+                                  FT_Int        load_flags )
+  {
+    FT_Face           face         = slot->face;
+    FT_Error          error;
+    FT_Fixed          x_scale      = size->metrics.x_scale;
+    FT_Fixed          y_scale      = size->metrics.y_scale;
+    AH_Face_Globals*  face_globals = FACE_GLOBALS( face );
+
+
+    /* first of all, we need to check that we're using the correct face and */
+    /* global hints to load the glyph                                       */
+    if ( hinter->face != face || hinter->globals != face_globals )
+    {
+      hinter->face = face;
+      if ( !face_globals )
+      {
+        error = ah_hinter_new_face_globals( hinter, face, 0 );
+        if ( error )
+          goto Exit;
+      }
+      hinter->globals = FACE_GLOBALS( face );
+      face_globals    = FACE_GLOBALS( face );
+    }
+
+    /* now, we must check the current character pixel size to see if we */
+    /* need to rescale the global metrics                               */
+    if ( face_globals->x_scale != x_scale ||
+         face_globals->y_scale != y_scale )
+      ah_hinter_scale_globals( hinter, x_scale, y_scale );
+
+    load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE;
+
+    ah_loader_rewind( hinter->loader );
+
+    error = ah_hinter_load( hinter, glyph_index, load_flags, 0 );
+
+  Exit:
+    return error;
+  }
+
+
+  /* retrieve a face's autohint globals for client applications */
+  void  ah_hinter_get_global_hints( AH_Hinter*  hinter,
+                                    FT_Face     face,
+                                    void**      global_hints,
+                                    long*       global_len )
+  {
+    AH_Globals*  globals = 0;
+    FT_Memory    memory  = hinter->memory;
+    FT_Error     error;
+
+
+    /* allocate new master globals */
+    if ( ALLOC( globals, sizeof ( *globals ) ) )
+      goto Fail;
+
+    /* compute face globals if needed */
+    if ( !FACE_GLOBALS( face ) )
+    {
+      error = ah_hinter_new_face_globals( hinter, face, 0 );
+      if ( error )
+        goto Fail;
+    }
+
+    *globals      = FACE_GLOBALS( face )->design;
+    *global_hints = globals;
+    *global_len   = sizeof( *globals );
+
+    return;
+
+  Fail:
+    FREE( globals );
+
+    *global_hints = 0;
+    *global_len   = 0;
+  }
+
+
+  void  ah_hinter_done_global_hints( AH_Hinter*  hinter,
+                                     void*       global_hints )
+  {
+    FT_Memory  memory = hinter->memory;
+
+
+    FREE( global_hints );
+  }
+
+
+/* END */
diff --git a/src/freetype/autohint/ahhint.h b/src/freetype/autohint/ahhint.h
new file mode 100644 (file)
index 0000000..bb297fb
--- /dev/null
@@ -0,0 +1,72 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahhint.h                                                               */
+/*                                                                         */
+/*    Glyph hinter (declaration).                                          */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef AHHINT_H
+#define AHHINT_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahglobal.h"
+
+#else
+
+#include <autohint/ahglobal.h>
+
+#endif
+
+
+#define AH_HINT_DEFAULT        0
+#define AH_HINT_NO_ALIGNMENT   1
+#define AH_HINT_NO_HORZ_EDGES  0x20000L
+#define AH_HINT_NO_VERT_EDGES  0x40000L
+
+
+  /* create a new empty hinter object */
+  FT_Error ah_hinter_new( FT_Library   library,
+                          AH_Hinter**  ahinter );
+
+  /* Load a hinted glyph in the hinter */
+  FT_Error  ah_hinter_load_glyph( AH_Hinter*    hinter,
+                                  FT_GlyphSlot  slot,
+                                  FT_Size       size,
+                                  FT_UInt       glyph_index,
+                                  FT_Int        load_flags );
+
+  /* finalize a hinter object */
+  void  ah_hinter_done( AH_Hinter*  hinter );
+
+  LOCAL_DEF
+  void  ah_hinter_done_face_globals( AH_Face_Globals*  globals );
+
+  void  ah_hinter_get_global_hints( AH_Hinter*  hinter,
+                                    FT_Face     face,
+                                    void**      global_hints,
+                                    long*       global_len );
+
+  void  ah_hinter_done_global_hints( AH_Hinter*  hinter,
+                                     void*       global_hints );
+
+
+#endif /* AHHINT_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahloader.h b/src/freetype/autohint/ahloader.h
new file mode 100644 (file)
index 0000000..4a8563c
--- /dev/null
@@ -0,0 +1,124 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahloader.h                                                             */
+/*                                                                         */
+/*    Glyph loader for the auto-hinting module (declaration only).         */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This defines the AH_GlyphLoader type in two different ways:           */
+  /*                                                                       */
+  /* - If the module is compiled within FreeType 2, the type is simply a   */
+  /*   typedef to FT_GlyphLoader.                                          */
+  /*                                                                       */
+  /* - If the module is compiled as a standalone object, AH_GlyphLoader    */
+  /*   has its own implementation.                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef AHLOADER_H
+#define AHLOADER_H
+
+
+#ifdef _STANDALONE_
+
+  typedef struct  AH_GlyphLoad_
+  {
+    FT_Outline    outline;       /* outline             */
+    FT_UInt       num_subglyphs; /* number of subglyphs */
+    FT_SubGlyph*  subglyphs;     /* subglyphs           */
+    FT_Vector*    extra_points;  /* extra points table  */
+
+  } AH_GlyphLoad;
+
+
+  struct  AH_GlyphLoader_
+  {
+    FT_Memory     memory;
+    FT_UInt       max_points;
+    FT_UInt       max_contours;
+    FT_UInt       max_subglyphs;
+    FT_Bool       use_extra;
+
+    AH_GlyphLoad  base;
+    AH_GlyphLoad  current;
+
+    void*         other;        /* for possible future extensions */
+  };
+
+
+  LOCAL_DEF
+  FT_Error  AH_GlyphLoader_New( FT_Memory         memory,
+                                AH_GlyphLoader**  aloader );
+
+  LOCAL_DEF
+  FT_Error  AH_GlyphLoader_Create_Extra( AH_GlyphLoader*  loader );
+
+  LOCAL_DEF
+  void  AH_GlyphLoader_Done( AH_GlyphLoader*  loader );
+
+  LOCAL_DEF
+  void  AH_GlyphLoader_Reset( AH_GlyphLoader*  loader );
+
+  LOCAL_DEF
+  void  AH_GlyphLoader_Rewind( AH_GlyphLoader*  loader );
+
+  LOCAL_DEF
+  FT_Error  AH_GlyphLoader_Check_Points( AH_GlyphLoader*  loader,
+                                         FT_UInt          n_points,
+                                         FT_UInt          n_contours );
+
+  LOCAL_DEF
+  FT_Error  AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader*  loader,
+                                            FT_UInt          n_subs );
+
+  LOCAL_DEF
+  void  AH_GlyphLoader_Prepare( AH_GlyphLoader*  loader );
+
+  LOCAL_DEF
+  void  AH_GlyphLoader_Add( AH_GlyphLoader*  loader );
+
+  LOCAL_DEF
+  FT_Error  AH_GlyphLoader_Copy_Points( AH_GlyphLoader*  target,
+                                        FT_GlyphLoader*  source );
+
+#else /* _STANDALONE */
+
+#include <freetype/internal/ftobjs.h>
+
+  #define AH_Load    FT_GlyphLoad
+  #define AH_Loader  FT_GlyphLoader
+
+  #define ah_loader_new              FT_GlyphLoader_New
+  #define ah_loader_done             FT_GlyphLoader_Done
+  #define ah_loader_reset            FT_GlyphLoader_Reset
+  #define ah_loader_rewind           FT_GlyphLoader_Rewind
+  #define ah_loader_create_extra     FT_GlyphLoader_Create_Extra
+  #define ah_loader_check_points     FT_GlyphLoader_Check_Points
+  #define ah_loader_check_subglyphs  FT_GlyphLoader_Check_Subglyphs
+  #define ah_loader_prepare          FT_GlyphLoader_Prepare
+  #define ah_loader_add              FT_GlyphLoader_Add
+  #define ah_loader_copy_points      FT_GlyphLoader_Copy_Points
+
+#endif /* _STANDALONE_ */
+
+#endif /* AHLOADER_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahmodule.c b/src/freetype/autohint/ahmodule.c
new file mode 100644 (file)
index 0000000..8575568
--- /dev/null
@@ -0,0 +1,127 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahmodule.c                                                             */
+/*                                                                         */
+/*    Auto-hinting module implementation (declaration).                    */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <freetype/ftmodule.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahhint.h"
+
+#else
+
+#include <autohint/ahhint.h>
+
+#endif
+
+
+  typedef struct  FT_AutoHinterRec_
+  {
+    FT_ModuleRec  root;
+    AH_Hinter*    hinter;
+
+  } FT_AutoHinterRec;
+
+
+  static
+  FT_Error  ft_autohinter_init( FT_AutoHinter  module )
+  {
+    return ah_hinter_new( module->root.library, &module->hinter );
+  }
+
+
+  static
+  void  ft_autohinter_done( FT_AutoHinter  module )
+  {
+    ah_hinter_done( module->hinter );
+  }
+
+
+  static
+  FT_Error  ft_autohinter_load( FT_AutoHinter  module,
+                                FT_GlyphSlot   slot,
+                                FT_Size        size,
+                                FT_UInt        glyph_index,
+                                FT_ULong       load_flags )
+  {
+    return ah_hinter_load_glyph( module->hinter,
+                                 slot, size, glyph_index, load_flags );
+  }
+
+
+  static
+  void   ft_autohinter_reset( FT_AutoHinter  module,
+                              FT_Face        face )
+  {
+    UNUSED( module );
+
+    if ( face->autohint.data )
+      ah_hinter_done_face_globals( (AH_Face_Globals*)(face->autohint.data) );
+  }
+
+
+  static
+  void  ft_autohinter_get_globals( FT_AutoHinter  module,
+                                   FT_Face        face,
+                                   void**         global_hints,
+                                   long*          global_len )
+  {
+    ah_hinter_get_global_hints( module->hinter, face,
+                                global_hints, global_len );
+  }
+
+
+  static
+  void  ft_autohinter_done_globals( FT_AutoHinter  module,
+                                    void*          global_hints )
+  {
+    ah_hinter_done_global_hints( module->hinter, global_hints );
+  }
+
+
+  static
+  const FT_AutoHinter_Interface  autohinter_interface =
+  {
+    ft_autohinter_reset,
+    ft_autohinter_load,
+    ft_autohinter_get_globals,
+    ft_autohinter_done_globals
+  };
+
+
+  const FT_Module_Class  autohint_module_class =
+  {
+    ft_module_hinter,
+    sizeof ( FT_AutoHinterRec ),
+
+    "autohinter",
+    0x10000L,   /* version 1.0 of the autohinter  */
+    0x20000L,   /* requires FreeType 2.0 or above */
+
+    (const void*)&autohinter_interface,
+
+    (FT_Module_Constructor)ft_autohinter_init,
+    (FT_Module_Destructor) ft_autohinter_done,
+    (FT_Module_Requester)  0
+  };
+
+
+/* END */
diff --git a/src/freetype/autohint/ahmodule.h b/src/freetype/autohint/ahmodule.h
new file mode 100644 (file)
index 0000000..28b0753
--- /dev/null
@@ -0,0 +1,32 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahmodule.h                                                             */
+/*                                                                         */
+/*    Auto-hinting module (declaration).                                   */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef AHMODULE_H
+#define AHMODULE_H
+
+#include <freetype/ftmodule.h>
+
+  FT_EXPORT_VAR( const FT_Module_Class )  autohint_module_class;
+
+#endif /* AHMODULE_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahoptim.c b/src/freetype/autohint/ahoptim.c
new file mode 100644 (file)
index 0000000..d301dd7
--- /dev/null
@@ -0,0 +1,889 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahoptim.c                                                              */
+/*                                                                         */
+/*    FreeType auto hinting outline optimization (body).                   */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This module is in charge of optimising the outlines produced by the   */
+  /* auto-hinter in direct mode. This is required at small pixel sizes in  */
+  /* order to ensure coherent spacing, among other things..                */
+  /*                                                                       */
+  /* The technique used in this module is a simplified simulated           */
+  /* annealing.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftobjs.h>  /* for ALLOC_ARRAY() and FREE() */
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahoptim.h"
+
+#else
+
+#include <autohint/ahoptim.h>
+
+#endif
+
+
+  /* define this macro to use brute force optimisation -- this is slow,  */
+  /* but a good way to perfect the distortion function `by hand' through */
+  /* tweaking                                                            */
+#define AH_BRUTE_FORCE
+
+
+#define xxxAH_DEBUG_OPTIM
+
+
+#undef LOG
+#ifdef AH_DEBUG_OPTIM
+
+#define LOG( x )  optim_log##x
+
+#else
+
+#define LOG( x )
+
+#endif /* AH_DEBUG_OPTIM */
+
+
+#ifdef AH_DEBUG_OPTIM
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FLOAT( x )  ( (float)( (x) / 64.0 ) )
+
+  static
+  void  optim_log( const char*  fmt, ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    vprintf( fmt, ap );
+    va_end( ap );
+  }
+
+
+  static
+  void  AH_Dump_Stems( AH_Optimizer*  optimizer )
+  {
+    int       n;
+    AH_Stem*  stem;
+
+
+    stem = optimizer->stems;
+    for ( n = 0; n < optimizer->num_stems; n++, stem++ )
+    {
+      LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}="
+            "<%1.f..%1.f> force=%.1f speed=%.1f\n",
+            optimizer->vertical ? 'V' : 'H', n,
+            FLOAT( stem->edge1->opos ), FLOAT( stem->edge2->opos ),
+            FLOAT( stem->edge1->pos ),  FLOAT( stem->edge2->pos ),
+            FLOAT( stem->min_pos ),     FLOAT( stem->max_pos ),
+            FLOAT( stem->force ),       FLOAT( stem->velocity ) ));
+    }
+  }
+
+
+  static
+  void  AH_Dump_Stems2( AH_Optimizer*  optimizer )
+  {
+    int       n;
+    AH_Stem*  stem;
+
+
+    stem = optimizer->stems;
+    for ( n = 0; n < optimizer->num_stems; n++, stem++ )
+    {
+      LOG(( " %c%2d [%.1f]=<%1.f..%1.f> force=%.1f speed=%.1f\n",
+            optimizer->vertical ? 'V' : 'H', n,
+            FLOAT( stem->pos ),
+            FLOAT( stem->min_pos ), FLOAT( stem->max_pos ),
+            FLOAT( stem->force ),   FLOAT( stem->velocity ) ));
+    }
+  }
+
+
+  static
+  void  AH_Dump_Springs( AH_Optimizer*  optimizer )
+  {
+    int  n;
+    AH_Spring*  spring;
+    AH_Stem*    stems;
+
+
+    spring = optimizer->springs;
+    stems  = optimizer->stems;
+    LOG(( "%cSprings ", optimizer->vertical ? 'V' : 'H' ));
+
+    for ( n = 0; n < optimizer->num_springs; n++, spring++ )
+    {
+      LOG(( " [%d-%d:%.1f:%1.f:%.1f]",
+            spring->stem1 - stems, spring->stem2 - stems,
+            FLOAT( spring->owidth ),
+            FLOAT( spring->stem2->pos - 
+                   ( spring->stem1->pos + spring->stem1->width ) ),
+            FLOAT( spring->tension ) ));
+    }
+
+    LOG(( "\n" ));
+  }
+
+#endif /* AH_DEBUG_OPTIM */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   COMPUTE STEMS AND SPRINGS IN AN OUTLINE                       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  int  valid_stem_segments( AH_Segment*  seg1,
+                            AH_Segment*  seg2 )
+  {
+    return seg1->serif == 0                   &&
+           seg2                               &&
+           seg2->link == seg1                 &&
+           seg1->pos < seg2->pos              &&
+           seg1->min_coord <= seg2->max_coord &&
+           seg2->min_coord <= seg1->max_coord;
+  }
+
+
+  /* compute all stems in an outline */
+  static
+  int  optim_compute_stems( AH_Optimizer*  optimizer )
+  {
+    AH_Outline*  outline = optimizer->outline;
+    FT_Fixed     scale;
+    FT_Memory    memory  = optimizer->memory;
+    FT_Error     error   = 0;
+    FT_Int       dimension;
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Stem**    p_stems;
+    FT_Int*      p_num_stems;
+
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+    scale      = outline->y_scale;
+
+    p_stems     = &optimizer->horz_stems;
+    p_num_stems = &optimizer->num_hstems;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Stem*  stems     = 0;
+      FT_Int    num_stems = 0;
+      AH_Edge*  edge;
+
+
+      /* first of all, count the number of stems in this direction */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        AH_Segment*  seg = edge->first;
+
+
+        do
+        {
+          if (valid_stem_segments( seg, seg->link ) )
+            num_stems++;
+
+          seg = seg->edge_next;
+
+        } while ( seg != edge->first );
+      }
+
+      /* now allocate the stems and build their table */
+      if ( num_stems > 0 )
+      {
+        AH_Stem*  stem;
+
+
+        if ( ALLOC_ARRAY( stems, num_stems, AH_Stem ) )
+          goto Exit;
+
+        stem = stems;
+        for ( edge = edges; edge < edge_limit; edge++ )
+        {
+          AH_Segment*  seg = edge->first;
+          AH_Segment*  seg2;
+
+
+          do
+          {
+            seg2 = seg->link;
+            if ( valid_stem_segments( seg, seg2 ) )
+            {
+              AH_Edge*  edge1 = seg->edge;
+              AH_Edge*  edge2 = seg2->edge;
+
+
+              stem->edge1  = edge1;
+              stem->edge2  = edge2;
+              stem->opos   = edge1->opos;
+              stem->pos    = edge1->pos;
+              stem->owidth = edge2->opos - edge1->opos;
+              stem->width  = edge2->pos  - edge1->pos;
+
+              /* compute min_coord and max_coord */
+              {
+                FT_Pos  min_coord = seg->min_coord;
+                FT_Pos  max_coord = seg->max_coord;
+
+
+                if ( seg2->min_coord > min_coord )
+                  min_coord = seg2->min_coord;
+
+                if ( seg2->max_coord < max_coord )
+                  max_coord = seg2->max_coord;
+
+                stem->min_coord = min_coord;
+                stem->max_coord = max_coord;
+              }
+
+              /* compute minimum and maximum positions for stem --   */
+              /* note that the left-most/bottom-most stem has always */
+              /* a fixed position                                    */
+              if ( stem == stems || edge1->blue_edge || edge2->blue_edge )
+              {
+                /* this stem cannot move; it is snapped to a blue edge */
+                stem->min_pos = stem->pos;
+                stem->max_pos = stem->pos;
+              }
+              else
+              {
+                /* this edge can move; compute its min and max positions */
+                FT_Pos  pos1 = stem->opos;
+                FT_Pos  pos2 = pos1 + stem->owidth - stem->width;
+                FT_Pos  min1 = pos1 & -64;
+                FT_Pos  min2 = pos2 & -64;
+
+
+                stem->min_pos = min1;
+                stem->max_pos = min1 + 64;
+                if ( min2 < min1 )
+                  stem->min_pos = min2;
+                else
+                  stem->max_pos = min2 + 64;
+
+                /* XXX: just to see what it does */
+                stem->max_pos += 64;
+
+                /* just for the case where direct hinting did some */
+                /* incredible things (e.g. blue edge shifts)       */
+                if ( stem->min_pos > stem->pos )
+                  stem->min_pos = stem->pos;
+
+                if ( stem->max_pos < stem->pos )
+                  stem->max_pos = stem->pos;
+              }
+
+              stem->velocity = 0;
+              stem->force    = 0;
+
+              stem++;
+            }
+            seg = seg->edge_next;
+
+          } while ( seg != edge->first );
+        }
+      }
+
+      *p_stems     = stems;
+      *p_num_stems = num_stems;
+
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+      scale      = outline->x_scale;
+
+      p_stems     = &optimizer->vert_stems;
+      p_num_stems = &optimizer->num_vstems;
+    }
+
+  Exit:
+
+#ifdef AH_DEBUG_OPTIM
+    AH_Dump_Stems( optimizer );
+#endif
+
+    return error;
+  }
+
+
+  /* returns the spring area between two stems, 0 if none */
+  static
+  FT_Pos  stem_spring_area( AH_Stem*  stem1,
+                            AH_Stem*  stem2 )
+  {
+    FT_Pos  area1 = stem1->max_coord - stem1->min_coord;
+    FT_Pos  area2 = stem2->max_coord - stem2->min_coord;
+    FT_Pos  min   = stem1->min_coord;
+    FT_Pos  max   = stem1->max_coord;
+    FT_Pos  area;
+
+
+    /* order stems */
+    if ( stem2->opos <= stem1->opos + stem1->owidth )
+      return 0;
+
+    if ( min < stem2->min_coord )
+      min = stem2->min_coord;
+
+    if ( max < stem2->max_coord )
+      max = stem2->max_coord;
+
+    area = ( max-min );
+    if ( 2 * area < area1 && 2 * area < area2 )
+      area = 0;
+
+    return area;
+  }
+
+
+  /* compute all springs in an outline */
+  static
+  int  optim_compute_springs( AH_Optimizer*  optimizer )
+  {
+    /* basically, a spring exists between two stems if most of their */
+    /* surface is aligned                                            */
+    FT_Memory    memory  = optimizer->memory;
+
+    AH_Stem*     stems;
+    AH_Stem*     stem_limit;
+    AH_Stem*     stem;
+    int          dimension;
+    int          error = 0;
+
+    FT_Int*      p_num_springs;
+    AH_Spring**  p_springs;
+
+
+    stems      = optimizer->horz_stems;
+    stem_limit = stems + optimizer->num_hstems;
+
+    p_springs     = &optimizer->horz_springs;
+    p_num_springs = &optimizer->num_hsprings;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      FT_Int      num_springs = 0;
+      AH_Spring*  springs     = 0;
+
+
+      /* first of all, count stem springs */
+      for ( stem = stems; stem + 1 < stem_limit; stem++ )
+      {
+        AH_Stem*  stem2;
+
+
+        for ( stem2 = stem+1; stem2 < stem_limit; stem2++ )
+          if ( stem_spring_area( stem, stem2 ) )
+            num_springs++;
+      }
+
+      /* then allocate and build the springs table */
+      if ( num_springs > 0 )
+      {
+        AH_Spring*  spring;
+
+
+        /* allocate table of springs */
+        if ( ALLOC_ARRAY( springs, num_springs, AH_Spring ) )
+          goto Exit;
+
+        /* fill the springs table */
+        spring = springs;
+        for ( stem = stems; stem+1 < stem_limit; stem++ )
+        {
+          AH_Stem*  stem2;
+          FT_Pos    area;
+
+
+          for ( stem2 = stem + 1; stem2 < stem_limit; stem2++ )
+          {
+            area = stem_spring_area( stem, stem2 );
+            if ( area )
+            {
+              /* add a new spring here */
+              spring->stem1   = stem;
+              spring->stem2   = stem2;
+              spring->owidth  = stem2->opos - ( stem->opos + stem->owidth );
+              spring->tension = 0;
+
+              spring++;
+            }
+          }
+        }
+      }
+      *p_num_springs = num_springs;
+      *p_springs     = springs;
+
+      stems      = optimizer->vert_stems;
+      stem_limit = stems + optimizer->num_vstems;
+
+      p_springs     = &optimizer->vert_springs;
+      p_num_springs = &optimizer->num_vsprings;
+    }
+
+  Exit:
+
+#ifdef AH_DEBUG_OPTIM
+    AH_Dump_Springs( optimizer );
+#endif
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   OPTIMIZE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-)      ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#ifndef AH_BRUTE_FORCE
+
+  /* compute all spring tensions */
+  static
+  void  optim_compute_tensions( AH_Optimizer*  optimizer )
+  {
+    AH_Spring*  spring = optimizer->springs;
+    AH_Spring*  limit  = spring + optimizer->num_springs;
+
+
+    for ( ; spring < limit; spring++ )
+    {
+      AH_Stem*  stem1 = spring->stem1;
+      AH_Stem*  stem2 = spring->stem2;
+      FT_Int    status;
+
+      FT_Pos  width;
+      FT_Pos  tension;
+      FT_Pos  sign;
+
+
+      /* compute the tension; it simply is -K*(new_width-old_width) */
+      width   = stem2->pos - ( stem1->pos + stem1->width );
+      tension = width - spring->owidth;
+
+      sign = 1;
+      if ( tension < 0 )
+      {
+        sign    = -1;
+        tension = -tension;
+      }
+
+      if ( width <= 0 )
+        tension = 32000;
+      else
+        tension = ( tension << 10 ) / width;
+
+      tension = -sign * FT_MulFix( tension, optimizer->tension_scale );
+      spring->tension = tension;
+
+      /* now, distribute tension among the englobing stems, if they */
+      /* are able to move                                           */
+      status = 0;
+      if ( stem1->pos <= stem1->min_pos )
+        status |= 1;
+      if ( stem2->pos >= stem2->max_pos )
+        status |= 2;
+
+      if ( !status )
+        tension /= 2;
+
+      if ( ( status & 1 ) == 0 )
+        stem1->force -= tension;
+
+      if ( ( status & 2 ) == 0 )
+        stem2->force += tension;
+    }
+  }
+
+
+  /* compute all stem movements -- returns 0 if nothing moved */
+  static
+  int  optim_compute_stem_movements( AH_Optimizer*  optimizer )
+  {
+    AH_Stem*  stems = optimizer->stems;
+    AH_Stem*  limit = stems + optimizer->num_stems;
+    AH_Stem*  stem  = stems;
+    int       moved = 0;
+
+
+    /* set initial forces to velocity */
+    for ( stem = stems; stem < limit; stem++ )
+    {
+      stem->force     = stem->velocity;
+      stem->velocity /= 2;                  /* XXX: Heuristics */
+    }
+
+    /* compute the sum of forces applied on each stem */
+    optim_compute_tensions( optimizer );
+
+#ifdef AH_DEBUG_OPTIM
+    AH_Dump_Springs( optimizer );
+    AH_Dump_Stems2( optimizer );
+#endif
+
+    /* now, see whether something can move */
+    for ( stem = stems; stem < limit; stem++ )
+    {
+      if ( stem->force > optimizer->tension_threshold )
+      {
+        /* there is enough tension to move the stem to the right */
+        if ( stem->pos < stem->max_pos )
+        {
+          stem->pos     += 64;
+          stem->velocity = stem->force / 2;
+          moved          = 1;
+        }
+        else
+          stem->velocity = 0;
+      }
+      else if ( stem->force < optimizer->tension_threshold )
+      {
+        /* there is enough tension to move the stem to the left */
+        if ( stem->pos > stem->min_pos )
+        {
+          stem->pos     -= 64;
+          stem->velocity = stem->force / 2;
+          moved          = 1;
+        }
+        else
+          stem->velocity = 0;
+      }
+    }
+
+    /* return 0 if nothing moved */
+    return moved;
+  }
+
+#endif /* AH_BRUTE_FORCE */
+
+
+  /* compute current global distortion from springs */
+  static
+  FT_Pos  optim_compute_distortion( AH_Optimizer*  optimizer )
+  {
+    AH_Spring*  spring = optimizer->springs;
+    AH_Spring*  limit  = spring + optimizer->num_springs;
+    FT_Pos      distortion = 0;
+
+
+    for ( ; spring < limit; spring++ )
+    {
+      AH_Stem*  stem1 = spring->stem1;
+      AH_Stem*  stem2 = spring->stem2;
+      FT_Pos  width;
+
+      width  = stem2->pos - ( stem1->pos + stem1->width );
+      width -= spring->owidth;
+      if ( width < 0 )
+        width = -width;
+
+      distortion += width;
+    }
+
+    return distortion;
+  }
+
+
+  /* record stems configuration in `best of' history */
+  static
+  void  optim_record_configuration( AH_Optimizer*  optimizer )
+  {
+    FT_Pos             distortion;
+    AH_Configuration*  configs = optimizer->configs;
+    AH_Configuration*  limit   = configs + optimizer->num_configs;
+    AH_Configuration*  config;
+
+
+    distortion = optim_compute_distortion( optimizer );
+    LOG(( "config distortion = %.1f ", FLOAT( distortion * 64 ) ));
+
+    /* check that we really need to add this configuration to our */
+    /* sorted history                                             */
+    if ( limit > configs && limit[-1].distortion < distortion )
+    {
+      LOG(( "ejected\n" ));
+      return;
+    }
+
+    /* add new configuration at the end of the table */
+    {
+      int  n;
+
+
+      config = limit;
+      if ( optimizer->num_configs < AH_MAX_CONFIGS )
+        optimizer->num_configs++;
+      else
+        config--;
+
+      config->distortion = distortion;
+
+      for ( n = 0; n < optimizer->num_stems; n++ )
+        config->positions[n] = optimizer->stems[n].pos;
+    }
+
+    /* move the current configuration towards the front of the list */
+    /* when necessary -- yes this is slow bubble sort ;-)           */
+    while ( config > configs && config[0].distortion < config[-1].distortion )
+    {
+      AH_Configuration  temp;
+
+
+      config--;
+      temp      = config[0];
+      config[0] = config[1];
+      config[1] = temp;
+    }
+    LOG(( "recorded!\n" ));
+  }
+
+
+#ifdef AH_BRUTE_FORCE
+
+  /* optimize outline in a single direction */
+  static
+  void  optim_compute( AH_Optimizer*  optimizer )
+  {
+    int       n;
+    FT_Bool   moved;
+
+    AH_Stem*  stem  = optimizer->stems;
+    AH_Stem*  limit = stem + optimizer->num_stems;
+
+
+    /* empty, exit */
+    if ( stem >= limit )
+      return;
+
+    optimizer->num_configs = 0;
+
+    stem = optimizer->stems;
+    for ( ; stem < limit; stem++ )
+      stem->pos = stem->min_pos;
+
+    do
+    {
+      /* record current configuration */
+      optim_record_configuration( optimizer );
+
+      /* now change configuration */
+      moved = 0;
+      for ( stem = optimizer->stems; stem < limit; stem++ )
+      {
+        if ( stem->pos < stem->max_pos )
+        {
+          stem->pos += 64;
+          moved      = 1;
+          break;
+        }
+
+        stem->pos = stem->min_pos;
+      }
+    } while ( moved );
+
+    /* now, set the best stem positions */
+    for ( n = 0; n < optimizer->num_stems; n++ )
+    {
+      AH_Stem*  stem = optimizer->stems + n;
+      FT_Pos    pos  = optimizer->configs[0].positions[n];
+
+
+      stem->edge1->pos = pos;
+      stem->edge2->pos = pos + stem->width;
+
+      stem->edge1->flags |= ah_edge_done;
+      stem->edge2->flags |= ah_edge_done;
+    }
+  }
+
+#else /* AH_BRUTE_FORCE */
+
+  /* optimize outline in a single direction */
+  static
+  void  optim_compute( AH_Optimizer*  optimizer )
+  {
+    int  n, counter, counter2;
+
+
+    optimizer->num_configs       = 0;
+    optimizer->tension_scale     = 0x80000L;
+    optimizer->tension_threshold = 64;
+
+    /* record initial configuration threshold */
+    optim_record_configuration( optimizer );
+
+    counter = 0;
+    for ( counter2 = optimizer->num_stems*8; counter2 >= 0; counter2-- )
+    {
+      if ( counter == 0 )
+        counter = 2 * optimizer->num_stems;
+
+      if ( !optim_compute_stem_movements( optimizer ) )
+        break;
+
+      optim_record_configuration( optimizer );
+
+      counter--;
+      if ( counter == 0 )
+        optimizer->tension_scale /= 2;
+    }
+
+    /* now, set the best stem positions */
+    for ( n = 0; n < optimizer->num_stems; n++ )
+    {
+      AH_Stem*  stem = optimizer->stems + n;
+      FT_Pos    pos  = optimizer->configs[0].positions[n];
+
+
+      stem->edge1->pos = pos;
+      stem->edge2->pos = pos + stem->width;
+
+      stem->edge1->flags |= ah_edge_done;
+      stem->edge2->flags |= ah_edge_done;
+    }
+  }
+
+#endif /* AH_BRUTE_FORCE */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   HIGH-LEVEL OPTIMIZER API                                      ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* releases the optimization data */
+  void AH_Optimizer_Done( AH_Optimizer*  optimizer )
+  {
+    if ( optimizer )
+    {
+      FT_Memory  memory = optimizer->memory;
+
+
+      FREE( optimizer->horz_stems );
+      FREE( optimizer->vert_stems );
+      FREE( optimizer->horz_springs );
+      FREE( optimizer->vert_springs );
+      FREE( optimizer->positions );
+    }
+  }
+
+
+  /* loads the outline into the optimizer */
+  int  AH_Optimizer_Init( AH_Optimizer*  optimizer,
+                          AH_Outline*    outline,
+                          FT_Memory      memory )
+  {
+    FT_Error  error;
+
+
+    MEM_Set( optimizer, 0, sizeof ( *optimizer ) );
+    optimizer->outline = outline;
+    optimizer->memory  = memory;
+
+    LOG(( "initializing new optimizer\n" ));
+    /* compute stems and springs */
+    error = optim_compute_stems  ( optimizer ) ||
+            optim_compute_springs( optimizer );
+    if ( error )
+      goto Fail;
+
+    /* allocate stem positions history and configurations */
+    {
+      int  n, max_stems;
+
+
+      max_stems = optimizer->num_hstems;
+      if ( max_stems < optimizer->num_vstems )
+        max_stems = optimizer->num_vstems;
+
+      if ( ALLOC_ARRAY( optimizer->positions,
+                        max_stems * AH_MAX_CONFIGS, FT_Pos ) )
+        goto Fail;
+
+      optimizer->num_configs = 0;
+      for ( n = 0; n < AH_MAX_CONFIGS; n++ )
+        optimizer->configs[n].positions = optimizer->positions +
+                                          n * max_stems;
+    }
+
+    return error;
+
+  Fail:
+    AH_Optimizer_Done( optimizer );
+    return error;
+  }
+
+
+  /* compute optimal outline */
+  void  AH_Optimizer_Compute( AH_Optimizer*  optimizer )
+  {
+    optimizer->num_stems   = optimizer->num_hstems;
+    optimizer->stems       = optimizer->horz_stems;
+    optimizer->num_springs = optimizer->num_hsprings;
+    optimizer->springs     = optimizer->horz_springs;
+
+    if ( optimizer->num_springs > 0 )
+    {
+      LOG(( "horizontal optimization ------------------------\n" ));
+      optim_compute( optimizer );
+    }
+
+    optimizer->num_stems   = optimizer->num_vstems;
+    optimizer->stems       = optimizer->vert_stems;
+    optimizer->num_springs = optimizer->num_vsprings;
+    optimizer->springs     = optimizer->vert_springs;
+
+    if ( optimizer->num_springs )
+    {
+      LOG(( "vertical optimization --------------------------\n" ));
+      optim_compute( optimizer );
+    }
+  }
+
+
+/* END */
diff --git a/src/freetype/autohint/ahoptim.h b/src/freetype/autohint/ahoptim.h
new file mode 100644 (file)
index 0000000..a1f52bf
--- /dev/null
@@ -0,0 +1,136 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahoptim.h                                                              */
+/*                                                                         */
+/*    FreeType auto hinting outline optimization (declaration).            */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef AHOPTIM_H
+#define AHOPTIM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahtypes.h"
+
+#else
+
+#include <autohint/ahtypes.h>
+
+#endif
+
+
+  /* the maximal number of stem configurations to record */
+  /* during optimization                                 */
+#define AH_MAX_CONFIGS  8
+
+
+  typedef struct  AH_Stem_
+  {
+    FT_Pos    pos;       /* current position        */
+    FT_Pos    velocity;  /* current velocity        */
+    FT_Pos    force;     /* sum of current forces   */
+    FT_Pos    width;     /* normalized width        */
+
+    FT_Pos    min_pos;   /* minimum grid position */
+    FT_Pos    max_pos;   /* maximum grid position */
+
+    AH_Edge*  edge1;     /* left/bottom edge */
+    AH_Edge*  edge2;     /* right/top edge   */
+
+    FT_Pos    opos;      /* original position */
+    FT_Pos    owidth;    /* original width    */
+
+    FT_Pos    min_coord; /* minimum coordinate */
+    FT_Pos    max_coord; /* maximum coordinate */
+
+  } AH_Stem;
+
+
+  /* A spring between two stems */
+  typedef struct  AH_Spring_
+  {
+    AH_Stem*  stem1;
+    AH_Stem*  stem2;
+    FT_Pos    owidth;   /* original width  */
+    FT_Pos    tension;  /* current tension */
+
+  } AH_Spring;
+
+
+  /* A configuration records the position of each stem at a given time  */
+  /* as well as the associated distortion                               */
+  typedef struct AH_Configuration_
+  {
+    FT_Pos*  positions;
+    FT_Long  distortion;
+
+  } AH_Configuration;
+
+
+  typedef struct  AH_Optimizer_
+  {
+    FT_Memory         memory;
+    AH_Outline*       outline;
+
+    FT_Int            num_hstems;
+    AH_Stem*          horz_stems;
+
+    FT_Int            num_vstems;
+    AH_Stem*          vert_stems;
+
+    FT_Int            num_hsprings;
+    FT_Int            num_vsprings;
+    AH_Spring*        horz_springs;
+    AH_Spring*        vert_springs;
+
+    FT_Int            num_configs;
+    AH_Configuration  configs[AH_MAX_CONFIGS];
+    FT_Pos*           positions;
+
+    /* during each pass, use these instead */
+    FT_Int            num_stems;
+    AH_Stem*          stems;
+
+    FT_Int            num_springs;
+    AH_Spring*        springs;
+    FT_Bool           vertical;
+
+    FT_Fixed          tension_scale;
+    FT_Pos            tension_threshold;
+
+  } AH_Optimizer;
+
+
+  /* loads the outline into the optimizer */
+  int  AH_Optimizer_Init( AH_Optimizer*  optimizer,
+                          AH_Outline*    outline,
+                          FT_Memory      memory );
+
+
+  /* compute optimal outline */
+  void  AH_Optimizer_Compute( AH_Optimizer*  optimizer );
+
+
+  /* release the optimization data */
+  void AH_Optimizer_Done( AH_Optimizer*  optimizer );
+
+
+#endif /* AHOPTIM_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/ahtypes.h b/src/freetype/autohint/ahtypes.h
new file mode 100644 (file)
index 0000000..3372ea9
--- /dev/null
@@ -0,0 +1,492 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahtypes.h                                                              */
+/*                                                                         */
+/*    General types and definitions for the auto-hint module               */
+/*    (specification only).                                                */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef AHTYPES_H
+#define AHTYPES_H
+
+
+#include <freetype/internal/ftobjs.h>  /* for freetype.h + LOCAL_DEF etc. */
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahloader.h"
+
+#else
+
+#include <autohint/ahloader.h>
+
+#endif
+
+
+#define xxAH_DEBUG
+
+
+#ifdef AH_DEBUG
+
+#include <stdio.h>
+
+#define AH_LOG( x )  printf##x
+
+#else
+
+#define AH_LOG( x )  do ; while ( 0 ) /* nothing */
+
+#endif
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /**** COMPILE-TIME BUILD OPTIONS                                      ****/
+  /****                                                                 ****/
+  /**** Toggle these configuration macros to experiment with `features' ****/
+  /**** of the auto-hinter.                                             ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* If this option is defined, only strong interpolation will be used to  */
+  /* place the points between edges.  Otherwise, `smooth' points are       */
+  /* detected and later hinted through weak interpolation to correct some  */
+  /* unpleasant artefacts.                                                 */
+  /*                                                                       */
+#undef AH_OPTION_NO_WEAK_INTERPOLATION
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* If this option is defined, only weak interpolation will be used to    */
+  /* place the points between edges.  Otherwise, `strong' points are       */
+  /* detected and later hinted through strong interpolation to correct     */
+  /* some unpleasant artefacts.                                            */
+  /*                                                                       */
+#undef AH_OPTION_NO_STRONG_INTERPOLATION
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Undefine this macro if you don't want to hint the metrics.  There is  */
+  /* no reason to do this (at least for non-CJK scripts), except for       */
+  /* experimentation.                                                      */
+  /*                                                                       */
+#define AH_HINT_METRICS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define this macro if you do not want to insert extra edges at a       */
+  /* glyph's x and y extremum (if there isn't one already available).      */
+  /* This helps to reduce a number of artefacts and allows hinting of      */
+  /* metrics.                                                              */
+  /*                                                                       */
+#undef AH_OPTION_NO_EXTREMUM_EDGES
+
+
+  /* don't touch for now */
+#define AH_MAX_WIDTHS   12
+#define AH_MAX_HEIGHTS  12
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   TYPE DEFINITIONS                                              ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* see agangles.h */
+  typedef FT_Int  AH_Angle;
+
+
+  /* hint flags */
+#define ah_flah_none       0
+
+  /* bezier control points flags */
+#define ah_flah_conic                 1
+#define ah_flah_cubic                 2
+#define ah_flah_control               ( ah_flah_conic | ah_flah_cubic )
+
+  /* extrema flags */
+#define ah_flah_extrema_x             4
+#define ah_flah_extrema_y             8
+
+  /* roundness */
+#define ah_flah_round_x              16
+#define ah_flah_round_y              32
+
+  /* touched */
+#define ah_flah_touch_x              64
+#define ah_flah_touch_y             128
+
+  /* weak interpolation */
+#define ah_flah_weak_interpolation  256
+
+  typedef FT_Int AH_Flags;
+
+
+  /* edge hint flags */
+#define ah_edge_normal  0
+#define ah_edge_round   1
+#define ah_edge_serif   2
+#define ah_edge_done    4
+
+  typedef FT_Int  AH_Edge_Flags;
+
+
+  /* hint directions -- the values are computed so that two vectors are */
+  /* in opposite directions iff `dir1+dir2 == 0'                        */
+#define ah_dir_none    4
+#define ah_dir_right   1
+#define ah_dir_left   -1
+#define ah_dir_up      2
+#define ah_dir_down   -2
+
+  typedef FT_Int  AH_Direction;
+
+
+  typedef struct AH_Point    AH_Point;
+  typedef struct AH_Segment  AH_Segment;
+  typedef struct AH_Edge     AH_Edge;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Point                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model an outline point to the AH_Outline type. */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags     :: The current point hint flags.                         */
+  /*                                                                       */
+  /*    ox, oy    :: The current original scaled coordinates.              */
+  /*                                                                       */
+  /*    fx, fy    :: The current coordinates in font units.                */
+  /*                                                                       */
+  /*    x,  y     :: The current hinter coordinates.                       */
+  /*                                                                       */
+  /*    u, v      :: Point coordinates -- meaning varies with context.     */
+  /*                                                                       */
+  /*    in_dir    :: The direction of the inwards vector (prev->point).    */
+  /*                                                                       */
+  /*    out_dir   :: The direction of the outwards vector (point->next).   */
+  /*                                                                       */
+  /*    in_angle  :: The angle of the inwards vector.                      */
+  /*                                                                       */
+  /*    out_angle :: The angle of the outwards vector.                     */
+  /*                                                                       */
+  /*    next      :: The next point in same contour.                       */
+  /*                                                                       */
+  /*    prev      :: The previous point in same contour.                   */
+  /*                                                                       */
+  struct AH_Point
+  {
+    AH_Flags      flags;    /* point flags used by hinter */
+    FT_Pos        ox, oy;
+    FT_Pos        fx, fy;
+    FT_Pos        x,  y;
+    FT_Pos        u,  v;
+
+    AH_Direction  in_dir;   /* direction of inwards vector  */
+    AH_Direction  out_dir;  /* direction of outwards vector */
+
+    AH_Angle      in_angle;
+    AH_Angle      out_angle;
+
+    AH_Point*     next;     /* next point in contour     */
+    AH_Point*     prev;     /* previous point in contour */
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Segment                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe an edge segment to the auto-hinter.   */
+  /*    A segment is simply a sequence of successive points located on the */
+  /*    same horizontal or vertical `position', in a given direction.      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags      :: The segment edge flags (straight, rounded, etc.).    */
+  /*                                                                       */
+  /*    dir        :: The segment direction.                               */
+  /*                                                                       */
+  /*    first      :: The first point in the segment.                      */
+  /*                                                                       */
+  /*    last       :: The last point in the segment.                       */
+  /*                                                                       */
+  /*    contour    :: A pointer to the first point of the segment's        */
+  /*                  contour.                                             */
+  /*                                                                       */
+  /*    pos        :: The segment position in font units.                  */
+  /*                                                                       */
+  /*    size       :: The segment size.                                    */
+  /*                                                                       */
+  /*    edge       :: The edge of the current segment.                     */
+  /*                                                                       */
+  /*    edge_next  :: The next segment on the same edge.                   */
+  /*                                                                       */
+  /*    link       :: The pairing segment for this edge.                   */
+  /*                                                                       */
+  /*    serif      :: The primary segment for serifs.                      */
+  /*                                                                       */
+  /*    num_linked :: The number of other segments that link to this one.  */
+  /*                                                                       */
+  /*    score      :: Used to score the segment when selecting them.       */
+  /*                                                                       */
+  struct AH_Segment
+  {
+    AH_Edge_Flags  flags;
+    AH_Direction   dir;
+
+    AH_Point*      first;       /* first point in edge segment             */
+    AH_Point*      last;        /* last point in edge segment              */
+    AH_Point**     contour;     /* ptr to first point of segment's contour */
+
+    FT_Pos         pos;         /* position of segment           */
+    FT_Pos         min_coord;   /* minimum coordinate of segment */
+    FT_Pos         max_coord;   /* maximum coordinate of segment */
+
+    AH_Edge*       edge;
+    AH_Segment*    edge_next;
+
+    AH_Segment*    link;        /* link segment               */
+    AH_Segment*    serif;       /* primary segment for serifs */
+    FT_Pos         num_linked;  /* number of linked segments  */
+    FT_Int         score;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Edge                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe an edge, which really is a horizontal */
+  /*    or vertical coordinate to be hinted depending on the segments      */
+  /*    located on it.                                                     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags      :: The segment edge flags (straight, rounded, etc.).    */
+  /*                                                                       */
+  /*    dir        :: The main segment direction on this edge.             */
+  /*                                                                       */
+  /*    first      :: The first edge segment.                              */
+  /*                                                                       */
+  /*    last       :: The last edge segment.                               */
+  /*                                                                       */
+  /*    fpos       :: The original edge position in font units.            */
+  /*                                                                       */
+  /*    opos       :: The original scaled edge position.                   */
+  /*                                                                       */
+  /*    pos        :: The hinted edge position.                            */
+  /*                                                                       */
+  /*    link       :: The linked edge.                                     */
+  /*                                                                       */
+  /*    serif      :: The serif edge.                                      */
+  /*                                                                       */
+  /*    num_paired :: The number of other edges that pair to this one.     */
+  /*                                                                       */
+  /*    score      :: Used to score the edge when selecting them.          */
+  /*                                                                       */
+  /*    blue_edge  :: Indicate the blue zone edge this edge is related to. */
+  /*                  Only set for some of the horizontal edges in a Latin */
+  /*                  font.                                                */
+  /*                                                                       */
+  struct AH_Edge
+  {
+    AH_Edge_Flags  flags;
+    AH_Direction   dir;
+
+    AH_Segment*    first;
+    AH_Segment*    last;
+
+    FT_Pos         fpos;
+    FT_Pos         opos;
+    FT_Pos         pos;
+
+    AH_Edge*       link;
+    AH_Edge*       serif;
+    FT_Int         num_linked;
+
+    FT_Int         score;
+    FT_Pos*        blue_edge;
+  };
+
+
+  /* an outline as seen by the hinter */
+  typedef struct  AH_Outline_
+  {
+    FT_Memory     memory;
+
+    AH_Direction  vert_major_dir;   /* vertical major direction   */
+    AH_Direction  horz_major_dir;   /* horizontal major direction */
+
+    FT_Fixed      x_scale;
+    FT_Fixed      y_scale;
+    FT_Pos        edge_distance_threshold;
+
+    FT_Int        max_points;
+    FT_Int        num_points;
+    AH_Point*     points;
+
+    FT_Int        max_contours;
+    FT_Int        num_contours;
+    AH_Point**    contours;
+
+    FT_Int        num_hedges;
+    AH_Edge*      horz_edges;
+
+    FT_Int        num_vedges;
+    AH_Edge*      vert_edges;
+
+    FT_Int        num_hsegments;
+    AH_Segment*   horz_segments;
+
+    FT_Int        num_vsegments;
+    AH_Segment*   vert_segments;
+
+  } AH_Outline;
+
+
+#define ah_blue_capital_top     0                              /* THEZOCQS */
+#define ah_blue_capital_bottom  ( ah_blue_capital_top + 1 )    /* HEZLOCUS */
+#define ah_blue_small_top       ( ah_blue_capital_bottom + 1 ) /* xzroesc  */
+#define ah_blue_small_bottom    ( ah_blue_small_top + 1 )      /* xzroesc  */
+#define ah_blue_small_minor     ( ah_blue_small_bottom + 1 )   /* pqgjy    */
+#define ah_blue_max             ( ah_blue_small_minor + 1 )
+
+  typedef FT_Int  AH_Blue;
+
+
+#define ah_hinter_monochrome  1
+#define ah_hinter_optimize    2
+
+  typedef FT_Int  AH_Hinter_Flags;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Globals                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Holds the global metrics for a given font face (be it in design    */
+  /*    units or scaled pixel values).                                     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_widths  :: The number of widths.                               */
+  /*                                                                       */
+  /*    num_heights :: The number of heights.                              */
+  /*                                                                       */
+  /*    widths      :: Snap widths, including standard one.                */
+  /*                                                                       */
+  /*    heights     :: Snap height, including standard one.                */
+  /*                                                                       */
+  /*    blue_refs   :: The reference positions of blue zones.              */
+  /*                                                                       */
+  /*    blue_shoots :: The overshoot positions of blue zones.              */
+  /*                                                                       */
+  typedef struct AH_Globals_
+  {
+    FT_Int    num_widths;
+    FT_Int    num_heights;
+
+    FT_Pos    widths [AH_MAX_WIDTHS];
+    FT_Pos    heights[AH_MAX_HEIGHTS];
+
+    FT_Pos    blue_refs  [ah_blue_max];
+    FT_Pos    blue_shoots[ah_blue_max];
+
+  } AH_Globals;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Face_Globals                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Holds the complete global metrics for a given font face (i.e., the */
+  /*    design units version + a scaled version + the current scales       */
+  /*    used).                                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    face    :: A handle to the source face object                      */
+  /*                                                                       */
+  /*    design  :: The globals in font design units.                       */
+  /*                                                                       */
+  /*    scaled  :: Scaled globals in sub-pixel values.                     */
+  /*                                                                       */
+  /*    x_scale :: The current horizontal scale.                           */
+  /*                                                                       */
+  /*    y_scale :: The current vertical scale.                             */
+  /*                                                                       */
+  typedef struct  AH_Face_Globals_
+  {
+    FT_Face     face;
+    AH_Globals  design;
+    AH_Globals  scaled;
+    FT_Fixed    x_scale;
+    FT_Fixed    y_scale;
+    FT_Bool     control_overshoot;
+
+  } AH_Face_Globals;
+
+
+  typedef struct  AH_Hinter
+  {
+    FT_Memory         memory;
+    AH_Hinter_Flags   flags;
+
+    FT_Int            algorithm;
+    FT_Face           face;
+
+    AH_Face_Globals*  globals;
+
+    AH_Outline*       glyph;
+
+    AH_Loader*        loader;
+    FT_Vector         pp1;
+    FT_Vector         pp2;
+
+  } AH_Hinter;
+
+
+#endif /* AHTYPES_H */
+
+
+/* END */
diff --git a/src/freetype/autohint/autohint.c b/src/freetype/autohint/autohint.c
new file mode 100644 (file)
index 0000000..5916b63
--- /dev/null
@@ -0,0 +1,43 @@
+/***************************************************************************/
+/*                                                                         */
+/*  autohint.c                                                             */
+/*                                                                         */
+/*    Automatic Hinting wrapper (body only).                               */
+/*                                                                         */
+/*  Copyright 2000 Catharon Productions Inc.                               */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ahangles.c"
+#include "ahglyph.c"
+#include "ahglobal.c"
+#include "ahhint.c"
+#include "ahmodule.c"
+
+#else
+
+#include <autohint/ahangles.c>
+#include <autohint/ahglyph.c>
+#include <autohint/ahglobal.c>
+#include <autohint/ahhint.c>
+#include <autohint/ahmodule.c>
+
+#endif
+
+
+/* END */
diff --git a/src/freetype/autohint/mather.py b/src/freetype/autohint/mather.py
new file mode 100644 (file)
index 0000000..b416fdf
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+
+#
+# autohint math table builder
+#
+
+
+# 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.
+
+
+import math
+
+ag_pi = 256
+
+def print_arctan( atan_bits ):
+    atan_base = 1 << atan_bits
+    
+    print "  static AH_Angle  ag_arctan[1L << AG_ATAN_BITS] ="
+    print "  {"
+    
+    count = 0
+    line  = "   "
+    
+    for n in range( atan_base ):
+        comma = ","
+        if ( n == atan_base - 1 ):
+            comma = ""
+            
+        angle = math.atan( n * 1.0 / atan_base ) / math.pi * ag_pi
+        line  = line + " " + repr( int( angle + 0.5 ) ) + comma
+        count = count + 1;
+        if ( count == 8 ):
+            count = 0
+            print line
+            line = "   "
+            
+    if ( count > 0 ):
+        print line
+    print "  };"
+
+
+# This routine is not used currently.
+#
+def print_sines():
+    print "  static FT_Fixed  ah_sines[AG_HALF_PI + 1] ="
+    print "  {"
+
+    count = 0
+    line  = "   "
+    
+    for n in range( ag_pi / 2 ):
+        sinus = math.sin( n * math.pi / ag_pi )
+        line  = line + " " + repr( int( 65536.0 * sinus ) ) + ","
+        count = count + 1
+        if ( count == 8 ):
+            count = 0
+            print line
+            line = "   "
+        
+    if ( count > 0 ):
+        print line
+    print "   65536"
+    print "  };"
+
+
+print_arctan( 8 )
+print
+
+
+# END
diff --git a/src/freetype/autohint/module.mk b/src/freetype/autohint/module.mk
new file mode 100644 (file)
index 0000000..71e5ee3
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_autohint_module
+
+add_autohint_module:
+       $(OPEN_DRIVER)autohint_module_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)autohint  $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/autohint/rules.mk b/src/freetype/autohint/rules.mk
new file mode 100644 (file)
index 0000000..87f7849
--- /dev/null
@@ -0,0 +1,77 @@
+#
+# FreeType 2 auto-hinter module configuration rules
+#
+
+
+# Copyright 2000 Catharon Productions Inc.
+# Author: David Turner
+#
+# This file is part of the Catharon Typography Project and shall only
+# be used, modified, and distributed under the terms of the Catharon
+# Open Source License that should come with this file under the name
+# `CatharonLicense.txt'.  By continuing to use, modify, or distribute
+# this file you indicate that you have read the license and
+# understand and accept it fully.
+#
+# Note that this license is compatible with the FreeType license.
+
+
+# AUTO driver directory
+#
+AUTO_DIR  := $(SRC_)autohint
+AUTO_DIR_ := $(AUTO_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+AUTO_COMPILE := $(FT_COMPILE)
+
+
+# AUTO driver sources (i.e., C files)
+#
+AUTO_DRV_SRC := $(AUTO_DIR_)ahangles.c  \
+                $(AUTO_DIR_)ahglobal.c  \
+                $(AUTO_DIR_)ahglyph.c   \
+                $(AUTO_DIR_)ahhint.c    \
+                $(AUTO_DIR_)ahmodule.c
+
+# AUTO driver headers
+#
+AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h)  \
+              $(AUTO_DIR_)ahloader.h \
+              $(AUTO_DIR_)ahtypes.h
+
+
+# AUTO driver object(s)
+#
+#   AUTO_DRV_OBJ_M is used during `multi' builds.
+#   AUTO_DRV_OBJ_S is used during `single' builds.
+#
+AUTO_DRV_OBJ_M := $(AUTO_DRV_SRC:$(AUTO_DIR_)%.c=$(OBJ_)%.$O)
+AUTO_DRV_OBJ_S := $(OBJ_)autohint.$O
+
+# AUTO driver source file for single build
+#
+AUTO_DRV_SRC_S := $(AUTO_DIR_)autohint.c
+
+
+# AUTO driver - single object
+#
+$(AUTO_DRV_OBJ_S): $(AUTO_DRV_SRC_S) $(AUTO_DRV_SRC) \
+                   $(FREETYPE_H) $(AUTO_DRV_H)
+       $(AUTO_COMPILE) $T$@ $(AUTO_DRV_SRC_S)
+
+
+# AUTO driver - multiple objects
+#
+$(OBJ_)%.$O: $(AUTO_DIR_)%.c $(FREETYPE_H) $(AUTO_DRV_H)
+       $(AUTO_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(AUTO_DRV_OBJ_S)
+DRV_OBJS_M += $(AUTO_DRV_OBJ_M)
+
+
+# EOF
diff --git a/src/freetype/base/ftbase.c b/src/freetype/base/ftbase.c
new file mode 100644 (file)
index 0000000..a110af4
--- /dev/null
@@ -0,0 +1,42 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftbase.c                                                               */
+/*                                                                         */
+/*    Single object library component (body only).                         */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftcalc.c"
+#include "ftobjs.c"
+#include "ftstream.c"
+#include "ftlist.c"
+#include "ftoutln.c"
+#include "ftextend.c"
+#include "ftnames.c"
+
+#else /* FT_FLAT_COMPILE */
+
+#include <base/ftcalc.c>
+#include <base/ftobjs.c>
+#include <base/ftstream.c>
+#include <base/ftlist.c>
+#include <base/ftoutln.c>
+#include <base/ftextend.c>
+#include <base/ftnames.c>
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
diff --git a/src/freetype/base/ftcalc.c b/src/freetype/base/ftcalc.c
new file mode 100644 (file)
index 0000000..d27de26
--- /dev/null
@@ -0,0 +1,773 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcalc.c                                                               */
+/*                                                                         */
+/*    Arithmetic computations (body).                                      */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Support for 1-complement arithmetic has been totally dropped in this  */
+  /* release.  You can still write your own code if you need it.           */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Implementing basic computation routines.                              */
+  /*                                                                       */
+  /* FT_MulDiv(), FT_MulFix(), and FT_DivFix() are declared in freetype.h. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>  /* for ABS() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_calc
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static const FT_Long  ft_square_roots[63] =
+  {
+       1L,    1L,    2L,     3L,     4L,     5L,     8L,    11L,
+      16L,   22L,   32L,    45L,    64L,    90L,   128L,   181L,
+     256L,  362L,  512L,   724L,  1024L,  1448L,  2048L,  2896L,
+    4096L, 5892L, 8192L, 11585L, 16384L, 23170L, 32768L, 46340L,
+
+      65536L,   92681L,  131072L,   185363L,   262144L,   370727L,
+     524288L,  741455L, 1048576L,  1482910L,  2097152L,  2965820L,
+    4194304L, 5931641L, 8388608L, 11863283L, 16777216L, 23726566L,
+
+      33554432L,   47453132L,   67108864L,   94906265L,
+     134217728L,  189812531L,  268435456L,  379625062L,
+     536870912L,  759250125L, 1073741824L, 1518500250L,
+    2147483647L
+  };
+
+#else
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Sqrt32                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the square root of an Int32 integer (which will be        */
+  /*    handled as an unsigned long value).                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: The value to compute the root for.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `sqrt(x)'.                                           */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Int32 )  FT_Sqrt32( FT_Int32  x )
+  {
+    FT_ULong  val, root, newroot, mask;
+
+
+    root = 0;
+    mask = 0x40000000L;
+    val  = (FT_ULong)x;
+
+    do
+    {
+      newroot = root + mask;
+      if ( newroot <= val )
+      {
+        val -= newroot;
+        root = newroot + mask;
+      }
+
+      root >>= 1;
+      mask >>= 2;
+
+    } while ( mask != 0 );
+
+    return root;
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#ifdef FT_LONG64
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulDiv                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation `(a*b)/c'   */
+  /*    with maximal accuracy (it uses a 64-bit intermediate integer       */
+  /*    whenever necessary).                                               */
+  /*                                                                       */
+  /*    This function isn't necessarily as fast as some processor specific */
+  /*    operations, but is at least completely portable.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.                                        */
+  /*    c :: The divisor.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/c'.  This function never traps when trying to */
+  /*    divide by zero; it simply returns `MaxInt' or `MinInt' depending   */
+  /*    on the signs of `a' and `b'.                                       */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Long )  FT_MulDiv( FT_Long  a,
+                                        FT_Long  b,
+                                        FT_Long  c )
+  {
+    FT_Int s;
+
+
+    s = 1;
+    if ( a < 0 ) { a = -a; s = -s; }
+    if ( b < 0 ) { b = -b; s = -s; }
+    if ( c < 0 ) { c = -c; s = -s; }
+
+    return s * ( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
+                       : 0x7FFFFFFFL );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*b)/0x10000' with maximal accuracy.  Most of the time this is   */
+  /*    used to multiply a given value by a 16.16 fixed float factor.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/0x10000'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function has been optimized for the case where the absolute   */
+  /*    value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
+  /*    As this happens mainly when scaling from notional units to         */
+  /*    fractional pixels in FreeType, it resulted in noticeable speed     */
+  /*    improvements between versions 2.x and 1.x.                         */
+  /*                                                                       */
+  /*    As a conclusion, always try to place a 16.16 factor as the         */
+  /*    _second_ argument of this function; this can make a great          */
+  /*    difference.                                                        */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Long )  FT_MulFix( FT_Long  a,
+                                        FT_Long  b )
+  {
+    FT_Int  s;
+
+
+    s = 1;
+    if ( a < 0 ) { a = -a; s = -s; }
+    if ( b < 0 ) { b = -b; s = -s; }
+
+    return s * (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_DivFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*0x10000)/b' with maximal accuracy.  Most of the time, this is  */
+  /*    used to divide a given value by a 16.16 fixed float factor.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*0x10000)/b'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The optimization for FT_DivFix() is simple: If (a << 16) fits in   */
+  /*    32 bits, then the division is computed directly.  Otherwise, we    */
+  /*    use a specialized version of the old FT_MulDiv64().                */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Long )  FT_DivFix( FT_Long  a,
+                                        FT_Long  b )
+  {
+    FT_Int32   s;
+    FT_UInt32  q;
+
+
+    s  = a; a = ABS(a);
+    s ^= b; b = ABS(b);
+
+    if ( b == 0 )
+      /* check for division by 0 */
+      q = 0x7FFFFFFFL;
+    else
+      /* compute result directly */
+      q = ( (FT_Int64)a << 16 ) / b;
+
+    return (FT_Int32)( s < 0 ? -q : q );
+  }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  /* a helper function for FT_Sqrt64() */
+
+  static
+  int  ft_order64( FT_Int64  z )
+  {
+    int  j = 0;
+
+
+    while ( z )
+    {
+      z = (unsigned FT_INT64)z >> 1;
+      j++;
+    }
+    return j - 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Sqrt64                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the square root of a 64-bit value.  That sounds stupid,   */
+  /*    but it is needed to obtain maximal accuracy in the TrueType        */
+  /*    bytecode interpreter.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    l :: A 64-bit integer.                                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The 32-bit square-root.                                            */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Int32 )  FT_Sqrt64( FT_Int64  l )
+  {
+    FT_Int64  r, s;
+
+
+    if ( l <= 0 ) return 0;
+    if ( l == 1 ) return 1;
+
+    r = ft_square_roots[ft_order64( l )];
+
+    do
+    {
+      s = r;
+      r = ( r + l / r ) >> 1;
+
+    } while ( r > s || r * r > l );
+
+    return r;
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#else /* FT_LONG64 */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulDiv                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation `(a*b)/c'   */
+  /*    with maximal accuracy (it uses a 64-bit intermediate integer       */
+  /*    whenever necessary).                                               */
+  /*                                                                       */
+  /*    This function isn't necessarily as fast as some processor specific */
+  /*    operations, but is at least completely portable.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.                                        */
+  /*    c :: The divisor.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/c'.  This function never traps when trying to */
+  /*    divide by zero; it simply returns `MaxInt' or `MinInt' depending   */
+  /*    on the signs of `a' and `b'.                                       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The FT_MulDiv() function has been optimized thanks to ideas from   */
+  /*    Graham Asher.  The trick is to optimize computation if everything  */
+  /*    fits within 32 bits (a rather common case).                        */
+  /*                                                                       */
+  /*    We compute `a*b+c/2', then divide it by `c' (positive values).     */
+  /*                                                                       */
+  /*      46340 is FLOOR(SQRT(2^31-1)).                                    */
+  /*                                                                       */
+  /*      if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 )       */
+  /*                                                                       */
+  /*      0x7FFFFFFF - 0x7FFEA810 = 0x157F0                                */
+  /*                                                                       */
+  /*      if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF )              */
+  /*                                                                       */
+  /*      and 2*0x157F0 = 176096.                                          */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Long )  FT_MulDiv( FT_Long  a,
+                                        FT_Long  b,
+                                        FT_Long  c )
+  {
+    long   s;
+
+
+    if ( a == 0 || b == c )
+      return a;
+
+    s  = a; a = ABS( a );
+    s ^= b; b = ABS( b );
+    s ^= c; c = ABS( c );
+
+    if ( a <= 46340 && b <= 46340 && c <= 176095L && c > 0 )
+    {
+      a = ( a * b + ( c >> 1 ) ) / c;
+    }
+    else if ( c > 0 )
+    {
+      FT_Int64  temp, temp2;
+
+
+      FT_MulTo64( a, b, &temp );
+      temp2.hi = (FT_Int32)( c >> 31 );
+      temp2.lo = (FT_UInt32)( c / 2 );
+      FT_Add64( &temp, &temp2, &temp );
+      a = FT_Div64by32( &temp, c );
+    }
+    else
+      a = 0x7FFFFFFFL;
+
+    return ( s < 0 ? -a : a );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*b)/0x10000' with maximal accuracy.  Most of the time, this is  */
+  /*    used to multiply a given value by a 16.16 fixed float factor.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/0x10000'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The optimization for FT_MulFix() is different.  We could simply be */
+  /*    happy by applying the same principles as with FT_MulDiv(), because */
+  /*                                                                       */
+  /*      c = 0x10000 < 176096                                             */
+  /*                                                                       */
+  /*    However, in most cases, we have a `b' with a value around 0x10000  */
+  /*    which is greater than 46340.                                       */
+  /*                                                                       */
+  /*    According to some testing, most cases have `a' < 2048, so a good   */
+  /*    idea is to use bounds like 2048 and 1048576 (=floor((2^31-1)/2048) */
+  /*    for `a' and `b', respectively.                                     */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Long )  FT_MulFix( FT_Long  a,
+                                        FT_Long  b )
+  {
+    FT_Long   s;
+    FT_ULong  ua, ub;
+
+
+    if ( a == 0 || b == 0x10000L )
+      return a;
+
+    s  = a; a = ABS(a);
+    s ^= b; b = ABS(b);
+
+    ua = (FT_ULong)a;
+    ub = (FT_ULong)b;
+
+    if ( ua <= 2048 && ub <= 1048576L )
+    {
+      ua = ( ua * ub + 0x8000 ) >> 16;
+    }
+    else
+    {
+      FT_ULong  al = ua & 0xFFFF;
+
+
+      ua = ( ua >> 16 ) * ub +
+           al * ( ub >> 16 ) +
+           ( al * ( ub & 0xFFFF ) >> 16 );
+    }
+
+    return ( s < 0 ? -(FT_Long)ua : ua );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_DivFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*0x10000)/b' with maximal accuracy.  Most of the time, this is  */
+  /*    used to divide a given value by a 16.16 fixed float factor.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*0x10000)/b'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The optimization for FT_DivFix() is simple: If (a << 16) fits into */
+  /*    32 bits, then the division is computed directly.  Otherwise, we    */
+  /*    use a specialized version of the old FT_MulDiv64().                */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Long )  FT_DivFix( FT_Long  a,
+                                        FT_Long  b )
+  {
+    FT_Int32   s;
+    FT_UInt32  q;
+
+
+    s  = a; a = ABS(a);
+    s ^= b; b = ABS(b);
+
+    if ( b == 0 )
+    {
+      /* check for division by 0 */
+      q = 0x7FFFFFFFL;
+    }
+    else if ( ( a >> 16 ) == 0 )
+    {
+      /* compute result directly */
+      q = (FT_UInt32)( a << 16 ) / (FT_UInt32)b;
+    }
+    else
+    {
+      /* we need more bits; we have to do it by hand */
+      FT_UInt32  c;
+
+
+      q  = ( a / b ) << 16;
+      c  = a % b;
+
+      /* we must compute C*0x10000/B: we simply shift C and B so */
+      /* C becomes smaller than 16 bits                          */
+      while ( c >> 16 )
+      {
+        c >>= 1;
+        b <<= 1;
+      }
+
+      q += ( c << 16 ) / b;
+    }
+
+    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add64                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Add two Int64 values.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: A pointer to the first value to be added.                     */
+  /*    y :: A pointer to the second value to be added.                    */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    z :: A pointer to the result of `x + y'.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Will be wrapped by the ADD_64() macro.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Add64( FT_Int64*  x,
+                                    FT_Int64*  y,
+                                    FT_Int64*  z )
+  {
+    register FT_UInt32  lo, hi;
+
+
+    lo = x->lo + y->lo;
+    hi = x->hi + y->hi + ( lo < x->lo );
+
+    z->lo = lo;
+    z->hi = hi;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulTo64                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Multiplies two Int32 integers.  Returns an Int64 integer.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: The first multiplier.                                         */
+  /*    y :: The second multiplier.                                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    z :: A pointer to the result of `x * y'.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Will be wrapped by the MUL_64() macro.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_MulTo64( FT_Int32   x,
+                                      FT_Int32   y,
+                                      FT_Int64*  z )
+  {
+    FT_Int32   s;
+
+
+    s  = x; x = ABS( x );
+    s ^= y; y = ABS( y );
+
+    {
+      FT_UInt32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;
+
+
+      lo1 = x & 0x0000FFFF;  hi1 = x >> 16;
+      lo2 = y & 0x0000FFFF;  hi2 = y >> 16;
+
+      lo = lo1 * lo2;
+      i1 = lo1 * hi2;
+      i2 = lo2 * hi1;
+      hi = hi1 * hi2;
+
+      /* Check carry overflow of i1 + i2 */
+      i1 += i2;
+      if ( i1 < i2 )
+        hi += 1L << 16;
+
+      hi += i1 >> 16;
+      i1  = i1 << 16;
+
+      /* Check carry overflow of i1 + lo */
+      lo += i1;
+      hi += ( lo < i1 );
+
+      z->lo = lo;
+      z->hi = hi;
+    }
+
+    if ( s < 0 )
+    {
+      z->lo = (FT_UInt32)-(FT_Int32)z->lo;
+      z->hi = ~z->hi + !( z->lo );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Div64by32                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Divides an Int64 value by an Int32 value.  Returns an Int32        */
+  /*    integer.                                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: A pointer to the dividend.                                    */
+  /*    y :: The divisor.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `x / y'.                                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Will be wrapped by the DIV_64() macro.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Int32 )  FT_Div64by32( FT_Int64*  x,
+                                            FT_Int32   y )
+  {
+    FT_Int32   s;
+    FT_UInt32  q, r, i, lo;
+
+
+    s  = x->hi;
+    if ( s < 0 )
+    {
+      x->lo = (FT_UInt32)-(FT_Int32)x->lo;
+      x->hi = ~x->hi + !( x->lo );
+    }
+    s ^= y;  y = ABS( y );
+
+    /* Shortcut */
+    if ( x->hi == 0 )
+    {
+      if ( y > 0 )
+        q = x->lo / y;
+      else
+        q = 0x7FFFFFFFL;
+
+      return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+    }
+
+    r  = x->hi;
+    lo = x->lo;
+
+    if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
+      return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
+                             /* Return Max/Min Int32 if division overflow.  */
+                             /* This includes division by zero!             */
+    q = 0;
+    for ( i = 0; i < 32; i++ )
+    {
+      r <<= 1;
+      q <<= 1;
+      r  |= lo >> 31;
+
+      if ( r >= (FT_UInt32)y )
+      {
+        r -= y;
+        q |= 1;
+      }
+      lo <<= 1;
+    }
+
+    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+  }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+
+  /* two helper functions for FT_Sqrt64() */
+
+  static
+  void  FT_Sub64( FT_Int64*  x,
+                  FT_Int64*  y,
+                  FT_Int64*  z )
+  {
+    register FT_UInt32  lo, hi;
+
+
+    lo = x->lo - y->lo;
+    hi = x->hi - y->hi - ( (FT_Int32)lo < 0 );
+
+    z->lo = lo;
+    z->hi = hi;
+  }
+
+
+  static
+  int  ft_order64( FT_Int64*  z )
+  {
+    FT_UInt32  i;
+    int        j;
+
+
+    i = z->lo;
+    j = 0;
+    if ( z->hi )
+    {
+      i = z->hi;
+      j = 32;
+    }
+
+    while ( i > 0 )
+    {
+      i >>= 1;
+      j++;
+    }
+    return j - 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Sqrt64                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the square root of a 64-bits value.  That sounds stupid,  */
+  /*    but it is needed to obtain maximal accuracy in the TrueType        */
+  /*    bytecode interpreter.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    z :: A pointer to a 64-bit integer.                                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The 32-bit square-root.                                            */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Int32 )  FT_Sqrt64( FT_Int64*  l )
+  {
+    FT_Int64  l2;
+    FT_Int32  r, s;
+
+
+    if ( (FT_Int32)l->hi < 0          ||
+         ( l->hi == 0 && l->lo == 0 ) )
+      return 0;
+
+    s = ft_order64( l );
+    if ( s == 0 )
+      return 1;
+
+    r = ft_square_roots[s];
+    do
+    {
+      s = r;
+      r = ( r + FT_Div64by32( l, r ) ) >> 1;
+      FT_MulTo64( r, r,   &l2 );
+      FT_Sub64  ( l, &l2, &l2 );
+
+    } while ( r > s || (FT_Int32)l2.hi < 0 );
+
+    return r;
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+#endif /* FT_LONG64 */
+
+
+/* END */
diff --git a/src/freetype/base/ftdebug.c b/src/freetype/base/ftdebug.c
new file mode 100644 (file)
index 0000000..32da789
--- /dev/null
@@ -0,0 +1,124 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftdebug.c                                                              */
+/*                                                                         */
+/*    Debugging and logging component (body).                              */
+/*                                                                         */
+/*  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 component contains various macros and functions used to ease the */
+  /* debugging of the FreeType engine.  Its main purpose is in assertion   */
+  /* checking, tracing, and error detection.                               */
+  /*                                                                       */
+  /* There are now three debugging modes:                                  */
+  /*                                                                       */
+  /* - trace mode                                                          */
+  /*                                                                       */
+  /*   Error and trace messages are sent to the log file (which can be the */
+  /*   standard error output).                                             */
+  /*                                                                       */
+  /* - error mode                                                          */
+  /*                                                                       */
+  /*   Only error messages are generated.                                  */
+  /*                                                                       */
+  /* - release mode:                                                       */
+  /*                                                                       */
+  /*   No error message is sent or generated.  The code is free from any   */
+  /*   debugging parts.                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+  char  ft_trace_levels[trace_max];
+#endif
+
+
+#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE )
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+  FT_EXPORT_FUNC( void )  FT_Message( const char*  fmt, ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    vprintf( fmt, ap );
+    va_end( ap );
+  }
+
+
+  FT_EXPORT_FUNC( void )  FT_Panic( const char*  fmt, ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    vprintf( fmt, ap );
+    va_end( ap );
+
+    exit( EXIT_FAILURE );
+  }
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_SetTraceLevel                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the trace level for debugging.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    component :: The component which should be traced.  See ftdebug.h  */
+  /*                 for a complete list.  If set to `trace_any', all      */
+  /*                 components will be traced.                            */
+  /*    level     :: The tracing level.                                    */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_SetTraceLevel( FT_Trace  component,
+                                            char      level )
+  {
+    if ( component >= trace_max )
+      return;
+
+    /* if component is `trace_any', change _all_ levels at once */
+    if ( component == trace_any )
+    {
+      int  n;
+
+
+      for ( n = trace_any; n < trace_max; n++ )
+        ft_trace_levels[n] = level;
+    }
+    else        /* otherwise, only change individual component */
+      ft_trace_levels[component] = level;
+  }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */
+
+
+/* END */
diff --git a/src/freetype/base/ftextend.c b/src/freetype/base/ftextend.c
new file mode 100644 (file)
index 0000000..f298b19
--- /dev/null
@@ -0,0 +1,332 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftextend.h                                                             */
+/*                                                                         */
+/*    FreeType extensions implementation (body).                           */
+/*                                                                         */
+/*  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 is an updated version of the extension component, now located   */
+  /*  in the main library's source directory.  It allows the dynamic       */
+  /*  registration/use of various face object extensions through a simple  */
+  /*  API.                                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftextend.h>
+#include <freetype/internal/ftdebug.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_extend
+
+
+  typedef struct  FT_Extension_Registry_
+  {
+    FT_Int              num_extensions;
+    FT_Long             cur_offset;
+    FT_Extension_Class  classes[FT_MAX_EXTENSIONS];
+
+  } FT_Extension_Registry;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Init_Extensions                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes the extension component.                               */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver :: A handle to the driver object.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  FT_Init_Extensions( FT_Driver  driver )
+  {
+    FT_Error                error;
+    FT_Memory               memory;
+    FT_Extension_Registry*  registry;
+
+
+    memory = driver->root.library->memory;
+    if ( ALLOC( registry, sizeof ( *registry ) ) )
+      return error;
+
+    registry->num_extensions = 0;
+    registry->cur_offset     = 0;
+    driver->extensions       = registry;
+
+    FT_TRACE2(( "FT_Init_Extensions: success\n" ));
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Extensions                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes the extension component.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver :: A handle to the driver object.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  FT_Done_Extensions( FT_Driver  driver )
+  {
+    FT_Memory  memory = driver->root.memory;
+
+
+    FREE( driver->extensions );
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Register_Extension                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Registers a new extension.                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver :: A handle to the driver object.                           */
+  /*    class  :: A pointer to a class describing the extension.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Register_Extension(
+                                FT_Driver            driver,
+                                FT_Extension_Class*  clazz )
+  {
+    FT_Extension_Registry*  registry;
+
+
+    if ( !driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    if ( !clazz )
+      return FT_Err_Invalid_Argument;
+
+    registry = (FT_Extension_Registry*)driver->extensions;
+    if ( registry )
+    {
+      FT_Int               n   = registry->num_extensions;
+      FT_Extension_Class*  cur = registry->classes + n;
+
+
+      if ( n >= FT_MAX_EXTENSIONS )
+        return FT_Err_Too_Many_Extensions;
+
+      *cur = *clazz;
+
+      cur->offset  = registry->cur_offset;
+
+      registry->num_extensions++;
+      registry->cur_offset +=
+        ( cur->size + FT_ALIGNMENT - 1 ) & -FT_ALIGNMENT;
+
+      FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered\n",
+                  cur->id ));
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Extension                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Queries an extension block by an extension ID string.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face                :: A handle to the face object.                */
+  /*    extension_id        :: An ID string identifying the extension.     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    extension_interface :: A generic pointer, usually pointing to a    */
+  /*                           table of functions implementing the         */
+  /*                           extension interface.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A generic pointer to the extension block.                          */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void* )  FT_Get_Extension(
+                             FT_Face      face,
+                             const char*  extension_id,
+                             void**       extension_interface )
+  {
+    FT_Extension_Registry*  registry;
+
+
+    if ( !face || !extension_id || !extension_interface )
+      return 0;
+
+    registry = (FT_Extension_Registry*)face->driver->extensions;
+    if ( registry && face->extensions )
+    {
+      FT_Extension_Class*  cur   = registry->classes;
+      FT_Extension_Class*  limit = cur + registry->num_extensions;
+
+
+      for ( ; cur < limit; cur++ )
+        if ( strcmp( cur->id, extension_id ) == 0 )
+        {
+          *extension_interface = cur->interface;
+
+          FT_TRACE1(( "FT_Get_Extension: got `%s'\n", extension_id ));
+
+          return (void*)((char*)face->extensions + cur->offset);
+        }
+    }
+
+    /* could not find the extension id */
+
+    FT_ERROR(( "FT_Get_Extension: couldn't find `%s'\n", extension_id ));
+
+    *extension_interface = 0;
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Destroy_Extensions                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys all extensions within a face object.                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face :: A handle to the face object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Called by the face object destructor.                              */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  FT_Destroy_Extensions( FT_Face  face )
+  {
+    FT_Extension_Registry*  registry;
+    FT_Memory               memory;
+
+
+    registry = (FT_Extension_Registry*)face->driver->extensions;
+    if ( registry && face->extensions )
+    {
+      FT_Extension_Class*  cur   = registry->classes;
+      FT_Extension_Class*  limit = cur + registry->num_extensions;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        char*  ext = (char*)face->extensions + cur->offset;
+
+        if ( cur->finalize )
+          cur->finalize( ext, face );
+      }
+
+      memory = face->driver->root.memory;
+      FREE( face->extensions );
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Create_Extensions                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates an extension object within a face object for all           */
+  /*    registered extensions.                                             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face :: A handle to the face object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Called by the face object constructor.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  FT_Create_Extensions( FT_Face  face )
+  {
+    FT_Extension_Registry*  registry;
+    FT_Memory               memory;
+    FT_Error                error;
+
+
+    face->extensions = 0;
+
+    /* load extensions registry; exit successfully if none is there */
+
+    registry = (FT_Extension_Registry*)face->driver->extensions;
+    if ( !registry )
+      return FT_Err_Ok;
+
+    memory = face->driver->root.memory;
+    if ( ALLOC( face->extensions, registry->cur_offset ) )
+      return error;
+
+    {
+      FT_Extension_Class*  cur   = registry->classes;
+      FT_Extension_Class*  limit = cur + registry->num_extensions;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        char*  ext = (char*)face->extensions + cur->offset;
+
+        if ( cur->init )
+        {
+          error = cur->init( ext, face );
+          if ( error )
+            break;
+        }
+      }
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/base/ftglyph.c b/src/freetype/base/ftglyph.c
new file mode 100644 (file)
index 0000000..4052e6e
--- /dev/null
@@ -0,0 +1,1184 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftglyph.c                                                              */
+/*                                                                         */
+/*    FreeType convenience functions to handle glyphs (body).              */
+/*                                                                         */
+/*  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 contains the definition of several convenience functions   */
+  /*  that can be used by client applications to easily retrieve glyph     */
+  /*  bitmaps and outlines from a given face.                              */
+  /*                                                                       */
+  /*  These functions should be optional if you are writing a font server  */
+  /*  or text layout engine on top of FreeType.  However, they are pretty  */
+  /*  handy for many other simple uses of the library.                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/ftglyph.h>
+#include <freetype/ftoutln.h>
+#include <freetype/internal/ftobjs.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_glyph
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   Convenience functions                                         ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Matrix_Multiply                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs the matrix operation `b = a*b'.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: A pointer to matrix `a'.                                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    b :: A pointer to matrix `b'.                                      */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The result is undefined if either `a' or `b' is zero.              */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Matrix_Multiply( FT_Matrix*  a,
+                                              FT_Matrix*  b )
+  {
+    FT_Fixed  xx, xy, yx, yy;
+
+
+    if ( !a || !b )
+      return;
+
+    xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
+    xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
+    yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
+    yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
+
+    b->xx = xx;  b->xy = xy;
+    b->yx = yx;  b->yy = yy;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Matrix_Invert                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inverts a 2x2 matrix.  Returns an error if it can't be inverted.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    matrix :: A pointer to the target matrix.  Remains untouched in    */
+  /*              case of error.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Matrix_Invert( FT_Matrix*  matrix )
+  {
+    FT_Pos  delta, xx, yy;
+
+
+    if ( !matrix )
+      return FT_Err_Invalid_Argument;
+
+    /* compute discriminant */
+    delta = FT_MulFix( matrix->xx, matrix->yy ) -
+            FT_MulFix( matrix->xy, matrix->yx );
+
+    if ( !delta )
+      return FT_Err_Invalid_Argument;  /* matrix can't be inverted */
+
+    matrix->xy = - FT_DivFix( matrix->xy, delta );
+    matrix->yx = - FT_DivFix( matrix->yx, delta );
+
+    xx = matrix->xx;
+    yy = matrix->yy;
+
+    matrix->xx = FT_DivFix( yy, delta );
+    matrix->yy = FT_DivFix( xx, delta );
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   FT_BitmapGlyph support                                        ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static
+  FT_Error  ft_bitmap_copy( FT_Memory   memory,
+                            FT_Bitmap*  source,
+                            FT_Bitmap*  target )
+  {
+    FT_Error  error;
+    FT_Int    pitch = source->pitch;
+    FT_ULong  size;
+
+
+    *target = *source;
+
+    if ( pitch < 0 )
+      pitch = -pitch;
+
+    size = (FT_ULong)( pitch * source->rows );
+
+    if ( !ALLOC( target->buffer, size ) )
+      MEM_Copy( source->buffer, target->buffer, size );
+
+    return error;
+  }
+
+
+  static
+  FT_Error  ft_bitmap_glyph_init( FT_BitmapGlyph  glyph,
+                                  FT_GlyphSlot    slot )
+  {
+    FT_Error    error   = FT_Err_Ok;
+    FT_Library  library = FT_GLYPH(glyph)->library;
+    FT_Memory   memory  = library->memory;
+
+
+    if ( slot->format != ft_glyph_format_bitmap )
+    {
+      error = FT_Err_Invalid_Glyph_Format;
+      goto Exit;
+    }
+
+    /* grab the bitmap in the slot - do lazy copying whenever possible */
+    glyph->bitmap = slot->bitmap;
+    glyph->left   = slot->bitmap_left;
+    glyph->top    = slot->bitmap_top;
+
+    if ( slot->flags & ft_glyph_own_bitmap )
+      slot->flags &= ~ft_glyph_own_bitmap;
+    else
+    {
+      /* copy the bitmap into a new buffer */
+      error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error  ft_bitmap_glyph_copy( FT_BitmapGlyph  source,
+                                  FT_BitmapGlyph  target )
+  {
+    FT_Memory  memory = source->root.library->memory;
+
+
+    target->left = source->left;
+    target->top  = source->top;
+
+    return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap );
+  }
+
+
+  static
+  void  ft_bitmap_glyph_done( FT_BitmapGlyph  glyph )
+  {
+    FT_Memory  memory = FT_GLYPH(glyph)->library->memory;
+
+
+    FREE( glyph->bitmap.buffer );
+  }
+
+
+  static
+  void  ft_bitmap_glyph_bbox( FT_BitmapGlyph  glyph,
+                              FT_BBox*        cbox )
+  {
+    cbox->xMin = glyph->left << 6;
+    cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
+    cbox->yMax = glyph->top << 6;
+    cbox->yMin = cbox->xMax - ( glyph->bitmap.rows << 6 );
+  }
+
+
+  const FT_Glyph_Class  ft_bitmap_glyph_class =
+  {
+    sizeof( FT_BitmapGlyphRec ),
+    ft_glyph_format_bitmap,
+
+    (FT_Glyph_Init_Func)     ft_bitmap_glyph_init,
+    (FT_Glyph_Done_Func)     ft_bitmap_glyph_done,
+    (FT_Glyph_Copy_Func)     ft_bitmap_glyph_copy,
+    (FT_Glyph_Transform_Func)0,
+    (FT_Glyph_BBox_Func)     ft_bitmap_glyph_bbox,
+    (FT_Glyph_Prepare_Func)  0
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   FT_OutlineGlyph support                                       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  ft_outline_glyph_init( FT_OutlineGlyph  glyph,
+                                   FT_GlyphSlot     slot )
+  {
+    FT_Error     error   = FT_Err_Ok;
+    FT_Library   library = FT_GLYPH(glyph)->library;
+    FT_Outline*  source  = &slot->outline;
+    FT_Outline*  target  = &glyph->outline;
+
+
+    /* check format in glyph slot */
+    if ( slot->format != ft_glyph_format_outline )
+    {
+      error = FT_Err_Invalid_Glyph_Format;
+      goto Exit;
+    }
+
+    /* allocate new outline */
+    error = FT_Outline_New( library, source->n_points, source->n_contours,
+                            &glyph->outline );
+    if ( error )
+      goto Exit;
+
+    /* copy it */
+    MEM_Copy( target->points, source->points,
+              source->n_points * sizeof ( FT_Vector ) );
+
+    MEM_Copy( target->tags, source->tags,
+              source->n_points * sizeof ( FT_Byte ) );
+
+    MEM_Copy( target->contours, source->contours,
+              source->n_contours * sizeof ( FT_Short ) );
+
+    /* copy all flags, except the `ft_outline_owner' one */
+    target->flags = source->flags | ft_outline_owner;
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  ft_outline_glyph_done( FT_OutlineGlyph  glyph )
+  {
+    FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
+  }
+
+
+  static
+  FT_Error  ft_outline_glyph_copy( FT_OutlineGlyph  source,
+                                   FT_OutlineGlyph  target )
+  {
+    FT_Error    error;
+    FT_Library  library = FT_GLYPH( source )->library;
+
+
+    error = FT_Outline_New( library, source->outline.n_points,
+                            source->outline.n_contours, &target->outline );
+    if ( !error )
+      FT_Outline_Copy( &source->outline, &target->outline );
+
+    return error;
+  }
+
+
+  static
+  void  ft_outline_glyph_transform( FT_OutlineGlyph  glyph,
+                                    FT_Matrix*       matrix,
+                                    FT_Vector*       delta )
+  {
+    if ( matrix )
+      FT_Outline_Transform( &glyph->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
+  }
+
+
+  static
+  void  ft_outline_glyph_bbox( FT_OutlineGlyph  glyph,
+                               FT_BBox*         bbox )
+  {
+    FT_Outline_Get_CBox( &glyph->outline, bbox );
+  }
+
+
+  static
+  FT_Error  ft_outline_glyph_prepare( FT_OutlineGlyph  glyph,
+                                      FT_GlyphSlot     slot )
+  {
+    slot->format         = ft_glyph_format_outline;
+    slot->outline        = glyph->outline;
+    slot->outline.flags &= ~ft_outline_owner;
+
+    return FT_Err_Ok;
+  }
+
+
+  const FT_Glyph_Class  ft_outline_glyph_class =
+  {
+    sizeof( FT_OutlineGlyphRec ),
+    ft_glyph_format_outline,
+
+    (FT_Glyph_Init_Func)     ft_outline_glyph_init,
+    (FT_Glyph_Done_Func)     ft_outline_glyph_done,
+    (FT_Glyph_Copy_Func)     ft_outline_glyph_copy,
+    (FT_Glyph_Transform_Func)ft_outline_glyph_transform,
+    (FT_Glyph_BBox_Func)     ft_outline_glyph_bbox,
+    (FT_Glyph_Prepare_Func)  ft_outline_glyph_prepare
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   FT_Glyph class and API                                        ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+   static
+   FT_Error  ft_new_glyph( FT_Library             library,
+                           const FT_Glyph_Class*  clazz,
+                           FT_Glyph*              aglyph )
+   {
+     FT_Memory  memory = library->memory;
+     FT_Error   error;
+     FT_Glyph   glyph;
+
+
+     *aglyph = 0;
+
+     if ( !ALLOC( glyph, clazz->glyph_size ) )
+     {
+       glyph->library = library;
+       glyph->clazz   = clazz;
+       glyph->format  = clazz->glyph_format;
+
+       *aglyph = glyph;
+     }
+
+     return error;
+   }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Copy                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to copy a glyph image.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    source :: A handle to the source glyph object.                     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    target :: A handle to the target glyph object.  0 in case of       */
+  /*              error.                                                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Glyph_Copy( FT_Glyph   source,
+                                             FT_Glyph*  target )
+  {
+    FT_Glyph               copy;
+    FT_Error               error;
+    const FT_Glyph_Class*  clazz;
+
+
+    /* check arguments */
+    if ( !target || !source || !source->clazz )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    *target = 0;
+
+    clazz = source->clazz;
+    error = ft_new_glyph( source->library, clazz, &copy );
+    if ( error )
+      goto Exit;
+
+    if ( clazz->glyph_copy )
+      error = clazz->glyph_copy( source, copy );
+
+    if ( error )
+      FT_Done_Glyph( copy );
+    else
+      *target = copy;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Glyph                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to extract a glyph image from a slot.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot   :: A handle to the source glyph slot.                       */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aglyph :: A handle to the glyph object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Get_Glyph( FT_GlyphSlot  slot,
+                                            FT_Glyph*     aglyph )
+  {
+    FT_Library  library = slot->library;
+    FT_Error    error;
+    FT_Glyph    glyph;
+
+    const FT_Glyph_Class*  clazz = 0;
+
+
+    if ( !slot )
+      return FT_Err_Invalid_Slot_Handle;
+
+    if ( !aglyph )
+      return FT_Err_Invalid_Argument;
+
+    /* if it is a bitmap, that's easy :-) */
+    if ( slot->format == ft_glyph_format_bitmap )
+      clazz = &ft_bitmap_glyph_class;
+
+    /* it it is an outline too */
+    else if ( slot->format == ft_glyph_format_outline )
+      clazz = &ft_outline_glyph_class;
+
+    else
+    {
+      /* try to find a renderer that supports the glyph image format */
+      FT_Renderer  render = FT_Lookup_Renderer( library, slot->format, 0 );
+
+
+      if ( render )
+        clazz = &render->glyph_class;
+    }
+
+    if ( !clazz )
+    {
+      error = FT_Err_Invalid_Glyph_Format;
+      goto Exit;
+    }
+
+    /* create FT_Glyph object */
+    error = ft_new_glyph( library, clazz, &glyph );
+    if ( error )
+      goto Exit;
+
+    /* copy advance while converting it to 16.16 format */
+    glyph->advance.x = slot->advance.x << 10;
+    glyph->advance.y = slot->advance.y << 10;
+
+    /* now import the image from the glyph slot */
+    error = clazz->glyph_init( glyph, slot );
+
+    /* if an error occurred, destroy the glyph */
+    if ( error )
+      FT_Done_Glyph( glyph );
+    else
+      *aglyph = glyph;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Transform                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Transforms a glyph image if its format is scalable.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph  :: A handle to the target glyph object.                     */
+  /*                                                                       */
+  /*    matrix :: A pointer to a 2x2 matrix to apply.                      */
+  /*                                                                       */
+  /*    delta  :: A pointer to a 2d vector to apply.  Coordinates are      */
+  /*              expressed in 1/64th of a pixel.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code (the glyph format is not scalable if it is     */
+  /*    not zero).                                                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The 2x2 transformation matrix is also applied to the glyph's       */
+  /*    advance vector.                                                    */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Glyph_Transform( FT_Glyph    glyph,
+                                                  FT_Matrix*  matrix,
+                                                  FT_Vector*  delta )
+  {
+    const FT_Glyph_Class*  clazz;
+    FT_Error               error = FT_Err_Ok;
+
+
+    if ( !glyph || !glyph->clazz )
+      error = FT_Err_Invalid_Argument;
+    else
+    {
+      clazz = glyph->clazz;
+      if ( clazz->glyph_transform )
+      {
+        /* transform glyph image */
+        clazz->glyph_transform( glyph, matrix, delta );
+
+        /* transform advance vector */
+        if ( matrix )
+          FT_Vector_Transform( &glyph->advance, matrix );
+      }
+      else
+        error = FT_Err_Invalid_Glyph_Format;
+    }
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Get_CBox                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the glyph image's bounding box.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: A handle to the source glyph object.                      */
+  /*                                                                       */
+  /*    mode  :: A set of bit flags that indicate how to interpret the     */
+  /*             returned bounding box values.                             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    box   :: The glyph bounding box.  Coordinates are expressed in     */
+  /*             1/64th of pixels if it is grid-fitted.                    */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Coordinates are relative to the glyph origin, using the Y-upwards  */
+  /*    convention.                                                        */
+  /*                                                                       */
+  /*    If `ft_glyph_bbox_subpixels' is set in `mode', the bbox            */
+  /*    coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels).   */
+  /*    Otherwise, coordinates are expressed in integer pixels.            */
+  /*                                                                       */
+  /*    Note that the maximum coordinates are exclusive, which means that  */
+  /*    one can compute the width and height of the glyph image (be it in  */
+  /*    integer or 26.6 pixels) as:                                        */
+  /*                                                                       */
+  /*      width  = bbox.xMax - bbox.xMin;                                  */
+  /*      height = bbox.yMax - bbox.yMin;                                  */
+  /*                                                                       */
+  /*    Note also that for 26.6 coordinates, if the                        */
+  /*    `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates     */
+  /*    will also be grid-fitted, which corresponds to:                    */
+  /*                                                                       */
+  /*      bbox.xMin = FLOOR(bbox.xMin);                                    */
+  /*      bbox.yMin = FLOOR(bbox.yMin);                                    */
+  /*      bbox.xMax = CEILING(bbox.xMax);                                  */
+  /*      bbox.yMax = CEILING(bbox.yMax);                                  */
+  /*                                                                       */
+  /*    The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'.   */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Glyph_Get_CBox( FT_Glyph  glyph,
+                                             FT_UInt   bbox_mode,
+                                             FT_BBox*  cbox )
+  {
+    const FT_Glyph_Class*  clazz;
+    FT_Error               error = FT_Err_Ok;
+
+
+    if ( !cbox || !glyph || !glyph->clazz )
+      error = FT_Err_Invalid_Argument;
+    else
+    {
+      clazz = glyph->clazz;
+      if ( !clazz->glyph_bbox )
+        error = FT_Err_Invalid_Glyph_Format;
+      else
+      {
+        /* retrieve bbox in 26.6 coordinates */
+        clazz->glyph_bbox( glyph, cbox );
+
+        /* perform grid fitting if needed */
+        if ( bbox_mode & ft_glyph_bbox_gridfit )
+        {
+          cbox->xMin &= -64;
+          cbox->yMin &= -64;
+          cbox->xMax  = ( cbox->xMax + 63 ) & -64;
+          cbox->yMax  = ( cbox->yMax + 63 ) & -64;
+        }
+
+        /* convert to integer pixels if needed */
+        if ( !( bbox_mode & ft_glyph_bbox_subpixels ) )
+        {
+          cbox->xMin >>= 6;
+          cbox->yMin >>= 6;
+          cbox->xMax >>= 6;
+          cbox->yMax >>= 6;
+        }
+      }
+    }
+    return;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_To_Bitmap                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a given glyph object to a bitmap glyph object.            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    glyph       :: A pointer to a handle to the target glyph.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    render_mode :: A set of bit flags that describe how the data is    */
+  /*                                                                       */
+  /*                                                                       */
+  /*    origin      :: A pointer to a vector used to translate the glyph   */
+  /*                   image before rendering.  Can be 0 (if no            */
+  /*                   translation).  The origin is expressed in           */
+  /*                   26.6 pixels.                                        */
+  /*                                                                       */
+  /*    destroy     :: A boolean that indicates that the original glyph    */
+  /*                   image should be destroyed by this function.  It is  */
+  /*                   never destroyed in case of error.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The glyph image is translated with the `origin' vector before      */
+  /*    rendering.  In case of error, it it translated back to its         */
+  /*    original position and the glyph is left untouched.                 */
+  /*                                                                       */
+  /*    The first parameter is a pointer to a FT_Glyph handle, that will   */
+  /*    be replaced by this function.  Typically, you would use (omitting  */
+  /*    error handling):                                                   */
+  /*                                                                       */
+  /*                                                                       */
+  /*      {                                                                */
+  /*        FT_Glyph        glyph;                                         */
+  /*        FT_BitmapGlyph  glyph_bitmap;                                  */
+  /*                                                                       */
+  /*                                                                       */
+  /*        // load glyph                                                  */
+  /*        error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT );     */
+  /*                                                                       */
+  /*        // extract glyph image                                         */
+  /*        error = FT_Get_Glyph( face->glyph, &glyph );                   */
+  /*                                                                       */
+  /*        // convert to a bitmap (default render mode + destroy old)     */
+  /*        if ( glyph->format != ft_glyph_format_bitmap )                 */
+  /*        {                                                              */
+  /*          error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default,  */
+  /*                                      0, 1 );                          */
+  /*          if ( error ) // glyph unchanged                              */
+  /*            ...                                                        */
+  /*        }                                                              */
+  /*                                                                       */
+  /*        // access bitmap content by typecasting                        */
+  /*        glyph_bitmap = (FT_BitmapGlyph)glyph;                          */
+  /*                                                                       */
+  /*        // do funny stuff with it, like blitting/drawing               */
+  /*        ...                                                            */
+  /*                                                                       */
+  /*        // discard glyph image (bitmap or not)                         */
+  /*        FT_Done_Glyph( glyph );                                        */
+  /*      }                                                                */
+  /*                                                                       */
+  /*                                                                       */
+  /*    This function will always fail if the glyph's format isn't         */
+  /*    scalable.                                                          */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Glyph_To_Bitmap( FT_Glyph*   the_glyph,
+                                                  FT_ULong    render_mode,
+                                                  FT_Vector*  origin,
+                                                  FT_Bool     destroy )
+  {
+    FT_GlyphSlotRec  dummy;
+    FT_Error         error;
+    FT_Glyph         glyph;
+    FT_BitmapGlyph   bitmap;
+
+    const FT_Glyph_Class*  clazz;
+
+
+    /* check argument */
+    if ( !the_glyph )
+      goto Bad;
+
+    /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
+    /* then calling FT_Render_Glyph_Internal()                            */
+
+    glyph = *the_glyph;
+    if ( !glyph )
+      goto Bad;
+
+    clazz = glyph->clazz;
+    if ( !clazz || !clazz->glyph_prepare )
+      goto Bad;
+
+    MEM_Set( &dummy, 0, sizeof ( dummy ) );
+    dummy.library = glyph->library;
+    dummy.format  = clazz->glyph_format;
+
+    /* if `origin' is set, translate the glyph image */
+    if ( origin )
+      FT_Glyph_Transform( glyph, 0, origin );
+
+    /* create result bitmap glyph */
+    error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
+                          (FT_Glyph*)&bitmap );
+    if ( error )
+      goto Exit;
+
+    /* prepare dummy slot for rendering */
+    error = clazz->glyph_prepare( glyph, &dummy ) ||
+            FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
+
+    if ( !destroy && origin )
+    {
+      FT_Vector  v;
+
+
+      v.x = -origin->x;
+      v.y = -origin->y;
+      FT_Glyph_Transform( glyph, 0, &v );
+    }
+
+    /* in case of succes, copy the bitmap to the glyph bitmap */
+    if ( !error )
+    {
+      error = ft_bitmap_glyph_init( bitmap, &dummy );
+      if ( error )
+      {
+        /* this should never happen, but let's be safe */
+        FT_Done_Glyph( FT_GLYPH( bitmap ) );
+        goto Exit;
+      }
+
+      if ( destroy )
+        FT_Done_Glyph( glyph );
+
+      *the_glyph = FT_GLYPH( bitmap );
+    }
+
+  Exit:
+    return error;
+
+  Bad:
+    error = FT_Err_Invalid_Argument;
+    goto Exit;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given glyph.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: A handle to the target glyph object.                      */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Done_Glyph( FT_Glyph  glyph )
+  {
+    if ( glyph )
+    {
+      FT_Memory              memory = glyph->library->memory;
+      const FT_Glyph_Class*  clazz  = glyph->clazz;
+
+
+      if ( clazz->glyph_done )
+        clazz->glyph_done( glyph );
+
+      FREE( glyph );
+    }
+  }
+
+
+#if 0
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT                    ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* Compute the norm of a vector */
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static
+  FT_Pos  ft_norm( FT_Vector*  vec )
+  {
+    FT_Int64  t1, t2;
+
+
+    MUL_64( vec->x, vec->x, t1 );
+    MUL_64( vec->y, vec->y, t2 );
+    ADD_64( t1, t2, t1 );
+
+    return (FT_Pos)SQRT_64( t1 );
+  }
+
+#else /* FT_CONFIG_OPTION_OLD_CALCS */
+
+  static
+  FT_Pos  ft_norm( FT_Vector*  vec )
+  {
+    FT_F26Dot6  u, v, d;
+    FT_Int      shift;
+    FT_ULong    H, L, L2, hi, lo, med;
+
+
+    u = vec->x; if ( u < 0 ) u = -u;
+    v = vec->y; if ( v < 0 ) v = -v;
+
+    if ( u < v )
+    {
+      d = u;
+      u = v;
+      v = d;
+    }
+
+    /* check that we are not trying to normalize zero! */
+    if ( u == 0 )
+      return 0;
+
+    /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
+    hi  = (FT_ULong)u >> 16;
+    lo  = (FT_ULong)u & 0xFFFF;
+    med = hi * lo;
+
+    H     = hi * hi + ( med >> 15 );
+    med <<= 17;
+    L     = lo * lo + med;
+    if ( L < med )
+      H++;
+
+    hi  = (FT_ULong)v >> 16;
+    lo  = (FT_ULong)v & 0xFFFF;
+    med = hi * lo;
+
+    H    += hi * hi + ( med >> 15 );
+    med <<= 17;
+    L2    = lo * lo + med;
+    if ( L2 < med )
+      H++;
+
+    L += L2;
+    if ( L < L2 )
+      H++;
+
+    /* if the value is smaller than 32 bits */
+    shift = 0;
+    if ( H == 0 )
+    {
+      while ( ( L & 0xC0000000UL ) == 0 )
+      {
+        L <<= 2;
+        shift++;
+      }
+      return ( FT_Sqrt32( L ) >> shift );
+    }
+    else
+    {
+      while ( H )
+      {
+        L   = ( L >> 2 ) | ( H << 30 );
+        H >>= 2;
+        shift++;
+      }
+      return ( FT_Sqrt32( L ) << shift );
+    }
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  static
+  int  ft_test_extrema( FT_Outline*  outline,
+                        int          n )
+  {
+    FT_Vector  *prev, *cur, *next;
+    FT_Pos      product;
+    FT_Int      first, last;
+
+
+    /* we need to compute the `previous' and `next' point */
+    /* for these extrema.                                 */
+    cur   = outline->points + n;
+    prev  = cur - 1;
+    next  = cur + 1;
+
+    first = 0;
+    for ( c = 0; c < outline->n_contours; c++ )
+    {
+      last  = outline->contours[c];
+
+      if ( n == first )
+        prev = outline->points + last;
+
+      if ( n == last )
+        next = outline->points + first;
+
+      first = last + 1;
+    }
+
+    product = FT_MulDiv( cur->x - prev->x,   /* in.x  */
+                         next->y - cur->y,   /* out.y */
+                         0x40 )
+              -
+              FT_MulDiv( cur->y - prev->y,   /* in.y  */
+                         next->x - cur->x,   /* out.x */
+                         0x40 );
+
+    if ( product )
+      product = product > 0 ? 1 : -1;
+
+    return product;
+  }
+
+
+  /* Compute the orientation of path filling.  It differs between TrueType */
+  /* and Type1 formats.  We could use the `ft_outline_reverse_fill' flag,  */
+  /* but it is better to re-compute it directly (it seems that this flag   */
+  /* isn't correctly set for some weird composite glyphs currently).       */
+  /*                                                                       */
+  /* We do this by computing bounding box points, and computing their      */
+  /* curvature.                                                            */
+  /*                                                                       */
+  /* The function returns either 1 or -1.                                  */
+  /*                                                                       */
+  static
+  int  ft_get_orientation( FT_Outline*  outline )
+  {
+    FT_BBox  box;
+    FT_BBox  indices;
+    int      n, last;
+
+
+    indices.xMin = -1;
+    indices.yMin = -1;
+    indices.xMax = -1;
+    indices.yMax = -1;
+
+    box.xMin = box.yMin = 32767;
+    box.xMax = box.yMax = -32768;
+
+    /* is it empty ? */
+    if ( outline->n_contours < 1 )
+      return 1;
+
+    last = outline->contours[outline->n_contours - 1];
+
+    for ( n = 0; n <= last; n++ )
+    {
+      FT_Pos  x, y;
+
+
+      x = outline->points[n].x;
+      if ( x < box.xMin )
+      {
+        box.xMin     = x;
+        indices.xMin = n;
+      }
+      if ( x > box.xMax )
+      {
+        box.xMax     = x;
+        indices.xMax = n;
+      }
+
+      y = outline->points[n].y;
+      if ( y < box.yMin )
+      {
+        box.yMin     = y;
+        indices.yMin = n;
+      }
+      if ( y > box.yMax )
+      {
+        box.yMax     = y;
+        indices.yMax = n;
+      }
+    }
+
+    /* test orientation of the xmin */
+    return ft_test_extrema( outline, indices.xMin ) ||
+           ft_test_extrema( outline, indices.yMin ) ||
+           ft_test_extrema( outline, indices.xMax ) ||
+           ft_test_extrema( outline, indices.yMax ) ||
+           1;  /* this is an empty glyph? */
+  }
+
+
+  static
+  FT_Error  ft_embolden( FT_Face      original,
+                         FT_Outline*  outline,
+                         FT_Pos*      advance )
+  {
+    FT_Vector  u, v;
+    FT_Vector* points;
+    FT_Vector  cur, prev, next;
+    FT_Pos     distance;
+    int        c, n, first, orientation;
+
+    FT_UNUSED( advance );
+
+
+    /* compute control distance */
+    distance = FT_MulFix( original->em_size / 60,
+                          original->size->metrics.y_scale );
+
+    orientation = ft_get_orientation( &original->glyph->outline );
+
+    points = original->glyph->outline.points;
+
+    first = 0;
+    for ( c = 0; c < outline->n_contours; c++ )
+    {
+      int  last = outline->contours[c];
+
+
+      prev = points[last];
+
+      for ( n = first; n <= last; n++ )
+      {
+        FT_Pos     norm, delta, d;
+        FT_Vector  in, out;
+
+
+        cur = points[n];
+        if ( n < last ) next = points[n + 1];
+        else            next = points[first];
+
+        /* compute the in and out vectors */
+        in.x  = cur.x - prev.x;
+        in.y  = cur.y - prev.y;
+
+        out.x = next.x - cur.x;
+        out.y = next.y - cur.y;
+
+        /* compute U and V */
+        norm = ft_norm( &in );
+        u.x = orientation *  FT_DivFix( in.y, norm );
+        u.y = orientation * -FT_DivFix( in.x, norm );
+
+        norm = ft_norm( &out );
+        v.x = orientation *  FT_DivFix( out.y, norm );
+        v.y = orientation * -FT_DivFix( out.x, norm );
+
+        d = distance;
+
+        if ( ( outline->flags[n] & FT_Curve_Tag_On ) == 0 )
+          d *= 2;
+
+        /* Check discriminant for parallel vectors */
+        delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x );
+        if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD )
+        {
+          /* Move point -- compute A and B */
+          FT_Pos  x, y, A, B;
+
+
+          A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y );
+          B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y );
+
+          x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y );
+          y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x );
+
+          outline->points[n].x = distance + FT_DivFix( x, delta );
+          outline->points[n].y = distance + FT_DivFix( y, delta );
+        }
+        else
+        {
+          /* Vectors are nearly parallel */
+          FT_Pos  x, y;
+
+
+          x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2;
+          y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2;
+
+          outline->points[n].x = x;
+          outline->points[n].y = y;
+        }
+
+        prev = cur;
+      }
+
+      first = last + 1;
+    }
+
+    if ( advance )
+      *advance = ( *advance + distance * 4 ) & -64;
+
+    return 0;
+  }
+
+#endif /* 0 -- EXPERIMENTAL STUFF! */
+
+
+/* END */
diff --git a/src/freetype/base/ftinit.c b/src/freetype/base/ftinit.c
new file mode 100644 (file)
index 0000000..cc754eb
--- /dev/null
@@ -0,0 +1,155 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftinit.c                                                               */
+/*                                                                         */
+/*    FreeType initialization layer (body).                                */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  The purpose of this file is to implement the following two           */
+  /*  functions:                                                           */
+  /*                                                                       */
+  /*  FT_Add_Default_Modules():                                            */
+  /*     This function is used to add the set of default modules to a      */
+  /*     fresh new library object.  The set is taken from the header file  */
+  /*     `freetype/config/ftmodule.h'.  See the document `FreeType 2.0     */
+  /*     Build System' for more information.                               */
+  /*                                                                       */
+  /*  FT_Init_FreeType():                                                  */
+  /*     This function creates a system object for the current platform,   */
+  /*     builds a library out of it, then calls FT_Default_Drivers().      */
+  /*                                                                       */
+  /*  Note that even if FT_Init_FreeType() uses the implementation of the  */
+  /*  system object defined at build time, client applications are still   */
+  /*  able to provide their own `ftsystem.c'.                              */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftmodule.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_init
+
+#undef  FT_USE_MODULE
+#define FT_USE_MODULE( x )  extern const FT_Module_Class*  x;
+
+#ifdef macintosh
+    FT_USE_MODULE(fond_driver_class)
+#endif
+#include <freetype/config/ftmodule.h>
+
+#undef  FT_USE_MODULE
+#define FT_USE_MODULE( x )  (const FT_Module_Class*)&x,
+
+static
+const FT_Module_Class*  ft_default_modules[] =
+  {
+#ifdef macintosh
+    FT_USE_MODULE(fond_driver_class)
+#endif
+#include <freetype/config/ftmodule.h>
+    0
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add_Default_Modules                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds the set of default drivers to a given library object.         */
+  /*    This is only useful when you create a library object with          */
+  /*    FT_New_Library() (usually to plug a custom memory manager).        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library :: A handle to a new library object.                       */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Add_Default_Modules( FT_Library  library )
+  {
+    FT_Error                 error;
+    const FT_Module_Class**  cur;
+
+
+    /* test for valid `library' delayed to FT_Add_Module() */
+
+    cur = ft_default_modules;
+    while ( *cur )
+    {
+      error = FT_Add_Module( library, *cur );
+      /* notify errors, but don't stop */
+      if ( error )
+      {
+        FT_ERROR(( "FT_Add_Default_Module: Cannot install `%s', error = %x\n",
+                   (*cur)->module_name, error ));
+      }
+      cur++;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Init_FreeType                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a new FreeType library object.  The set of drivers     */
+  /*    that are registered by this function is determined at build time.  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    library :: A handle to a new library object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Init_FreeType( FT_Library*  library )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+
+
+    /* First of all, allocate a new system object -- this function is part */
+    /* of the system-specific component, i.e. `ftsystem.c'.                */
+
+    memory = FT_New_Memory();
+    if ( !memory )
+    {
+      FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));
+      return FT_Err_Unimplemented_Feature;
+    }
+
+    /* build a library out of it, then fill it with the set of */
+    /* default drivers.                                        */
+
+    error = FT_New_Library( memory, library );
+    if ( !error )
+      FT_Add_Default_Modules( *library );
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/base/ftlist.c b/src/freetype/base/ftlist.c
new file mode 100644 (file)
index 0000000..0158ba4
--- /dev/null
@@ -0,0 +1,301 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftlist.c                                                               */
+/*                                                                         */
+/*    Generic list support for FreeType (body).                            */
+/*                                                                         */
+/*  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 implements functions relative to list processing.  Its     */
+  /*  data structures are defined in `freetype/internal/ftlist.h'.         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftlist.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_list
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Find                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds the list node for a given listed object.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*    data :: The address of the listed object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    List node.  NULL if it wasn't found.                               */
+  /*                                                                       */
+  BASE_FUNC( FT_ListNode )  FT_List_Find( FT_List  list,
+                                          void*    data )
+  {
+    FT_ListNode  cur;
+
+
+    cur = list->head;
+    while ( cur )
+    {
+      if ( cur->data == data )
+        return cur;
+
+      cur = cur->next;
+    }
+
+    return (FT_ListNode)0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Add                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Appends an element to the end of a list.                           */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*    node :: The node to append.                                        */
+  /*                                                                       */
+  BASE_FUNC( void )  FT_List_Add( FT_List      list,
+                                  FT_ListNode  node )
+  {
+    FT_ListNode  before = list->tail;
+
+
+    node->next = 0;
+    node->prev = before;
+
+    if ( before )
+      before->next = node;
+    else
+      list->head = node;
+
+    list->tail = node;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Insert                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inserts an element at the head of a list.                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to parent list.                                  */
+  /*    node :: The node to insert.                                        */
+  /*                                                                       */
+  BASE_FUNC( void )  FT_List_Insert( FT_List      list,
+                                     FT_ListNode  node )
+  {
+    FT_ListNode  after = list->head;
+
+
+    node->next = after;
+    node->prev = 0;
+
+    if ( !after )
+      list->tail = node;
+    else
+      after->prev = node;
+
+    list->head = node;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Remove                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Removes a node from a list.  This function doesn't check whether   */
+  /*    the node is in the list!                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    node :: The node to remove.                                        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*                                                                       */
+  BASE_FUNC( void )  FT_List_Remove( FT_List      list,
+                                     FT_ListNode  node )
+  {
+    FT_ListNode  before, after;
+
+
+    before = node->prev;
+    after  = node->next;
+
+    if ( before )
+      before->next = after;
+    else
+      list->head = after;
+
+    if ( after )
+      after->prev = before;
+    else
+      list->tail = before;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Up                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Moves a node to the head/top of a list.  Used to maintain LRU      */
+  /*    lists.                                                             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*    node :: The node to move.                                          */
+  /*                                                                       */
+  BASE_FUNC( void )  FT_List_Up( FT_List      list,
+                                 FT_ListNode  node )
+  {
+    FT_ListNode  before, after;
+
+
+    before = node->prev;
+    after  = node->next;
+
+    /* check whether we are already on top of the list */
+    if ( !before )
+      return;
+
+    before->next = after;
+
+    if ( after )
+      after->prev = before;
+    else
+      list->tail = before;
+
+    node->prev       = 0;
+    node->next       = list->head;
+    list->head->prev = node;
+    list->head       = node;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Iterate                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a list and calls a given iterator function on each element. */
+  /*    Note that parsing is stopped as soon as one of the iterator calls  */
+  /*    returns a non-zero value.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    list     :: A handle to the list.                                  */
+  /*    iterator :: An interator function, called on each node of the      */
+  /*                list.                                                  */
+  /*    user     :: A user-supplied field which is passed as the second    */
+  /*                argument to the iterator.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result (a FreeType error code) of the last iterator call.      */
+  /*                                                                       */
+  BASE_FUNC( FT_Error )  FT_List_Iterate( FT_List            list,
+                                          FT_List_Iterator   iterator,
+                                          void*              user )
+  {
+    FT_ListNode  cur   = list->head;
+    FT_Error     error = FT_Err_Ok;
+
+
+    while ( cur )
+    {
+      FT_ListNode  next = cur->next;
+
+
+      error = iterator( cur, user );
+      if ( error )
+        break;
+
+      cur = next;
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Finalize                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys all elements in the list as well as the list itself.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    list    :: A handle to the list.                                   */
+  /*                                                                       */
+  /*    destroy :: A list destructor that will be applied to each element  */
+  /*               of the list.                                            */
+  /*                                                                       */
+  /*    memory  :: The current memory object which handles deallocation.   */
+  /*                                                                       */
+  /*    user    :: A user-supplied field which is passed as the last       */
+  /*               argument to the destructor.                             */
+  /*                                                                       */
+  BASE_FUNC( void )  FT_List_Finalize( FT_List             list,
+                                       FT_List_Destructor  destroy,
+                                       FT_Memory           memory,
+                                       void*               user )
+  {
+    FT_ListNode  cur;
+
+
+    cur = list->head;
+    while ( cur )
+    {
+      FT_ListNode  next = cur->next;
+      void*        data = cur->data;
+
+
+      if ( destroy )
+        destroy( memory, data, user );
+
+      FREE( cur );
+      cur = next;
+    }
+
+    list->head = 0;
+    list->tail = 0;
+  }
+
+
+/* END */
diff --git a/src/freetype/base/ftmm.c b/src/freetype/base/ftmm.c
new file mode 100644 (file)
index 0000000..0f6fdde
--- /dev/null
@@ -0,0 +1,176 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmm.c                                                                 */
+/*                                                                         */
+/*    Multiple Master font support (body).                                 */
+/*                                                                         */
+/*  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 <freetype/ftmm.h>
+#include <freetype/internal/ftobjs.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_mm
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Multi_Master                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the Multiple Master descriptor of a given font.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the source face.                             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    master :: The Multiple Masters descriptor.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Get_Multi_Master( FT_Face           face,
+                                                   FT_Multi_Master*  master )
+  {
+    FT_Error  error;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    error = FT_Err_Invalid_Argument;
+
+    if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+    {
+      FT_Driver       driver = face->driver;
+      FT_Get_MM_Func  func;
+
+
+      func = (FT_Get_MM_Func)driver->root.clazz->get_interface(
+                               FT_MODULE( driver ), "get_mm" );
+      if ( func )
+        error = func( face, master );
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_MM_Design_Coordinates                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Masters fonts, choose an interpolated font design     */
+  /*    through design coordinates.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /*    num_coords :: The number of design coordinates (must be equal to   */
+  /*                  the number of axes in the font).                     */
+  /*                                                                       */
+  /*    coords     :: The design coordinates.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Set_MM_Design_Coordinates(
+                                FT_Face   face,
+                                FT_UInt   num_coords,
+                                FT_Long*  coords )
+  {
+    FT_Error  error;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    error = FT_Err_Invalid_Argument;
+
+    if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+    {
+      FT_Driver              driver = face->driver;
+      FT_Set_MM_Design_Func  func;
+
+
+      func = (FT_Set_MM_Design_Func)driver->root.clazz->get_interface(
+                                      FT_MODULE( driver ), "set_mm_design" );
+      if ( func )
+        error = func( face, num_coords, coords );
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_MM_Blend_Coordinates                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Masters fonts, choose an interpolated font design     */
+  /*    through normalized blend coordinates.                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /*    num_coords :: The number of design coordinates (must be equal to   */
+  /*                  the number of axes in the font).                     */
+  /*                                                                       */
+  /*    coords     :: The design coordinates (each one must be between 0   */
+  /*                  and 1.0).                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Set_MM_Blend_Coordinates(
+                                FT_Face    face,
+                                FT_UInt    num_coords,
+                                FT_Fixed*  coords )
+  {
+    FT_Error  error;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    error = FT_Err_Invalid_Argument;
+
+    if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+    {
+      FT_Driver             driver = face->driver;
+      FT_Set_MM_Blend_Func  func;
+
+
+      func = (FT_Set_MM_Blend_Func)driver->root.clazz->get_interface(
+                                     FT_MODULE( driver ), "set_mm_blend" );
+      if ( func )
+        error = func( face, num_coords, coords );
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/base/ftnames.c b/src/freetype/base/ftnames.c
new file mode 100644 (file)
index 0000000..43a0d12
--- /dev/null
@@ -0,0 +1,70 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftnames.c                                                              */
+/*                                                                         */
+/*    Simple interface to access SFNT name tables (which are used          */
+/*    to hold font names, copyright info, notices, etc.).                  */
+/*                                                                         */
+/*    This is _not_ used to retrieve glyph names!                          */
+/*                                                                         */
+/*  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 <freetype/ftnames.h>
+#include <freetype/internal/tttypes.h>
+
+
+#ifdef FT_CONFIG_OPTION_SFNT_NAMES
+
+
+  FT_EXPORT_FUNC( FT_UInt )  FT_Get_Sfnt_Name_Count( FT_Face  face )
+  {
+    return face && ( FT_IS_SFNT( face ) ? ((TT_Face)face)->num_names : 0 );
+  }
+  
+  
+  FT_EXPORT_FUNC( FT_Error ) FT_Get_Sfnt_Name( FT_Face       face,
+                                               FT_UInt       index,
+                                               FT_SfntName*  aname )
+  {
+    FT_Error  error = FT_Err_Invalid_Argument;
+    
+
+    if ( aname && face && FT_IS_SFNT( face ) )
+    {
+      TT_Face  ttface = (TT_Face)face;
+      
+
+      if ( index < ttface->num_names )
+      {
+        TT_NameRec*  name = ttface->name_table.names + index;
+        
+
+        aname->platform_id = name->platformID;
+        aname->encoding_id = name->encodingID;
+        aname->language_id = name->languageID;
+        aname->name_id     = name->nameID;
+        aname->string      = (FT_Byte*)name->string;
+        aname->string_len  = name->stringLength;
+        
+        error = FT_Err_Ok;
+      }
+    }
+    
+    return error;
+  }                                             
+
+
+#endif /* FT_CONFIG_OPTION_SFNT_NAMES */
+
+
+/* END */
diff --git a/src/freetype/base/ftobjs.c b/src/freetype/base/ftobjs.c
new file mode 100644 (file)
index 0000000..de74882
--- /dev/null
@@ -0,0 +1,3246 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftobjs.c                                                               */
+/*                                                                         */
+/*    The FreeType private base classes (body).                            */
+/*                                                                         */
+/*  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 <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftlist.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+#include <freetype/tttables.h>
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           M E M O R Y                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_memory
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Alloc                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Allocates a new block of memory.  The returned area is always      */
+  /*    zero-filled; this is a strong convention in many FreeType parts.   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to a given `memory object' which handles        */
+  /*              allocation.                                              */
+  /*                                                                       */
+  /*    size   :: The size in bytes of the block to allocate.              */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    P      :: A pointer to the fresh new block.  It should be set to   */
+  /*              NULL if `size' is 0, or in case of error.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  BASE_FUNC( FT_Error )  FT_Alloc( FT_Memory  memory,
+                                   FT_Long    size,
+                                   void**     P )
+  {
+    FT_Assert( P != 0 );
+
+    if ( size > 0 )
+    {
+      *P = memory->alloc( memory, size );
+      if ( !*P )
+      {
+        FT_ERROR(( "FT_Alloc:" ));
+        FT_ERROR(( " Out of memory? (%ld requested)\n",
+                   size ));
+
+        return FT_Err_Out_Of_Memory;
+      }
+      MEM_Set( *P, 0, size );
+    }
+    else
+      *P = NULL;
+
+    FT_TRACE7(( "FT_Alloc:" ));
+    FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
+                size, *P, P ));
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Realloc                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reallocates a block of memory pointed to by `*P' to `Size' bytes   */
+  /*    from the heap, possibly changing `*P'.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory  :: A handle to a given `memory object' which handles       */
+  /*               reallocation.                                           */
+  /*                                                                       */
+  /*    current :: The current block size in bytes.                        */
+  /*                                                                       */
+  /*    size    :: The new block size in bytes.                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    P       :: A pointer to the fresh new block.  It should be set to  */
+  /*               NULL if `size' is 0, or in case of error.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    All callers of FT_Realloc() _must_ provide the current block size  */
+  /*    as well as the new one.                                            */
+  /*                                                                       */
+  BASE_FUNC( FT_Error )  FT_Realloc( FT_Memory  memory,
+                                     FT_Long    current,
+                                     FT_Long    size,
+                                     void**     P )
+  {
+    void*  Q;
+
+
+    FT_Assert( P != 0 );
+
+    /* if the original pointer is NULL, call FT_Alloc() */
+    if ( !*P )
+      return FT_Alloc( memory, size, P );
+
+    /* if the new block if zero-sized, clear the current one */
+    if ( size <= 0 )
+    {
+      FT_Free( memory, P );
+      return FT_Err_Ok;
+    }
+
+    Q = memory->realloc( memory, current, size, *P );
+    if ( !Q )
+      goto Fail;
+
+    *P = Q;
+    return FT_Err_Ok;
+
+  Fail:
+    FT_ERROR(( "FT_Realloc:" ));
+    FT_ERROR(( " Failed (current %ld, requested %ld)\n",
+               current, size ));
+    return FT_Err_Out_Of_Memory;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Free                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Releases a given block of memory allocated through FT_Alloc().     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to a given `memory object' which handles        */
+  /*              memory deallocation                                      */
+  /*                                                                       */
+  /*    P      :: This is the _address_ of a _pointer_ which points to the */
+  /*              allocated block.  It is always set to NULL on exit.      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If P or *P are NULL, this function should return successfully.     */
+  /*    This is a strong convention within all of FreeType and its         */
+  /*    drivers.                                                           */
+  /*                                                                       */
+  BASE_FUNC( void )  FT_Free( FT_Memory  memory,
+                              void**     P )
+  {
+    FT_TRACE7(( "FT_Free:" ));
+    FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
+                P, P ? *P : (void*)0 ));
+
+    if ( P && *P )
+    {
+      memory->free( memory, *P );
+      *P = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           S T R E A M                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_new_input_stream                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new input stream object from an FT_Open_Args structure.  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function expects a valid `astream' parameter.                  */
+  /*                                                                       */
+  static
+  FT_Error  ft_new_input_stream( FT_Library     library,
+                                 FT_Open_Args*  args,
+                                 FT_Stream*     astream )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+    FT_Stream  stream;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !args )
+      return FT_Err_Invalid_Argument;
+
+    *astream = 0;
+    memory   = library->memory;
+    if ( ALLOC( stream, sizeof ( *stream ) ) )
+      goto Exit;
+
+    stream->memory = memory;
+
+    /* now, look at the stream flags */
+    if ( args->flags & ft_open_memory )
+    {
+      error = 0;
+      FT_New_Memory_Stream( library,
+                            args->memory_base,
+                            args->memory_size,
+                            stream );
+    }
+    else if ( args->flags & ft_open_pathname )
+    {
+      error = FT_New_Stream( args->pathname, stream );
+      stream->pathname.pointer = args->pathname;
+    }
+    else if ( args->flags & ft_open_stream && args->stream )
+    {
+      *stream        = *(args->stream);
+      stream->memory = memory;
+    }
+    else
+      error = FT_Err_Invalid_Argument;
+
+    if ( error )
+      FREE( stream );
+
+    *astream = stream;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Stream                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Closes and destroys a stream object.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: The stream to be closed and destroyed.                   */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Done_Stream( FT_Stream  stream )
+  {
+    if ( stream && stream->close )
+      stream->close( stream );
+  }
+
+
+  static
+  void  ft_done_stream( FT_Stream*  astream )
+  {
+    FT_Stream  stream = *astream;
+    FT_Memory  memory = stream->memory;
+
+
+    if ( stream->close )
+      stream->close( stream );
+
+    FREE( stream );
+    *astream = 0;
+  }
+
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_objs
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                     G L Y P H   L O A D E R                     ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The glyph loader is a simple object which is used to load a set of    */
+  /* glyphs easily.  It is critical for the correct loading of composites. */
+  /*                                                                       */
+  /* Ideally, one can see it as a stack of abstract `glyph' objects.       */
+  /*                                                                       */
+  /*   loader.base     Is really the bottom of the stack.  It describes a  */
+  /*                   single glyph image made of the juxtaposition of     */
+  /*                   several glyphs (those `in the stack').              */
+  /*                                                                       */
+  /*   loader.current  Describes the top of the stack, on which a new      */
+  /*                   glyph can be loaded.                                */
+  /*                                                                       */
+  /*   Rewind          Clears the stack.                                   */
+  /*   Prepare         Set up `loader.current' for addition of a new glyph */
+  /*                   image.                                              */
+  /*   Add             Add the `current' glyph image to the `base' one,    */
+  /*                   and prepare for another one.                        */
+  /*                                                                       */
+  /* The glyph loader is now a base object.  Each driver used to           */
+  /* re-implement it in one way or the other, which wasted code and        */
+  /* energy.                                                               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* create a new glyph loader */
+  BASE_FUNC( FT_Error )  FT_GlyphLoader_New( FT_Memory         memory,
+                                             FT_GlyphLoader**  aloader )
+  {
+    FT_GlyphLoader*  loader;
+    FT_Error         error;
+
+
+    if ( !ALLOC( loader, sizeof ( *loader ) ) )
+    {
+      loader->memory = memory;
+      *aloader       = loader;
+    }
+    return error;
+  }
+
+
+  /* rewind the glyph loader - reset counters to 0 */
+  BASE_FUNC( void )  FT_GlyphLoader_Rewind( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad*  base    = &loader->base;
+    FT_GlyphLoad*  current = &loader->current;
+
+
+    base->outline.n_points   = 0;
+    base->outline.n_contours = 0;
+    base->num_subglyphs      = 0;
+
+    *current = *base;
+  }
+
+
+  /* reset the glyph loader, frees all allocated tables */
+  /* and starts from zero                               */
+  BASE_FUNC( void )  FT_GlyphLoader_Reset( FT_GlyphLoader*  loader )
+  {
+    FT_Memory memory = loader->memory;
+
+
+    FREE( loader->base.outline.points );
+    FREE( loader->base.outline.tags );
+    FREE( loader->base.outline.contours );
+    FREE( loader->base.extra_points );
+    FREE( loader->base.subglyphs );
+
+    loader->max_points    = 0;
+    loader->max_contours  = 0;
+    loader->max_subglyphs = 0;
+
+    FT_GlyphLoader_Rewind( loader );
+  }
+
+
+  /* delete a glyph loader */
+  BASE_FUNC( void )  FT_GlyphLoader_Done( FT_GlyphLoader*  loader )
+  {
+    if ( loader )
+    {
+      FT_Memory memory = loader->memory;
+
+
+      FT_GlyphLoader_Reset( loader );
+      FREE( loader );
+    }
+  }
+
+
+  /* re-adjust the `current' outline fields */
+  static
+  void  FT_GlyphLoader_Adjust_Points( FT_GlyphLoader*  loader )
+  {
+    FT_Outline*  base    = &loader->base.outline;
+    FT_Outline*  current = &loader->current.outline;
+
+
+    current->points   = base->points   + base->n_points;
+    current->tags     = base->tags     + base->n_points;
+    current->contours = base->contours + base->n_contours;
+
+    /* handle extra points table - if any */
+    if ( loader->use_extra )
+      loader->current.extra_points =
+        loader->base.extra_points + base->n_points;
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_GlyphLoader_Create_Extra(
+                           FT_GlyphLoader*  loader )
+  {
+    FT_Error   error;
+    FT_Memory  memory = loader->memory;
+
+
+    if ( !ALLOC_ARRAY( loader->base.extra_points,
+                       loader->max_points, FT_Vector ) )
+    {
+      loader->use_extra = 1;
+      FT_GlyphLoader_Adjust_Points( loader );
+    }
+    return error;
+  }
+
+
+  /* re-adjust the `current' subglyphs field */
+  static
+  void  FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad* base    = &loader->base;
+    FT_GlyphLoad* current = &loader->current;
+
+
+    current->subglyphs = base->subglyphs + base->num_subglyphs;
+  }
+
+
+  /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
+  /* function reallocates its outline tables if necessary.  Note that it   */
+  /* DOESN'T change the number of points within the loader!                */
+  /*                                                                       */
+  BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Points(
+                          FT_GlyphLoader*  loader,
+                          FT_UInt          n_points,
+                          FT_UInt          n_contours )
+  {
+    FT_Memory    memory  = loader->memory;
+    FT_Error     error   = FT_Err_Ok;
+    FT_Outline*  base    = &loader->base.outline;
+    FT_Outline*  current = &loader->current.outline;
+    FT_Bool      adjust  = 1;
+
+    FT_UInt      new_max;
+
+
+    /* check points & tags */
+    new_max = base->n_points + current->n_points + n_points;
+    if ( new_max > loader->max_points )
+    {
+      new_max = ( new_max + 7 ) & -8;
+      if ( REALLOC_ARRAY( base->points, base->n_points,
+                          new_max, FT_Vector )          ||
+           REALLOC_ARRAY( base->tags, base->n_points,
+                          new_max, FT_Byte   )          )
+       goto Exit;
+
+      if ( loader->use_extra &&
+           REALLOC_ARRAY( loader->base.extra_points, base->n_points,
+                          new_max, FT_Vector ) )
+       goto Exit;
+
+      adjust = 1;
+      loader->max_points = new_max;
+    }
+
+    /* check contours */
+    new_max = base->n_contours + current->n_contours +
+              n_contours;
+    if ( new_max > loader->max_contours )
+    {
+      new_max = ( new_max + 3 ) & -4;
+      if ( REALLOC_ARRAY( base->contours, base->n_contours,
+                          new_max, FT_Short ) )
+        goto Exit;
+
+      adjust = 1;
+      loader->max_contours = new_max;
+    }
+
+    if ( adjust )
+      FT_GlyphLoader_Adjust_Points( loader );
+
+  Exit:
+    return error;
+  }
+
+
+  /* Ensure that we can add `n_subglyphs' to our glyph. this function */
+  /* reallocates its subglyphs table if necessary.  Note that it DOES */
+  /* NOT change the number of subglyphs within the loader!            */
+  /*                                                                  */
+  BASE_FUNC( FT_Error )  FT_GlyphLoader_Check_Subglyphs(
+                           FT_GlyphLoader*  loader,
+                           FT_UInt          n_subs )
+  {
+    FT_Memory  memory = loader->memory;
+    FT_Error   error  = FT_Err_Ok;
+    FT_UInt    new_max;
+
+    FT_GlyphLoad*  base    = &loader->base;
+    FT_GlyphLoad*  current = &loader->current;
+
+
+    new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
+    if ( new_max > loader->max_subglyphs )
+    {
+      new_max = ( new_max + 1 ) & -2;
+      if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs,
+                          new_max, FT_SubGlyph ) )
+        goto Exit;
+
+      loader->max_subglyphs = new_max;
+
+      FT_GlyphLoader_Adjust_Subglyphs( loader );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* prepare loader for the addition of a new glyph on top of the base one */
+  BASE_FUNC( void )  FT_GlyphLoader_Prepare( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad*  current = &loader->current;
+
+
+    current->outline.n_points   = 0;
+    current->outline.n_contours = 0;
+    current->num_subglyphs      = 0;
+
+    FT_GlyphLoader_Adjust_Points   ( loader );
+    FT_GlyphLoader_Adjust_Subglyphs( loader );
+  }
+
+
+  /* add current glyph to the base image - and prepare for another */
+  BASE_FUNC( void )  FT_GlyphLoader_Add( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad*  base    = &loader->base;
+    FT_GlyphLoad*  current = &loader->current;
+
+    FT_UInt        n_curr_contours = current->outline.n_contours;
+    FT_UInt        n_base_points   = base->outline.n_points;
+    FT_UInt        n;
+
+
+    base->outline.n_points   += current->outline.n_points;
+    base->outline.n_contours += current->outline.n_contours;
+    base->num_subglyphs      += current->num_subglyphs;
+
+    /* adjust contours count in newest outline */
+    for ( n = 0; n < n_curr_contours; n++ )
+      current->outline.contours[n] += n_base_points;
+
+    /* prepare for another new glyph image */
+    FT_GlyphLoader_Prepare( loader );
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_GlyphLoader_Copy_Points( FT_GlyphLoader*  target,
+                                                     FT_GlyphLoader*  source )
+  {
+    FT_Error  error;
+    FT_UInt   num_points   = source->base.outline.n_points;
+    FT_UInt   num_contours = source->base.outline.n_contours;
+
+
+    error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
+    if ( !error )
+    {
+      FT_Outline*  out = &target->base.outline;
+      FT_Outline*  in  = &source->base.outline;
+
+
+      MEM_Copy( out->points, in->points,
+                num_points * sizeof ( FT_Vector ) );
+      MEM_Copy( out->tags, in->tags,
+                num_points * sizeof ( char ) );
+      MEM_Copy( out->contours, in->contours,
+                num_contours * sizeof ( short ) );
+
+      /* do we need to copy the extra points? */
+      if ( target->use_extra && source->use_extra )
+        MEM_Copy( target->base.extra_points, source->base.extra_points,
+                  num_points * sizeof ( FT_Vector ) );
+
+      out->n_points   = num_points;
+      out->n_contours = num_contours;
+
+      FT_GlyphLoader_Adjust_Points( target );
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  ft_glyphslot_init( FT_GlyphSlot  slot )
+  {
+    FT_Driver         driver = slot->face->driver;
+    FT_Driver_Class*  clazz  = driver->clazz;
+    FT_Memory         memory = driver->root.memory;
+    FT_Error          error  = FT_Err_Ok;
+
+
+    slot->library = driver->root.library;
+
+    if ( FT_DRIVER_USES_OUTLINES( driver ) )
+      error = FT_GlyphLoader_New( memory, &slot->loader );
+
+    if ( !error && clazz->init_slot )
+      error = clazz->init_slot( slot );
+
+    return error;
+  }
+
+
+  static
+  void  ft_glyphslot_clear( FT_GlyphSlot  slot )
+  {
+    /* free bitmap if needed */
+    if ( slot->flags & ft_glyph_own_bitmap )
+    {
+      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
+
+
+      FREE( slot->bitmap.buffer );
+      slot->flags &= ~ft_glyph_own_bitmap;
+    }
+
+    /* clear all public fields in the glyph slot */
+    MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
+    MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
+    MEM_Set( &slot->bitmap,  0, sizeof ( slot->bitmap )  );
+
+    slot->bitmap_left   = 0;
+    slot->bitmap_top    = 0;
+    slot->num_subglyphs = 0;
+    slot->subglyphs     = 0;
+    slot->control_data  = 0;
+    slot->control_len   = 0;
+    slot->other         = 0;
+    slot->format        = ft_glyph_format_none;
+
+    slot->linearHoriAdvance = 0;
+    slot->linearVertAdvance = 0;
+  }
+
+
+  static
+  void  ft_glyphslot_done( FT_GlyphSlot  slot )
+  {
+    FT_Driver         driver = slot->face->driver;
+    FT_Driver_Class*  clazz  = driver->clazz;
+    FT_Memory         memory = driver->root.memory;
+
+
+    /* free bitmap buffer if needed */
+    if ( slot->flags & ft_glyph_own_bitmap )
+      FREE( slot->bitmap.buffer );
+
+    /* free glyph loader */
+    if ( FT_DRIVER_USES_OUTLINES( driver ) )
+    {
+      FT_GlyphLoader_Done( slot->loader );
+      slot->loader = 0;
+    }
+
+    if ( clazz->done_slot )
+      clazz->done_slot( slot );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_GlyphSlot                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    It is sometimes useful to have more than one glyph slot for a      */
+  /*    given face object.  This function is used to create additional     */
+  /*    slots.  All of them are automatically discarded when the face is   */
+  /*    destroyed.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face  :: A handle to a parent face object.                         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aslot :: A handle to a new glyph slot object.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_New_GlyphSlot( FT_Face        face,
+                                                FT_GlyphSlot*  aslot )
+  {
+    FT_Error          error;
+    FT_Driver         driver;
+    FT_Driver_Class*  clazz;
+    FT_Memory         memory;
+    FT_GlyphSlot      slot;
+
+
+    if ( !face || !aslot || !face->driver )
+      return FT_Err_Invalid_Argument;
+
+    *aslot = 0;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+    memory = driver->root.memory;
+
+    FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
+    if ( !ALLOC( slot, clazz->slot_object_size ) )
+    {
+      slot->face = face;
+
+      error = ft_glyphslot_init( slot );
+      if ( error )
+      {
+        ft_glyphslot_done( slot );
+        FREE( slot );
+        goto Exit;
+      }
+
+      *aslot = slot;
+    }
+
+  Exit:
+    FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_GlyphSlot                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given glyph slot.  Remember however that all slots are  */
+  /*    automatically destroyed with its parent.  Using this function is   */
+  /*    not always mandatory.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot :: A handle to a target glyph slot.                           */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Done_GlyphSlot( FT_GlyphSlot  slot )
+  {
+    if ( slot )
+    {
+      FT_Driver         driver = slot->face->driver;
+      FT_Memory         memory = driver->root.memory;
+      FT_GlyphSlot*     parent;
+      FT_GlyphSlot      cur;
+
+
+      /* Remove slot from its parent face's list */
+      parent = &slot->face->glyph;
+      cur    = *parent;
+
+      while ( cur )
+      {
+        if ( cur == slot )
+        {
+          *parent = cur->next;
+          ft_glyphslot_done( slot );
+          FREE( slot );
+          break;
+        }
+        cur = cur->next;
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Transform                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to set the transformation that is applied to glyph */
+  /*    images just before they are converted to bitmaps in a glyph slot   */
+  /*    when FT_Render_Glyph() is called.                                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the source face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to the transformation's 2x2 matrix.  Use 0 for */
+  /*              the identity matrix.                                     */
+  /*    delta  :: A pointer to the translation vector.  Use 0 for the null */
+  /*              vector.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The transformation is only applied to scalable image formats after */
+  /*    the glyph has been loaded.  It means that hinting is unaltered by  */
+  /*    the transformation and is performed on the character size given in */
+  /*    the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes().      */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Set_Transform( FT_Face     face,
+                                            FT_Matrix*  matrix,
+                                            FT_Vector*  delta )
+  {
+    if ( !face )
+      return;
+
+    face->transform_flags = 0;
+
+    if ( !matrix )
+    {
+      face->transform_matrix.xx = 0x10000L;
+      face->transform_matrix.xy = 0;
+      face->transform_matrix.yx = 0;
+      face->transform_matrix.yy = 0x10000L;
+      matrix = &face->transform_matrix;
+    }
+    else
+      face->transform_matrix = *matrix;
+
+    /* set transform_flags bit flag 0 if `matrix' isn't the identity */
+    if ( ( matrix->xy | matrix->yx ) ||
+         matrix->xx != 0x10000L      ||
+         matrix->yy != 0x10000L      )
+      face->transform_flags |= 1;
+
+    if ( !delta )
+    {
+      face->transform_delta.x = 0;
+      face->transform_delta.y = 0;
+      delta = &face->transform_delta;
+    }
+    else
+      face->transform_delta = *delta;
+
+    /* set transform_flags bit flag 1 if `delta' isn't the null vector */
+    if ( delta->x | delta->y )
+      face->transform_flags |= 2;
+  }
+
+
+  static FT_Renderer  ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Load_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the target face object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the glyph image is not a bitmap, and if the bit flag            */
+  /*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         */
+  /*    transformed with the information passed to a previous call to      */
+  /*    FT_Set_Transform.                                                  */
+  /*                                                                       */
+  /*    Note that this also transforms the `face.glyph.advance' field, but */
+  /*    *not* the values in `face.glyph.metrics'.                          */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Load_Glyph( FT_Face  face,
+                                             FT_UInt  glyph_index,
+                                             FT_Int   load_flags )
+  {
+    FT_Error      error;
+    FT_Driver     driver;
+    FT_GlyphSlot  slot;
+    FT_Library    library;
+    FT_Bool       autohint;
+    FT_Module     hinter;
+
+
+    if ( !face || !face->size || !face->glyph )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( glyph_index >= (FT_UInt)face->num_glyphs )
+      return FT_Err_Invalid_Argument;
+
+    slot = face->glyph;
+    ft_glyphslot_clear( slot );
+
+    driver = face->driver;
+
+    /* when the flag NO_RECURSE is set, we disable hinting and scaling */
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    /* do we need to load the glyph through the auto-hinter? */
+    library  = driver->root.library;
+    hinter   = library->auto_hinter;
+    autohint = hinter &&
+               !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) );
+    if ( autohint )
+    {
+      if ( FT_DRIVER_HAS_HINTER( driver ) &&
+           !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
+        autohint = 0;
+    }
+
+    if ( autohint )
+    {
+      FT_AutoHinter_Interface*  hinting;
+
+
+      hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
+      error = hinting->load_glyph( (FT_AutoHinter)hinter, slot, face->size,
+                                   glyph_index, load_flags );
+    }
+    else
+      error = driver->clazz->load_glyph( slot,
+                                         face->size,
+                                         glyph_index,
+                                         load_flags );
+    if ( error )
+      goto Exit;
+
+    /* compute the advance */
+    if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+    {
+      slot->advance.x = 0;
+      slot->advance.y = slot->metrics.vertAdvance;
+    }
+    else
+    {
+      slot->advance.x = slot->metrics.horiAdvance;
+      slot->advance.y = 0;
+    }
+
+    /* now, transform the glyph image when needed */
+    if ( face->transform_flags )
+    {
+      /* get renderer */
+      FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );
+
+
+      if ( renderer )
+        error = renderer->clazz->transform_glyph( renderer, slot,
+                                                  &face->transform_matrix,
+                                                  &face->transform_delta );
+      /* transform advance */
+      FT_Vector_Transform( &slot->advance, &face->transform_matrix );
+    }
+
+    /* do we need to render the image now? */
+    if ( !error                                    &&
+         slot->format != ft_glyph_format_bitmap    &&
+         slot->format != ft_glyph_format_composite &&
+         load_flags & FT_LOAD_RENDER )
+    {
+      error = FT_Render_Glyph( slot,
+                               ( load_flags & FT_LOAD_MONOCHROME )
+                                  ? ft_render_mode_mono
+                                  : ft_render_mode_normal );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Load_Char                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size, according to its character code.                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a target face object where the glyph    */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    char_code   :: The glyph's character code, according to the        */
+  /*                   current charmap used in the face.                   */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the face has no current charmap, or if the character code       */
+  /*    is not defined in the charmap, this function will return an        */
+  /*    error.                                                             */
+  /*                                                                       */
+  /*    If the glyph image is not a bitmap, and if the bit flag            */
+  /*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         */
+  /*    transformed with the information passed to a previous call to      */
+  /*    FT_Set_Transform().                                                */
+  /*                                                                       */
+  /*    Note that this also transforms the `face.glyph.advance' field, but */
+  /*    *not* the values in `face.glyph.metrics'.                          */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Load_Char( FT_Face   face,
+                                            FT_ULong  char_code,
+                                            FT_Int    load_flags )
+  {
+    FT_UInt  glyph_index;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    glyph_index = (FT_UInt)char_code;
+    if ( face->charmap )
+      glyph_index = FT_Get_Char_Index( face, char_code );
+
+    return FT_Load_Glyph( face, glyph_index, load_flags );
+  }
+
+
+  /* destructor for sizes list */
+  static
+  void  destroy_size( FT_Memory  memory,
+                      FT_Size    size,
+                      FT_Driver  driver )
+  {
+    /* finalize client-specific data */
+    if ( size->generic.finalizer )
+      size->generic.finalizer( size );
+
+    /* finalize format-specific stuff */
+    if ( driver->clazz->done_size )
+      driver->clazz->done_size( size );
+
+    FREE( size );
+  }
+
+
+  /* destructor for faces list */
+  static
+  void  destroy_face( FT_Memory  memory,
+                      FT_Face    face,
+                      FT_Driver  driver )
+  {
+    FT_Driver_Class*  clazz = driver->clazz;
+
+
+    /* discard auto-hinting data */
+    if ( face->autohint.finalizer )
+      face->autohint.finalizer( face->autohint.data );
+      
+    /* Discard glyph slots for this face                           */
+    /* Beware!  FT_Done_GlyphSlot() changes the field `face->slot' */
+    while ( face->glyph )
+      FT_Done_GlyphSlot( face->glyph );
+
+    /* Discard all sizes for this face */
+    FT_List_Finalize( &face->sizes_list,
+                     (FT_List_Destructor)destroy_size,
+                     memory,
+                     driver );
+    face->size = 0;
+
+    /* Now discard client data */
+    if ( face->generic.finalizer )
+      face->generic.finalizer( face );
+
+    /* finalize format-specific stuff */
+    if ( clazz->done_face )
+      clazz->done_face( face );
+
+    /* close the stream for this face if needed */
+    if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 )
+      ft_done_stream( &face->stream );
+
+    /* get rid of it */
+    FREE( face );
+  }
+
+
+  static
+  void  Destroy_Driver( FT_Driver  driver )
+  {
+    FT_List_Finalize( &driver->faces_list,
+                      (FT_List_Destructor)destroy_face,
+                      driver->root.memory,
+                      driver );
+
+    /* check whether we need to drop the driver's glyph loader */
+    if ( FT_DRIVER_USES_OUTLINES( driver ) )
+      FT_GlyphLoader_Done( driver->glyph_loader );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    open_face                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function does some work for FT_Open_Face().                   */
+  /*                                                                       */
+  static
+  FT_Error  open_face( FT_Driver      driver,
+                       FT_Stream      stream,
+                       FT_Long        face_index,
+                       FT_Int         num_params,
+                       FT_Parameter*  params,
+                       FT_Face*       aface )
+  {
+    FT_Memory         memory;
+    FT_Driver_Class*  clazz;
+    FT_Face           face = 0;
+    FT_Error          error;
+
+
+    clazz  = driver->clazz;
+    memory = driver->root.memory;
+
+    /* allocate the face object and perform basic initialization */
+    if ( ALLOC( face, clazz->face_object_size ) )
+      goto Fail;
+
+    face->driver = driver;
+    face->memory = memory;
+    face->stream = stream;
+
+    error = clazz->init_face( stream,
+                              face,
+                              face_index,
+                              num_params,
+                              params );
+    if ( error )
+      goto Fail;
+
+    *aface = face;
+
+  Fail:
+    if ( error )
+    {
+      clazz->done_face( face );
+      FREE( face );
+      *aface = 0;
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Face                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new face object from a given resource and typeface index */
+  /*    using a pathname to the font file.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pathname   :: A path to the font file.                             */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    Note that additional slots can be added to each face with the      */
+  /*    FT_New_GlyphSlot() API function.  Slots are linked in a single     */
+  /*    list through their `next' field.                                   */
+  /*                                                                       */
+  /*    FT_New_Face() can be used to determine and/or check the font       */
+  /*    format of a given font resource.  If the `face_index' field is     */
+  /*    negative, the function will _not_ return any face handle in        */
+  /*    `*face'.  Its return value should be 0 if the resource is          */
+  /*    recognized, or non-zero if not.                                    */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_New_Face( FT_Library   library,
+                                           const char*  pathname,
+                                           FT_Long      face_index,
+                                           FT_Face*     aface )
+  {
+    FT_Open_Args  args;
+
+
+    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+    if ( !pathname )
+      return FT_Err_Invalid_Argument;
+
+    args.flags    = ft_open_pathname;
+    args.pathname = (char*)pathname;
+
+    return FT_Open_Face( library, &args, face_index, aface );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Memory_Face                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new face object from a given resource and typeface index */
+  /*    using a font file already loaded into memory.                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    file_base  :: A pointer to the beginning of the font data.         */
+  /*                                                                       */
+  /*    file_size  :: The size of the memory chunk used by the font data.  */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    face       :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    Note that additional slots can be added to each face with the      */
+  /*    FT_New_GlyphSlot() API function.  Slots are linked in a single     */
+  /*    list through their `next' field.                                   */
+  /*                                                                       */
+  /*    FT_New_Memory_Face() can be used to determine and/or check the     */
+  /*    font format of a given font resource.  If the `face_index' field   */
+  /*    is negative, the function will _not_ return any face handle in     */
+  /*    `*face'.  Its return value should be 0 if the resource is          */
+  /*    recognized, or non-zero if not.                                    */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_New_Memory_Face( FT_Library  library,
+                                                  FT_Byte*    file_base,
+                                                  FT_Long     file_size,
+                                                  FT_Long     face_index,
+                                                  FT_Face*    face )
+  {
+    FT_Open_Args  args;
+
+
+    /* test for valid `library' and `face' delayed to FT_Open_Face() */
+    if ( !file_base )
+      return FT_Err_Invalid_Argument;
+
+    args.flags       = ft_open_memory;
+    args.memory_base = file_base;
+    args.memory_size = file_size;
+
+    return FT_Open_Face( library, &args, face_index, face );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Open_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Opens a face object from a given resource and typeface index using */
+  /*    an `FT_Open_Args' structure.  If the face object doesn't exist, it */
+  /*    will be created.                                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    args       :: A pointer to an `FT_Open_Args' structure which must  */
+  /*                  be filled by the caller.                             */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    Note that additional slots can be added to each face with the      */
+  /*    FT_New_GlyphSlot() API function.  Slots are linked in a single     */
+  /*    list through their `next' field.                                   */
+  /*                                                                       */
+  /*    FT_Open_Face() can be used to determine and/or check the font      */
+  /*    format of a given font resource.  If the `face_index' field is     */
+  /*    negative, the function will _not_ return any face handle in        */
+  /*    `*face'.  Its return value should be 0 if the resource is          */
+  /*    recognized, or non-zero if not.                                    */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Open_Face( FT_Library     library,
+                                            FT_Open_Args*  args,
+                                            FT_Long        face_index,
+                                            FT_Face*       aface )
+  {
+    FT_Error     error;
+    FT_Driver    driver;
+    FT_Memory    memory;
+    FT_Stream    stream;
+    FT_Face      face = 0;
+    FT_ListNode  node = 0;
+
+
+    /* test for valid `library' and `args' delayed to */
+    /* ft_new_input_stream()                          */
+
+    if ( !aface )
+      return FT_Err_Invalid_Argument;
+
+    *aface = 0;
+
+    /* create input stream */
+    error = ft_new_input_stream( library, args, &stream );
+    if ( error )
+      goto Exit;
+
+    memory = library->memory;
+
+    /* If the font driver is specified in the `args' structure, use */
+    /* it.  Otherwise, we scan the list of registered drivers.      */
+    if ( args->flags & ft_open_driver && args->driver )
+    {
+      driver = FT_DRIVER( args->driver );
+
+      /* not all modules are drivers, so check... */
+      if ( FT_MODULE_IS_DRIVER( driver ) )
+      {
+        FT_Int         num_params = 0;
+        FT_Parameter*  params     = 0;
+
+
+        if ( args->flags & ft_open_params )
+        {
+          num_params = args->num_params;
+          params     = args->params;
+        }
+
+        error = open_face( driver, stream, face_index,
+                           num_params, params, &face );
+        if ( !error )
+          goto Success;
+      }
+      else
+        error = FT_Err_Invalid_Handle;
+
+      ft_done_stream( &stream );
+      goto Fail;
+    }
+    else
+    {
+      /* check each font driver for an appropriate format */
+      FT_Module*  cur   = library->modules;
+      FT_Module*  limit = cur + library->num_modules;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        /* not all modules are font drivers, so check... */
+        if ( FT_MODULE_IS_DRIVER( cur[0] ) )
+        {
+          FT_Int         num_params = 0;
+          FT_Parameter*  params     = 0;
+
+
+          driver = FT_DRIVER( cur[0] );
+
+          if ( args->flags & ft_open_params )
+          {
+            num_params = args->num_params;
+            params     = args->params;
+          }
+
+          error = open_face( driver, stream, face_index,
+                             num_params, params, &face );
+          if ( !error )
+            goto Success;
+
+          if ( error != FT_Err_Unknown_File_Format )
+            goto Fail;
+        }
+      }
+
+      ft_done_stream( &stream );
+
+      /* no driver is able to handle this format */
+      error = FT_Err_Unknown_File_Format;
+      goto Fail;
+    }
+
+  Success:
+    FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" ));
+
+    /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
+    if ( args->flags & ft_open_stream && args->stream )
+      face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
+
+    /* add the face object to its driver's list */
+    if ( ALLOC( node, sizeof ( *node ) ) )
+      goto Fail;
+
+    node->data = face;
+    /* don't assume driver is the same as face->driver, so use */
+    /* face->driver instead.                                   */
+    FT_List_Add( &face->driver->faces_list, node );
+
+    /* now allocate a glyph slot object for the face */
+    {
+      FT_GlyphSlot  slot;
+
+
+      FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
+
+      error = FT_New_GlyphSlot( face, &slot );
+      if ( error )
+        goto Fail;
+
+      face->glyph = slot;
+    }
+
+    /* finally, allocate a size object for the face */
+    {
+      FT_Size  size;
+
+
+      FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
+
+      error = FT_New_Size( face, &size );
+      if ( error )
+        goto Fail;
+
+      face->size = size;
+    }
+
+    /* initialize transformation for convenience functions */
+    face->transform_matrix.xx = 0x10000L;
+    face->transform_matrix.xy = 0;
+    face->transform_matrix.yx = 0;
+    face->transform_matrix.yy = 0x10000L;
+
+    face->transform_delta.x = 0;
+    face->transform_delta.y = 0;
+
+    *aface = face;
+    goto Exit;
+
+  Fail:
+    FT_Done_Face( face );
+
+  Exit:
+    FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Attach_File                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    `Attaches' a given font file to an existing face.  This is usually */
+  /*    to read additional information for a single face object.  For      */
+  /*    example, it is used to read the AFM files that come with Type 1    */
+  /*    fonts in order to add kerning data and other metrics.              */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face         :: The target face object.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    filepathname :: An 8-bit pathname naming the `metrics' file.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If your font file is in memory, or if you want to provide your     */
+  /*    own input stream object, use FT_Attach_Stream().                   */
+  /*                                                                       */
+  /*    The meaning of the `attach' action (i.e., what really happens when */
+  /*    the new file is read) is not fixed by FreeType itself.  It really  */
+  /*    depends on the font format (and thus the font driver).             */
+  /*                                                                       */
+  /*    Client applications are expected to know what they are doing       */
+  /*    when invoking this function.  Most drivers simply do not implement */
+  /*    file attachments.                                                  */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Attach_File( FT_Face      face,
+                                              const char*  filepathname )
+  {
+    FT_Open_Args  open;
+
+
+    /* test for valid `face' delayed to FT_Attach_Stream() */
+
+    if ( !filepathname )
+      return FT_Err_Invalid_Argument;
+
+    open.flags    = ft_open_pathname;
+    open.pathname = (char*)filepathname;
+
+    return FT_Attach_Stream( face, &open );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Attach_Stream                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is similar to FT_Attach_File() with the exception    */
+  /*    that it reads the attachment from an arbitrary stream.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: The target face object.                              */
+  /*                                                                       */
+  /*    parameters :: A pointer to an FT_Open_Args structure used to       */
+  /*                  describe the input stream to FreeType.               */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The meaning of the `attach' (i.e. what really happens when the     */
+  /*    new file is read) is not fixed by FreeType itself.  It really      */
+  /*    depends on the font format (and thus the font driver).             */
+  /*                                                                       */
+  /*    Client applications are expected to know what they are doing       */
+  /*    when invoking this function.  Most drivers simply do not implement */
+  /*    file attachments.                                                  */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Attach_Stream( FT_Face        face,
+                                                FT_Open_Args*  parameters )
+  {
+    FT_Stream  stream;
+    FT_Error   error;
+    FT_Driver  driver;
+
+    FT_Driver_Class*  clazz;
+
+
+    /* test for valid `parameters' delayed to ft_new_input_stream() */
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver = face->driver;
+    if ( !driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    error = ft_new_input_stream( driver->root.library, parameters, &stream );
+    if ( error )
+      goto Exit;
+
+    /* we implement FT_Attach_Stream in each driver through the */
+    /* `attach_file' interface                                  */
+
+    error = FT_Err_Unimplemented_Feature;
+    clazz = driver->clazz;
+    if ( clazz->attach_file )
+      error = clazz->attach_file( face, stream );
+
+    /* close the attached stream */
+    if ( !parameters->stream || ( parameters->flags & ft_open_stream ) )
+      ft_done_stream( &stream );
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given face object, as well as all of its child slots    */
+  /*    and sizes.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to a target face object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Done_Face( FT_Face  face )
+  {
+    FT_Error     error;
+    FT_Driver    driver;
+    FT_Memory    memory;
+    FT_ListNode  node;
+
+
+    error = FT_Err_Invalid_Face_Handle;
+    if ( face && face->driver )
+    {
+      driver = face->driver;
+      memory = driver->root.memory;
+
+      /* find face in driver's list */
+      node = FT_List_Find( &driver->faces_list, face );
+      if ( node )
+      {
+        /* remove face object from the driver's list */
+        FT_List_Remove( &driver->faces_list, node );
+        FREE( node );
+
+        /* now destroy the object proper */
+        destroy_face( memory, face, driver );
+        error = FT_Err_Ok;
+      }
+    }
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Size                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new size object from a given face object.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to a parent face object.                          */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    asize :: A handle to a new size object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_New_Size( FT_Face   face,
+                                           FT_Size*  asize )
+  {
+    FT_Error          error;
+    FT_Memory         memory;
+    FT_Driver         driver;
+    FT_Driver_Class*  clazz;
+
+    FT_Size           size = 0;
+    FT_ListNode       node = 0;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( !asize )
+      return FT_Err_Invalid_Size_Handle;
+
+    if ( !face->driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    *asize = 0;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+    memory = face->memory;
+
+    /* Allocate new size object and perform basic initialisation */
+    if ( ALLOC( size, clazz->size_object_size ) ||
+         ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
+      goto Exit;
+
+    size->face = face;
+
+    if ( clazz->init_size )
+      error = clazz->init_size( size );
+
+    /* in case of success, add to the face's list */
+    if ( !error )
+    {
+      *asize     = size;
+      node->data = size;
+      FT_List_Add( &face->sizes_list, node );
+    }
+
+  Exit:
+    if ( error )
+    {
+      FREE( node );
+      FREE( size );
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given size object.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to a target size object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Done_Size( FT_Size  size )
+  {
+    FT_Error     error;
+    FT_Driver    driver;
+    FT_Memory    memory;
+    FT_Face      face;
+    FT_ListNode  node;
+
+
+    if ( !size )
+      return FT_Err_Invalid_Size_Handle;
+
+    face = size->face;
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver = face->driver;
+    if ( !driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    memory = driver->root.memory;
+
+    error = FT_Err_Ok;
+    node  = FT_List_Find( &face->sizes_list, size );
+    if ( node )
+    {
+      FT_List_Remove( &face->sizes_list, node );
+      FREE( node );
+
+      if ( face->size == size )
+      {
+        face->size = 0;
+        if ( face->sizes_list.head )
+          face->size = (FT_Size)(face->sizes_list.head->data);
+      }
+
+      destroy_size( memory, size, driver );
+    }
+    else
+      error = FT_Err_Invalid_Size_Handle;
+
+    return FT_Err_Ok;
+  }
+
+
+  static
+  void  ft_recompute_scaled_metrics( FT_Face           face,
+                                     FT_Size_Metrics*  metrics )
+  {
+    /* Compute root ascender, descender, test height, and max_advance */
+
+    metrics->ascender    = ( FT_MulFix( face->ascender,
+                                        metrics->y_scale ) + 32 ) & -64;
+
+    metrics->descender   = ( FT_MulFix( face->descender,
+                                        metrics->y_scale ) + 32 ) & -64;
+
+    metrics->height      = ( FT_MulFix( face->height,
+                                        metrics->y_scale ) + 32 ) & -64;
+
+    metrics->max_advance = ( FT_MulFix( face->max_advance_width,
+                                        metrics->x_scale ) + 32 ) & -64;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Char_Size                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the character dimensions of a given face object.  The         */
+  /*    `char_width' and `char_height' values are used for the width and   */
+  /*    height, respectively, expressed in 26.6 fractional points.         */
+  /*                                                                       */
+  /*    If the horizontal or vertical resolution values are zero, a        */
+  /*    default value of 72dpi is used.  Similarly, if one of the          */
+  /*    character dimensions is zero, its value is set equal to the other. */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size            :: A handle to a target size object.               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_width      :: The character width, in 26.6 fractional points. */
+  /*                                                                       */
+  /*    char_height     :: The character height, in 26.6 fractional        */
+  /*                       points.                                         */
+  /*                                                                       */
+  /*    horz_resolution :: The horizontal resolution.                      */
+  /*                                                                       */
+  /*    vert_resolution :: The vertical resolution.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    When dealing with fixed-size faces (i.e., non-scalable formats),   */
+  /*    use the function FT_Set_Pixel_Sizes().                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Set_Char_Size( FT_Face     face,
+                                                FT_F26Dot6  char_width,
+                                                FT_F26Dot6  char_height,
+                                                FT_UInt     horz_resolution,
+                                                FT_UInt     vert_resolution )
+  {
+    FT_Error          error = FT_Err_Ok;
+    FT_Driver         driver;
+    FT_Memory         memory;
+    FT_Driver_Class*  clazz;
+    FT_Size_Metrics*  metrics;
+    FT_Long           dim_x, dim_y;
+
+
+    if ( !face || !face->size || !face->driver )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver  = face->driver;
+    metrics = &face->size->metrics;
+
+    if ( !char_width )
+      char_width = char_height;
+
+    else if ( !char_height )
+      char_height = char_width;
+
+    if ( !horz_resolution )
+      horz_resolution = 72;
+
+    if ( !vert_resolution )
+      vert_resolution = 72;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+    memory = driver->root.memory;
+
+    /* default processing -- this can be overridden by the driver */
+    if ( char_width  < 1 * 64 )
+      char_width  = 1 * 64;
+    if ( char_height < 1 * 64 )
+      char_height = 1 * 64;
+
+    /* Compute pixel sizes in 26.6 units */
+    dim_x = ( ( ( char_width  * horz_resolution ) / 72 ) + 32 ) & -64;
+    dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
+
+    metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
+    metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
+
+    metrics->x_scale = 0x10000L;
+    metrics->y_scale = 0x10000L;
+
+    if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+    {
+      metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
+      metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
+
+      ft_recompute_scaled_metrics( face, metrics );
+    }
+
+    if ( clazz->set_char_sizes )
+      error = clazz->set_char_sizes( face->size,
+                                     char_width,
+                                     char_height,
+                                     horz_resolution,
+                                     vert_resolution );
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Pixel_Sizes                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the character dimensions of a given face object.  The width   */
+  /*    and height are expressed in integer pixels.                        */
+  /*                                                                       */
+  /*    If one of the character dimensions is zero, its value is set equal */
+  /*    to the other.                                                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face         :: A handle to the target face object.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pixel_width  :: The character width, in integer pixels.            */
+  /*                                                                       */
+  /*    pixel_height :: The character height, in integer pixels.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Set_Pixel_Sizes( FT_Face  face,
+                                                  FT_UInt  pixel_width,
+                                                  FT_UInt  pixel_height )
+  {
+    FT_Error          error = FT_Err_Ok;
+    FT_Driver         driver;
+    FT_Memory         memory;
+    FT_Driver_Class*  clazz;
+    FT_Size_Metrics*  metrics = &face->size->metrics;
+
+
+    if ( !face || !face->size || !face->driver )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+    memory = driver->root.memory;
+
+    /* default processing -- this can be overridden by the driver */
+    if ( pixel_width == 0 )
+      pixel_width = pixel_height;
+
+    else if ( pixel_height == 0 )
+      pixel_height = pixel_width;
+
+    if ( pixel_width  < 1 )
+      pixel_width  = 1;
+    if ( pixel_height < 1 )
+      pixel_height = 1;
+
+    metrics->x_ppem = pixel_width;
+    metrics->y_ppem = pixel_height;
+
+    if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+    {
+      metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
+                                    face->units_per_EM );
+
+      metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
+                                    face->units_per_EM );
+
+      ft_recompute_scaled_metrics( face, metrics );
+    }
+
+    if ( clazz->set_pixel_sizes )
+      error = clazz->set_pixel_sizes( face->size,
+                                      pixel_width,
+                                      pixel_height );
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Kerning                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the kerning vector between two glyphs of a same face.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a source face object.                   */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /*    kern_mode   :: See FT_Kerning_Mode() for more information.         */
+  /*                   Determines the scale/dimension of the returned      */
+  /*                   kerning vector.                                     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this method.  Other layouts, or more sophisticated    */
+  /*    kernings, are out of the scope of this API function -- they can be */
+  /*    implemented through format-specific interfaces.                    */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Get_Kerning( FT_Face     face,
+                                              FT_UInt     left_glyph,
+                                              FT_UInt     right_glyph,
+                                              FT_UInt     kern_mode,
+                                              FT_Vector*  kerning )
+  {
+    FT_Error   error = FT_Err_Ok;
+    FT_Driver  driver;
+    FT_Memory  memory;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( !kerning )
+      return FT_Err_Invalid_Argument;
+
+    driver = face->driver;
+    memory = driver->root.memory;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    if ( driver->clazz->get_kerning )
+    {
+      error = driver->clazz->get_kerning( face,
+                                          left_glyph,
+                                          right_glyph,
+                                          kerning );
+      if ( !error )
+      {
+        if ( kern_mode != ft_kerning_unscaled )
+        {
+          kerning->x = FT_MulFix( kerning->x, face->size->metrics.x_scale );
+          kerning->y = FT_MulFix( kerning->y, face->size->metrics.y_scale );
+
+          if ( kern_mode != ft_kerning_unfitted )
+          {
+            kerning->x = ( kerning->x + 32 ) & -64;
+            kerning->y = ( kerning->y + 32 ) & -64;
+          }
+        }
+      }
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Select_Charmap                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Selects a given charmap by its encoding tag (as listed in          */
+  /*    `freetype.h').                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*                                                                       */
+  /*    encoding :: A handle to the selected charmap.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will return an error if no charmap in the face       */
+  /*    corresponds to the encoding queried here.                          */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Select_Charmap( FT_Face      face,
+                                                 FT_Encoding  encoding )
+  {
+    FT_CharMap*  cur;
+    FT_CharMap*  limit;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    cur = face->charmaps;
+    if ( !cur )
+      return FT_Err_Invalid_CharMap_Handle;
+
+    limit = cur + face->num_charmaps;
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur[0]->encoding == encoding )
+      {
+        face->charmap = cur[0];
+        return 0;
+      }
+    }
+
+    return FT_Err_Invalid_Argument;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Charmap                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Selects a given charmap for character code to glyph index          */
+  /*    decoding.                                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*    charmap  :: A handle to the selected charmap.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will return an error if the charmap is not part of   */
+  /*    the face (i.e., if it is not listed in the face->charmaps[]        */
+  /*    table).                                                            */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Set_Charmap( FT_Face     face,
+                                              FT_CharMap  charmap )
+  {
+    FT_CharMap*  cur;
+    FT_CharMap*  limit;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    cur = face->charmaps;
+    if ( !cur )
+      return FT_Err_Invalid_CharMap_Handle;
+
+    limit = cur + face->num_charmaps;
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur[0] == charmap )
+      {
+        face->charmap = cur[0];
+        return 0;
+      }
+    }
+    return FT_Err_Invalid_Argument;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Char_Index                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the glyph index of a given character code.  This function  */
+  /*    uses a charmap object to do the translation.                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*                                                                       */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph index.  0 means `undefined character code'.              */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_UInt )  FT_Get_Char_Index( FT_Face   face,
+                                                FT_ULong  charcode )
+  {
+    FT_UInt    result;
+    FT_Driver  driver;
+
+
+    result = 0;
+    if ( face && face->charmap )
+    {
+      driver = face->driver;
+      result = driver->clazz->get_char_index( face->charmap, charcode );
+    }
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Glyph_Name                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the ASCII name of a given glyph in a face.  This only    */
+  /*    works for those faces where FT_HAS_GLYPH_NAME(face) returns true.  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a source face object.                   */
+  /*                                                                       */
+  /*    glyph_index :: The glyph index.                                    */
+  /*                                                                       */
+  /*    buffer      :: A pointer to a target buffer where the name will be */
+  /*                   copied to.                                          */
+  /*                                                                       */
+  /*    buffer_max  :: The maximal number of bytes available in the        */
+  /*                   buffer.                                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error is returned if the face doesn't provide glyph names or if */
+  /*    the glyph index is invalid.  In all cases of failure, the first    */
+  /*    byte of `buffer' will be set to 0 to indicate an empty name.       */
+  /*                                                                       */
+  /*    The glyph name is truncated to fit within the buffer if it is too  */
+  /*    long.  The returned string is always zero-terminated.              */
+  /*                                                                       */
+  /*    This function is not compiled within the library if the config     */
+  /*    macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in                */
+  /*    `include/freetype/config/ftoptions.h'                              */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Get_Glyph_Name( FT_Face     face,
+                                                 FT_UInt     glyph_index,
+                                                 FT_Pointer  buffer,
+                                                 FT_UInt     buffer_max )
+  {
+    FT_Error  error = FT_Err_Invalid_Argument;
+    
+
+    /* clean up buffer */
+    if ( buffer && buffer_max > 0 )
+      ((FT_Byte*)buffer)[0] = 0;
+      
+    if ( face                                    &&
+         glyph_index < (FT_UInt)face->num_glyphs &&
+         FT_HAS_GLYPH_NAMES( face )              )
+    {
+      /* now, lookup for glyph name */
+      FT_Driver        driver = face->driver;
+      FT_Module_Class* clazz  = FT_MODULE_CLASS( driver );
+
+
+      if ( clazz->get_interface )
+      {
+        FT_Glyph_Name_Requester  requester;
+        
+
+        requester = (FT_Glyph_Name_Requester)clazz->get_interface(
+                      FT_MODULE( driver ), "glyph_name" );
+        if ( requester )
+          error = requester( face, glyph_index, buffer, buffer_max );
+      }
+    }
+
+    return error;
+  }                                                 
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Sfnt_Table                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a pointer to a given SFNT table within a face.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source face object.                        */
+  /*    tag  :: An index of an SFNT table.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A type-less pointer to the table.  This will be 0 in case of       */
+  /*    error, or if the corresponding table was not found *OR* loaded     */
+  /*    from the file.                                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The table is owned by the face object, and disappears with it.     */
+  /*                                                                       */
+  /*    This function is only useful to access SFNT tables that are loaded */
+  /*    by the sfnt/truetype/opentype drivers.  See the FT_Sfnt_Tag        */
+  /*    enumeration in `tttables.h' for a list.                            */
+  /*                                                                       */
+  /*    You can load any table with a different function.. XXX             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void* )  FT_Get_Sfnt_Table( FT_Face      face,
+                                              FT_Sfnt_Tag  tag )
+  {
+    void*                   table = 0;
+    FT_Get_Sfnt_Table_Func  func;
+    FT_Driver               driver;
+
+
+    if ( !face || !FT_IS_SFNT( face ) )
+      goto Exit;
+
+    driver = face->driver;
+    func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
+                                     FT_MODULE( driver ), "get_sfnt" );
+    if ( func )
+      table = func( face, tag );
+
+  Exit:
+    return table;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                        R E N D E R E R S                        ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* lookup a renderer by glyph format in the library's list */
+  BASE_FUNC( FT_Renderer )  FT_Lookup_Renderer( FT_Library       library,
+                                                FT_Glyph_Format  format,
+                                                FT_ListNode*     node )
+  {
+    FT_ListNode   cur;
+    FT_Renderer   result = 0;
+
+
+    if ( !library )
+      goto Exit;
+
+    cur = library->renderers.head;
+
+    if ( node )
+    {
+      if ( *node )
+        cur = (*node)->next;
+      *node = 0;
+    }
+
+    while ( cur )
+    {
+      FT_Renderer  renderer = FT_RENDERER( cur->data );
+
+
+      if ( renderer->glyph_format == format )
+      {
+        if ( node )
+          *node = cur;
+
+        result = renderer;
+        break;
+      }
+      cur = cur->next;
+    }
+
+  Exit:
+    return result;
+  }
+
+
+  static
+  FT_Renderer  ft_lookup_glyph_renderer( FT_GlyphSlot  slot )
+  {
+    FT_Face      face    = slot->face;
+    FT_Library   library = FT_FACE_LIBRARY( face );
+    FT_Renderer  result  = library->cur_renderer;
+
+
+    if ( !result || result->glyph_format != slot->format )
+      result = FT_Lookup_Renderer( library, slot->format, 0 );
+
+    return result;
+  }
+
+
+  static
+  void  ft_set_current_renderer( FT_Library  library )
+  {
+    FT_Renderer  renderer;
+
+
+    renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
+    library->cur_renderer = renderer;
+  }
+
+
+  static
+  FT_Error  ft_add_renderer( FT_Module  module )
+  {
+    FT_Library   library = module->library;
+    FT_Memory    memory  = library->memory;
+    FT_Error     error;
+    FT_ListNode  node;
+
+
+    if ( ALLOC( node, sizeof ( *node ) ) )
+      goto Exit;
+
+    {
+      FT_Renderer         render = FT_RENDERER( module );
+      FT_Renderer_Class*  clazz  = (FT_Renderer_Class*)module->clazz;
+
+
+      render->clazz        = clazz;
+      render->glyph_format = clazz->glyph_format;
+
+      /* allocate raster object if needed */
+      if ( clazz->glyph_format == ft_glyph_format_outline &&
+           clazz->raster_class->raster_new )
+      {
+        error = clazz->raster_class->raster_new( memory, &render->raster );
+        if ( error )
+          goto Fail;
+
+        render->raster_render = clazz->raster_class->raster_render;
+        render->render        = clazz->render_glyph;
+      }
+
+      /* add to list */
+      node->data = module;
+      FT_List_Add( &library->renderers, node );
+
+      ft_set_current_renderer( library );
+    }
+
+  Fail:
+    if ( error )
+      FREE( node );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  ft_remove_renderer( FT_Module  module )
+  {
+    FT_Library   library = module->library;
+    FT_Memory    memory  = library->memory;
+    FT_ListNode  node;
+
+
+    node = FT_List_Find( &library->renderers, module );
+    if ( node )
+    {
+      FT_Renderer  render = FT_RENDERER( module );
+
+
+      /* release raster object, if any */
+      if ( render->raster )
+        render->clazz->raster_class->raster_done( render->raster );
+
+      /* remove from list */
+      FT_List_Remove( &library->renderers, node );
+      FREE( node );
+
+      ft_set_current_renderer( library );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Renderer                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the current renderer for a given glyph format.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the library object.                         */
+  /*                                                                       */
+  /*    format  :: The glyph format.                                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A renderer handle.  0 if none found.                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error will be returned if a module already exists by that name, */
+  /*    or if the module requires a version of FreeType that is too great. */
+  /*                                                                       */
+  /*    To add a new renderer, simply use FT_Add_Module().  To retrieve a  */
+  /*    renderer by its name, use FT_Get_Module().                         */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Renderer )  FT_Get_Renderer( FT_Library       library,
+                                                  FT_Glyph_Format  format )
+  {
+    /* test for valid `library' delayed to FT_Lookup_Renderer() */
+
+    return  FT_Lookup_Renderer( library, format, 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Renderer                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the current renderer to use, and set additional mode.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library    :: A handle to the library object.                      */
+  /*                                                                       */
+  /*    renderer   :: A handle to the renderer object.                     */
+  /*                                                                       */
+  /*    num_params :: The number of additional parameters.                 */
+  /*                                                                       */
+  /*    parameters :: Additional parameters.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In case of success, the renderer will be used to convert glyph     */
+  /*    images in the renderer's known format into bitmaps.                */
+  /*                                                                       */
+  /*    This doesn't change the current renderer for other formats.        */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Set_Renderer( FT_Library     library,
+                                              FT_Renderer    renderer,
+                                              FT_UInt        num_params,
+                                              FT_Parameter*  parameters )
+  {
+    FT_ListNode  node;
+    FT_Error     error = FT_Err_Ok;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !renderer )
+      return FT_Err_Invalid_Argument;
+
+    node = FT_List_Find( &library->renderers, renderer );
+    if ( !node )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    FT_List_Up( &library->renderers, node );
+
+    if ( renderer->glyph_format == ft_glyph_format_outline )
+      library->cur_renderer = renderer;
+
+    if ( num_params > 0 )
+    {
+      FTRenderer_setMode  set_mode = renderer->clazz->set_mode;
+
+
+      for ( ; num_params > 0; num_params-- )
+      {
+        error = set_mode( renderer, parameters->tag, parameters->data );
+        if ( error )
+          break;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  FT_Render_Glyph_Internal( FT_Library    library,
+                                      FT_GlyphSlot  slot,
+                                      FT_UInt       render_mode )
+  {
+    FT_Error     error = FT_Err_Ok;
+    FT_Renderer  renderer;
+
+
+    /* if it is already a bitmap, no need to do anything */
+    switch ( slot->format )
+    {
+    case ft_glyph_format_bitmap:   /* already a bitmap, don't do anything */
+      break;
+
+    default:
+      {
+        FT_ListNode  node   = 0;
+        FT_Bool      update = 0;
+
+
+        /* small shortcut for the very common case */
+        if ( slot->format == ft_glyph_format_outline )
+        {
+          renderer = library->cur_renderer;
+          node     = library->renderers.head;
+        }
+        else
+          renderer = FT_Lookup_Renderer( library, slot->format, &node );
+
+        error = FT_Err_Unimplemented_Feature;
+        while ( renderer )
+        {
+          error = renderer->render( renderer, slot, render_mode, 0 );
+          if ( !error || error != FT_Err_Cannot_Render_Glyph )
+            break;
+
+          /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
+          /* is unsupported by the current renderer for this glyph image */
+          /* format.                                                     */
+
+          /* now, look for another renderer that supports the same */
+          /* format.                                               */
+          renderer = FT_Lookup_Renderer( library, slot->format, &node );
+          update   = 1;
+        }
+
+        /* if we changed the current renderer for the glyph image format */
+        /* we need to select it as the next current one                  */
+        if ( !error && update && renderer )
+          FT_Set_Renderer( library, renderer, 0, 0 );
+      }
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Render_Glyph                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a given glyph image to a bitmap.  It does so by           */
+  /*    inspecting the glyph image format, find the relevant renderer, and */
+  /*    invoke it.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot        :: A handle to the glyph slot containing the image to  */
+  /*                   convert.                                            */
+  /*                                                                       */
+  /*    render_mode :: This is the render mode used to render the glyph    */
+  /*                   image into a bitmap.  See FT_Render_Mode for a list */
+  /*                   of possible values.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Render_Glyph( FT_GlyphSlot  slot,
+                                               FT_UInt       render_mode )
+  {
+    FT_Library   library;
+
+
+    if ( !slot )
+      return FT_Err_Invalid_Argument;
+
+    library = FT_FACE_LIBRARY( slot->face );
+
+    return FT_Render_Glyph_Internal( library, slot, render_mode );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                         M O D U L E S                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Destroy_Module                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given module object.  For drivers, this also destroys   */
+  /*    all child faces.                                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*     module :: A handle to the target driver object.                   */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*     The driver _must_ be LOCKED!                                      */
+  /*                                                                       */
+  static
+  void  Destroy_Module( FT_Module  module )
+  {
+    FT_Memory         memory  = module->memory;
+    FT_Module_Class*  clazz   = module->clazz;
+    FT_Library        library = module->library;
+
+
+    /* finalize client-data - before anything else */
+    if ( module->generic.finalizer )
+      module->generic.finalizer( module );
+
+    if ( library && library->auto_hinter == module )
+      library->auto_hinter = 0;
+
+    /* if the module is a renderer */
+    if ( FT_MODULE_IS_RENDERER( module ) )
+      ft_remove_renderer( module );
+
+    /* if the module is a font driver, add some steps */
+    if ( FT_MODULE_IS_DRIVER( module ) )
+      Destroy_Driver( FT_DRIVER( module ) );
+
+    /* finalize the module object */
+    if ( clazz->module_done )
+      clazz->module_done( module );
+
+    /* discard it */
+    FREE( module );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add_Module                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds a new module to a given library instance.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the library object.                         */
+  /*                                                                       */
+  /*    clazz   :: A pointer to class descriptor for the module.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error will be returned if a module already exists by that name, */
+  /*    or if the module requires a version of FreeType that is too great. */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Add_Module( FT_Library              library,
+                                             const FT_Module_Class*  clazz )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+    FT_Module  module;
+    FT_UInt    nn;
+
+
+#define FREETYPE_VER_FIXED  ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
+                                FREETYPE_MINOR                  )
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !clazz )
+      return FT_Err_Invalid_Argument;
+
+    /* check freetype version */
+    if ( clazz->module_requires > FREETYPE_VER_FIXED )
+      return FT_Err_Invalid_Version;
+
+    /* look for a module with the same name in the library's table */
+    for ( nn = 0; nn < library->num_modules; nn++ )
+    {
+      module = library->modules[nn];
+      if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
+      {
+        /* this installed module has the same name, compare their versions */
+        if ( clazz->module_version <= module->clazz->module_version )
+          return FT_Err_Lower_Module_Version;
+
+        /* remove the module from our list, then exit the loop to replace */
+        /* it by our new version..                                        */
+        FT_Remove_Module( library, module );
+        break;
+      }
+    }
+
+    memory = library->memory;
+    error  = FT_Err_Ok;
+
+    if ( library->num_modules >= FT_MAX_MODULES )
+    {
+      error = FT_Err_Too_Many_Drivers;
+      goto Exit;
+    }
+
+    /* allocate module object */
+    if ( ALLOC( module,clazz->module_size ) )
+      goto Exit;
+
+    /* base initialization */
+    module->library = library;
+    module->memory  = memory;
+    module->clazz   = (FT_Module_Class*)clazz;
+
+    /* check whether the module is a renderer - this must be performed */
+    /* before the normal module initialization                         */
+    if ( FT_MODULE_IS_RENDERER( module ) )
+    {
+      /* add to the renderers list */
+      error = ft_add_renderer( module );
+      if ( error )
+        goto Fail;
+    }
+
+    /* is the module a auto-hinter? */
+    if ( FT_MODULE_IS_HINTER( module ) )
+      library->auto_hinter = module;
+
+    /* if the module is a font driver */
+    if ( FT_MODULE_IS_DRIVER( module ) )
+    {
+      /* allocate glyph loader if needed */
+      FT_Driver   driver = FT_DRIVER( module );
+
+
+      driver->clazz = (FT_Driver_Class*)module->clazz;
+      if ( FT_DRIVER_USES_OUTLINES( driver ) )
+      {
+        error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
+        if ( error )
+          goto Fail;
+      }
+    }
+
+    if ( clazz->module_init )
+    {
+      error = clazz->module_init( module );
+      if ( error )
+        goto Fail;
+    }
+
+    /* add module to the library's table */
+    library->modules[library->num_modules++] = module;
+
+  Exit:
+    return error;
+
+  Fail:
+    if ( FT_MODULE_IS_DRIVER( module ) )
+    {
+      FT_Driver  driver = FT_DRIVER( module );
+
+
+      if ( FT_DRIVER_USES_OUTLINES( driver ) )
+        FT_GlyphLoader_Done( driver->glyph_loader );
+    }
+
+    if ( FT_MODULE_IS_RENDERER( module ) )
+    {
+      FT_Renderer  renderer = FT_RENDERER( module );
+
+
+      if ( renderer->raster )
+        renderer->clazz->raster_class->raster_done( renderer->raster );
+    }
+
+    FREE( module );
+    goto Exit;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Module                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds a module by its name.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object.                     */
+  /*                                                                       */
+  /*    module_name :: The module's name (as an ASCII string).             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A module handle.  0 if none was found.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should better be familiar with FreeType internals to know      */
+  /*    which module to look for :-)                                       */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Module ) FT_Get_Module( FT_Library   library,
+                                             const char*  module_name )
+  {
+    FT_Module   result = 0;
+    FT_Module*  cur;
+    FT_Module*  limit;
+
+
+    if ( !library || !module_name )
+      return result;
+
+    cur   = library->modules;
+    limit = cur + library->num_modules;
+
+    for ( ; cur < limit; cur++ )
+      if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
+      {
+        result = cur[0];
+        break;
+      }
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Module_Interface                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds a module and returns its specific interface as a typeless    */
+  /*    pointer.                                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object.                     */
+  /*                                                                       */
+  /*    module_name :: The module's name (as an ASCII string).             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A module-specific interface if available, 0 otherwise.             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should better be familiar with FreeType internals to know      */
+  /*    which module to look for, and what its interface is :-)            */
+  /*                                                                       */
+  BASE_FUNC( const void* )  FT_Get_Module_Interface( FT_Library   library,
+                                                     const char*  mod_name )
+  {
+    FT_Module  module;
+
+
+    /* test for valid `library' delayed to FT_Get_Module() */
+
+    module = FT_Get_Module( library, mod_name );
+
+    return module ? module->clazz->module_interface : 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Remove_Module                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Removes a given module from a library instance.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a library object.                           */
+  /*                                                                       */
+  /*    module  :: A handle to a module object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The module object is destroyed by the function in case of success. */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Remove_Module( FT_Library  library,
+                                                FT_Module   module )
+  {
+    /* try to find the module from the table, then remove it from there */
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( module )
+    {
+      FT_Module*  cur   = library->modules;
+      FT_Module*  limit = cur + library->num_modules;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        if ( cur[0] == module )
+        {
+          /* remove it from the table */
+          library->num_modules--;
+          limit--;
+          while ( cur < limit )
+          {
+            cur[0] = cur[1];
+            cur++;
+          }
+          limit[0] = 0;
+
+          /* destroy the module */
+          Destroy_Module( module );
+
+          return FT_Err_Ok;
+        }
+      }
+    }
+    return FT_Err_Invalid_Driver_Handle;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                         L I B R A R Y                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Library                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to create a new FreeType library instance    */
+  /*    from a given memory object.  It is thus possible to use libraries  */
+  /*    with distinct memory allocators within the same program.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory   :: A handle to the original memory object.                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    alibrary :: A pointer to handle of a new library object.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_New_Library( FT_Memory    memory,
+                                              FT_Library*  alibrary )
+  {
+    FT_Library  library = 0;
+    FT_Error    error;
+
+
+    if ( !memory )
+      return FT_Err_Invalid_Argument;
+
+    /* first of all, allocate the library object */
+    if ( ALLOC( library, sizeof ( *library ) ) )
+      return error;
+
+    library->memory = memory;
+
+    /* allocate the render pool */
+    library->raster_pool_size = FT_RENDER_POOL_SIZE;
+    if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
+      goto Fail;
+
+    /* That's ok now */
+    *alibrary = library;
+
+    return FT_Err_Ok;
+
+  Fail:
+    FREE( library );
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Library                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given library object.  This closes all drivers and      */
+  /*    discards all resource objects.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the target library.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Done_Library( FT_Library  library )
+  {
+    FT_Memory  memory;
+    FT_UInt    n;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    memory = library->memory;
+
+    /* Discard client-data */
+    if ( library->generic.finalizer )
+      library->generic.finalizer( library );
+
+    /* Close all modules in the library */
+    for ( n = 0; n < library->num_modules; n++ )
+    {
+      FT_Module  module = library->modules[n];
+
+
+      if ( module )
+      {
+        Destroy_Module( module );
+        library->modules[n] = 0;
+      }
+    }
+
+    /* Destroy raster objects */
+    FREE( library->raster_pool );
+    library->raster_pool_size = 0;
+
+    FREE( library );
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Debug_Hook                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets a debug hook function for debugging the interpreter of a font */
+  /*    format.                                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library    :: A handle to the library object.                      */
+  /*                                                                       */
+  /*    hook_index :: The index of the debug hook.  You should use the     */
+  /*                  values defined in ftobjs.h, e.g.                     */
+  /*                  FT_DEBUG_HOOK_TRUETYPE                               */
+  /*                                                                       */
+  /*    debug_hook :: The function used to debug the interpreter.          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Currently, four debug hook slots are available, but only two (for  */
+  /*    the TrueType and the Type 1 interpreter) are defined.              */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Set_Debug_Hook( FT_Library         library,
+                                             FT_UInt            hook_index,
+                                             FT_DebugHook_Func  debug_hook )
+  {
+    if ( library && debug_hook &&
+         hook_index <
+           ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
+      library->debug_hooks[hook_index] = debug_hook;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_FreeType                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given FreeType library object and all of its childs,    */
+  /*    including resources, drivers, faces, sizes, etc.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the target library object.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Done_FreeType( FT_Library  library )
+  {
+    /* test for valid `library' delayed to FT_Done_Library() */
+
+    /* Discard the library object */
+    FT_Done_Library( library );
+
+    return FT_Err_Ok;
+  }
+
+
+/* END */
diff --git a/src/freetype/base/ftoutln.c b/src/freetype/base/ftoutln.c
new file mode 100644 (file)
index 0000000..20292d0
--- /dev/null
@@ -0,0 +1,842 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftoutln.c                                                              */
+/*                                                                         */
+/*    FreeType outline management (body).                                  */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* All functions are declared in freetype.h.                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/ftoutln.h>
+#include <freetype/internal/ftobjs.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_outline
+
+
+  static
+  const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Decompose                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Walks over an outline's structure to decompose it into individual  */
+  /*    segments and Bezier arcs.  This function is also able to emit      */
+  /*    `move to' and `close to' operations to indicate the start and end  */
+  /*    of new contours in the outline.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline   :: A pointer to the source target.                       */
+  /*                                                                       */
+  /*    interface :: A table of `emitters', i.e,. function pointers called */
+  /*                 during decomposition to indicate path operations.     */
+  /*                                                                       */
+  /*    user      :: A typeless pointer which is passed to each emitter    */
+  /*                 during the decomposition.  It can be used to store    */
+  /*                 the state during the decomposition.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means sucess.                              */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_Decompose(
+                                FT_Outline*        outline,
+                                FT_Outline_Funcs*  interface,
+                                void*              user )
+  {
+#undef SCALED
+#define SCALED( x )  ( ( (x) << shift ) - delta )
+
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    FT_Error    error;
+
+    FT_Int   n;         /* index of contour in outline     */
+    FT_UInt  first;     /* index of first point in contour */
+    char     tag;       /* current point's state           */
+
+    FT_Int   shift;
+    FT_Pos   delta;
+
+
+    if ( !outline || !interface )
+      return FT_Err_Invalid_Argument;
+
+    shift = interface->shift;
+    delta = interface->delta;
+    first = 0;
+
+    for ( n = 0; n < outline->n_contours; n++ )
+    {
+      FT_Int  last;  /* index of last point in contour */
+
+
+      last  = outline->contours[n];
+      limit = outline->points + last;
+
+      v_start = outline->points[first];
+      v_last  = outline->points[last];
+
+      v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+      v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
+
+      v_control = v_start;
+
+      point = outline->points + first;
+      tags  = outline->tags  + first;
+      tag   = FT_CURVE_TAG( tags[0] );
+
+      /* A contour cannot start with a cubic control point! */
+      if ( tag == FT_Curve_Tag_Cubic )
+        goto Invalid_Outline;
+
+      /* check first point to determine origin */
+      if ( tag == FT_Curve_Tag_Conic )
+      {
+        /* first point is conic control.  Yes, this happens. */
+        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
+        {
+          /* start at last point if it is on the curve */
+          v_start = v_last;
+          limit--;
+        }
+        else
+        {
+          /* if both first and last points are conic,         */
+          /* start at their middle and record its position    */
+          /* for closure                                      */
+          v_start.x = ( v_start.x + v_last.x ) / 2;
+          v_start.y = ( v_start.y + v_last.y ) / 2;
+
+          v_last = v_start;
+        }
+        point--;
+        tags--;
+      }
+
+      error = interface->move_to( &v_start, user );
+      if ( error )
+        goto Exit;
+
+      while ( point < limit )
+      {
+        point++;
+        tags++;
+
+        tag = FT_CURVE_TAG( tags[0] );
+        switch ( tag )
+        {
+        case FT_Curve_Tag_On:  /* emit a single line_to */
+          {
+            FT_Vector  vec;
+
+
+            vec.x = SCALED( point->x );
+            vec.y = SCALED( point->y );
+
+            error = interface->line_to( &vec, user );
+            if ( error )
+              goto Exit;
+            continue;
+          }
+
+        case FT_Curve_Tag_Conic:  /* consume conic arcs */
+          v_control.x = SCALED( point->x );
+          v_control.y = SCALED( point->y );
+
+        Do_Conic:
+          if ( point < limit )
+          {
+            FT_Vector  vec;
+            FT_Vector  v_middle;
+
+
+            point++;
+            tags++;
+            tag = FT_CURVE_TAG( tags[0] );
+
+            vec.x = SCALED( point->x );
+            vec.y = SCALED( point->y );
+
+            if ( tag == FT_Curve_Tag_On )
+            {
+              error = interface->conic_to( &v_control, &vec, user );
+              if ( error )
+                goto Exit;
+              continue;
+            }
+
+            if ( tag != FT_Curve_Tag_Conic )
+              goto Invalid_Outline;
+
+            v_middle.x = ( v_control.x + vec.x ) / 2;
+            v_middle.y = ( v_control.y + vec.y ) / 2;
+
+            error = interface->conic_to( &v_control, &v_middle, user );
+            if ( error )
+              goto Exit;
+
+            v_control = vec;
+            goto Do_Conic;
+          }
+
+          error = interface->conic_to( &v_control, &v_start, user );
+          goto Close;
+
+        default:  /* FT_Curve_Tag_Cubic */
+          {
+            FT_Vector  vec1, vec2;
+
+
+            if ( point + 1 > limit                             ||
+                 FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+              goto Invalid_Outline;
+
+            point += 2;
+            tags  += 2;
+
+            vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+            vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+            if ( point <= limit )
+            {
+              FT_Vector  vec;
+
+
+              vec.x = SCALED( point->x );
+              vec.y = SCALED( point->y );
+
+              error = interface->cubic_to( &vec1, &vec2, &vec, user );
+              if ( error )
+                goto Exit;
+              continue;
+            }
+
+            error = interface->cubic_to( &vec1, &vec2, &v_start, user );
+            goto Close;
+          }
+        }
+      }
+
+      /* close the contour with a line segment */
+      error = interface->line_to( &v_start, user );
+
+    Close:
+      if ( error )
+        goto Exit;
+
+      first = last + 1;
+    }
+
+    return 0;
+
+  Exit:
+    return error;
+
+  Invalid_Outline:
+    return FT_Err_Invalid_Outline;
+  }
+
+
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_New_Internal(
+                                FT_Memory    memory,
+                                FT_UInt      numPoints,
+                                FT_Int       numContours,
+                                FT_Outline*  outline )
+  {
+    FT_Error  error;
+
+
+    if ( !outline || !memory )
+      return FT_Err_Invalid_Argument;
+
+    *outline = null_outline;
+
+    if ( ALLOC_ARRAY( outline->points,   numPoints * 2L, FT_Pos    ) ||
+         ALLOC_ARRAY( outline->tags,     numPoints,      FT_Byte   ) ||
+         ALLOC_ARRAY( outline->contours, numContours,    FT_UShort ) )
+      goto Fail;
+
+    outline->n_points    = (FT_UShort)numPoints;
+    outline->n_contours  = (FT_Short)numContours;
+    outline->flags      |= ft_outline_owner;
+
+    return FT_Err_Ok;
+
+  Fail:
+    outline->flags |= ft_outline_owner;
+    FT_Outline_Done_Internal( memory, outline );
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_New                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new outline of a given size.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object from where the       */
+  /*                   outline is allocated.  Note however that the new    */
+  /*                   outline will NOT necessarily be FREED, when         */
+  /*                   destroying the library, by FT_Done_FreeType().      */
+  /*                                                                       */
+  /*    numPoints   :: The maximal number of points within the outline.    */
+  /*                                                                       */
+  /*    numContours :: The maximal number of contours within the outline.  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    outline     :: A handle to the new outline.  NULL in case of       */
+  /*                   error.                                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    No.                                                                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The reason why this function takes a `library' parameter is simply */
+  /*    to use the library's memory allocator.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_New( FT_Library   library,
+                                              FT_UInt      numPoints,
+                                              FT_Int       numContours,
+                                              FT_Outline*  outline )
+  {
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    return FT_Outline_New_Internal( library->memory, numPoints,
+                                    numContours, outline );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Copy                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Copies an outline into another one.  Both objects must have the    */
+  /*    same sizes (number of points & number of contours) when this       */
+  /*    function is called.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    source :: A handle to the source outline.                          */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    target :: A handle to the target outline.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_Copy( FT_Outline*  source,
+                                               FT_Outline*  target )
+  {
+    FT_Int  is_owner;
+
+
+    if ( !source            || !target            ||
+         source->n_points   != target->n_points   ||
+         source->n_contours != target->n_contours )
+      return FT_Err_Invalid_Argument;
+
+    MEM_Copy( target->points, source->points,
+              source->n_points * sizeof ( FT_Vector ) );
+
+    MEM_Copy( target->tags, source->tags,
+              source->n_points * sizeof ( FT_Byte ) );
+
+    MEM_Copy( target->contours, source->contours,
+              source->n_contours * sizeof ( FT_Short ) );
+
+    /* copy all flags, except the `ft_outline_owner' one */
+    is_owner      = target->flags & ft_outline_owner;
+    target->flags = source->flags;
+
+    target->flags &= ~ft_outline_owner;
+    target->flags |= is_owner;
+
+    return FT_Err_Ok;
+  }
+
+
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_Done_Internal( FT_Memory    memory,
+                                                        FT_Outline*  outline )
+  {
+    if ( outline )
+    {
+      if ( outline->flags & ft_outline_owner )
+      {
+        FREE( outline->points   );
+        FREE( outline->tags     );
+        FREE( outline->contours );
+      }
+      *outline = null_outline;
+
+      return FT_Err_Ok;
+    }
+    else
+      return FT_Err_Invalid_Argument;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Done                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys an outline created with FT_Outline_New().                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle of the library object used to allocate the     */
+  /*               outline.                                                */
+  /*                                                                       */
+  /*    outline :: A pointer to the outline object to be discarded.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    No.                                                                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the outline's `owner' field is not set, only the outline        */
+  /*    descriptor will be released.                                       */
+  /*                                                                       */
+  /*    The reason why this function takes an `outline' parameter is       */
+  /*    simply to use FT_Free().                                           */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_Done( FT_Library   library,
+                                               FT_Outline*  outline )
+  {
+    /* check for valid `outline' in FT_Outline_Done_Internal() */
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    return FT_Outline_Done_Internal( library->memory, outline );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_CBox                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns an outline's `control box'.  The control box encloses all  */
+  /*    the outline's points, including Bezier control points.  Though it  */
+  /*    coincides with the exact bounding box for most glyphs, it can be   */
+  /*    slightly larger in some situations (like when rotating an outline  */
+  /*    which contains Bezier outside arcs).                               */
+  /*                                                                       */
+  /*    Computing the control box is very fast, while getting the bounding */
+  /*    box can take much more time as it needs to walk over all segments  */
+  /*    and arcs in the outline.  To get the latter, you can use the       */
+  /*    `ftbbox' component which is dedicated to this single task.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    cbox    :: The outline's control box.                              */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Outline_Get_CBox( FT_Outline*  outline,
+                                               FT_BBox*     cbox )
+  {
+    FT_Pos  xMin, yMin, xMax, yMax;
+
+
+    if ( outline && cbox )
+    {
+      if ( outline->n_points == 0 )
+      {
+        xMin = 0;
+        yMin = 0;
+        xMax = 0;
+        yMax = 0;
+      }
+      else
+      {
+        FT_Vector*  vec   = outline->points;
+        FT_Vector*  limit = vec + outline->n_points;
+
+
+        xMin = xMax = vec->x;
+        yMin = yMax = vec->y;
+        vec++;
+
+        for ( ; vec < limit; vec++ )
+        {
+          FT_Pos  x, y;
+
+
+          x = vec->x;
+          if ( x < xMin ) xMin = x;
+          if ( x > xMax ) xMax = x;
+
+          y = vec->y;
+          if ( y < yMin ) yMin = y;
+          if ( y > yMax ) yMax = y;
+        }
+      }
+      cbox->xMin = xMin;
+      cbox->xMax = xMax;
+      cbox->yMin = yMin;
+      cbox->yMax = yMax;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Translate                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Applies a simple translation to the points of an outline.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /*    xOffset :: The horizontal offset.                                  */
+  /*                                                                       */
+  /*    yOffset :: The vertical offset.                                    */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Outline_Translate( FT_Outline*  outline,
+                                                FT_Pos       xOffset,
+                                                FT_Pos       yOffset )
+  {
+    FT_UShort   n;
+    FT_Vector*  vec = outline->points;
+
+
+    for ( n = 0; n < outline->n_points; n++ )
+    {
+      vec->x += xOffset;
+      vec->y += yOffset;
+      vec++;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Reverse                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reverses the drawing direction of an outline.  This is used to     */
+  /*    ensure consistent fill conventions for mirrored glyphs.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This functions toggles the bit flag `ft_outline_reverse_fill' in   */
+  /*    the outline's `flags' field.                                       */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Outline_Reverse( FT_Outline*  outline )
+  {
+    FT_UShort  n;
+    FT_Int     first, last;
+
+
+    first = 0;
+
+    for ( n = 0; n < outline->n_contours; n++ )
+    {
+      last  = outline->contours[n];
+
+      /* reverse point table */
+      {
+        FT_Vector*  p = outline->points + first;
+        FT_Vector*  q = outline->points + last;
+        FT_Vector   swap;
+
+
+        while ( p < q )
+        {
+          swap = *p;
+          *p   = *q;
+          *q   = swap;
+          p++;
+          q--;
+        }
+      }
+
+      /* reverse tags table */
+      {
+        char*  p = outline->tags + first;
+        char*  q = outline->tags + last;
+        char   swap;
+
+
+        while ( p < q )
+        {
+          swap = *p;
+          *p   = *q;
+          *q   = swap;
+          p++;
+          q--;
+        }
+      }
+
+      first = last + 1;
+    }
+
+    outline->flags ^= ft_outline_reverse_fill;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Render                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders an outline within a bitmap using the current scan-convert. */
+  /*    This functions uses an FT_Raster_Params structure as an argument,  */
+  /*    allowing advanced features like direct composition, translucency,  */
+  /*    etc.                                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a FreeType library object.                  */
+  /*                                                                       */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /*    params  :: A pointer to a FT_Raster_Params structure used to       */
+  /*               describe the rendering operation.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    YES.  Rendering is synchronized, so that concurrent calls to the   */
+  /*    scan-line converter will be serialized.                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should know what you are doing and how FT_Raster_Params works  */
+  /*    to use this function.                                              */
+  /*                                                                       */
+  /*    The field `params.source' will be set to `outline' before the scan */
+  /*    converter is called, which means that the value you give to it is  */
+  /*    actually ignored.                                                  */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_Render( FT_Library         library,
+                                                 FT_Outline*        outline,
+                                                 FT_Raster_Params*  params )
+  {
+    FT_Error     error;
+    FT_Bool      update = 0;
+    FT_Renderer  renderer;
+    FT_ListNode  node;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !params )
+      return FT_Err_Invalid_Argument;
+
+    renderer = library->cur_renderer;
+    node     = library->renderers.head;
+
+    params->source = (void*)outline;
+
+    error = FT_Err_Cannot_Render_Glyph;
+    while ( renderer )
+    {
+      error = renderer->raster_render( renderer->raster, params );
+      if ( !error || error != FT_Err_Cannot_Render_Glyph )
+        break;
+
+      /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
+      /* is unsupported by the current renderer for this glyph image */
+      /* format                                                      */
+
+      /* now, look for another renderer that supports the same */
+      /* format                                                */
+      renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline,
+                                     &node );
+      update   = 1;
+    }
+
+    /* if we changed the current renderer for the glyph image format */
+    /* we need to select it as the next current one                  */
+    if ( !error && update && renderer )
+      FT_Set_Renderer( library, renderer, 0, 0 );
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_Bitmap                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders an outline within a bitmap.  The outline's image is simply */
+  /*    OR-ed to the target bitmap.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a FreeType library object.                  */
+  /*                                                                       */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /*    map     :: A pointer to the target bitmap descriptor.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    YES.  Rendering is synchronized, so that concurrent calls to the   */
+  /*    scan-line converter will be serialized.                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT CREATE the bitmap, it only renders an       */
+  /*    outline image within the one you pass to it!                       */
+  /*                                                                       */
+  /*    It will use the raster correponding to the default glyph format.   */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_Outline_Get_Bitmap( FT_Library   library,
+                                                     FT_Outline*  outline,
+                                                     FT_Bitmap*   bitmap )
+  {
+    FT_Raster_Params  params;
+
+
+    if ( !bitmap )
+      return FT_Err_Invalid_Argument;
+
+    /* other checks are delayed to FT_Outline_Render() */
+
+    params.target = bitmap;
+    params.flags  = 0;
+
+    if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+      params.flags |= ft_raster_flag_aa;
+
+    return FT_Outline_Render( library, outline, &params );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Vector_Transform                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Transforms a single vector through a 2x2 matrix.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    vector :: The target vector to transform.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to the source 2x2 matrix.                      */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The result is undefined if either `vector' or `matrix' is invalid. */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Vector_Transform( FT_Vector*  vector,
+                                               FT_Matrix*  matrix )
+  {
+    FT_Pos xz, yz;
+
+
+    if ( !vector || !matrix )
+      return;
+
+    xz = FT_MulFix( vector->x, matrix->xx ) +
+         FT_MulFix( vector->y, matrix->xy );
+
+    yz = FT_MulFix( vector->x, matrix->yx ) +
+         FT_MulFix( vector->y, matrix->yy );
+
+    vector->x = xz;
+    vector->y = yz;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Transform                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Applies a simple 2x2 matrix to all of an outline's points.  Useful */
+  /*    for applying rotations, slanting, flipping, etc.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /*    matrix  :: A pointer to the transformation matrix.                 */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You can use FT_Outline_Translate() if you need to translate the    */
+  /*    outline's points.                                                  */
+  /*                                                                       */
+  FT_EXPORT_FUNC( void )  FT_Outline_Transform( FT_Outline*  outline,
+                                                FT_Matrix*   matrix )
+  {
+    FT_Vector*  vec = outline->points;
+    FT_Vector*  limit = vec + outline->n_points;
+
+
+    for ( ; vec < limit; vec++ )
+      FT_Vector_Transform( vec, matrix );
+  }
+
+/* END */
diff --git a/src/freetype/base/ftstream.c b/src/freetype/base/ftstream.c
new file mode 100644 (file)
index 0000000..768586e
--- /dev/null
@@ -0,0 +1,818 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftstream.c                                                             */
+/*                                                                         */
+/*    I/O stream support (body).                                           */
+/*                                                                         */
+/*  Copyright 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 <freetype/internal/ftstream.h>
+#include <freetype/internal/ftdebug.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_stream
+
+
+  BASE_FUNC( void )  FT_New_Memory_Stream( FT_Library  library,
+                                           FT_Byte*    base,
+                                           FT_ULong    size,
+                                           FT_Stream   stream )
+  {
+    stream->memory = library->memory;
+    stream->base   = base;
+    stream->size   = size;
+    stream->pos    = 0;
+    stream->cursor = 0;
+    stream->read   = 0;
+    stream->close  = 0;
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_Seek_Stream( FT_Stream  stream,
+                                         FT_ULong   pos )
+  {
+    FT_Error  error;
+
+
+    stream->pos = pos;
+
+    if ( stream->read )
+    {
+      if ( stream->read( stream, pos, 0, 0 ) )
+      {
+        FT_ERROR(( "FT_Seek_Stream:" ));
+        FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+                   pos, stream->size ));
+
+        error = FT_Err_Invalid_Stream_Operation;
+      }
+      else
+        error = FT_Err_Ok;
+    }
+    /* note that seeking to the first position after the file is valid */
+    else if ( pos > stream->size )
+    {
+      FT_ERROR(( "FT_Seek_Stream:" ));
+      FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+                 pos, stream->size ));
+
+      error = FT_Err_Invalid_Stream_Operation;
+    }
+
+    else
+      error = FT_Err_Ok;
+
+    return error;
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_Skip_Stream( FT_Stream  stream,
+                                         FT_Long    distance )
+  {
+    return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) );
+  }
+
+
+  BASE_FUNC( FT_Long )  FT_Stream_Pos( FT_Stream  stream )
+  {
+    return stream->pos;
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_Read_Stream( FT_Stream  stream,
+                                         FT_Byte*   buffer,
+                                         FT_ULong   count )
+  {
+    return FT_Read_Stream_At( stream, stream->pos, buffer, count );
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_Read_Stream_At( FT_Stream  stream,
+                                            FT_ULong   pos,
+                                            FT_Byte*   buffer,
+                                            FT_ULong   count )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_ULong  read_bytes;
+
+
+    if ( pos >= stream->size )
+    {
+      FT_ERROR(( "FT_Read_Stream_At:" ));
+      FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+                 pos, stream->size ));
+
+      return FT_Err_Invalid_Stream_Operation;
+    }
+
+    if ( stream->read )
+      read_bytes = stream->read( stream, pos, buffer, count );
+    else
+    {
+      read_bytes = stream->size - pos;
+      if ( read_bytes > count )
+        read_bytes = count;
+
+      MEM_Copy( buffer, stream->base + pos, read_bytes );
+    }
+
+    stream->pos = pos + read_bytes;
+
+    if ( read_bytes < count )
+    {
+      FT_ERROR(( "FT_Read_Stream_At:" ));
+      FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+                 count, read_bytes ));
+
+      error = FT_Err_Invalid_Stream_Operation;
+    }
+
+    return error;
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_Extract_Frame( FT_Stream  stream,
+                                           FT_ULong   count,
+                                           FT_Byte**  pbytes )
+  {
+    FT_Error  error;
+
+
+    error = FT_Access_Frame( stream, count );
+    if ( !error )
+    {
+      *pbytes = (FT_Byte*)stream->cursor;
+
+      /* equivalent to FT_Forget_Frame(), with no memory block release */
+      stream->cursor = 0;
+      stream->limit  = 0;
+    }
+
+    return error;
+  }
+
+
+  BASE_FUNC( void )  FT_Release_Frame( FT_Stream  stream,
+                                       FT_Byte**  pbytes )
+  {
+    if ( stream->read )
+    {
+      FT_Memory  memory = stream->memory;
+
+
+      FREE( *pbytes );
+    }
+    *pbytes = 0;
+  }
+
+
+  BASE_FUNC( FT_Error )  FT_Access_Frame( FT_Stream  stream,
+                                          FT_ULong   count )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_ULong  read_bytes;
+
+
+    /* check for nested frame access */
+    FT_Assert( stream && stream->cursor == 0 );
+
+    if ( stream->read )
+    {
+      /* allocate the frame in memory */
+      FT_Memory  memory = stream->memory;
+
+
+      if ( ALLOC( stream->base, count ) )
+        goto Exit;
+
+      /* read it */
+      read_bytes = stream->read( stream, stream->pos,
+                                 stream->base, count );
+      if ( read_bytes < count )
+      {
+        FT_ERROR(( "FT_Access_Frame:" ));
+        FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+                   count, read_bytes ));
+
+        FREE( stream->base );
+        error = FT_Err_Invalid_Stream_Operation;
+      }
+      stream->cursor = stream->base;
+      stream->limit  = stream->cursor + count;
+      stream->pos   += read_bytes;
+    }
+    else
+    {
+      /* check current and new position */
+      if ( stream->pos >= stream->size        ||
+           stream->pos + count > stream->size )
+      {
+        FT_ERROR(( "FT_Access_Frame:" ));
+        FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
+                   stream->pos, count, stream->size ));
+
+        error = FT_Err_Invalid_Stream_Operation;
+        goto Exit;
+      }
+
+      /* set cursor */
+      stream->cursor = stream->base + stream->pos;
+      stream->limit  = stream->cursor + count;
+      stream->pos   += count;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  BASE_FUNC( void )  FT_Forget_Frame( FT_Stream  stream )
+  {
+    /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
+    /*            that it is possible to access a frame of length 0 in    */
+    /*            some weird fonts (usually, when accessing an array of   */
+    /*            0 records, like in some strange kern tables).           */
+    /*                                                                    */
+    /*  In this case, the loader code handles the 0-length table          */
+    /*  gracefully; however, stream.cursor is really set to 0 by the      */
+    /*  FT_Access_Frame() call, and this is not an error.                 */
+    /*                                                                    */
+    FT_Assert( stream );
+
+    if ( stream->read )
+    {
+      FT_Memory  memory = stream->memory;
+
+
+      FREE( stream->base );
+    }
+    stream->cursor = 0;
+    stream->limit  = 0;
+  }
+
+
+  BASE_FUNC( FT_Char )  FT_Get_Char( FT_Stream  stream )
+  {
+    FT_Char  result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result = 0;
+    if ( stream->cursor < stream->limit )
+      result = *stream->cursor++;
+
+    return result;
+  }
+
+
+  BASE_FUNC( FT_Short )  FT_Get_Short( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Short  result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 1 < stream->limit )
+      result       = NEXT_Short( p );
+    stream->cursor = p;
+
+    return result;
+  }
+
+
+  BASE_FUNC( FT_Short )  FT_Get_ShortLE( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Short  result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 1 < stream->limit )
+      result       = NEXT_ShortLE( p );
+    stream->cursor = p;
+
+    return result;
+  }
+
+
+  BASE_FUNC( FT_Long )  FT_Get_Offset( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Long   result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 2 < stream->limit )
+      result       = NEXT_Offset( p );
+    stream->cursor = p;
+    return result;
+  }
+
+
+  BASE_FUNC( FT_Long )  FT_Get_Long( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Long   result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 3 < stream->limit )
+      result       = NEXT_Long( p );
+    stream->cursor = p;
+    return result;
+  }
+
+
+  BASE_FUNC( FT_Long )  FT_Get_LongLE( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Long   result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 3 < stream->limit )
+      result       = NEXT_LongLE( p );
+    stream->cursor = p;
+    return result;
+  }
+
+
+  BASE_FUNC( FT_Char )  FT_Read_Char( FT_Stream  stream,
+                                      FT_Error*  error )
+  {
+    FT_Byte  result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->read )
+    {
+      if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
+        goto Fail;
+    }
+    else
+    {
+      if ( stream->pos < stream->size )
+        result = stream->base[stream->pos];
+      else
+        goto Fail;
+    }
+    stream->pos++;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Char:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  BASE_FUNC( FT_Short )  FT_Read_Short( FT_Stream  stream,
+                                        FT_Error*  error )
+  {
+    FT_Byte   reads[2];
+    FT_Byte*  p = 0;
+    FT_Short  result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 1 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_Short( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 2;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Short:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  BASE_FUNC( FT_Short )  FT_Read_ShortLE( FT_Stream  stream,
+                                          FT_Error*  error )
+  {
+    FT_Byte   reads[2];
+    FT_Byte*  p = 0;
+    FT_Short  result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 1 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_ShortLE( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 2;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Short:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  BASE_FUNC( FT_Long )  FT_Read_Offset( FT_Stream  stream,
+                                        FT_Error*  error )
+  {
+    FT_Byte   reads[3];
+    FT_Byte*  p = 0;
+    FT_Long   result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 2 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_Offset( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 3;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Offset:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  BASE_FUNC( FT_Long )  FT_Read_Long( FT_Stream  stream,
+                                      FT_Error*  error )
+  {
+    FT_Byte   reads[4];
+    FT_Byte*  p = 0;
+    FT_Long   result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 3 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_Long( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 4;
+
+    return result;
+
+  Fail:
+    FT_ERROR(( "FT_Read_Long:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+    *error = FT_Err_Invalid_Stream_Operation;
+
+    return 0;
+  }
+
+
+  BASE_FUNC( FT_Long )  FT_Read_LongLE( FT_Stream  stream,
+                                        FT_Error*  error )
+  {
+    FT_Byte   reads[4];
+    FT_Byte*  p = 0;
+    FT_Long   result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 3 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_LongLE( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 4;
+
+    return result;
+
+  Fail:
+    FT_ERROR(( "FT_Read_Long:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+    *error = FT_Err_Invalid_Stream_Operation;
+
+    return 0;
+  }
+
+
+  BASE_FUNC( FT_Error ) FT_Read_Fields( FT_Stream              stream,
+                                        const FT_Frame_Field*  fields,
+                                        void*                  structure )
+  {
+    FT_Error  error;
+    FT_Bool   frame_accessed = 0;
+
+
+    if ( !fields || !stream )
+      return FT_Err_Invalid_Argument;
+
+    error = FT_Err_Ok;
+    do
+    {
+      FT_ULong  value;
+      FT_Int    sign_shift;
+      FT_Byte*  p;
+
+
+      switch ( fields->value )
+      {
+      case ft_frame_start:  /* access a new frame */
+        error = FT_Access_Frame( stream, fields->offset );
+        if ( error )
+          goto Exit;
+
+        frame_accessed = 1;
+        fields++;
+        continue;  /* loop! */
+
+      case ft_frame_bytes:  /* read a byte sequence */
+      case ft_frame_skip:   /* skip some bytes      */
+        {
+          FT_Int  len = fields->size;
+
+
+          if ( stream->cursor + len > stream->limit )
+          {
+            error = FT_Err_Invalid_Stream_Operation;
+            goto Exit;
+          }
+
+          if ( fields->value == ft_frame_bytes )
+          {
+            p = (FT_Byte*)structure + fields->offset;
+            MEM_Copy( p, stream->cursor, len );
+          }
+          stream->cursor += len;
+          fields++;
+          continue;
+        }
+
+      case ft_frame_byte:
+      case ft_frame_schar:  /* read a single byte */
+        value = GET_Byte();
+        sign_shift = 24;
+        break;
+
+      case ft_frame_short_be:
+      case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
+        value = GET_UShort();
+        sign_shift = 16;
+        break;
+
+      case ft_frame_short_le:
+      case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
+        {
+          FT_Byte*  p;
+
+
+          value = 0;
+          p     = stream->cursor;
+
+          if ( p + 1 < stream->limit )
+          {
+            value = ( FT_UShort)p[0] | ((FT_UShort)p[1] << 8 );
+            stream->cursor += 2;
+          }
+          sign_shift = 16;
+          break;
+        }
+
+      case ft_frame_long_be:
+      case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
+        value = GET_ULong();
+        sign_shift = 0;
+        break;
+
+      case ft_frame_long_le:
+      case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
+        {
+          FT_Byte*  p;
+
+
+          value = 0;
+          p     = stream->cursor;
+
+          if ( p + 3 < stream->limit )
+          {
+            value =   (FT_ULong)p[0]         |
+                    ( (FT_ULong)p[1] << 8  ) |
+                    ( (FT_ULong)p[2] << 16 ) |
+                    ( (FT_ULong)p[3] << 24 );
+            stream->cursor += 4;
+          }
+          sign_shift = 0;
+          break;
+        }
+
+      case ft_frame_off3_be:
+      case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
+        value = GET_UOffset();
+        sign_shift = 8;
+        break;
+
+      case ft_frame_off3_le:
+      case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
+        {
+          FT_Byte*  p;
+
+
+          value = 0;
+          p     = stream->cursor;
+
+          if ( p + 2 < stream->limit )
+          {
+            value =   (FT_ULong)p[0]         |
+                    ( (FT_ULong)p[1] << 8  ) |
+                    ( (FT_ULong)p[2] << 16 );
+            stream->cursor += 3;
+          }
+          sign_shift = 8;
+          break;
+        }
+
+      default:
+        /* otherwise, exit the loop */
+        goto Exit;
+      }
+
+      /* now, compute the signed value is necessary */
+      if ( fields->value & FT_FRAME_OP_SIGNED )
+        value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
+
+      /* finally, store the value in the object */
+
+      p = (FT_Byte*)structure + fields->offset;
+      switch ( fields->size )
+      {
+      case 1:
+        *(FT_Byte*)p = (FT_Byte)value;
+        break;
+
+      case 2:
+        *(FT_UShort*)p = (FT_UShort)value;
+        break;
+
+      case 4:
+        *(FT_UInt32*)p = (FT_UInt32)value;
+        break;
+
+      default:  /* for 64-bit systems */
+        *(FT_ULong*)p = (FT_ULong)value;
+      }
+
+      /* go to next field */
+      fields++;
+    }
+    while ( 1 );
+
+  Exit:
+    /* close the frame if it was opened by this read */
+    if ( frame_accessed )
+      FT_Forget_Frame( stream );
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/base/ftsystem.c b/src/freetype/base/ftsystem.c
new file mode 100644 (file)
index 0000000..b99b0ea
--- /dev/null
@@ -0,0 +1,299 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsystem.c                                                             */
+/*                                                                         */
+/*    ANSI-specific FreeType low-level system interface (body).            */
+/*                                                                         */
+/*  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 contains the default interface used by FreeType to access   */
+  /* low-level, i.e. memory management, i/o access as well as thread       */
+  /* synchronisation.  It can be replaced by user-specific routines if     */
+  /* necessary.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftsystem.h>
+#include <freetype/fterrors.h>
+#include <freetype/fttypes.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       MEMORY MANAGEMENT INTERFACE                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* It is not necessary to do any error checking for the                  */
+  /* allocation-related functions.  This will be done by the higher level  */
+  /* routines like FT_Alloc() or FT_Realloc().                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_alloc                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory allocation function.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A pointer to the memory object.                          */
+  /*                                                                       */
+  /*    size   :: The requested size in bytes.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    block  :: The address of newly allocated block.                    */
+  /*                                                                       */
+  static
+  void*  ft_alloc( FT_Memory  memory,
+                   long       size )
+  {
+    FT_UNUSED( memory );
+
+    return malloc( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_realloc                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory reallocation function.                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory   :: A pointer to the memory object.                        */
+  /*                                                                       */
+  /*    cur_size :: The current size of the allocated memory block.        */
+  /*                                                                       */
+  /*    new_size :: The newly requested size in bytes.                     */
+  /*                                                                       */
+  /*    block    :: The current address of the block in memory.            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the reallocated memory block.                       */
+  /*                                                                       */
+  static
+  void*  ft_realloc( FT_Memory  memory,
+                     long       cur_size,
+                     long       new_size,
+                     void*      block )
+  {
+    FT_UNUSED( memory );
+    FT_UNUSED( cur_size );
+
+    return realloc( block, new_size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_free                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory release function.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory  :: A pointer to the memory object.                         */
+  /*                                                                       */
+  /*    block   :: The address of block in memory to be freed.             */
+  /*                                                                       */
+  static
+  void  ft_free( FT_Memory  memory,
+                 void*      block )
+  {
+    FT_UNUSED( memory );
+
+    free( block );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     RESOURCE MANAGEMENT INTERFACE                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_io
+
+  /* We use the macro STREAM_FILE for convenience to extract the       */
+  /* system-specific stream handle from a given FreeType stream object */
+#define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_close_stream                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The function to close a stream.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A pointer to the stream object.                          */
+  /*                                                                       */
+  static
+  void  ft_close_stream( FT_Stream  stream )
+  {
+    fclose( STREAM_FILE( stream ) );
+
+    stream->descriptor.pointer = NULL;
+    stream->size               = 0;
+    stream->base               = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_io_stream                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The function to open a stream.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A pointer to the stream object.                          */
+  /*                                                                       */
+  /*    offset :: The position in the data stream to start reading.        */
+  /*                                                                       */
+  /*    buffer :: The address of buffer to store the read data.            */
+  /*                                                                       */
+  /*    count  :: The number of bytes to read from the stream.             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The number of bytes actually read.                                 */
+  /*                                                                       */
+  static
+  unsigned long  ft_io_stream( FT_Stream       stream,
+                               unsigned long   offset,
+                               unsigned char*  buffer,
+                               unsigned long   count )
+  {
+    FILE*  file;
+
+
+    file = STREAM_FILE( stream );
+
+    fseek( file, offset, SEEK_SET );
+
+    return (unsigned long)fread( buffer, 1, count, file );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Stream                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new stream object.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    filepathname :: The name of the stream (usually a file) to be      */
+  /*                    opened.                                            */
+  /*                                                                       */
+  /*    stream       :: A pointer to the stream object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_New_Stream( const char*  filepathname,
+                                             FT_Stream    stream )
+  {
+    FILE*  file;
+
+
+    if ( !stream )
+      return FT_Err_Invalid_Stream_Handle;
+
+    file = fopen( filepathname, "rb" );
+    if ( !file )
+    {
+      FT_ERROR(( "FT_New_Stream:" ));
+      FT_ERROR(( " could not open `%s'\n", filepathname ));
+
+      return FT_Err_Cannot_Open_Resource;
+    }
+
+    fseek( file, 0, SEEK_END );
+    stream->size = ftell( file );
+    fseek( file, 0, SEEK_SET );
+
+    stream->descriptor.pointer = file;
+    stream->pathname.pointer   = (char*)filepathname;
+    stream->pos                = 0;
+
+    stream->read  = ft_io_stream;
+    stream->close = ft_close_stream;
+
+    FT_TRACE1(( "FT_New_Stream:" ));
+    FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
+                filepathname, stream->size ));
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Memory                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new memory object.                                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A pointer to the new memory object.  0 in case of error.           */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Memory )  FT_New_Memory( void )
+  {
+    FT_Memory  memory;
+
+
+    memory = (FT_Memory)malloc( sizeof ( *memory ) );
+    if ( memory )
+    {
+      memory->user    = 0;
+      memory->alloc   = ft_alloc;
+      memory->realloc = ft_realloc;
+      memory->free    = ft_free;
+    }
+
+    return memory;
+  }
+
+
+/* END */
diff --git a/src/freetype/base/rules.mk b/src/freetype/base/rules.mk
new file mode 100644 (file)
index 0000000..1763a09
--- /dev/null
@@ -0,0 +1,83 @@
+#
+# FreeType 2 base layer configuration rules
+#
+
+
+# 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.
+
+
+# It sets the following variables which are used by the master Makefile
+# after the call:
+#
+#   BASE_OBJ_S:   The single-object base layer.
+#   BASE_OBJ_M:   A list of all objects for a multiple-objects build.
+#   BASE_EXT_OBJ: A list of base layer extensions, i.e., components found
+#                 in `freetype/src/base' which are not compiled within the
+#                 base layer proper.
+#
+# BASE_H is defined in freetype.mk to simplify the dependency rules.
+
+
+BASE_COMPILE := $(FT_COMPILE) $I$(SRC_)base
+
+
+# Base layer sources
+#
+#   ftsystem, ftinit, and ftdebug are handled by freetype.mk
+#
+BASE_SRC := $(BASE_)ftcalc.c   \
+            $(BASE_)ftextend.c \
+            $(BASE_)ftlist.c   \
+            $(BASE_)ftobjs.c   \
+            $(BASE_)ftstream.c \
+            $(BASE_)ftoutln.c
+
+# Base layer `extensions' sources
+#
+# An extension is added to the library file (.a or .lib) as a separate
+# object.  It will then be linked to the final executable only if one of its
+# symbols is used by the application.
+#
+BASE_EXT_SRC := $(BASE_)ftglyph.c  \
+                $(BASE_)ftmm.c
+
+# Default extensions objects
+#
+BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_)%.c=$(OBJ_)%.$O)
+
+
+# Base layer object(s)
+#
+#   BASE_OBJ_M is used during `multi' builds (each base source file compiles
+#   to a single object file).
+#
+#   BASE_OBJ_S is used during `single' builds (the whole base layer is
+#   compiled as a single object file using ftbase.c).
+#
+BASE_OBJ_M := $(BASE_SRC:$(BASE_)%.c=$(OBJ_)%.$O)
+BASE_OBJ_S := $(OBJ_)ftbase.$O
+
+# Base layer root source file for single build
+#
+BASE_SRC_S := $(BASE_)ftbase.c
+
+
+# Base layer - single object build
+#
+$(BASE_OBJ_S): $(BASE_SRC_S) $(BASE_SRC) $(FREETYPE_H)
+       $(BASE_COMPILE) $T$@ $(BASE_SRC_S)
+
+
+# Multiple objects build + extensions
+#
+$(OBJ_)%.$O: $(BASE_)%.c $(FREETYPE_H)
+       $(BASE_COMPILE) $T$@ $<
+
+# EOF
diff --git a/src/freetype/cff/cff.c b/src/freetype/cff/cff.c
new file mode 100644 (file)
index 0000000..5a987f1
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cff.c                                                                  */
+/*                                                                         */
+/*    FreeType OpenType driver component (body only).                      */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2driver.c"    /* driver interface     */
+#include "t2parse.c"     /* token parser         */
+#include "t2load.c"      /* tables loader        */
+#include "t2objs.c"      /* object management    */
+#include "t2gload.c"     /* glyph loader         */
+
+#else
+
+#include <cff/t2driver.c>    /* driver interface     */
+#include <cff/t2parse.c>     /* token parser         */
+#include <cff/t2load.c>      /* tables loader        */
+#include <cff/t2objs.c>      /* object management    */
+#include <cff/t2gload.c>     /* glyph loader         */
+
+#endif
+
+
+/* END */
diff --git a/src/freetype/cff/module.mk b/src/freetype/cff/module.mk
new file mode 100644 (file)
index 0000000..9bc5c8f
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_cff_driver
+
+add_cff_driver:
+       $(OPEN_DRIVER)cff_driver_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)cff       $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/cff/rules.mk b/src/freetype/cff/rules.mk
new file mode 100644 (file)
index 0000000..ba87af5
--- /dev/null
@@ -0,0 +1,69 @@
+#
+# FreeType 2 OpenType/CFF driver configuration rules
+#
+
+
+# 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.
+
+
+# OpenType driver directory
+#
+T2_DIR  := $(SRC_)cff
+T2_DIR_ := $(T2_DIR)$(SEP)
+
+
+T2_COMPILE := $(FT_COMPILE)
+
+
+# T2 driver sources (i.e., C files)
+#
+T2_DRV_SRC := $(T2_DIR_)t2objs.c   \
+              $(T2_DIR_)t2load.c   \
+              $(T2_DIR_)t2gload.c  \
+              $(T2_DIR_)t2parse.c  \
+              $(T2_DIR_)t2driver.c
+
+# T2 driver headers
+#
+T2_DRV_H := $(T2_DRV_SRC:%.c=%.h) \
+            $(T2_DIR_)t2tokens.h
+
+
+# T2 driver object(s)
+#
+#   T2_DRV_OBJ_M is used during `multi' builds
+#   T2_DRV_OBJ_S is used during `single' builds
+#
+T2_DRV_OBJ_M := $(T2_DRV_SRC:$(T2_DIR_)%.c=$(OBJ_)%.$O)
+T2_DRV_OBJ_S := $(OBJ_)cff.$O
+
+# T2 driver source file for single build
+#
+T2_DRV_SRC_S := $(T2_DIR_)cff.c
+
+
+# T2 driver - single object
+#
+$(T2_DRV_OBJ_S): $(T2_DRV_SRC_S) $(T2_DRV_SRC) $(FREETYPE_H) $(T2_DRV_H)
+       $(T2_COMPILE) $T$@ $(T2_DRV_SRC_S)
+
+
+# T2 driver - multiple objects
+#
+$(OBJ_)%.$O: $(T2_DIR_)%.c $(FREETYPE_H) $(T2_DRV_H)
+       $(T2_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T2_DRV_OBJ_S)
+DRV_OBJS_M += $(T2_DRV_OBJ_M)
+
+# EOF
diff --git a/src/freetype/cff/t2driver.c b/src/freetype/cff/t2driver.c
new file mode 100644 (file)
index 0000000..d1e1b18
--- /dev/null
@@ -0,0 +1,377 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2driver.c                                                             */
+/*                                                                         */
+/*    OpenType font driver implementation (body).                          */
+/*                                                                         */
+/*  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 <freetype/freetype.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/ttnameid.h>
+
+#include <freetype/internal/t2errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2driver.h"
+#include "t2gload.h"
+
+#else
+
+#include <cff/t2driver.h>
+#include <cff/t2gload.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t2driver
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                          F A C E S                              ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#undef  PAIR_TAG
+#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
+                                     (FT_ULong)right        )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings, are out of scope of this method (the basic driver        */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static
+  FT_Error  Get_Kerning( TT_Face     face,
+                         FT_UInt     left_glyph,
+                         FT_UInt     right_glyph,
+                         FT_Vector*  kerning )
+  {
+    TT_Kern_0_Pair*  pair;
+
+
+    if ( !face )
+      return T2_Err_Invalid_Face_Handle;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    if ( face->kern_pairs )
+    {
+      /* there are some kerning pairs in this font file! */
+      FT_ULong  search_tag = PAIR_TAG( left_glyph, right_glyph );
+      FT_Long   left, right;
+
+
+      left  = 0;
+      right = face->num_kern_pairs - 1;
+
+      while ( left <= right )
+      {
+        FT_Int    middle = left + ( ( right - left ) >> 1 );
+        FT_ULong  cur_pair;
+
+
+        pair     = face->kern_pairs + middle;
+        cur_pair = PAIR_TAG( pair->left, pair->right );
+
+        if ( cur_pair == search_tag )
+          goto Found;
+
+        if ( cur_pair < search_tag )
+          left = middle + 1;
+        else
+          right = middle - 1;
+      }
+    }
+
+  Exit:
+    return T2_Err_Ok;
+
+  Found:
+    kerning->x = pair->value;
+    goto Exit;
+  }
+
+
+#undef PAIR_TAG
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_Glyph                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to load a glyph within a given glyph slot.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot        :: A handle to the target slot object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled, loaded, etc.                        */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FTLOAD_??? constants can be used to control the     */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Load_Glyph( T2_GlyphSlot  slot,
+                        T2_Size       size,
+                        FT_UShort     glyph_index,
+                        FT_UInt       load_flags )
+  {
+    FT_Error  error;
+
+
+    if ( !slot )
+      return T2_Err_Invalid_Glyph_Handle;
+
+    /* check whether we want a scaled outline or bitmap */
+    if ( !size )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    if ( load_flags & FT_LOAD_NO_SCALE )
+      size = NULL;
+
+    /* reset the size object if necessary */
+    if ( size )
+    {
+      /* these two object must have the same parent */
+      if ( size->face != slot->root.face )
+        return T2_Err_Invalid_Face_Handle;
+    }
+
+    /* now load the glyph outline if necessary */
+    error = T2_Load_Glyph( slot, size, glyph_index, load_flags );
+
+    /* force drop-out mode to 2 - irrelevant now */
+    /* slot->outline.dropout_mode = 2; */
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****             C H A R A C T E R   M A P P I N G S                 ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  FT_UInt  t2_get_char_index( TT_CharMap  charmap,
+                              FT_Long     charcode )
+  {
+    FT_Error       error;
+    T2_Face        face;
+    TT_CMapTable*  cmap;
+
+
+    cmap = &charmap->cmap;
+    face = (T2_Face)charmap->root.face;
+
+    /* Load table if needed */
+    if ( !cmap->loaded )
+    {
+      SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+
+      error = sfnt->load_charmap( face, cmap, face->root.stream );
+      if ( error )
+        return 0;
+
+      cmap->loaded = TRUE;
+    }
+
+    return ( cmap->get_index ? cmap->get_index( cmap, charcode ) : 0 );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                D R I V E R  I N T E R F A C E                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Module_Interface  t2_get_interface( T2_Driver    driver,
+                                         const char*  interface )
+  {
+    FT_Module  sfnt;
+
+
+    /* we simply pass our request to the `sfnt' module */
+    sfnt = FT_Get_Module( driver->root.root.library, "sfnt" );
+
+    return sfnt ? sfnt->clazz->get_interface( sfnt, interface ) : 0;
+  }
+
+
+  /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+  const FT_Driver_Class   cff_driver_class =
+  {
+    /* begin with the FT_Module_Class fields */
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( T2_DriverRec ),
+      "cff",
+      0x10000L,
+      0x20000L,
+
+      0,   /* module-specific interface */
+
+      (FT_Module_Constructor)T2_Init_Driver,
+      (FT_Module_Destructor) T2_Done_Driver,
+      (FT_Module_Requester)  t2_get_interface,
+    },
+
+    /* now the specific driver fields */
+    sizeof( TT_FaceRec ),
+    sizeof( FT_SizeRec ),
+    sizeof( T2_GlyphSlotRec ),
+
+    (FTDriver_initFace)     T2_Init_Face,
+    (FTDriver_doneFace)     T2_Done_Face,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) 0,
+    (FTDriver_setPixelSizes)0,
+
+    (FTDriver_loadGlyph)    Load_Glyph,
+    (FTDriver_getCharIndex) t2_get_char_index,
+
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   0,
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  EXPORT_FUNC( FT_Driver_Class* )  getDriverClass( void )
+  {
+    return &cff_driver_class;
+  }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/src/freetype/cff/t2driver.h b/src/freetype/cff/t2driver.h
new file mode 100644 (file)
index 0000000..e0b0afd
--- /dev/null
@@ -0,0 +1,30 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2driver.h                                                             */
+/*                                                                         */
+/*    High-level OpenType driver interface (specification).                */
+/*                                                                         */
+/*  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 T2DRIVER_H
+#define T2DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+  FT_EXPORT_VAR( const FT_Driver_Class )  cff_driver_class;
+
+
+#endif /* T2DRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/cff/t2gload.c b/src/freetype/cff/t2gload.c
new file mode 100644 (file)
index 0000000..1023e3c
--- /dev/null
@@ -0,0 +1,2045 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2gload.c                                                              */
+/*                                                                         */
+/*    OpenType Glyph Loader (body).                                        */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/ftoutln.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2load.h"
+#include "t2gload.h"
+
+#else
+
+#include <cff/t2load.h>
+#include <cff/t2gload.h>
+
+#endif
+
+
+#include <freetype/internal/t2errors.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t2gload
+
+
+  typedef enum  T2_Operator_
+  {
+    t2_op_unknown = 0,
+
+    t2_op_rmoveto,
+    t2_op_hmoveto,
+    t2_op_vmoveto,
+
+    t2_op_rlineto,
+    t2_op_hlineto,
+    t2_op_vlineto,
+
+    t2_op_rrcurveto,
+    t2_op_hhcurveto,
+    t2_op_hvcurveto,
+    t2_op_rcurveline,
+    t2_op_rlinecurve,
+    t2_op_vhcurveto,
+    t2_op_vvcurveto,
+
+    t2_op_flex,
+    t2_op_hflex,
+    t2_op_hflex1,
+    t2_op_flex1,
+
+    t2_op_endchar,
+
+    t2_op_hstem,
+    t2_op_vstem,
+    t2_op_hstemhm,
+    t2_op_vstemhm,
+
+    t2_op_hintmask,
+    t2_op_cntrmask,
+
+    t2_op_abs,
+    t2_op_add,
+    t2_op_sub,
+    t2_op_div,
+    t2_op_neg,
+    t2_op_random,
+    t2_op_mul,
+    t2_op_sqrt,
+
+    t2_op_blend,
+
+    t2_op_drop,
+    t2_op_exch,
+    t2_op_index,
+    t2_op_roll,
+    t2_op_dup,
+
+    t2_op_put,
+    t2_op_get,
+    t2_op_store,
+    t2_op_load,
+
+    t2_op_and,
+    t2_op_or,
+    t2_op_not,
+    t2_op_eq,
+    t2_op_ifelse,
+
+    t2_op_callsubr,
+    t2_op_callgsubr,
+    t2_op_return,
+
+    /* do not remove */
+    t2_op_max
+
+  } T2_Operator;
+
+
+#define T2_COUNT_CHECK_WIDTH  0x80
+#define T2_COUNT_EXACT        0x40
+#define T2_COUNT_CLEAR_STACK  0x20
+
+
+  static const FT_Byte  t2_argument_counts[] =
+  {
+    0,  /* unknown */
+
+    2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */
+    1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
+    1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT,
+
+    0 | T2_COUNT_CLEAR_STACK,  /* rlineto */
+    0 | T2_COUNT_CLEAR_STACK,
+    0 | T2_COUNT_CLEAR_STACK,
+
+    0 | T2_COUNT_CLEAR_STACK,  /* rrcurveto */
+    0 | T2_COUNT_CLEAR_STACK,
+    0 | T2_COUNT_CLEAR_STACK,
+    0 | T2_COUNT_CLEAR_STACK,
+    0 | T2_COUNT_CLEAR_STACK,
+    0 | T2_COUNT_CLEAR_STACK,
+    0 | T2_COUNT_CLEAR_STACK,
+
+    13, /* flex */
+    7,
+    9,
+    11,
+
+    0, /* endchar */
+
+    2 | T2_COUNT_CHECK_WIDTH, /* hstem */
+    2 | T2_COUNT_CHECK_WIDTH,
+    2 | T2_COUNT_CHECK_WIDTH,
+    2 | T2_COUNT_CHECK_WIDTH,
+
+    0, /* hintmask */
+    0, /* cntrmask */
+
+    1, /* abs */
+    2,
+    2,
+    2,
+    1,
+    0,
+    2,
+    1,
+
+    1, /* blend */
+
+    1, /* drop */
+    2,
+    1,
+    2,
+    1,
+
+    2, /* put */
+    1,
+    4,
+    3,
+
+    2, /* and */
+    2,
+    1,
+    2,
+    4,
+
+    1, /* callsubr */
+    1,
+    0
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********             GENERIC CHARSTRING PARSING               *********/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_Builder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph builder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    builder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    glyph   :: The current glyph object.                               */
+  /*                                                                       */
+  static
+  void  T2_Init_Builder( T2_Builder*   builder,
+                         TT_Face       face,
+                         T2_Size       size,
+                         T2_GlyphSlot  glyph )
+  {
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->glyph  = glyph;
+    builder->memory = face->root.memory;
+
+    if ( glyph )
+    {
+      FT_GlyphLoader*  loader = glyph->root.loader;
+
+
+      builder->loader  = loader;
+      builder->base    = &loader->base.outline;
+      builder->current = &loader->current.outline;
+      FT_GlyphLoader_Rewind( loader );
+    }
+
+    if ( size )
+    {
+      builder->scale_x = size->metrics.x_scale;
+      builder->scale_y = size->metrics.y_scale;
+    }
+
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Done_Builder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given glyph builder.  Its contents can still be used   */
+  /*    after the call, but the function saves important information       */
+  /*    within the corresponding glyph slot.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder :: A pointer to the glyph builder to finalize.             */
+  /*                                                                       */
+  static
+  void  T2_Done_Builder( T2_Builder*  builder )
+  {
+    T2_GlyphSlot  glyph = builder->glyph;
+
+
+    if ( glyph )
+      glyph->root.outline = *builder->base;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t2_compute_bias                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the bias value in dependence of the number of glyph       */
+  /*    subroutines.                                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    num_subrs :: The number of glyph subroutines.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The bias value.                                                    */
+  static
+  FT_Int  t2_compute_bias( FT_UInt  num_subrs )
+  {
+    FT_Int  result;
+
+
+    if ( num_subrs < 1240 )
+      result = 107;
+    else if ( num_subrs < 33900 )
+      result = 1131;
+    else
+      result = 32768;
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_Decoder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph decoder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    slot    :: The current glyph object.                               */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T2_Init_Decoder( T2_Decoder*  decoder,
+                         TT_Face      face,
+                         T2_Size      size,
+                         T2_GlyphSlot slot )
+  {
+    CFF_Font*  cff = (CFF_Font*)face->extra.data;
+
+
+    /* clear everything */
+    MEM_Set( decoder, 0, sizeof ( *decoder ) );
+
+    /* initialize builder */
+    T2_Init_Builder( &decoder->builder, face, size, slot );
+
+    /* initialize Type2 decoder */
+    decoder->num_globals  = cff->num_global_subrs;
+    decoder->globals      = cff->global_subrs;
+    decoder->globals_bias = t2_compute_bias( decoder->num_globals );
+  }
+
+
+  /* this function is used to select the locals subrs array */
+  LOCAL_DEF
+  void  T2_Prepare_Decoder( T2_Decoder*  decoder,
+                            FT_UInt      glyph_index )
+  {
+    CFF_Font*     cff = (CFF_Font*)decoder->builder.face->extra.data;
+    CFF_SubFont*  sub = &cff->top_font;
+
+
+    /* manage CID fonts */
+    if ( cff->num_subfonts >= 1 )
+    {
+      FT_Byte  fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
+
+
+      sub = cff->subfonts[fd_index];
+    }
+
+    decoder->num_locals    = sub->num_local_subrs;
+    decoder->locals        = sub->local_subrs;
+    decoder->locals_bias   = t2_compute_bias( decoder->num_locals );
+
+    decoder->glyph_width   = sub->private_dict.default_width;
+    decoder->nominal_width = sub->private_dict.nominal_width;
+  }
+
+
+  /* check that there is enough room for `count' more points */
+  static
+  FT_Error  check_points( T2_Builder*  builder,
+                          FT_Int       count )
+  {
+    return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+  }
+
+
+  /* add a new point, do not check space */
+  static
+  void  add_point( T2_Builder*  builder,
+                   FT_Pos       x,
+                   FT_Pos       y,
+                   FT_Byte      flag )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    if ( builder->load_points )
+    {
+      FT_Vector*  point   = outline->points + outline->n_points;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+      point->x = x >> 16;
+      point->y = y >> 16;
+      *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
+
+      builder->last = *point;
+    }
+    outline->n_points++;
+  }
+
+
+  /* check space for a new on-curve point, then add it */
+  static
+  FT_Error  add_point1( T2_Builder*  builder,
+                        FT_Pos       x,
+                        FT_Pos       y )
+  {
+    FT_Error  error;
+
+
+    error = check_points( builder, 1 );
+    if ( !error )
+      add_point( builder, x, y, 1 );
+
+    return error;
+  }
+
+
+  /* check room for a new contour, then add it */
+  static
+  FT_Error  add_contour( T2_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+    FT_Error     error;
+
+
+    if ( !builder->load_points )
+    {
+      outline->n_contours++;
+      return T2_Err_Ok;
+    }
+
+    error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+    if ( !error )
+    {
+      if ( outline->n_contours > 0 )
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+      outline->n_contours++;
+    }
+
+    return error;
+  }
+
+
+  /* if a path was begun, add its first on-curve point */
+  static
+  FT_Error  start_point( T2_Builder*  builder,
+                         FT_Pos       x,
+                         FT_Pos       y )
+  {
+    FT_Error  error = 0;
+
+
+    /* test whether we are building a new contour */
+    if ( !builder->path_begun )
+    {
+      builder->path_begun = 1;
+      error = add_contour( builder );
+      if ( !error )
+        error = add_point1( builder, x, y );
+    }
+    return error;
+  }
+
+
+  /* close the current contour */
+  static
+  void  close_contour( T2_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+
+    /* XXXX: We must not include the last point in the path if it */
+    /*       is located on the first point.                       */
+    if ( outline->n_points > 1 )
+    {
+      FT_Int      first = 0;
+      FT_Vector*  p1    = outline->points + first;
+      FT_Vector*  p2    = outline->points + outline->n_points - 1;
+
+      if ( outline->n_contours > 1 )
+      {
+        first = outline->contours[outline->n_contours - 2] + 1;
+        p1    = outline->points + first;
+      }
+
+      if ( p1->x == p2->x && p1->y == p2->y )
+        outline->n_points--;
+    }
+
+    if ( outline->n_contours > 0 )
+      outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+  }
+
+
+#define USE_ARGS( n )  do                            \
+                       {                             \
+                         top -= n;                   \
+                         if ( top < decoder->stack ) \
+                           goto Stack_Underflow;     \
+                       } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Parse_CharStrings                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given Type 2 charstrings program.                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder         :: The current Type 1 decoder.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charstring_base :: The base of the charstring stream.              */
+  /*                                                                       */
+  /*    charstring_len  :: The length in bytes of the charstring stream.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T2_Parse_CharStrings( T2_Decoder*  decoder,
+                                  FT_Byte*     charstring_base,
+                                  FT_Int       charstring_len )
+  {
+    FT_Error          error;
+    T2_Decoder_Zone*  zone;
+    FT_Byte*          ip;
+    FT_Byte*          limit;
+    T2_Builder*       builder = &decoder->builder;
+    FT_Outline*       outline;
+    FT_Pos            x, y;
+    FT_Fixed          seed;
+    FT_Fixed*         stack;
+
+
+    /* set default width */
+    decoder->num_hints  = 0;
+    decoder->read_width = 1;
+
+    /* compute random seed from stack address of parameter */
+    seed = (FT_Fixed)(char*)&seed           ^
+           (FT_Fixed)(char*)&decoder        ^
+           (FT_Fixed)(char*)&charstring_base;
+    seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF;
+    if ( seed == 0 )
+      seed = 0x7384;
+
+    /* initialize the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+    stack         = decoder->top;
+
+    builder->path_begun = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error   = T2_Err_Ok;
+    outline = builder->current;
+
+    x = builder->pos_x;
+    y = builder->pos_y;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      T2_Operator  op;
+      FT_Byte      v;
+      FT_Byte      count;
+
+
+      /********************************************************************/
+      /*                                                                  */
+      /* Decode operator or operand                                       */
+      /*                                                                  */
+      v = *ip++;
+      if ( v >= 32 || v == 28 )
+      {
+        FT_Int    shift = 16;
+        FT_Int32  val;
+
+
+        /* this is an operand, push it on the stack */
+        if ( v == 28 )
+        {
+          if ( ip + 1 >= limit )
+            goto Syntax_Error;
+          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
+          ip += 2;
+        }
+        else if ( v < 247 )
+          val = (FT_Long)v - 139;
+        else if ( v < 251 )
+        {
+          if ( ip >= limit )
+            goto Syntax_Error;
+          val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
+        }
+        else if ( v < 255 )
+        {
+          if ( ip >= limit )
+            goto Syntax_Error;
+          val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
+        }
+        else
+        {
+          if ( ip + 3 >= limit )
+            goto Syntax_Error;
+          val = ( (FT_Int32)ip[0] << 24 ) |
+                ( (FT_Int32)ip[1] << 16 ) |
+                ( (FT_Int32)ip[2] <<  8 ) |
+                            ip[3];
+          ip    += 4;
+          shift  = 0;
+        }
+        if ( decoder->top - stack >= T2_MAX_OPERANDS )
+          goto Stack_Overflow;
+
+        val           <<= shift;
+        *decoder->top++ = val;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        if ( !( val & 0xFFFF ) )
+          FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
+        else
+          FT_TRACE4(( " %.2f", val/65536.0 ));
+#endif
+
+      }
+      else
+      {
+        FT_Fixed*  args     = decoder->top;
+        FT_Int     num_args = args - decoder->stack;
+        FT_Int     req_args;
+
+
+        /* find operator */
+        op = t2_op_unknown;
+
+        switch ( v )
+        {
+        case 1:
+          op = t2_op_hstem;
+          break;
+        case 3:
+          op = t2_op_vstem;
+          break;
+        case 4:
+          op = t2_op_vmoveto;
+          break;
+        case 5:
+          op = t2_op_rlineto;
+          break;
+        case 6:
+          op = t2_op_hlineto;
+          break;
+        case 7:
+          op = t2_op_vlineto;
+          break;
+        case 8:
+          op = t2_op_rrcurveto;
+          break;
+        case 10:
+          op = t2_op_callsubr;
+          break;
+        case 11:
+          op = t2_op_return;
+          break;
+        case 12:
+          {
+            if ( ip >= limit )
+              goto Syntax_Error;
+            v = *ip++;
+
+            switch ( v )
+            {
+            case 3:
+              op = t2_op_and;
+              break;
+            case 4:
+              op = t2_op_or;
+              break;
+            case 5:
+              op = t2_op_not;
+              break;
+            case 8:
+              op = t2_op_store;
+              break;
+            case 9:
+              op = t2_op_abs;
+              break;
+            case 10:
+              op = t2_op_add;
+              break;
+            case 11:
+              op = t2_op_sub;
+              break;
+            case 12:
+              op = t2_op_div;
+              break;
+            case 13:
+              op = t2_op_load;
+              break;
+            case 14:
+              op = t2_op_neg;
+              break;
+            case 15:
+              op = t2_op_eq;
+              break;
+            case 18:
+              op = t2_op_drop;
+              break;
+            case 20:
+              op = t2_op_put;
+              break;
+            case 21:
+              op = t2_op_get;
+              break;
+            case 22:
+              op = t2_op_ifelse;
+              break;
+            case 23:
+              op = t2_op_random;
+              break;
+            case 24:
+              op = t2_op_mul;
+              break;
+            case 26:
+              op = t2_op_sqrt;
+              break;
+            case 27:
+              op = t2_op_dup;
+              break;
+            case 28:
+              op = t2_op_exch;
+              break;
+            case 29:
+              op = t2_op_index;
+              break;
+            case 30:
+              op = t2_op_roll;
+              break;
+            case 34:
+              op = t2_op_hflex;
+              break;
+            case 35:
+              op = t2_op_flex;
+              break;
+            case 36:
+              op = t2_op_hflex1;
+              break;
+            case 37:
+              op = t2_op_flex1;
+              break;
+            default:
+              /* decrement ip for syntax error message */
+              ip--;
+            }
+          }
+          break;
+        case 14:
+          op = t2_op_endchar;
+          break;
+        case 16:
+          op = t2_op_blend;
+          break;
+        case 18:
+          op = t2_op_hstemhm;
+          break;
+        case 19:
+          op = t2_op_hintmask;
+          break;
+        case 20:
+          op = t2_op_cntrmask;
+          break;
+        case 21:
+          op = t2_op_rmoveto;
+          break;
+        case 22:
+          op = t2_op_hmoveto;
+          break;
+        case 23:
+          op = t2_op_vstemhm;
+          break;
+        case 24:
+          op = t2_op_rcurveline;
+          break;
+        case 25:
+          op = t2_op_rlinecurve;
+          break;
+        case 26:
+          op = t2_op_vvcurveto;
+          break;
+        case 27:
+          op = t2_op_hhcurveto;
+          break;
+        case 29:
+          op = t2_op_callgsubr;
+          break;
+        case 30:
+          op = t2_op_vhcurveto;
+          break;
+        case 31:
+          op = t2_op_hvcurveto;
+          break;
+        default:
+          ;
+        }
+        if ( op == t2_op_unknown )
+          goto Syntax_Error;
+
+        /* check arguments */
+        req_args = count = t2_argument_counts[op];
+        if ( req_args & T2_COUNT_CHECK_WIDTH )
+        {
+          args = stack;
+          if ( num_args & 1 && decoder->read_width )
+          {
+            decoder->glyph_width = decoder->nominal_width +
+                                     ( stack[0] >> 16 );
+            num_args--;
+            args++;
+          }
+          decoder->read_width  = 0;
+          req_args = 0;
+        }
+
+        req_args &= 15;
+        if ( num_args < req_args )
+          goto Stack_Underflow;
+        args     -= req_args;
+        num_args -= req_args;
+
+        switch ( op )
+        {
+        case t2_op_hstem:
+        case t2_op_vstem:
+        case t2_op_hstemhm:
+        case t2_op_vstemhm:
+          /* if the number of arguments is not even, the first one */
+          /* is simply the glyph width, encoded as the difference  */
+          /* to nominalWidthX                                      */
+          FT_TRACE4(( op == t2_op_hstem   ? " hstem"   :
+                      op == t2_op_vstem   ? " vstem"   :
+                      op == t2_op_hstemhm ? " hstemhm" :
+                                            " vstemhm" ));
+          decoder->num_hints += num_args / 2;
+          args = stack;
+          break;
+
+        case t2_op_hintmask:
+        case t2_op_cntrmask:
+          FT_TRACE4(( op == t2_op_hintmask ? " hintmask"
+                                           : " cntrmask" ));
+
+          decoder->num_hints += num_args / 2;
+          ip += ( decoder->num_hints + 7 ) >> 3;
+          if ( ip >= limit )
+            goto Syntax_Error;
+          args = stack;
+          break;
+
+        case t2_op_rmoveto:
+          FT_TRACE4(( " rmoveto" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          x   += args[0];
+          y   += args[1];
+          args = stack;
+          break;
+
+        case t2_op_vmoveto:
+          FT_TRACE4(( " vmoveto" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          y   += args[0];
+          args = stack;
+          break;
+
+        case t2_op_hmoveto:
+          FT_TRACE4(( " hmoveto" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          x   += args[0];
+          args = stack;
+          break;
+
+        case t2_op_rlineto:
+          FT_TRACE4(( " rlineto" ));
+
+          if ( start_point ( builder, x, y )         ||
+               check_points( builder, num_args / 2 ) )
+            goto Memory_Error;
+
+          if ( num_args < 2 || num_args & 1 )
+            goto Stack_Underflow;
+
+          args = stack;
+          while ( args < decoder->top )
+          {
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 1 );
+            args += 2;
+          }
+          args = stack;
+          break;
+
+        case t2_op_hlineto:
+        case t2_op_vlineto:
+          {
+            FT_Int  phase = ( op == t2_op_hlineto );
+
+
+            FT_TRACE4(( op == t2_op_hlineto ? " hlineto"
+                                            : " vlineto" ));
+
+            if ( start_point ( builder, x, y )     ||
+                 check_points( builder, num_args ) )
+              goto Memory_Error;
+
+            args = stack;
+            while (args < decoder->top )
+            {
+              if ( phase )
+                x += args[0];
+              else
+                y += args[0];
+
+              if ( add_point1( builder, x, y ) )
+                goto Memory_Error;
+
+              args++;
+              phase ^= 1;
+            }
+            args = stack;
+          }
+          break;
+
+        case t2_op_rrcurveto:
+          FT_TRACE4(( " rrcurveto" ));
+
+          /* check number of arguments; must be a multiple of 6 */
+          if ( num_args % 6 != 0 )
+            goto Stack_Underflow;
+
+          if ( start_point ( builder, x, y )         ||
+               check_points( builder, num_args / 2 ) )
+            goto Memory_Error;
+
+          args = stack;
+          while ( args < decoder->top )
+          {
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 0 );
+            x += args[2];
+            y += args[3];
+            add_point( builder, x, y, 0 );
+            x += args[4];
+            y += args[5];
+            add_point( builder, x, y, 1 );
+            args += 6;
+          }
+          args = stack;
+          break;
+
+        case t2_op_vvcurveto:
+          FT_TRACE4(( " vvcurveto" ));
+
+          if ( start_point ( builder, x, y ) )
+            goto Memory_Error;
+
+          args = stack;
+          if ( num_args & 1 )
+          {
+            x += args[0];
+            args++;
+            num_args--;
+          }
+
+          if ( num_args % 4 != 0 )
+            goto Stack_Underflow;
+
+          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+            goto Memory_Error;
+
+          while ( args < decoder->top )
+          {
+            y += args[0];
+            add_point( builder, x, y, 0 );
+            x += args[1];
+            y += args[2];
+            add_point( builder, x, y, 0 );
+            y += args[3];
+            add_point( builder, x, y, 1 );
+            args += 4;
+          }
+          args = stack;
+          break;
+
+        case t2_op_hhcurveto:
+          FT_TRACE4(( " hhcurveto" ));
+
+          if ( start_point ( builder, x, y ) )
+            goto Memory_Error;
+
+          args = stack;
+          if ( num_args & 1 )
+          {
+            y += args[0];
+            args++;
+            num_args--;
+          }
+
+          if ( num_args % 4 != 0 )
+            goto Stack_Underflow;
+
+          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+            goto Memory_Error;
+
+          while ( args < decoder->top )
+          {
+            x += args[0];
+            add_point( builder, x, y, 0 );
+            x += args[1];
+            y += args[2];
+            add_point( builder, x, y, 0 );
+            x += args[3];
+            add_point( builder, x, y, 1 );
+            args += 4;
+          }
+          args = stack;
+          break;
+
+        case t2_op_vhcurveto:
+        case t2_op_hvcurveto:
+          {
+            FT_Int  phase;
+
+
+            FT_TRACE4(( op == t2_op_vhcurveto ? " vhcurveto"
+                                              : " hvcurveto" ));
+
+            if ( start_point ( builder, x, y ) )
+              goto Memory_Error;
+
+            args = stack;
+            if (num_args < 4 || ( num_args % 4 ) > 1 )
+              goto Stack_Underflow;
+
+            if ( check_points( builder, ( num_args / 4 ) * 3 ) )
+              goto Stack_Underflow;
+
+            phase = ( op == t2_op_hvcurveto );
+
+            while ( num_args >= 4 )
+            {
+              num_args -= 4;
+              if ( phase )
+              {
+                x += args[0];
+                add_point( builder, x, y, 0 );
+                x += args[1];
+                y += args[2];
+                add_point( builder, x, y, 0 );
+                y += args[3];
+                if ( num_args == 1 )
+                  x += args[4];
+                add_point( builder, x, y, 1 );
+              }
+              else
+              {
+                y += args[0];
+                add_point( builder, x, y, 0 );
+                x += args[1];
+                y += args[2];
+                add_point( builder, x, y, 0 );
+                x += args[3];
+                if ( num_args == 1 )
+                  y += args[4];
+                add_point( builder, x, y, 1 );
+              }
+              args  += 4;
+              phase ^= 1;
+            }
+            args = stack;
+          }
+          break;
+
+        case t2_op_rlinecurve:
+          {
+            FT_Int  num_lines = ( num_args - 6 ) / 2;
+
+
+            FT_TRACE4(( " rlinecurve" ));
+
+            if ( num_args < 8 || ( num_args - 6 ) & 1 )
+              goto Stack_Underflow;
+
+            if ( start_point( builder, x, y )           ||
+                 check_points( builder, num_lines + 3 ) )
+              goto Memory_Error;
+
+            args = stack;
+
+            /* first, add the line segments */
+            while ( num_lines > 0 )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y, 1 );
+              args += 2;
+              num_lines--;
+            }
+
+            /* then the curve */
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 0 );
+            x += args[2];
+            y += args[3];
+            add_point( builder, x, y, 0 );
+            x += args[4];
+            y += args[5];
+            add_point( builder, x, y, 1 );
+            args = stack;
+          }
+          break;
+
+        case t2_op_rcurveline:
+          {
+            FT_Int  num_curves = ( num_args - 2 ) / 6;
+
+
+            FT_TRACE4(( " rcurveline" ));
+
+            if ( num_args < 8 || ( num_args - 2 ) % 6 )
+              goto Stack_Underflow;
+
+            if ( start_point ( builder, x, y )             ||
+                 check_points( builder, num_curves*3 + 2 ) )
+              goto Memory_Error;
+
+            args = stack;
+
+            /* first, add the curves */
+            while ( num_curves > 0 )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y, 0 );
+              x += args[2];
+              y += args[3];
+              add_point( builder, x, y, 0 );
+              x += args[4];
+              y += args[5];
+              add_point( builder, x, y, 1 );
+              args += 6;
+              num_curves--;
+            }
+
+            /* then the final line */
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 1 );
+            args = stack;
+          }
+          break;
+
+        case t2_op_hflex1:
+          {
+            FT_Pos start_y;
+
+
+            FT_TRACE4(( " hflex1" ));
+
+            args = stack;
+
+            /* adding five more points; 4 control points, 1 on-curve point */
+            /* make sure we have enough space for the start point if it    */
+            /* needs to be added..                                         */
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 6 )   )
+              goto Memory_Error;
+
+            /* Record the starting point's y postion for later use */
+            start_y = y;
+
+            /* first control point */
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 0 );
+
+            /* second control point */
+            x += args[2];
+            y += args[3];
+            add_point( builder, x, y, 0 );
+
+            /* join point; on curve, with y-value the same as the last */
+            /* control point's y-value                                 */
+            x += args[4];
+            add_point( builder, x, y, 1 );
+
+            /* third control point, with y-value the same as the join */
+            /* point's y-value                                        */
+            x += args[5];
+            add_point( builder, x, y, 0 );
+
+            /* fourth control point */
+            x += args[6];
+            y += args[7];
+            add_point( builder, x, y, 0 );
+
+            /* ending point, with y-value the same as the start   */
+            x += args[8];
+            y  = start_y;
+            add_point( builder, x, y, 1 );
+
+            args = stack;
+            break;
+          }
+
+        case t2_op_hflex:
+          {
+            FT_Pos start_y;
+
+
+            FT_TRACE4(( " hflex" ));
+
+            args = stack;
+
+            /* adding six more points; 4 control points, 2 on-curve points */
+            if ( start_point( builder, x, y ) ||
+                 check_points ( builder, 6 )  )
+              goto Memory_Error;
+
+            /* record the starting point's y-position for later use */
+            start_y = y;
+
+            /* first control point */
+            x += args[0];
+            add_point( builder, x, y, 0 );
+
+            /* second control point */
+            x += args[1];
+            y += args[2];
+            add_point( builder, x, y, 0 );
+
+            /* join point; on curve, with y-value the same as the last */
+            /* control point's y-value                                 */
+            x += args[3];
+            add_point( builder, x, y, 1 );
+
+            /* third control point, with y-value the same as the join */
+            /* point's y-value                                        */
+            x += args[4];
+            add_point( builder, x, y, 0 );
+
+            /* fourth control point */
+            x += args[5];
+            y  = start_y;
+            add_point( builder, x, y, 0 );
+
+            /* ending point, with y-value the same as the start point's */
+            /* y-value -- we don't add this point, though               */
+            x += args[6];
+            add_point( builder, x, y, 1 );
+
+            args = stack;
+            break;
+          }
+
+        case t2_op_flex1:
+          {
+            FT_Pos  start_x, start_y; /* record start x, y values for alter */
+                                      /* use                                */
+            FT_Int  dx = 0, dy = 0;   /* used in horizontal/vertical        */
+                                      /* algorithm below                    */
+            FT_Int  horizontal, count;
+
+
+            FT_TRACE4(( " flex1" ));
+
+            /* adding six more points; 4 control points, 2 on-curve points */
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 6 )   )
+               goto Memory_Error;
+
+            /* record the starting point's x, y postion for later use */
+            start_x = x;
+            start_y = y;
+
+            /* XXX: figure out whether this is supposed to be a horizontal */
+            /*      or vertical flex; the Type 2 specification is vague... */
+
+            args = stack;
+
+            /* grab up to the last argument */
+            for ( count = 5; count > 0; count-- )
+            {
+              dx += args[0];
+              dy += args[1];
+              args += 2;
+            }
+
+            /* rewind */
+            args = stack;
+
+            if ( dx < 0 ) dx = -dx;
+            if ( dy < 0 ) dy = -dy;
+
+            /* strange test, but here it is... */
+            horizontal = ( dx > dy );
+
+            for ( count = 5; count > 0; count-- )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y, (FT_Bool)( count == 3 ) );
+              args += 2;
+            }
+
+            /* is last operand an x- or y-delta? */
+            if ( horizontal )
+            {
+              x += args[0];
+              y  = start_y;
+            }
+            else
+            {
+              x  = start_x;
+              y += args[0];
+            }
+
+            add_point( builder, x, y, 1 );
+
+            args = stack;
+            break;
+           }
+
+        case t2_op_flex:
+          {
+            FT_UInt  count;
+
+
+            FT_TRACE4(( " flex" ));
+
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 6 )   )
+              goto Memory_Error;
+
+            args = stack;
+            for ( count = 6; count > 0; count-- )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y,
+                         (FT_Bool)( count == 3 || count == 0 ) );
+              args += 2;
+            }
+
+            args = stack;
+          }
+          break;
+
+        case t2_op_endchar:
+          FT_TRACE4(( " endchar" ));
+
+          close_contour( builder );
+
+          /* add current outline to the glyph slot */
+          FT_GlyphLoader_Add( builder->loader );
+
+          /* return now! */
+          FT_TRACE4(( "\n\n" ));
+          return T2_Err_Ok;
+
+        case t2_op_abs:
+          FT_TRACE4(( " abs" ));
+
+          if ( args[0] < 0 )
+            args[0] = -args[0];
+          args++;
+          break;
+
+        case t2_op_add:
+          FT_TRACE4(( " add" ));
+
+          args[0] += args[1];
+          args++;
+          break;
+
+        case t2_op_sub:
+          FT_TRACE4(( " sub" ));
+
+          args[0] -= args[1];
+          args++;
+          break;
+
+        case t2_op_div:
+          FT_TRACE4(( " div" ));
+
+          args[0] = FT_DivFix( args[0], args[1] );
+          args++;
+          break;
+
+        case t2_op_neg:
+          FT_TRACE4(( " neg" ));
+
+          args[0] = -args[0];
+          args++;
+          break;
+
+        case t2_op_random:
+          {
+            FT_Fixed  rand;
+
+
+            FT_TRACE4(( " rand" ));
+
+            rand = seed;
+            if ( rand >= 0x8000 )
+              rand++;
+
+            args[0] = rand;
+            seed    = FT_MulFix( seed, 0x10000L - seed );
+            if ( seed == 0 )
+              seed += 0x2873;
+            args++;
+          }
+          break;
+
+        case t2_op_mul:
+          FT_TRACE4(( " mul" ));
+
+          args[0] = FT_MulFix( args[0], args[1] );
+          args++;
+          break;
+
+        case t2_op_sqrt:
+          FT_TRACE4(( " sqrt" ));
+
+          if ( args[0] > 0 )
+          {
+            FT_Int    count = 9;
+            FT_Fixed  root  = args[0];
+            FT_Fixed  new_root;
+
+
+            for (;;)
+            {
+              new_root = ( root + FT_DivFix(args[0],root) + 1 ) >> 1;
+              if ( new_root == root || count <= 0 )
+                break;
+              root = new_root;
+            }
+            args[0] = new_root;
+          }
+          else
+            args[0] = 0;
+          args++;
+          break;
+
+        case t2_op_drop:
+          /* nothing */
+          FT_TRACE4(( " drop" ));
+
+          break;
+
+        case t2_op_exch:
+          {
+            FT_Fixed  tmp;
+
+
+            FT_TRACE4(( " exch" ));
+
+            tmp     = args[0];
+            args[0] = args[1];
+            args[1] = tmp;
+            args   += 2;
+          }
+          break;
+
+        case t2_op_index:
+          {
+            FT_Int  index = args[0] >> 16;
+
+
+            FT_TRACE4(( " index" ));
+
+            if ( index < 0 )
+              index = 0;
+            else if ( index > num_args - 2 )
+              index = num_args - 2;
+            args[0] = args[-( index + 1 )];
+            args++;
+          }
+          break;
+
+        case t2_op_roll:
+          {
+            FT_Int count = (FT_Int)( args[0] >> 16 );
+            FT_Int index = (FT_Int)( args[1] >> 16 );
+
+
+            FT_TRACE4(( " roll" ));
+
+            if ( count <= 0 )
+              count = 1;
+
+            args -= count;
+            if ( args < stack )
+              goto Stack_Underflow;
+
+            if ( index >= 0 )
+            {
+              while ( index > 0 )
+              {
+                FT_Fixed tmp = args[count - 1];
+                FT_Int   i;
+
+
+                for ( i = count - 2; i >= 0; i-- )
+                  args[i + 1] = args[i];
+                args[0] = tmp;
+                index--;
+              }
+            }
+            else
+            {
+              while ( index < 0 )
+              {
+                FT_Fixed  tmp = args[0];
+                FT_Int    i;
+
+
+                for ( i = 0; i < count - 1; i++ )
+                  args[i] = args[i + 1];
+                args[count - 1] = tmp;
+                index++;
+              }
+            }
+            args += count;
+          }
+          break;
+
+        case t2_op_dup:
+          FT_TRACE4(( " dup" ));
+
+          args[1] = args[0];
+          args++;
+          break;
+
+        case t2_op_put:
+          {
+            FT_Fixed  val   = args[0];
+            FT_Int    index = (FT_Int)( args[1] >> 16 );
+
+
+            FT_TRACE4(( " put" ));
+
+            if ( index >= 0 && index < decoder->len_buildchar )
+              decoder->buildchar[index] = val;
+          }
+          break;
+
+        case t2_op_get:
+          {
+            FT_Int   index = (FT_Int)( args[0] >> 16 );
+            FT_Fixed val   = 0;
+
+
+            FT_TRACE4(( " get" ));
+
+            if ( index >= 0 && index < decoder->len_buildchar )
+              val = decoder->buildchar[index];
+
+            args[0] = val;
+            args++;
+          }
+          break;
+
+        case t2_op_store:
+          FT_TRACE4(( " store "));
+
+          goto Unimplemented;
+
+        case t2_op_load:
+          FT_TRACE4(( " load" ));
+
+          goto Unimplemented;
+
+        case t2_op_and:
+          {
+            FT_Fixed  cond = args[0] && args[1];
+
+
+            FT_TRACE4(( " and" ));
+
+            args[0] = cond ? 0x10000L : 0;
+            args++;
+          }
+          break;
+
+        case t2_op_or:
+          {
+            FT_Fixed  cond = args[0] || args[1];
+
+
+            FT_TRACE4(( " or" ));
+
+            args[0] = cond ? 0x10000L : 0;
+            args++;
+          }
+          break;
+
+        case t2_op_eq:
+          {
+            FT_Fixed  cond = !args[0];
+
+
+            FT_TRACE4(( " eq" ));
+
+            args[0] = cond ? 0x10000L : 0;
+            args++;
+          }
+          break;
+
+        case t2_op_ifelse:
+          {
+            FT_Fixed  cond = (args[2] <= args[3]);
+
+
+            FT_TRACE4(( " ifelse" ));
+
+            if ( !cond )
+              args[0] = args[1];
+            args++;
+          }
+          break;
+
+        case t2_op_callsubr:
+          {
+            FT_UInt  index = (FT_UInt)( ( args[0] >> 16 ) +
+                                        decoder->locals_bias );
+
+
+            FT_TRACE4(( " callsubr(%d)", index ));
+
+            if ( index >= decoder->num_locals )
+            {
+              FT_ERROR(( "T2_Parse_CharStrings:" ));
+              FT_ERROR(( "  invalid local subr index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = decoder->locals[index];
+            zone->limit  = decoder->locals[index+1];
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+          }
+          break;
+
+        case t2_op_callgsubr:
+          {
+            FT_UInt  index = (FT_UInt)( ( args[0] >> 16 ) +
+                                        decoder->globals_bias );
+
+
+            FT_TRACE4(( " callgsubr(%d)", index ));
+
+            if ( index >= decoder->num_globals )
+            {
+              FT_ERROR(( "T2_Parse_CharStrings:" ));
+              FT_ERROR(( " invalid global subr index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = decoder->globals[index];
+            zone->limit  = decoder->globals[index+1];
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+          }
+          break;
+
+        case t2_op_return:
+          FT_TRACE4(( " return" ));
+
+          if ( decoder->zone <= decoder->zones )
+          {
+            FT_ERROR(( "T2_Parse_CharStrings: unexpected return\n" ));
+            goto Syntax_Error;
+          }
+
+          decoder->zone--;
+          zone  = decoder->zone;
+          ip    = zone->cursor;
+          limit = zone->limit;
+          break;
+
+        default:
+        Unimplemented:
+          FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
+
+          if ( ip[-1] == 12 )
+            FT_ERROR(( " %d", ip[0] ));
+          FT_ERROR(( "\n" ));
+
+          return T2_Err_Unimplemented_Feature;
+        }
+
+      decoder->top = args;
+
+      } /* general operator processing */
+
+    } /* while ip < limit */
+
+    FT_TRACE4(( "..end..\n\n" ));
+
+    return error;
+
+  Syntax_Error:
+    FT_TRACE4(( "T2_Parse_CharStrings: syntax error!" ));
+    return T2_Err_Invalid_File_Format;
+
+  Stack_Underflow:
+    FT_TRACE4(( "T2_Parse_CharStrings: stack underflow!" ));
+    return T2_Err_Too_Few_Arguments;
+
+  Stack_Overflow:
+    FT_TRACE4(( "T2_Parse_CharStrings: stack overflow!" ));
+    return T2_Err_Stack_Overflow;
+
+  Memory_Error:
+    return builder->error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#if 0 /* unused until we support pure CFF fonts */
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Compute_Max_Advance( TT_Face  face,
+                                    FT_Int*  max_advance )
+  {
+    FT_Error    error = 0;
+    T2_Decoder  decoder;
+    FT_Int      glyph_index;
+    CFF_Font*   cff = (CFF_Font*)face->other;
+
+
+    *max_advance = 0;
+
+    /* Initialize load decoder */
+    T2_Init_Decoder( &decoder, face, 0, 0 );
+
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    /* For each glyph, parse the glyph charstring and extract */
+    /* the advance width.                                     */
+    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+          glyph_index++ )
+    {
+      FT_Byte*  charstring;
+      FT_ULong  charstring_len;
+
+
+      /* now get load the unscaled outline */
+      error = T2_Access_Element( &cff->charstrings_index, glyph_index,
+                                 &charstring, &charstring_len );
+      if ( !error )
+      {
+        T2_Prepare_Decoder( &decoder, glyph_index );
+        error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+        T2_Forget_Element( &cff->charstrings_index, &charstring );
+      }
+
+      /* ignore the error if one has occurred -- skip to next glyph */
+      error = 0;
+    }
+
+    *max_advance = decoder.builder.advance.x;
+
+    return T2_Err_Ok;
+  }
+
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********               UNHINTED GLYPH LOADER                  *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of loading a      *********/
+  /**********    single outline.  It completely ignores hinting    *********/
+  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Load_Glyph( T2_GlyphSlot  glyph,
+                           T2_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags )
+  {
+    FT_Error    error;
+    T2_Decoder  decoder;
+    TT_Face     face = (TT_Face)glyph->root.face;
+    FT_Bool     hinting;
+    CFF_Font*   cff = (CFF_Font*)face->extra.data;
+
+
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = 0x10000L;
+    glyph->y_scale = 0x10000L;
+    if ( size )
+    {
+      glyph->x_scale = size->metrics.x_scale;
+      glyph->y_scale = size->metrics.y_scale;
+    }
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+              ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+    glyph->root.format = ft_glyph_format_outline;  /* by default */
+
+    {
+      FT_Byte*  charstring;
+      FT_ULong  charstring_len;
+
+
+      T2_Init_Decoder( &decoder, face, size, glyph );
+
+      decoder.builder.no_recurse =
+        (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+      /* now load the unscaled outline */
+      error = T2_Access_Element( &cff->charstrings_index, glyph_index,
+                                 &charstring, &charstring_len );
+      if ( !error )
+      {
+        T2_Prepare_Decoder( &decoder, glyph_index );
+        error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+        T2_Forget_Element( &cff->charstrings_index, &charstring );
+      }
+
+      /* save new glyph tables */
+      T2_Done_Builder( &decoder.builder );
+    }
+
+    /* Now, set the metrics -- this is rather simple, as   */
+    /* the left side bearing is the xMin, and the top side */
+    /* bearing the yMax.                                   */
+    if ( !error )
+    {
+      /* for composite glyphs, return only left side bearing and */
+      /* advance width                                           */
+      if ( glyph->root.format == ft_glyph_format_composite )
+      {
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
+      }
+      else
+      {
+        FT_BBox            cbox;
+        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
+
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance = decoder.glyph_width;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        glyph->root.outline.flags = 0;
+        if ( size && size->metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur     = &glyph->root.outline;
+          FT_Vector*   vec     = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_Fixed     y_scale = glyph->y_scale;
+
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+          /* Then scale the metrics */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        }
+
+#if 0
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline, cff->font_matrix );
+#endif
+
+        /* compute the other metrics */
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if ( hinting )
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+      }
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/cff/t2gload.h b/src/freetype/cff/t2gload.h
new file mode 100644 (file)
index 0000000..2654d4b
--- /dev/null
@@ -0,0 +1,213 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2gload.h                                                              */
+/*                                                                         */
+/*    OpenType Glyph Loader (specification).                               */
+/*                                                                         */
+/*  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 T2GLOAD_H
+#define T2GLOAD_H
+
+#include <freetype/freetype.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2objs.h"
+
+#else
+
+#include <cff/t2objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+#define T2_MAX_OPERANDS     48
+#define T2_MAX_SUBRS_CALLS  32
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    T2_Builder                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*     A structure used during glyph loading to store its outline.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory       :: The current memory object.                         */
+  /*                                                                       */
+  /*    face         :: The current face object.                           */
+  /*                                                                       */
+  /*    glyph        :: The current glyph slot.                            */
+  /*                                                                       */
+  /*    current      :: The current glyph outline.                         */
+  /*                                                                       */
+  /*    base         :: The base glyph outline.                            */
+  /*                                                                       */
+  /*    max_points   :: maximum points in builder outline                  */
+  /*                                                                       */
+  /*    max_contours :: Maximal number of contours in builder outline.     */
+  /*                                                                       */
+  /*    last         :: The last point position.                           */
+  /*                                                                       */
+  /*    scale_x      :: The horizontal scale (FUnits to sub-pixels).       */
+  /*                                                                       */
+  /*    scale_y      :: The vertical scale (FUnits to sub-pixels).         */
+  /*                                                                       */
+  /*    pos_x        :: The horizontal translation (if composite glyph).   */
+  /*                                                                       */
+  /*    pos_y        :: The vertical translation (if composite glyph).     */
+  /*                                                                       */
+  /*    left_bearing :: The left side bearing point.                       */
+  /*                                                                       */
+  /*    advance      :: The horizontal advance vector.                     */
+  /*                                                                       */
+  /*    bbox         :: Unused.                                            */
+  /*                                                                       */
+  /*    path_begun   :: A flag which indicates that a new path has begun.  */
+  /*                                                                       */
+  /*    load_points  :: If this flag is not set, no points are loaded.     */
+  /*                                                                       */
+  /*    no_recurse   :: Set but not used.                                  */
+  /*                                                                       */
+  /*    error        :: An error code that is only used to report memory   */
+  /*                    allocation problems.                               */
+  /*                                                                       */
+  /*    metrics_only :: A boolean indicating that we only want to compute  */
+  /*                    the metrics of a given glyph, not load all of its  */
+  /*                    points.                                            */
+  /*                                                                       */
+  typedef struct  T2_Builder_
+  {
+    FT_Memory        memory;
+    TT_Face          face;
+    T2_GlyphSlot     glyph;
+    FT_GlyphLoader*  loader;
+    FT_Outline*      base;
+    FT_Outline*      current;
+
+    FT_Vector        last;
+
+    FT_Fixed         scale_x;
+    FT_Fixed         scale_y;
+
+    FT_Pos           pos_x;
+    FT_Pos           pos_y;
+
+    FT_Vector        left_bearing;
+    FT_Vector        advance;
+
+    FT_BBox          bbox;          /* bounding box */
+    FT_Bool          path_begun;
+    FT_Bool          load_points;
+    FT_Bool          no_recurse;
+
+    FT_Error         error;         /* only used for memory errors */
+    FT_Bool          metrics_only;
+
+  } T2_Builder;
+
+
+  /* execution context charstring zone */
+
+  typedef struct  T2_Decoder_Zone_
+  {
+    FT_Byte*  base;
+    FT_Byte*  limit;
+    FT_Byte*  cursor;
+
+  } T2_Decoder_Zone;
+
+
+  typedef struct  T2_Decoder_
+  {
+    T2_Builder        builder;
+    CFF_Font*         cff;
+
+    FT_Fixed          stack[T2_MAX_OPERANDS + 1];
+    FT_Fixed*         top;
+
+    T2_Decoder_Zone   zones[T2_MAX_SUBRS_CALLS + 1];
+    T2_Decoder_Zone*  zone;
+
+    FT_Int            flex_state;
+    FT_Int            num_flex_vectors;
+    FT_Vector         flex_vectors[7];
+
+    FT_Pos            glyph_width;
+    FT_Pos            nominal_width;
+
+    FT_Bool           read_width;
+    FT_Int            num_hints;
+    FT_Fixed*         buildchar;
+    FT_Int            len_buildchar;
+
+    FT_UInt           num_locals;
+    FT_UInt           num_globals;
+
+    FT_Int            locals_bias;
+    FT_Int            globals_bias;
+
+    FT_Byte**         locals;
+    FT_Byte**         globals;
+
+  } T2_Decoder;
+
+
+  LOCAL_DEF
+  void  T2_Init_Decoder( T2_Decoder*   decoder,
+                         TT_Face       face,
+                         T2_Size       size,
+                         T2_GlyphSlot  slot );
+
+  LOCAL_DEF
+  void  T2_Prepare_Decoder( T2_Decoder*  decoder,
+                            FT_UInt      glyph_index );
+
+#if 0  /* unused until we support pure CFF fonts */
+
+  /* Compute the maximum advance width of a font through quick parsing */
+  LOCAL_DEF
+  FT_Error  T2_Compute_Max_Advance( TT_Face  face,
+                                    FT_Int*  max_advance );
+
+#endif /* 0 */
+
+  LOCAL_DEF
+  FT_Error  T2_Parse_CharStrings( T2_Decoder*  decoder,
+                                  FT_Byte*     charstring_base,
+                                  FT_Int       charstring_len );
+
+  LOCAL_DEF
+  FT_Error  T2_Load_Glyph( T2_GlyphSlot  glyph,
+                           T2_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T2GLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/cff/t2load.c b/src/freetype/cff/t2load.c
new file mode 100644 (file)
index 0000000..4a77693
--- /dev/null
@@ -0,0 +1,757 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2load.c                                                               */
+/*                                                                         */
+/*    TrueType glyph data/program tables loader (body).                    */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <freetype/internal/t2errors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2load.h"
+#include "t2parse.h"
+
+#else
+
+#include <cff/t2load.h>
+#include <cff/t2parse.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t2load
+
+
+ /* read a CFF offset from memory */
+  static
+  FT_ULong  t2_get_offset( FT_Byte*  p,
+                           FT_Byte   off_size )
+  {
+    FT_ULong  result;
+
+
+    for ( result = 0; off_size > 0; off_size-- )
+    {
+      result <<= 8;
+      result  |= *p++;
+    }
+
+    return result;
+  }
+
+
+  static
+  FT_Error  t2_new_cff_index( CFF_Index*  index,
+                              FT_Stream   stream,
+                              FT_Bool     load )
+  {
+    FT_Error  error;
+    FT_Memory memory = stream->memory;
+    FT_UShort count;
+
+
+    MEM_Set( index, 0, sizeof ( *index ) );
+
+    index->stream = stream;
+    if ( !READ_UShort( count ) &&
+         count > 0             )
+    {
+      FT_Byte*   p;
+      FT_Byte    offsize;
+      FT_ULong   data_size;
+      FT_ULong*  poff;
+
+
+      /* there is at least one element; read the offset size,           */
+      /* then access the offset table to compute the index's total size */
+      if ( READ_Byte( offsize ) )
+        goto Exit;
+
+      index->stream   = stream;
+      index->count    = count;
+      index->off_size = offsize;
+      data_size       = (FT_ULong)( count + 1 ) * offsize;
+
+      if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) ||
+           ACCESS_Frame( data_size )                          )
+        goto Exit;
+
+      poff = index->offsets;
+      p    = (FT_Byte*)stream->cursor;
+
+      for ( ; (FT_Short)count >= 0; count-- )
+      {
+        poff[0] = t2_get_offset( p, offsize );
+        poff++;
+        p += offsize;
+      }
+
+      FORGET_Frame();
+
+      index->data_offset = FILE_Pos();
+      data_size          = poff[-1] - 1;
+
+      if ( load )
+      {
+        /* load the data */
+        if ( EXTRACT_Frame( data_size, index->bytes ) )
+          goto Exit;
+      }
+      else
+      {
+        /* skip the data */
+        (void)FILE_Skip( data_size );
+      }
+    }
+
+  Exit:
+    if ( error )
+      FREE( index->offsets );
+
+    return error;
+  }
+
+
+  static
+  void  t2_done_cff_index( CFF_Index*  index )
+  {
+    if ( index->stream )
+    {
+      FT_Stream  stream = index->stream;
+      FT_Memory  memory = stream->memory;
+
+
+      if ( index->bytes )
+        RELEASE_Frame( index->bytes );
+
+      FREE( index->offsets );
+      MEM_Set( index, 0, sizeof ( *index ) );
+    }
+  }
+
+
+  static
+  FT_Error  t2_explicit_cff_index( CFF_Index*  index,
+                                   FT_Byte***  table )
+  {
+    FT_Error   error  = 0;
+    FT_Memory  memory = index->stream->memory;
+    FT_UInt    n, offset, old_offset;
+    FT_Byte**  t;
+
+
+    *table = 0;
+
+    if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) )
+    {
+      old_offset = 1;
+      for ( n = 0; n <= index->count; n++ )
+      {
+        offset = index->offsets[n];
+        if ( !offset )
+          offset = old_offset;
+
+        t[n] = index->bytes + offset - 1;
+
+        old_offset = offset;
+      }
+      *table = t;
+    }
+
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Access_Element( CFF_Index*  index,
+                               FT_UInt     element,
+                               FT_Byte**   pbytes,
+                               FT_ULong*   pbyte_len )
+  {
+    FT_Error  error = 0;
+
+
+    if ( index && index->count > element )
+    {
+      /* compute start and end offsets */
+      FT_ULong  off1, off2;
+
+
+      off1 = index->offsets[element];
+      if ( off1 )
+      {
+        do
+        {
+          element++;
+          off2 = index->offsets[element];
+
+        } while ( off2 == 0 && element < index->count );
+
+        if ( !off2 )
+          off1 = 0;
+      }
+
+      /* access element */
+      if ( off1 )
+      {
+        *pbyte_len = off2 - off1;
+
+        if ( index->bytes )
+        {
+          /* this index was completely loaded in memory, that's easy */
+          *pbytes = index->bytes + off1 - 1;
+        }
+        else
+        {
+          /* this index is still on disk/file, access it through a frame */
+          FT_Stream  stream = index->stream;
+
+
+          if ( FILE_Seek( index->data_offset + off1 - 1 ) ||
+               EXTRACT_Frame( off2 - off1, *pbytes )      )
+            goto Exit;
+        }
+      }
+      else
+      {
+        /* empty index element */
+        *pbytes    = 0;
+        *pbyte_len = 0;
+      }
+    }
+    else
+      error = T2_Err_Invalid_Argument;
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  T2_Forget_Element( CFF_Index*  index,
+                           FT_Byte**   pbytes )
+  {
+    if ( index->bytes == 0 )
+    {
+      FT_Stream  stream = index->stream;
+
+
+      RELEASE_Frame( *pbytes );
+    }
+  }
+
+
+  LOCAL_FUNC
+  FT_String*  T2_Get_Name( CFF_Index*  index,
+                           FT_UInt     element )
+  {
+    FT_Memory   memory = index->stream->memory;
+    FT_Byte*    bytes;
+    FT_ULong    byte_len;
+    FT_Error    error;
+    FT_String*  name = 0;
+
+
+    error = T2_Access_Element( index, element, &bytes, &byte_len );
+    if ( error )
+      goto Exit;
+
+    if ( !ALLOC( name, byte_len + 1 ) )
+    {
+      MEM_Copy( name, bytes, byte_len );
+      name[byte_len] = 0;
+    }
+    T2_Forget_Element( index, &bytes );
+
+  Exit:
+    return name;
+  }
+
+
+  LOCAL_FUNC
+  FT_String*  T2_Get_String( CFF_Index*          index,
+                             FT_UInt             sid,
+                             PSNames_Interface*  interface )
+  {
+    /* if it is not a standard string, return it */
+    if ( sid > 390 )
+      return T2_Get_Name( index, sid - 390 );
+
+    /* that's a standard string, fetch a copy from the PSName module */
+    {
+      FT_String*   name       = 0;
+      const char*  adobe_name = interface->adobe_std_strings( sid );
+      FT_UInt      len;
+
+
+      if ( adobe_name )
+      {
+        FT_Memory memory = index->stream->memory;
+        FT_Error  error;
+
+
+        len = (FT_UInt)strlen( adobe_name );
+        if ( !ALLOC( name, len + 1 ) )
+        {
+          MEM_Copy( name, adobe_name, len );
+          name[len] = 0;
+        }
+      }
+
+      return name;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***   FD Select table support                                         ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  void  CFF_Done_FD_Select( CFF_FD_Select*  select,
+                            FT_Stream       stream )
+  {
+    if ( select->data )
+      RELEASE_Frame( select->data );
+
+    select->data_size   = 0;
+    select->format      = 0;
+    select->range_count = 0;
+  }
+
+
+  static
+  FT_Error  CFF_Load_FD_Select( CFF_FD_Select*  select,
+                                FT_UInt         num_glyphs,
+                                FT_Stream       stream,
+                                FT_ULong        offset )
+  {
+    FT_Error       error;
+    FT_Byte        format;
+    FT_UInt        num_ranges;
+
+
+    /* read format */
+    if ( FILE_Seek( offset ) || READ_Byte( format ) )
+      goto Exit;
+
+    select->format      = format;
+    select->cache_count = 0;   /* clear cache */
+
+    switch ( format )
+    {
+    case 0:     /* format 0, that's simple */
+      select->data_size = num_glyphs;
+      goto Load_Data;
+
+    case 3:     /* format 3, a tad more complex */
+      if ( READ_UShort( num_ranges ) )
+        goto Exit;
+
+      select->data_size = num_ranges * 3 + 2;
+
+    Load_Data:
+      if ( EXTRACT_Frame( select->data_size, select->data ) )
+        goto Exit;
+      break;
+
+    default:    /* hmm... that's wrong */
+      error = T2_Err_Invalid_File_Format;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Byte  CFF_Get_FD( CFF_FD_Select*  select,
+                       FT_UInt         glyph_index )
+  {
+    FT_Byte  fd = 0;
+
+
+    switch ( select->format )
+    {
+    case 0:
+      fd = select->data[glyph_index];
+      break;
+
+    case 3:
+      /* first, compare to cache */
+      if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count )
+      {
+        fd = select->cache_fd;
+        break;
+      }
+
+      /* then, lookup the ranges array */
+      {
+        FT_Byte*  p       = select->data;
+        FT_Byte*  p_limit = p + select->data_size;
+        FT_Byte   fd2;
+        FT_UInt   first, limit;
+
+
+        first = NEXT_UShort( p );
+        do
+        {
+          if ( glyph_index < first )
+            break;
+
+          fd2   = *p++;
+          limit = NEXT_UShort( p );
+
+          if ( glyph_index < limit )
+          {
+            fd = fd2;
+
+            /* update cache */
+            select->cache_first = first;
+            select->cache_count = limit-first;
+            select->cache_fd    = fd2;
+            break;
+          }
+          first = limit;
+
+        } while ( p < p_limit );
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    return fd;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***   CFF font support                                                ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  CFF_Load_SubFont( CFF_SubFont*  font,
+                              CFF_Index*    index,
+                              FT_UInt       font_index,
+                              FT_Stream     stream,
+                              FT_ULong      base_offset )
+  {
+    FT_Error        error;
+    T2_Parser       parser;
+    FT_Byte*        dict;
+    FT_ULong        dict_len;
+    CFF_Font_Dict*  top  = &font->font_dict;
+    CFF_Private*    priv = &font->private_dict;
+
+
+    T2_Parser_Init( &parser, T2CODE_TOPDICT, &font->font_dict );
+
+    /* set defaults */
+    MEM_Set( top, 0, sizeof ( *top ) );
+
+    top->underline_position  = -100;
+    top->underline_thickness = 50;
+    top->charstring_type     = 2;
+    top->font_matrix.xx      = 0x10000L;
+    top->font_matrix.yy      = 0x10000L;
+    top->cid_count           = 8720;
+
+    error = T2_Access_Element( index, font_index, &dict, &dict_len ) ||
+            T2_Parser_Run( &parser, dict, dict + dict_len );
+
+    T2_Forget_Element( index, &dict );
+
+    if ( error )
+      goto Exit;
+
+    /* if it is a CID font, we stop there */
+    if ( top->cid_registry )
+      goto Exit;
+
+    /* parse the private dictionary, if any */
+    if ( top->private_offset && top->private_size )
+    {
+      /* set defaults */
+      MEM_Set( priv, 0, sizeof ( *priv ) );
+
+      priv->blue_shift       = 7;
+      priv->blue_fuzz        = 1;
+      priv->lenIV            = -1;
+      priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
+      priv->blue_scale       = (FT_Fixed)0.039625 * 0x10000L;
+
+      T2_Parser_Init( &parser, T2CODE_PRIVATE, priv );
+
+      if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
+           ACCESS_Frame( font->font_dict.private_size )              )
+        goto Exit;
+
+      error = T2_Parser_Run( &parser,
+                             (FT_Byte*)stream->cursor,
+                             (FT_Byte*)stream->limit );
+      FORGET_Frame();
+      if ( error )
+        goto Exit;
+    }
+
+    /* read the local subrs, if any */
+    if ( priv->local_subrs_offset )
+    {
+      if ( FILE_Seek( base_offset + top->private_offset +
+                      priv->local_subrs_offset ) )
+        goto Exit;
+
+      error = t2_new_cff_index( &font->local_subrs_index, stream, 1 );
+      if ( error )
+        goto Exit;
+
+      font->num_local_subrs = font->local_subrs_index.count;
+      error = t2_explicit_cff_index( &font->local_subrs_index,
+                                     &font->local_subrs );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  CFF_Done_SubFont( FT_Memory     memory,
+                          CFF_SubFont*  subfont )
+  {
+    if ( subfont )
+    {
+      t2_done_cff_index( &subfont->local_subrs_index );
+      FREE( subfont->local_subrs );
+    }
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Load_CFF_Font( FT_Stream  stream,
+                              FT_Int     face_index,
+                              CFF_Font*  font )
+  {
+    static const FT_Frame_Field  cff_header_fields[] =
+    {
+      FT_FRAME_START( 4 ),
+        FT_FRAME_BYTE( CFF_Font, version_major ),
+        FT_FRAME_BYTE( CFF_Font, version_minor ),
+        FT_FRAME_BYTE( CFF_Font, header_size ),
+        FT_FRAME_BYTE( CFF_Font, absolute_offsize ),
+      FT_FRAME_END
+    };
+
+    FT_Error        error;
+    FT_Memory       memory = stream->memory;
+    FT_ULong        base_offset;
+    CFF_Font_Dict*  dict;
+
+
+    MEM_Set( font, 0, sizeof ( *font ) );
+    font->stream = stream;
+    font->memory = memory;
+    dict         = &font->top_font.font_dict;
+    base_offset  = FILE_Pos();
+
+    /* read CFF font header */
+    if ( READ_Fields( cff_header_fields, font ) )
+      goto Exit;
+
+    /* check format */
+    if ( font->version_major   != 1 ||
+         font->header_size      < 4 ||
+         font->absolute_offsize > 4 )
+    {
+      FT_TRACE2(( "[not a CFF font header!]\n" ));
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* skip the rest of the header */
+    (void)FILE_Skip( font->header_size - 4 );
+
+    /* read the name, top dict, string and global subrs index */
+    error = t2_new_cff_index( &font->name_index, stream, 0 )       ||
+            t2_new_cff_index( &font->font_dict_index, stream, 0 )  ||
+            t2_new_cff_index( &font->string_index, stream, 0 )     ||
+            t2_new_cff_index( &font->global_subrs_index, stream, 1 );
+    if ( error )
+      goto Exit;
+
+    /* well, we don't really forget the `disabled' fonts... */
+    font->num_faces = font->name_index.count;
+    if ( face_index >= (FT_Int)font->num_faces )
+    {
+      FT_ERROR(( "T2_Load_CFF_Font: incorrect face index = %d\n",
+                 face_index ));
+      error = T2_Err_Invalid_Argument;
+    }
+
+    /* in case of a font format check, simply exit now */
+    if ( face_index < 0 )
+      goto Exit;
+
+    /* now, parse the top-level font dictionary */
+    error = CFF_Load_SubFont( &font->top_font,
+                              &font->font_dict_index,
+                              face_index,
+                              stream,
+                              base_offset );
+    if ( error )
+      goto Exit;
+
+    /* now, check for a CID font */
+    if ( dict->cid_registry )
+    {
+      CFF_Index     fd_index;
+      CFF_SubFont*  sub;
+      FT_UInt       index;
+
+
+      /* this is a CID-keyed font, we must now allocate a table of */
+      /* sub-fonts, then load each of them separately              */
+      if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) )
+        goto Exit;
+
+      error = t2_new_cff_index( &fd_index, stream, 0 );
+      if ( error )
+        goto Exit;
+
+      if ( fd_index.count > CFF_MAX_CID_FONTS )
+      {
+        FT_ERROR(( "T2_Load_CFF_Font: FD array too large in CID font\n" ));
+        goto Fail_CID;
+      }
+
+      /* allocate & read each font dict independently */
+      font->num_subfonts = fd_index.count;
+      if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) )
+        goto Fail_CID;
+
+      /* setup pointer table */
+      for ( index = 0; index < fd_index.count; index++ )
+        font->subfonts[index] = sub + index;
+
+      /* now load each sub font independently */
+      for ( index = 0; index < fd_index.count; index++ )
+      {
+        sub = font->subfonts[index];
+        error = CFF_Load_SubFont( sub, &fd_index, index,
+                                  stream, base_offset );
+        if ( error )
+          goto Fail_CID;
+      }
+
+      /* now load the FD Select array */
+      error = CFF_Load_FD_Select( &font->fd_select,
+                                  dict->cid_count,
+                                  stream,
+                                  base_offset + dict->cid_fd_select_offset );
+
+   Fail_CID:
+      t2_done_cff_index( &fd_index );
+
+      if ( error )
+        goto Exit;
+    }
+    else
+      font->num_subfonts = 0;
+
+    /* read the charstrings index now */
+    if ( dict->charstrings_offset == 0 )
+    {
+      FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" ));
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
+      goto Exit;
+
+    error = t2_new_cff_index( &font->charstrings_index, stream, 0 );
+    if ( error )
+      goto Exit;
+
+    /* explicit the global subrs */
+    font->num_global_subrs = font->global_subrs_index.count;
+    font->num_glyphs       = font->charstrings_index.count;
+
+    error = t2_explicit_cff_index( &font->global_subrs_index,
+                                   &font->global_subrs ) ;
+
+    if ( error )
+      goto Exit;
+
+    /* get the font name */
+    font->font_name = T2_Get_Name( &font->name_index, face_index );
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  T2_Done_CFF_Font( CFF_Font*  font )
+  {
+    FT_Memory  memory = font->memory;
+    FT_UInt    index;
+
+
+    t2_done_cff_index( &font->global_subrs_index );
+    t2_done_cff_index( &font->string_index );
+    t2_done_cff_index( &font->font_dict_index );
+    t2_done_cff_index( &font->name_index );
+    t2_done_cff_index( &font->charstrings_index );
+
+    /* release font dictionaries */
+    for ( index = 0; index < font->num_subfonts; index++ )
+      CFF_Done_SubFont( memory, font->subfonts[index] );
+
+    CFF_Done_SubFont( memory, &font->top_font );
+
+    CFF_Done_FD_Select( &font->fd_select, font->stream );
+
+    FREE( font->global_subrs );
+    FREE( font->font_name );
+  }
+
+
+/* END */
diff --git a/src/freetype/cff/t2load.h b/src/freetype/cff/t2load.h
new file mode 100644 (file)
index 0000000..7ebc76d
--- /dev/null
@@ -0,0 +1,69 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2load.h                                                               */
+/*                                                                         */
+/*    OpenType glyph data/program tables loader (specification).           */
+/*                                                                         */
+/*  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 T2LOAD_H
+#define T2LOAD_H
+
+#include <freetype/internal/t2types.h>
+#include <freetype/internal/psnames.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  LOCAL_DEF
+  FT_String*  T2_Get_Name( CFF_Index*  index,
+                           FT_UInt     element );
+
+  LOCAL_DEF
+  FT_String*  T2_Get_String( CFF_Index*          index,
+                             FT_UInt             sid,
+                             PSNames_Interface*  interface );
+
+  LOCAL_DEF
+  FT_Error  T2_Access_Element( CFF_Index*  index,
+                               FT_UInt     element,
+                               FT_Byte**   pbytes,
+                               FT_ULong*   pbyte_len );
+
+  LOCAL_DEF
+  void  T2_Forget_Element( CFF_Index*  index,
+                           FT_Byte**   pbytes );
+
+  LOCAL_DEF
+  FT_Error  T2_Load_CFF_Font( FT_Stream  stream,
+                              FT_Int     face_index,
+                              CFF_Font*  font );
+
+  LOCAL_DEF
+  void  T2_Done_CFF_Font( CFF_Font*  font );
+
+  LOCAL_DEF
+  FT_Byte  CFF_Get_FD( CFF_FD_Select*  select,
+                       FT_UInt         glyph_index );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T2LOAD_H */
+
+
+/* END */
diff --git a/src/freetype/cff/t2objs.c b/src/freetype/cff/t2objs.c
new file mode 100644 (file)
index 0000000..1d59a58
--- /dev/null
@@ -0,0 +1,600 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2objs.c                                                               */
+/*                                                                         */
+/*    OpenType objects manager (body).                                     */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/fterrors.h>
+#include <freetype/ttnameid.h>
+#include <freetype/tttags.h>
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2objs.h"
+#include "t2load.h"
+
+#else
+
+#include <cff/t2objs.h>
+#include <cff/t2load.h>
+
+#endif
+
+
+#include <freetype/internal/t2errors.h>
+
+#include <string.h>         /* for strlen() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t2objs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           FACE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  FT_String*  T2_StrCopy( FT_Memory         memory,
+                          const FT_String*  source )
+  {
+    FT_Error    error;
+    FT_String*  result = 0;
+    FT_Int      len = (FT_Int)strlen( source );
+
+
+    if ( !ALLOC( result, len + 1 ) )
+    {
+      MEM_Copy( result, source, len );
+      result[len] = 0;
+    }
+    return result;
+  }
+
+
+#if 0
+
+  /* this function is used to build a Unicode charmap from the glyph names */
+  /* in a file                                                             */
+  static
+  FT_Error  CFF_Build_Unicode_Charmap( T2_Face             face,
+                                       FT_ULong            base_offset,
+                                       PSNames_Interface*  psnames )
+  {
+    CFF_Font*       font = (CFF_Font*)face->extra.data;
+    FT_Memory       memory = FT_FACE_MEMORY(face);
+    FT_UInt         n, num_glyphs = face->root.num_glyphs;
+    const char**    glyph_names;
+    FT_Error        error;
+    CFF_Font_Dict*  dict = &font->top_font.font_dict;
+    FT_ULong        charset_offset;
+    FT_Byte         format;
+    FT_Stream       stream = face->root.stream;
+
+
+    charset_offset = dict->charset_offset;
+    if ( !charset_offset )
+    {
+      FT_ERROR(( "CFF.Build_Unicode_Charmap: charset table is missing\n" ));
+      error = T2_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* allocate the charmap */
+    if ( ALLOC( face->charmap, ...
+
+    /* seek to charset table and allocate glyph names table */
+    if ( FILE_Seek( base_offset + charset_offset )           ||
+         ALLOC_ARRAY( glyph_names, num_glyphs, const char* ) )
+      goto Exit;
+
+    /* now, read each glyph name and store it in the glyph name table */
+    if ( READ_Byte( format ) )
+      goto Fail;
+
+    switch ( format )
+    {
+      case 0:  /* format 0 - one SID per glyph */
+        {
+          const char**  gname = glyph_names;
+          const char**  limit = gname + num_glyphs;
+
+          if ( ACCESS_Frame( num_glyphs*2 ) )
+            goto Fail;
+
+          for ( ; gname < limit; gname++ )
+            gname[0] = T2_Get_String( &font->string_index,
+                                      GET_UShort(),
+                                      psnames );
+          FORGET_Frame();
+          break;
+        }
+
+      case 1:  /* format 1 - sequential ranges                    */
+      case 2:  /* format 2 - sequential ranges with 16-bit counts */
+        {
+          const char**  gname = glyph_names;
+          const char**  limit = gname + num_glyphs;
+          FT_UInt       len = 3;
+
+          if (format == 2)
+            len++;
+
+          while (gname < limit)
+          {
+            FT_UInt   first;
+            FT_UInt   count;
+
+            if ( ACCESS_Frame( len ) )
+              goto Fail;
+
+            first = GET_UShort();
+            if (format == 3)
+              count = GET_UShort();
+            else
+              count = GET_Byte();
+
+            FORGET_Frame();
+
+            for ( ; count > 0; count-- )
+            {
+              gname[0] = T2_Get_String( &font->string_index,
+                                        first,
+                                        psnames );
+              gname++;
+              first++;
+            }
+          }
+          break;
+        }
+
+      default:   /* unknown charset format! */
+        FT_ERROR(( "CFF: unknown charset format!\n" ));
+        error = T2_Err_Invalid_File_Format;
+        goto Fail;
+    }
+
+    /* all right, the glyph names were loaded, we now need to create */
+    /* the corresponding unicode charmap..                           */
+
+  Fail:
+    for ( n = 0; n < num_glyphs; n++ )
+      FREE( glyph_names[n] );
+
+    FREE( glyph_names );
+
+  Exit:
+    return error;
+  }
+
+#endif /* 0 */
+
+
+  static
+  FT_Encoding  find_encoding( int  platform_id,
+                              int  encoding_id )
+  {
+    typedef struct  TEncoding
+    {
+      int          platform_id;
+      int          encoding_id;
+      FT_Encoding  encoding;
+
+    } TEncoding;
+
+    static
+    const TEncoding  tt_encodings[] =
+    {
+      { TT_PLATFORM_ISO,           -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_APPLE_UNICODE, -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     ft_encoding_apple_roman },
+
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       ft_encoding_sjis },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     ft_encoding_gb2312 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      ft_encoding_big5 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    ft_encoding_wansung },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      ft_encoding_johab }
+    };
+
+    const TEncoding  *cur, *limit;
+
+
+    cur   = tt_encodings;
+    limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur->platform_id == platform_id )
+      {
+        if ( cur->encoding_id == encoding_id ||
+             cur->encoding_id == -1          )
+          return cur->encoding;
+      }
+    }
+
+    return ft_encoding_none;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given OpenType face object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The source font stream.                              */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The newly built face object.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T2_Init_Face( FT_Stream      stream,
+                          T2_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params )
+  {
+    FT_Error            error;
+    SFNT_Interface*     sfnt;
+    PSNames_Interface*  psnames;
+    FT_Bool             pure_cff    = 1;
+    FT_Bool             sfnt_format = 0;
+
+
+    sfnt = (SFNT_Interface*)FT_Get_Module_Interface(
+             face->root.driver->root.library, "sfnt" );
+    if ( !sfnt )
+      goto Bad_Format;
+
+    psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                face->root.driver->root.library, "psnames" );
+
+    /* create input stream from resource */
+    if ( FILE_Seek( 0 ) )
+      goto Exit;
+
+    /* check that we have a valid OpenType file */
+    error = sfnt->init_face( stream, face, face_index, num_params, params );
+    if ( !error )
+    {
+      if ( face->format_tag != 0x4F54544FL )  /* `OTTO'; OpenType/CFF font */
+      {
+        FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
+        goto Bad_Format;
+      }
+
+      /* If we are performing a simple font format check, exit immediately */
+      if ( face_index < 0 )
+        return T2_Err_Ok;
+
+      sfnt_format = 1;
+
+      /* now, the font can be either an OpenType/CFF font, or a SVG CEF */
+      /* font in the later case; it doesn't have a `head' table         */
+      error = face->goto_table( face, TTAG_head, stream, 0 );
+      if ( !error )
+      {
+        pure_cff = 0;
+
+        /* Load font directory */
+        error = sfnt->load_face( stream, face,
+                                 face_index, num_params, params );
+        if ( error )
+          goto Exit;
+      }
+      else
+      {
+        /* load the `cmap' table by hand */
+        error = sfnt->load_charmaps( face, stream );
+        if ( error )
+          goto Exit;
+
+        /* XXX: for now, we don't load the GPOS table, as OpenType Layout */
+        /* support will be added later to FreeType 2 as a separate module */
+      }
+
+      /* now, load the CFF part of the file */
+      error = face->goto_table( face, TTAG_CFF, stream, 0 );
+      if ( error )
+        goto Exit;
+    }
+    else
+    {
+      /* rewind to start of file; we are going to load a pure-CFF font */
+      (void)FILE_Seek( 0 );
+      error = FT_Err_Ok;
+    }
+
+    /* now load and parse the CFF table in the file */
+    {
+      CFF_Font*  cff;
+      FT_Memory  memory = face->root.memory;
+      FT_Face    root;
+      FT_UInt    flags;
+      FT_ULong   base_offset;
+
+
+      if ( ALLOC( cff, sizeof ( *cff ) ) )
+        goto Exit;
+
+      base_offset = FILE_Pos();
+
+      face->extra.data = cff;
+      error = T2_Load_CFF_Font( stream, face_index, cff );
+      if ( error )
+        goto Exit;
+
+      /* Complement the root flags with some interesting information. */
+      /* Note that this is only necessary for pure CFF and CEF fonts  */
+
+      root = &face->root;
+      if ( pure_cff )
+      {
+        CFF_Font_Dict*  dict = &cff->top_font.font_dict;
+
+
+        /* we need the `PSNames' module for pure-CFF and CEF formats */
+        if ( !psnames )
+        {
+          FT_ERROR(( "T2_Init_Face:" ));
+          FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
+          FT_ERROR(( "             " ));
+          FT_ERROR(( " without the `PSNames' module\n" ));
+          goto Bad_Format;
+        }
+
+        /* compute number of glyphs */
+        if ( dict->cid_registry )
+          root->num_glyphs = dict->cid_count;
+        else
+          root->num_glyphs = cff->charstrings_index.count;
+
+        /* set global bbox, as well as EM size */
+        root->units_per_EM = (FT_UInt)FT_DivFix( 1000L << 16,
+                                                 dict->font_matrix.yy ) >> 16;
+        root->bbox      = dict->font_bbox;
+        root->ascender  = (FT_Short)root->bbox.yMax;
+        root->descender = (FT_Short)root->bbox.yMin;
+
+        /* retrieve font family & style name */
+        root->family_name = T2_Get_Name( &cff->name_index, face_index );
+        if ( dict->cid_registry )
+        {
+          root->style_name = T2_StrCopy( memory, "Regular" );  /* XXXX */
+        }
+        else
+        {
+          root->style_name = T2_Get_String( &cff->string_index,
+                                            dict->weight,
+                                            psnames );
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Compute face flags.                                             */
+        /*                                                                 */
+        flags = FT_FACE_FLAG_SCALABLE  |    /* scalable outlines */
+                FT_FACE_FLAG_HORIZONTAL;    /* horizontal data   */
+
+        if ( sfnt_format )
+          flags |= FT_FACE_FLAG_SFNT;
+
+        /* fixed width font? */
+        if ( dict->is_fixed_pitch )
+          flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+/* XXXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
+#if 0
+        /* kerning available? */
+        if ( face->kern_pairs )
+          flags |= FT_FACE_FLAG_KERNING;
+#endif
+
+        root->face_flags = flags;
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Compute style flags.                                            */
+        /*                                                                 */
+        flags = 0;
+
+        if ( dict->italic_angle )
+          flags |= FT_STYLE_FLAG_ITALIC;
+
+        /* XXX: may not be correct */
+        if ( cff->top_font.private_dict.force_bold )
+          flags |= FT_STYLE_FLAG_BOLD;
+
+        root->style_flags = flags;
+
+        /* set the charmaps if any */
+        if ( sfnt_format )
+        {
+          /*****************************************************************/
+          /*                                                               */
+          /* Polish the charmaps.                                          */
+          /*                                                               */
+          /*   Try to set the charmap encoding according to the platform & */
+          /*   encoding ID of each charmap.                                */
+          /*                                                               */
+          TT_CharMap  charmap;
+          FT_Int      n;
+
+
+          charmap            = face->charmaps;
+          root->num_charmaps = face->num_charmaps;
+
+          /* allocate table of pointers */
+          if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
+            goto Exit;
+
+          for ( n = 0; n < root->num_charmaps; n++, charmap++ )
+          {
+            FT_Int  platform = charmap->cmap.platformID;
+            FT_Int  encoding = charmap->cmap.platformEncodingID;
+
+
+            charmap->root.face        = (FT_Face)face;
+            charmap->root.platform_id = platform;
+            charmap->root.encoding_id = encoding;
+            charmap->root.encoding    = find_encoding( platform, encoding );
+
+            /* now, set root->charmap with a unicode charmap */
+            /* wherever available                            */
+            if ( !root->charmap                                &&
+                 charmap->root.encoding == ft_encoding_unicode )
+              root->charmap = (FT_CharMap)charmap;
+
+            root->charmaps[n] = (FT_CharMap)charmap;
+          }
+        }
+      }
+    }
+
+  Exit:
+    return error;
+
+  Bad_Format:
+    error = FT_Err_Unknown_File_Format;
+    goto Exit;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given face object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A pointer to the face object to destroy.                   */
+  /*                                                                       */
+  LOCAL_DEF
+  void  T2_Done_Face( T2_Face  face )
+  {
+    FT_Memory        memory = face->root.memory;
+    SFNT_Interface*  sfnt   = (SFNT_Interface*)face->sfnt;
+
+
+    if ( sfnt )
+      sfnt->done_face( face );
+
+    {
+      CFF_Font*  cff = (CFF_Font*)face->extra.data;
+
+
+      if ( cff )
+      {
+        T2_Done_CFF_Font( cff );
+        FREE( face->extra.data );
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Init_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given OpenType driver object.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T2_Init_Driver( T2_Driver  driver )
+  {
+    /* init extension registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+    return TT_Init_Extensions( driver );
+
+#else
+
+    FT_UNUSED( driver );
+
+    return T2_Err_Ok;
+
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T2_Done_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given OpenType driver.                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target OpenType driver.                  */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T2_Done_Driver( T2_Driver  driver )
+  {
+    /* destroy extensions registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+    TT_Done_Extensions( driver );
+
+#else
+
+    FT_UNUSED( driver );
+
+#endif
+  }
+
+
+/* END */
diff --git a/src/freetype/cff/t2objs.h b/src/freetype/cff/t2objs.h
new file mode 100644 (file)
index 0000000..2602862
--- /dev/null
@@ -0,0 +1,148 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2objs.h                                                               */
+/*                                                                         */
+/*    OpenType objects manager (specification).                            */
+/*                                                                         */
+/*  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 T2OBJS_H
+#define T2OBJS_H
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/t2types.h>
+#include <freetype/internal/t2errors.h>
+#include <freetype/internal/psnames.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T2_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType driver object.                             */
+  /*                                                                       */
+  typedef struct T2_DriverRec_*  T2_Driver;
+
+  typedef TT_Face  T2_Face;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T2_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType size object.                               */
+  /*                                                                       */
+  typedef FT_Size  T2_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T2_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType glyph slot object.                         */
+  /*                                                                       */
+  typedef struct T2_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+  } T2_GlyphSlotRec, *T2_GlyphSlot;
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Subglyph transformation record.                                       */
+  /*                                                                       */
+  typedef struct  T2_Transform_
+  {
+    FT_Fixed    xx, xy;     /* transformation matrix coefficients */
+    FT_Fixed    yx, yy;
+    FT_F26Dot6  ox, oy;     /* offsets        */
+
+  } T2_Transform;
+
+
+  /* this is only used in the case of a pure CFF font with no charmap */
+  typedef struct  T2_CharMapRec_
+  {
+    TT_CharMapRec  root;
+    PS_Unicodes    unicodes;
+
+  } T2_CharMapRec, *T2_CharMap;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* TrueType driver class.                                              */
+  /*                                                                     */
+  typedef struct  T2_DriverRec_
+  {
+    FT_DriverRec  root;
+
+    void*         extension_component;
+
+  } T2_DriverRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Face functions                                                        */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T2_Init_Face( FT_Stream      stream,
+                          T2_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  T2_Done_Face( T2_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Driver functions                                                      */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T2_Init_Driver( T2_Driver  driver );
+
+  LOCAL_DEF
+  void  T2_Done_Driver( T2_Driver  driver );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T2OBJS_H */
+
+
+/* END */
diff --git a/src/freetype/cff/t2parse.c b/src/freetype/cff/t2parse.c
new file mode 100644 (file)
index 0000000..7d62fef
--- /dev/null
@@ -0,0 +1,641 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2parse.c                                                              */
+/*                                                                         */
+/*    OpenType parser (body).                                              */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2parse.h"
+
+#else
+
+#include <cff/t2parse.h>
+
+#endif
+
+
+#include <freetype/internal/t2errors.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t2parse
+
+
+#define T2_Err_Stack_Underflow   FT_Err_Invalid_Argument
+#define T2_Err_Syntax_Error      FT_Err_Invalid_Argument
+
+
+  enum
+  {
+    t2_kind_none = 0,
+    t2_kind_num,
+    t2_kind_fixed,
+    t2_kind_string,
+    t2_kind_bool,
+    t2_kind_delta,
+    t2_kind_callback,
+
+    t2_kind_max  /* do not remove */
+  };
+
+
+  /* now generate handlers for the most simple fields */
+  typedef FT_Error  (*T2_Field_Reader)( T2_Parser*  parser );
+
+  typedef struct  T2_Field_Handler_
+  {
+    int              kind;
+    int              code;
+    FT_UInt          offset;
+    FT_Byte          size;
+    T2_Field_Reader  reader;
+    FT_UInt          array_max;
+    FT_UInt          count_offset;
+
+  } T2_Field_Handler;
+
+
+  LOCAL_FUNC
+  void  T2_Parser_Init( T2_Parser*  parser,
+                        FT_UInt     code,
+                        void*       object )
+  {
+    MEM_Set( parser, 0, sizeof ( *parser ) );
+
+    parser->top         = parser->stack;
+    parser->object_code = code;
+    parser->object      = object;
+  }
+
+
+  /* reads an integer */
+  static
+  FT_Long  parse_t2_integer( FT_Byte*  start,
+                             FT_Byte*  limit )
+  {
+    FT_Byte*  p   = start;
+    FT_Int    v   = *p++;
+    FT_Long   val = 0;
+
+
+    if ( v == 28 )
+    {
+      if ( p + 2 > limit )
+        goto Bad;
+
+      val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
+      p  += 2;
+    }
+    else if ( v == 29 )
+    {
+      if ( p + 4 > limit )
+        goto Bad;
+
+      val = ( (FT_Long)p[0] << 24 ) |
+            ( (FT_Long)p[1] << 16 ) |
+            ( (FT_Long)p[2] <<  8 ) |
+                       p[3];
+      p += 4;
+    }
+    else if ( v < 247 )
+    {
+      val = v - 139;
+    }
+    else if ( v < 251 )
+    {
+      if ( p + 1 > limit )
+        goto Bad;
+
+      val = ( v - 247 ) * 256 + p[0] + 108;
+      p++;
+    }
+    else
+    {
+      if ( p + 1 > limit )
+        goto Bad;
+
+      val = -( v - 251 ) * 256 - p[0] - 108;
+      p++;
+    }
+
+  Exit:
+    return val;
+
+  Bad:
+    val = 0;
+    goto Exit;
+  }
+
+
+  /* read a real */
+  static
+  FT_Fixed  parse_t2_real( FT_Byte*  start,
+                           FT_Byte*  limit,
+                           FT_Int    power_ten )
+  {
+    FT_Byte*  p    = start;
+    FT_Long   num, divider, result, exp;
+    FT_Int    sign = 0, exp_sign = 0;
+    FT_Byte   nib;
+    FT_Byte   phase;
+
+
+    result  = 0;
+    num     = 0;
+    divider = 1;
+
+    /* first of all, read the integer part */
+    phase = 4;
+    p--;
+
+    for (;;)
+    {
+      /* read one nibble at a time */
+      if ( phase && ++p >= limit )
+        goto Bad;
+
+      nib   = ( p[0] >> phase ) & 0xF;
+      phase = 4 - phase;
+
+      if ( nib == 0xE )
+        sign = 1;
+      else if ( nib > 9 )
+        break;
+      else
+        result = result * 10 + nib;
+    }
+
+    /* read decimal part, if any */
+    if ( nib == 0xa )
+      for (;;)
+      {
+        /* read one nibble at a time */
+        if ( !phase && ++p >= limit )
+          goto Bad;
+
+        phase = 4 - phase;
+        nib   = ( p[0] >> phase ) & 0xF;
+
+        if ( nib >= 10 )
+          break;
+
+        if (divider < 10000000L)
+        {
+          num      = num * 10 + nib;
+          divider *= 10;
+        }
+      }
+
+    /* read exponent, if any */
+    if ( nib == 12 )
+    {
+      exp_sign = 1;
+      nib      = 11;
+    }
+
+    if ( nib == 11 )
+    {
+      exp = 0;
+
+      for (;;)
+      {
+        /* read one nibble at a time */
+        if ( !phase && ++p >= limit )
+          goto Bad;
+
+        phase = 4 - phase;
+        nib   = ( p[0] >> phase ) & 0xF;
+
+        if ( nib >= 10 )
+          break;
+
+        exp = exp * 10 + nib;
+      }
+
+      if ( exp_sign )
+        exp = -exp;
+
+      power_ten += exp;
+    }
+
+    /* raise to power of ten if needed */
+    while ( power_ten > 0 )
+    {
+      result = result * 10;
+      num    = num * 10;
+
+      power_ten--;
+    }
+
+    while ( power_ten < 0 )
+    {
+      result  = result / 10;
+      divider = divider * 10;
+
+      power_ten++;
+    }
+
+    if ( num )
+      result += FT_DivFix( num, divider );
+
+    if ( sign )
+      result = -result;
+
+  Exit:
+    return result;
+
+  Bad:
+    result = 0;
+    goto Exit;
+  }
+
+
+  /* read a number, either integer or real */
+  static
+  FT_Long  t2_parse_num( FT_Byte**  d )
+  {
+    return ( **d == 30 ? ( parse_t2_real( d[0], d[1], 0 ) >> 16 )
+                       : parse_t2_integer( d[0], d[1] ) );
+  }
+
+
+  /* reads a floating point number, either integer or real */
+  static
+  FT_Fixed  t2_parse_fixed( FT_Byte**  d )
+  {
+    return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 )
+                       : parse_t2_integer( d[0], d[1] ) << 16 );
+  }
+
+
+  static
+  FT_Error  parse_font_matrix( T2_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict   = (CFF_Font_Dict*)parser->object;
+    FT_Matrix*      matrix = &dict->font_matrix;
+    FT_Byte**       data   = parser->stack;
+    FT_Error        error;
+
+
+    error = T2_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 4 )
+    {
+      matrix->xx = t2_parse_fixed( data++ );
+      matrix->yx = t2_parse_fixed( data++ );
+      matrix->xy = t2_parse_fixed( data++ );
+      matrix->yy = t2_parse_fixed( data   );
+      error = T2_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+  static
+  FT_Error  parse_font_bbox( T2_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict = (CFF_Font_Dict*)parser->object;
+    FT_BBox*        bbox = &dict->font_bbox;
+    FT_Byte**       data = parser->stack;
+    FT_Error        error;
+
+
+    error = T2_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 4 )
+    {
+      bbox->xMin = t2_parse_num( data++ );
+      bbox->yMin = t2_parse_num( data++ );
+      bbox->xMax = t2_parse_num( data++ );
+      bbox->yMax = t2_parse_num( data   );
+      error = T2_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+  static
+  FT_Error  parse_private_dict( T2_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict = (CFF_Font_Dict*)parser->object;
+    FT_Byte**       data = parser->stack;
+    FT_Error        error;
+
+
+    error = T2_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 2 )
+    {
+      dict->private_size   = t2_parse_num( data++ );
+      dict->private_offset = t2_parse_num( data   );
+      error = T2_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+  static
+  FT_Error  parse_cid_ros( T2_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict   = (CFF_Font_Dict*)parser->object;
+    FT_Byte**       data   = parser->stack;
+    FT_Error        error;
+
+
+    error = T2_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 3 )
+    {
+      dict->cid_registry   = (FT_UInt)t2_parse_num( data++ );
+      dict->cid_ordering   = (FT_UInt)t2_parse_num( data++ );
+      dict->cid_supplement = (FT_ULong)t2_parse_num( data );
+      error = T2_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+#define T2_FIELD_NUM( code, name ) \
+          T2_FIELD( code, name, t2_kind_num )
+#define T2_FIELD_FIXED( code, name ) \
+          T2_FIELD( code, name, t2_kind_fixed )
+#define T2_FIELD_STRING( code, name ) \
+          T2_FIELD( code, name, t2_kind_string )
+#define T2_FIELD_BOOL( code, name ) \
+          T2_FIELD( code, name, t2_kind_bool )
+#define T2_FIELD_DELTA( code, name,max ) \
+          T2_FIELD( code, name, t2_kind_delta )
+
+#define T2_REF( s, f )  ( ((s*)0)->f )
+
+#define T2_FIELD_CALLBACK( code, name ) \
+          {                             \
+            t2_kind_callback,           \
+            code | T2CODE,              \
+            0, 0,                       \
+            parse_ ## name,             \
+            0, 0                        \
+          },
+
+#undef  T2_FIELD
+#define T2_FIELD( code, name, kind )                 \
+          {                                          \
+            kind,                                    \
+            code | T2CODE,                           \
+            (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
+            sizeof( T2_REF( T2TYPE, name ) ),        \
+            0, 0, 0                                  \
+          },
+
+#undef  T2_FIELD_DELTA
+#define T2_FIELD_DELTA( code, name, max )                    \
+        {                                                    \
+          t2_kind_delta,                                     \
+          code | T2CODE,                                     \
+          (FT_UInt)(char*)&T2_REF( T2TYPE, name ),           \
+          sizeof( T2_REF( T2TYPE, name )[0] ),               \
+          0,                                                 \
+          max,                                               \
+          (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name )    \
+        },
+
+#define T2CODE_TOPDICT  0x1000
+#define T2CODE_PRIVATE  0x2000
+
+  static const T2_Field_Handler  t2_field_handlers[] =
+  {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t2tokens.h"
+
+#else
+
+#include <cff/t2tokens.h>
+
+#endif
+
+    { 0, 0, 0, 0, 0, 0, 0 }
+  };
+
+
+  LOCAL_FUNC
+  FT_Error  T2_Parser_Run( T2_Parser*  parser,
+                           FT_Byte*    start,
+                           FT_Byte*    limit )
+  {
+    FT_Byte*  p     = start;
+    FT_Error  error = T2_Err_Ok;
+
+
+    parser->top    = parser->stack;
+    parser->start  = start;
+    parser->limit  = limit;
+    parser->cursor = start;
+
+    while ( p < limit )
+    {
+      FT_Byte  v = *p;
+
+
+      if ( v >= 27 && v != 31 )
+      {
+        /* it's a number; we will push its position on the stack */
+        if ( parser->top - parser->stack >= T2_MAX_STACK_DEPTH )
+          goto Stack_Overflow;
+
+        *parser->top ++ = p;
+
+        /* now, skip it */
+        if ( v == 30 )
+        {
+          /* skip real number */
+          for (;;)
+          {
+            if ( p >= limit )
+              goto Syntax_Error;
+            v = p[0] >> 4;
+            if ( v == 15 )
+              break;
+            v = p[0] & 0xF;
+            if ( v == 15 )
+              break;
+            p++;
+          }
+          p++;
+        }
+        else if ( v == 28 )
+          p += 2;
+        else if ( v == 29 )
+          p += 4;
+        else if ( v > 246 )
+          p += 1;
+      }
+      else
+      {
+        /* This is not a number, hence it's an operator.  Compute its code */
+        /* and look for it in our current list.                            */
+
+        FT_UInt                  code;
+        FT_UInt                  num_args = (FT_UInt)
+                                              ( parser->top - parser->stack );
+        const T2_Field_Handler*  field;
+
+
+        /* first of all, a trivial check */
+        if ( num_args < 1 )
+          goto Stack_Underflow;
+
+        *parser->top = p;
+        code = v;
+        if ( v == 12 )
+        {
+          /* two byte operator */
+          p++;
+          code = 0x100 | p[0];
+        }
+        code = code | parser->object_code;
+
+        for ( field = t2_field_handlers; field->kind; field++ )
+        {
+          if ( field->code == (FT_Int)code )
+          {
+            /* we found our field's handler; read it */
+            FT_Long   val;
+            FT_Byte*  q = (FT_Byte*)parser->object + field->offset;
+
+
+            switch ( field->kind )
+            {
+            case t2_kind_bool:
+            case t2_kind_string:
+            case t2_kind_num:
+              val = t2_parse_num( parser->stack );
+              goto Store_Number;
+
+            case t2_kind_fixed:
+              val = t2_parse_fixed( parser->stack );
+
+            Store_Number:
+              switch ( field->size )
+              {
+              case 1:
+                *(FT_Byte*)q = (FT_Byte)val;
+                break;
+
+              case 2:
+                *(FT_Short*)q = (FT_Short)val;
+                break;
+
+              case 4:
+                *(FT_Int32*)q = (FT_Int)val;
+                break;
+
+              default:  /* for 64-bit systems where long is 8 bytes */
+                *(FT_Long*)q = val;
+              }
+              break;
+
+            case t2_kind_delta:
+              {
+                FT_Byte*   qcount = (FT_Byte*)parser->object +
+                                      field->count_offset;
+
+                FT_Long    val;
+                FT_Byte**  data = parser->stack;
+
+
+                if ( num_args > field->array_max )
+                  num_args = field->array_max;
+
+                /* store count */
+                *qcount = (FT_Byte)num_args;
+
+                val = 0;
+                while ( num_args > 0 )
+                {
+                  val += t2_parse_num( data++ );
+                  switch ( field->size )
+                  {
+                  case 1:
+                    *(FT_Byte*)q = (FT_Byte)val;
+                    break;
+
+                  case 2:
+                    *(FT_Short*)q = (FT_Short)val;
+                    break;
+
+                  case 4:
+                    *(FT_Int32*)q = (FT_Int)val;
+                    break;
+
+                  default:  /* for 64-bit systems */
+                    *(FT_Long*)q = val;
+                  }
+
+                  q += field->size;
+                  num_args--;
+                }
+              }
+              break;
+
+            default:  /* callback */
+              error = field->reader( parser );
+              if ( error )
+                goto Exit;
+            }
+            goto Found;
+          }
+        }
+
+        /* this is an unknown operator, or it is unsupported; */
+        /* we will ignore it for now.                         */
+
+      Found:
+        /* clear stack */
+        parser->top = parser->stack;
+      }
+      p++;
+    }
+
+  Exit:
+    return error;
+
+  Stack_Overflow:
+    error = T2_Err_Invalid_Argument;
+    goto Exit;
+
+  Stack_Underflow:
+    error = T2_Err_Invalid_Argument;
+    goto Exit;
+
+  Syntax_Error:
+    error = T2_Err_Invalid_Argument;
+    goto Exit;
+  }
+
+
+/* END */
diff --git a/src/freetype/cff/t2parse.h b/src/freetype/cff/t2parse.h
new file mode 100644 (file)
index 0000000..2238444
--- /dev/null
@@ -0,0 +1,70 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2parse.h                                                              */
+/*                                                                         */
+/*    OpenType parser (specification).                                     */
+/*                                                                         */
+/*  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 T2PARSE_H
+#define T2PARSE_H
+
+#include <freetype/internal/t2types.h>
+#include <freetype/internal/ftobjs.h>
+
+#define T2_MAX_STACK_DEPTH  96
+
+#define T2CODE_TOPDICT  0x1000
+#define T2CODE_PRIVATE  0x2000
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  typedef struct  T2_Parser_
+  {
+    FT_Byte*   start;
+    FT_Byte*   limit;
+    FT_Byte*   cursor;
+
+    FT_Byte*   stack[T2_MAX_STACK_DEPTH + 1];
+    FT_Byte**  top;
+
+    FT_UInt    object_code;
+    void*      object;
+
+  } T2_Parser;
+
+
+  LOCAL_DEF
+  void  T2_Parser_Init( T2_Parser*  parser,
+                        FT_UInt     code,
+                        void*       object );
+
+  LOCAL_DEF
+  FT_Error  T2_Parser_Run( T2_Parser*  parser,
+                           FT_Byte*    start,
+                           FT_Byte*    limit );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T2PARSE_H */
+
+
+/* END */
diff --git a/src/freetype/cff/t2tokens.h b/src/freetype/cff/t2tokens.h
new file mode 100644 (file)
index 0000000..13a15e4
--- /dev/null
@@ -0,0 +1,96 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2tokens.h                                                             */
+/*                                                                         */
+/*    OpenType token definitions (specification only).                     */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#undef  T2TYPE
+#undef  T2CODE
+#define T2TYPE  CFF_Font_Dict
+#define T2CODE  T2CODE_TOPDICT
+
+  T2_FIELD_STRING  ( 0, version )
+  T2_FIELD_STRING  ( 1, notice )
+  T2_FIELD_STRING  ( 0x100, copyright )
+  T2_FIELD_STRING  ( 2, full_name )
+  T2_FIELD_STRING  ( 3, family_name )
+  T2_FIELD_STRING  ( 4, weight )
+  T2_FIELD_BOOL    ( 0x101, is_fixed_pitch )
+  T2_FIELD_FIXED   ( 0x102, italic_angle )
+  T2_FIELD_NUM     ( 0x103, underline_position )
+  T2_FIELD_NUM     ( 0x104, underline_thickness )
+  T2_FIELD_NUM     ( 0x105, paint_type )
+  T2_FIELD_NUM     ( 0x106, charstring_type )
+  T2_FIELD_CALLBACK( 0x107, font_matrix )
+  T2_FIELD_NUM     ( 13, unique_id )
+  T2_FIELD_CALLBACK( 5, font_bbox )
+  T2_FIELD_NUM     ( 0x108, stroke_width )
+  T2_FIELD_NUM     ( 15, charset_offset )
+  T2_FIELD_NUM     ( 16, encoding_offset )
+  T2_FIELD_NUM     ( 17, charstrings_offset )
+  T2_FIELD_CALLBACK( 18, private_dict )
+  T2_FIELD_NUM     ( 0x114, synthetic_base )
+  T2_FIELD_STRING  ( 0x115, postscript )
+  T2_FIELD_STRING  ( 0x116, base_font_name )
+
+#if 0
+  T2_FIELD_DELTA   ( 0x117, base_font_blend, 16 )
+  T2_FIELD_CALLBACK( 0x118, multiple_master )
+  T2_FIELD_CALLBACK( 0x119, blend_axit_types )
+#endif
+
+  T2_FIELD_CALLBACK( 0x11E, cid_ros )
+  T2_FIELD_NUM     ( 0x11F, cid_font_version )
+  T2_FIELD_NUM     ( 0x120, cid_font_revision )
+  T2_FIELD_NUM     ( 0x121, cid_font_type )
+  T2_FIELD_NUM     ( 0x122, cid_count )
+  T2_FIELD_NUM     ( 0x123, cid_uid_base )
+  T2_FIELD_NUM     ( 0x124, cid_fd_array_offset )
+  T2_FIELD_NUM     ( 0x125, cid_fd_select_offset )
+  T2_FIELD_STRING  ( 0x126, cid_font_name )
+
+#if 0
+  T2_FIELD_NUM     ( 0x127, chameleon )
+#endif
+
+
+#undef  T2TYPE
+#undef  T2CODE
+#define T2TYPE  CFF_Private
+#define T2CODE  T2CODE_PRIVATE
+
+  T2_FIELD_DELTA( 6, blue_values, 14 )
+  T2_FIELD_DELTA( 7, other_blues, 10 )
+  T2_FIELD_DELTA( 8, family_blues, 14 )
+  T2_FIELD_DELTA( 9, family_other_blues, 10 )
+  T2_FIELD_FIXED( 0x109, blue_scale )
+  T2_FIELD_NUM  ( 0x10A, blue_shift )
+  T2_FIELD_NUM  ( 0x10B, blue_fuzz )
+  T2_FIELD_NUM  ( 10, standard_width )
+  T2_FIELD_NUM  ( 11, standard_height )
+  T2_FIELD_DELTA( 0x10C, snap_widths, 13 )
+  T2_FIELD_DELTA( 0x10D, snap_heights, 13 )
+  T2_FIELD_BOOL ( 0x10E, force_bold )
+  T2_FIELD_FIXED( 0x10F, force_bold_threshold )
+  T2_FIELD_NUM  ( 0x110, lenIV )
+  T2_FIELD_NUM  ( 0x111, language_group )
+  T2_FIELD_FIXED( 0x112, expansion_factor )
+  T2_FIELD_NUM  ( 0x113, initial_random_seed )
+  T2_FIELD_NUM  ( 19, local_subrs_offset )
+  T2_FIELD_NUM  ( 20, default_width )
+  T2_FIELD_NUM  ( 21, nominal_width )
+
+
+/* END */
diff --git a/src/freetype/cid/cidafm.c b/src/freetype/cid/cidafm.c
new file mode 100644 (file)
index 0000000..b563883
--- /dev/null
@@ -0,0 +1,293 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidafm.c                                                               */
+/*                                                                         */
+/*    AFM support for CID-keyed fonts (body).                              */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidafm.h"
+
+#else
+
+#include <cid/cidafm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+
+#include <stdlib.h>  /* for qsort()   */
+#include <string.h>  /* for strcmp()  */
+#include <ctype.h>   /* for isalnum() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cidafm
+
+
+  LOCAL_FUNC
+  void  CID_Done_AFM( FT_Memory  memory,
+                      CID_AFM*   afm )
+  {
+    FREE( afm->kern_pairs );
+    afm->num_pairs = 0;
+  }
+
+
+#undef  IS_KERN_PAIR
+#define IS_KERN_PAIR( p )  ( p[0] == 'K' && p[1] == 'P' )
+
+#define IS_ALPHANUM( c )  ( isalnum( c ) || \
+                            c == '_'     || \
+                            c == '.'     )
+
+
+  /* read a glyph name and return the equivalent glyph index */
+  static
+  FT_UInt  afm_atoindex( FT_Byte**  start,
+                         FT_Byte*   limit,
+                         T1_Font*   type1 )
+  {
+    FT_Byte*  p = *start;
+    FT_Int    len;
+    FT_UInt   result = 0;
+    char      temp[64];
+
+
+    /* skip whitespace */
+    while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
+            p < limit                                             )
+      p++;
+    *start = p;
+
+    /* now, read glyph name */
+    while ( IS_ALPHANUM( *p ) && p < limit )
+      p++;
+
+    len = p - *start;
+
+    if ( len > 0 && len < 64 )
+    {
+      FT_Int  n;
+
+
+      /* copy glyph name to intermediate array */
+      MEM_Copy( temp, *start, len );
+      temp[len] = 0;
+
+      /* lookup glyph name in face array */
+      for ( n = 0; n < type1->num_glyphs; n++ )
+      {
+        char*  gname = (char*)type1->glyph_names[n];
+
+
+        if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 )
+        {
+          result = n;
+          break;
+        }
+      }
+    }
+    *start = p;
+    return result;
+  }
+
+
+  /* read an integer */
+  static
+  int  afm_atoi( FT_Byte**  start,
+                 FT_Byte*   limit )
+  {
+    FT_Byte*  p    = *start;
+    int       sum  = 0;
+    int       sign = 1;
+
+
+    /* skip everything that is not a number */
+    while ( p < limit && !isdigit( *p ) )
+    {
+      sign = 1;
+      if ( *p == '-' )
+        sign = -1;
+
+      p++;
+    }
+
+    while ( p < limit && isdigit( *p ) )
+    {
+      sum = sum * 10 + ( *p - '0' );
+      p++;
+    }
+    *start = p;
+
+    return sum * sign;
+  }
+
+
+#undef  KERN_INDEX
+#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+
+  /* compare two kerning pairs */
+  static
+  int  compare_kern_pairs( const void*  a,
+                           const void*  b )
+  {
+    CID_Kern_Pair*  pair1 = (CID_Kern_Pair*)a;
+    CID_Kern_Pair*  pair2 = (CID_Kern_Pair*)b;
+
+    FT_ULong  index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
+    FT_ULong  index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
+
+
+    return ( index1 - index2 );
+  }
+
+
+  /* parse an AFM file -- for now, only read the kerning pairs */
+  LOCAL_FUNC
+  FT_Error  CID_Read_AFM( FT_Face    cid_face,
+                          FT_Stream  stream )
+  {
+    FT_Error        error;
+    FT_Memory       memory = stream->memory;
+    FT_Byte*        start;
+    FT_Byte*        limit;
+    FT_Byte*        p;
+    FT_Int          count = 0;
+    CID_Kern_Pair*  pair;
+    T1_Font*        type1 = &((T1_Face)t1_face)->type1;
+    CID_AFM*        afm   = 0;
+
+
+    if ( ACCESS_Frame( stream->size ) )
+      return error;
+
+    start = (FT_Byte*)stream->cursor;
+    limit = (FT_Byte*)stream->limit;
+    p     = start;
+
+    /* we are now going to count the occurrences of `KP' or `KPX' in */
+    /* the AFM file.                                                 */
+    count = 0;
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+        count++;
+    }
+
+    /* Actually, kerning pairs are simply optional! */
+    if ( count == 0 )
+      goto Exit;
+
+    /* allocate the pairs */
+    if ( ALLOC( afm, sizeof ( *afm ) )                        ||
+         ALLOC_ARRAY( afm->kern_pairs, count, CID_Kern_Pair ) )
+      goto Exit;
+
+    /* now, read each kern pair */
+    pair           = afm->kern_pairs;
+    afm->num_pairs = count;
+
+    /* save in face object */
+    ((T1_Face)t1_face)->afm_data = afm;
+
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+      {
+        FT_Byte*  q;
+
+
+        /* skip keyword (`KP' or `KPX') */
+        q = p + 2;
+        if ( *q == 'X' )
+          q++;
+
+        pair->glyph1    = afm_atoindex( &q, limit, type1 );
+        pair->glyph2    = afm_atoindex( &q, limit, type1 );
+        pair->kerning.x = afm_atoi( &q, limit );
+
+        pair->kerning.y = 0;
+        if ( p[2] != 'X' )
+          pair->kerning.y = afm_atoi( &q, limit );
+
+        pair++;
+      }
+    }
+
+    /* now, sort the kern pairs according to their glyph indices */
+    qsort( afm->kern_pairs, count, sizeof ( CID_Kern_Pair ),
+           compare_kern_pairs );
+
+  Exit:
+    if ( error )
+      FREE( afm );
+
+    FORGET_Frame();
+
+    return error;
+  }
+
+
+  /* find the kerning for a given glyph pair */
+  LOCAL_FUNC
+  void  CID_Get_Kerning( CID_AFM*    afm,
+                         FT_UInt     glyph1,
+                         FT_UInt     glyph2,
+                         FT_Vector*  kerning )
+  {
+    CID_Kern_Pair  *min, *mid, *max;
+    FT_ULong       index = KERN_INDEX( glyph1, glyph2 );
+
+
+    /* simple binary search */
+    min = afm->kern_pairs;
+    max = min + afm->num_pairs - 1;
+
+    while ( min <= max )
+    {
+      FT_ULong  midi;
+
+
+      mid = min + ( max - min ) / 2;
+      midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
+      if ( midi == index )
+      {
+        *kerning = mid->kerning;
+        return;
+      }
+
+      if ( midi < index )
+        min = mid + 1;
+      else
+        max = mid - 1;
+    }
+
+    kerning->x = 0;
+    kerning->y = 0;
+  }
+
+
+/* END */
diff --git a/src/freetype/cid/cidafm.h b/src/freetype/cid/cidafm.h
new file mode 100644 (file)
index 0000000..542604e
--- /dev/null
@@ -0,0 +1,78 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidafm.h                                                               */
+/*                                                                         */
+/*    AFM support for CID-keyed fonts (specification).                     */
+/*                                                                         */
+/*  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 CIDAFM_H
+#define CIDAFM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidobjs.h"
+
+#else
+
+#include <cid/cidobjs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  typedef struct  CID_Kern_Pair_
+  {
+    FT_UInt    glyph1;
+    FT_UInt    glyph2;
+    FT_Vector  kerning;
+
+  } CID_Kern_Pair;
+
+  typedef struct  CID_AFM_
+  {
+    FT_UInt         num_pairs;
+    CID_Kern_Pair*  kern_pairs;
+
+  } CID_AFM;
+
+
+  LOCAL_DEF
+  FT_Error  CID_Read_AFM( FT_Face    cid_face,
+                          FT_Stream  stream );
+
+  LOCAL_DEF
+  void  CID_Done_AFM( FT_Memory  memory,
+                      CID_AFM*   afm );
+
+  LOCAL_DEF
+  void  CID_Get_Kerning( CID_AFM*    afm,
+                         FT_UInt     glyph1,
+                         FT_UInt     glyph2,
+                         FT_Vector*  kerning );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* CIDAFM_H */
+
+
+/* END */
diff --git a/src/freetype/cid/cidgload.c b/src/freetype/cid/cidgload.c
new file mode 100644 (file)
index 0000000..97c9252
--- /dev/null
@@ -0,0 +1,1558 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidgload.c                                                             */
+/*                                                                         */
+/*    CID-keyed Type1 Glyph Loader (body).                                 */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidload.h"
+#include "cidgload.h"
+
+#else
+
+#include <cid/cidload.h>
+#include <cid/cidgload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cidgload
+
+
+  /* forward */
+  static
+  FT_Error  cid_load_glyph( CID_Decoder*  decoder,
+                            FT_UInt       glyph_index );
+
+
+  typedef enum  CID_Operator_
+  {
+    op_none = 0,
+
+    op_endchar,
+    op_hsbw,
+    op_seac,
+    op_sbw,
+    op_closepath,
+
+    op_hlineto,
+    op_hmoveto,
+    op_hvcurveto,
+    op_rlineto,
+    op_rmoveto,
+    op_rrcurveto,
+    op_vhcurveto,
+    op_vlineto,
+    op_vmoveto,
+
+    op_dotsection,
+
+    op_hstem,
+    op_hstem3,
+    op_vstem,
+    op_vstem3,
+
+    op_div,
+    op_callothersubr,
+    op_callsubr,
+    op_pop,
+    op_return,
+    op_setcurrentpoint,
+
+    op_max    /* never remove this one */
+
+  } CID_Operator;
+
+  static
+  const FT_Int  t1_args_count[op_max] =
+  {
+    0, /* none */
+    0, /* endchar */
+    2, /* hsbw */
+    5, /* seac */
+    4, /* sbw */
+    0, /* closepath */
+
+    1, /* hlineto */
+    1, /* hmoveto */
+    4, /* hvcurveto */
+    2, /* rlineto */
+    2, /* rmoveto */
+    6, /* rrcurveto */
+    4, /* vhcurveto */
+    1, /* vlineto */
+    1, /* vmoveto */
+
+    0, /* dotsection */
+
+    2, /* hstem */
+    6, /* hstem3 */
+    2, /* vstem */
+    6, /* vstem3 */
+
+    2, /* div */
+   -1, /* callothersubr */
+    1, /* callsubr */
+    0, /* pop */
+    0, /* return */
+    2  /* setcurrentpoint */
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********             GENERIC CHARSTRING PARSING               *********/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Init_Builder                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph builder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    builder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    glyph   :: The current glyph object.                               */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  CID_Init_Builder( CID_Builder*   builder,
+                          CID_Face       face,
+                          CID_Size       size,
+                          CID_GlyphSlot  glyph )
+  {
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->glyph  = glyph;
+    builder->memory = face->root.memory;
+
+    if ( glyph )
+    {
+      FT_GlyphLoader*  loader = glyph->root.loader;
+
+
+      builder->loader  = loader;
+      builder->base    = &loader->base.outline;
+      builder->current = &loader->current.outline;
+
+      FT_GlyphLoader_Rewind( loader );
+    }
+
+    if ( size )
+    {
+      builder->scale_x = size->root.metrics.x_scale;
+      builder->scale_y = size->root.metrics.y_scale;
+    }
+
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Done_Builder                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given glyph builder.  Its contents can still be used   */
+  /*    after the call, but the function saves important information       */
+  /*    within the corresponding glyph slot.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder :: A pointer to the glyph builder to finalize.             */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  CID_Done_Builder( CID_Builder*  builder )
+  {
+    CID_GlyphSlot  glyph = builder->glyph;
+
+
+    if ( glyph )
+      glyph->root.outline = *builder->base;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Init_Decoder                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph decoder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  CID_Init_Decoder( CID_Decoder*  decoder )
+  {
+    MEM_Set( decoder, 0, sizeof ( *decoder ) );
+
+    decoder->font_matrix.xx = 0x10000L;
+    decoder->font_matrix.yy = 0x10000L;
+  }
+
+
+  /* check that there is enough space for `count' more points */
+  static
+  FT_Error  check_points( CID_Builder*  builder,
+                          FT_Int        count )
+  {
+    return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+  }
+
+
+  /* add a new point, but do not check space */
+  static
+  void  add_point( CID_Builder*  builder,
+                   FT_Pos        x,
+                   FT_Pos        y,
+                   FT_Byte       flag )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    if ( builder->load_points )
+    {
+      FT_Vector*  point   = outline->points + outline->n_points;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+      point->x = x;
+      point->y = y;
+      *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
+
+      builder->last = *point;
+    }
+
+    outline->n_points++;
+  }
+
+
+  /* check space for a new on-curve point, then add it */
+  static
+  FT_Error  add_point1( CID_Builder*  builder,
+                        FT_Pos        x,
+                        FT_Pos        y )
+  {
+    FT_Error  error;
+
+
+    error = check_points( builder, 1 );
+    if ( !error )
+      add_point( builder, x, y, 1 );
+
+    return error;
+  }
+
+
+  /* check room for a new contour, then add it */
+  static
+  FT_Error  add_contour( CID_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+    FT_Error     error;
+
+
+    if ( !builder->load_points )
+    {
+      outline->n_contours++;
+      return T1_Err_Ok;
+    }
+
+    error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+    if ( !error )
+    {
+      if ( outline->n_contours > 0 )
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+      outline->n_contours++;
+    }
+    return error;
+  }
+
+
+  /* if a path has been started, add its first on-curve point */
+  static
+  FT_Error  start_point( CID_Builder*  builder,
+                         FT_Pos        x,
+                         FT_Pos        y )
+  {
+    /* test whether we are building a new contour */
+    if ( !builder->path_begun )
+    {
+      FT_Error  error;
+
+
+      builder->path_begun = 1;
+      error = add_contour( builder );
+      if ( error )
+        return error;
+    }
+
+    return add_point1( builder, x, y );
+  }
+
+
+  /* close the current contour */
+  static
+  void  close_contour( CID_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    /* XXX: We must not include the last point in the path if it */
+    /*      is located on the first point.                       */
+    if ( outline->n_points > 1 )
+    {
+      FT_Int      first = 0;
+      FT_Vector*  p1    = outline->points + first;
+      FT_Vector*  p2    = outline->points + outline->n_points - 1;
+
+
+      if ( outline->n_contours > 1 )
+      {
+        first = outline->contours[outline->n_contours - 2] + 1;
+        p1    = outline->points + first;
+      }
+
+      if ( p1->x == p2->x && p1->y == p2->y )
+        outline->n_points--;
+    }
+
+    if ( outline->n_contours > 0 )
+      outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+  }
+
+
+#if 0
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    lookup_glyph_by_stdcharcode                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks up a given glyph by its StandardEncoding charcode.  Used     */
+  /*    to implement the SEAC Type 1 operator.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: The current face object.                               */
+  /*                                                                       */
+  /*    charcode :: The character code to look for.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A glyph index in the font face.  Returns -1 if the corresponding   */
+  /*    glyph wasn't found.                                                */
+  /*                                                                       */
+  static
+  FT_Int  lookup_glyph_by_stdcharcode( CID_Face  face,
+                                       FT_Int    charcode )
+  {
+    FT_Int              n;
+    const FT_String*    glyph_name;
+    PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+
+    /* check range of standard char code */
+    if ( charcode < 0 || charcode > 255 )
+      return -1;
+
+    glyph_name = psnames->adobe_std_strings(
+                   psnames->adobe_std_encoding[charcode]);
+
+    for ( n = 0; n < face->cid.cid_count; n++ )
+    {
+      FT_String*  name = (FT_String*)face->type1.glyph_names[n];
+
+
+      if ( name && strcmp( name, glyph_name ) == 0 )
+        return n;
+    }
+
+    return -1;
+  }
+
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1operator_seac                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder  :: The current CID decoder.                               */
+  /*                                                                       */
+  /*    asb      :: The accent's side bearing.                             */
+  /*                                                                       */
+  /*    adx      :: The horizontal offset of the accent.                   */
+  /*                                                                       */
+  /*    ady      :: The vertical offset of the accent.                     */
+  /*                                                                       */
+  /*    bchar    :: The base character's StandardEncoding charcode.        */
+  /*                                                                       */
+  /*    achar    :: The accent character's StandardEncoding charcode.      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  t1operator_seac( CID_Decoder*  decoder,
+                             FT_Pos        asb,
+                             FT_Pos        adx,
+                             FT_Pos        ady,
+                             FT_Int        bchar,
+                             FT_Int        achar )
+  {
+    FT_Error     error;
+    FT_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  base = decoder->builder.base;
+    FT_Vector    left_bearing, advance;
+
+
+    bchar_index = bchar;
+    achar_index = achar;
+
+    if ( bchar_index < 0 || achar_index < 0 )
+    {
+      FT_ERROR(( "t1operator_seac:" ));
+      FT_ERROR(( " invalid seac character code arguments\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* if we are trying to load a composite glyph, do not load the */
+    /* accent character and return the array of subglyphs.         */
+    if ( decoder->builder.no_recurse )
+    {
+      FT_GlyphSlot     glyph = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_GlyphLoader*  loader = glyph->loader;
+      FT_SubGlyph*     subg;
+
+
+      /* reallocate subglyph array if necessary */
+      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+      if ( error )
+        goto Exit;
+
+      subg = loader->current.subglyphs;
+
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
+
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->subglyphs     = loader->current.subglyphs;
+      glyph->format        = ft_glyph_format_composite;
+
+      loader->current.num_subglyphs = 2;
+    }
+
+    /* First load `bchar' in builder */
+    /* now load the unscaled outline */
+    if ( decoder->builder.loader )
+      FT_GlyphLoader_Prepare( decoder->builder.loader );
+
+    error = cid_load_glyph( decoder, bchar_index );  /* load one glyph */
+    if ( error )
+      goto Exit;
+
+    n_base_points = base->n_points;
+
+    {
+      /* save the left bearing and width of the base character */
+      /* as they will be erased by the next load.              */
+
+      left_bearing = decoder->builder.left_bearing;
+      advance      = decoder->builder.advance;
+
+      decoder->builder.left_bearing.x = 0;
+      decoder->builder.left_bearing.y = 0;
+
+      /* Now load `achar' on top of */
+      /* the base outline           */
+      error = cid_load_glyph( decoder, achar_index );
+      if ( error )
+        return error;
+
+      /* restore the left side bearing and   */
+      /* advance width of the base character */
+
+      decoder->builder.left_bearing = left_bearing;
+      decoder->builder.advance      = advance;
+
+      /* Finally, move the accent */
+      if ( decoder->builder.load_points )
+      {
+        FT_Outline  dummy;
+
+
+        dummy.n_points = base->n_points - n_base_points;
+        dummy.points   = base->points   + n_base_points;
+        FT_Outline_Translate( &dummy, adx - asb, ady );
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#define USE_ARGS( n )  do                            \
+                       {                             \
+                         top -= n;                   \
+                         if ( top < decoder->stack ) \
+                           goto Stack_Underflow;     \
+                       } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Parse_CharStrings                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given CID charstrings program.                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder         :: The current CID decoder.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charstring_base :: The base of the charstring stream.              */
+  /*                                                                       */
+  /*    charstring_len  :: The length in bytes of the charstring stream.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  CID_Parse_CharStrings( CID_Decoder*  decoder,
+                                   FT_Byte*      charstring_base,
+                                   FT_Int        charstring_len )
+  {
+    FT_Error           error;
+    CID_Decoder_Zone*  zone;
+    FT_Byte*           ip;
+    FT_Byte*           limit;
+    CID_Builder*       builder = &decoder->builder;
+    FT_Outline*        outline;
+    FT_Pos             x, y;
+
+
+    /* First of all, initialize the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+
+    builder->path_begun  = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error   = T1_Err_Ok;
+    outline = builder->current;
+
+    x = builder->pos_x;
+    y = builder->pos_y;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      FT_Int*       top   = decoder->top;
+      CID_Operator  op    = op_none;
+      FT_Long       value = 0;
+
+
+      /********************************************************************/
+      /*                                                                  */
+      /* Decode operator or operand                                       */
+      /*                                                                  */
+
+      /* First of all, decompress operator or value */
+      switch ( *ip++ )
+      {
+      case 1:
+        op = op_hstem;
+        break;
+
+      case 3:
+        op = op_vstem;
+        break;
+      case 4:
+        op = op_vmoveto;
+        break;
+      case 5:
+        op = op_rlineto;
+        break;
+      case 6:
+        op = op_hlineto;
+        break;
+      case 7:
+        op = op_vlineto;
+        break;
+      case 8:
+        op = op_rrcurveto;
+        break;
+      case 9:
+        op = op_closepath;
+        break;
+      case 10:
+        op = op_callsubr;
+        break;
+      case 11:
+        op = op_return;
+        break;
+
+      case 13:
+        op = op_hsbw;
+        break;
+      case 14:
+        op = op_endchar;
+        break;
+
+      case 21:
+        op = op_rmoveto;
+        break;
+      case 22:
+        op = op_hmoveto;
+        break;
+
+      case 30:
+        op = op_vhcurveto;
+        break;
+      case 31:
+        op = op_hvcurveto;
+        break;
+
+      case 12:
+        if ( ip > limit )
+        {
+          FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+EOF)\n" ));
+          goto Syntax_Error;
+        }
+
+        switch ( *ip++ )
+        {
+        case 0:
+          op = op_dotsection;
+          break;
+        case 1:
+          op = op_vstem3;
+          break;
+        case 2:
+          op = op_hstem3;
+          break;
+        case 6:
+          op = op_seac;
+          break;
+        case 7:
+          op = op_sbw;
+          break;
+        case 12:
+          op = op_div;
+          break;
+        case 16:
+          op = op_callothersubr;
+          break;
+        case 17:
+          op = op_pop;
+          break;
+        case 33:
+          op = op_setcurrentpoint;
+          break;
+
+        default:
+          FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+        break;
+
+      case 255:    /* four bytes integer */
+        if ( ip + 4 > limit )
+        {
+          FT_ERROR(( "CID_Parse_CharStrings: unexpected EOF in integer\n" ));
+          goto Syntax_Error;
+        }
+
+        value = ( (long)ip[0] << 24 ) |
+                ( (long)ip[1] << 16 ) |
+                ( (long)ip[2] << 8  ) |
+                        ip[3];
+        ip += 4;
+        break;
+
+      default:
+        if ( ip[-1] >= 32 )
+        {
+          if ( ip[-1] < 247 )
+            value = (long)ip[-1] - 139;
+          else
+          {
+            if ( ++ip > limit )
+            {
+              FT_ERROR(( "CID_Parse_CharStrings:" ));
+              FT_ERROR(( " unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( ip[-2] < 251 )
+              value =  ( (long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+            else
+              value = -( ( ( (long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+          }
+        }
+        else
+        {
+          FT_ERROR(( "CID_Parse_CharStrings: invalid byte (%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+      }
+
+      /********************************************************************/
+      /*                                                                  */
+      /*  Push value on stack, or process operator                        */
+      /*                                                                  */
+      if ( op == op_none )
+      {
+        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+        {
+          FT_ERROR(( "CID_Parse_CharStrings: Stack overflow!\n" ));
+          goto Syntax_Error;
+        }
+
+        FT_TRACE4(( " %ld", value ));
+        *top++       = value;
+        decoder->top = top;
+      }
+      else if ( op == op_callothersubr )  /* callothersubr */
+      {
+        FT_TRACE4(( " callothersubr" ));
+
+        if ( top - decoder->stack < 2 )
+          goto Stack_Underflow;
+
+        top -= 2;
+        switch ( top[1] )
+        {
+        case 1: /* start flex feature ---------------------- */
+          if ( top[0] != 0 )
+            goto Unexpected_OtherSubr;
+
+          decoder->flex_state       = 1;
+          decoder->num_flex_vectors = 0;
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 6 )   )
+            goto Memory_Error;
+          break;
+
+        case 2: /* add flex vectors ------------------------ */
+          {
+            FT_Int  index;
+
+
+            if ( top[0] != 0 )
+              goto Unexpected_OtherSubr;
+
+            /* note that we should not add a point for index 0. */
+            /* this will move our current position to the flex  */
+            /* point without adding any point to the outline    */
+            index = decoder->num_flex_vectors++;
+            if ( index > 0 && index < 7 )
+              add_point( builder,
+                         x,
+                         y,
+                         (FT_Byte)( index==3 || index==6 ) );
+          }
+          break;
+
+        case 0: /* end flex feature ------------------------- */
+          if ( top[0] != 3 )
+            goto Unexpected_OtherSubr;
+
+          if ( decoder->flex_state       == 0 ||
+               decoder->num_flex_vectors != 7 )
+          {
+            FT_ERROR(( "CID_Parse_CharStrings: unexpected flex end\n" ));
+            goto Syntax_Error;
+          }
+
+          /* now consume the remaining `pop pop setcurpoint' */
+          if ( ip + 6 > limit              ||
+               ip[0] != 12  || ip[1] != 17 || /* pop */
+               ip[2] != 12  || ip[3] != 17 || /* pop */
+               ip[4] != 12  || ip[5] != 33 )  /* setcurpoint */
+          {
+            FT_ERROR(( "CID_Parse_CharStrings: invalid flex charstring\n" ));
+            goto Syntax_Error;
+          }
+
+          ip += 6;
+          decoder->flex_state = 0;
+          break;
+
+        case 3:  /* change hints ---------------------------- */
+          if ( top[0] != 1 )
+            goto Unexpected_OtherSubr;
+
+          /* eat the following `pop' */
+          if ( ip + 2 > limit )
+          {
+            FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
+                       ip[-1] ));
+            goto Syntax_Error;
+          }
+
+          if ( ip[0] != 12 || ip[1] != 17 )
+          {
+            FT_ERROR(( "CID_Parse_CharStrings:" ));
+            FT_ERROR(( " `pop' expected, found (%d %d)\n",
+                       ip[0], ip[1] ));
+            goto Syntax_Error;
+          }
+          ip += 2;
+          break;
+
+        case 12:
+        case 13:
+          /* counter control hints, clear stack */
+          top = decoder->stack;
+          break;
+
+#if 0
+
+        case 14:
+        case 15:
+        case 16:
+        case 17:
+        case 18: /* multiple masters */
+          {
+            T1_Blend*  blend = decoder->blend;
+            FT_UInt    num_points, nn, mm;
+            FT_Int*    delta;
+            FT_Int*    values;
+
+
+            if ( !blend )
+            {
+              FT_ERROR(( "CID_Parse_CharStrings:" ));
+              FT_ERROR(( " unexpected multiple masters operator!\n" ));
+              goto Syntax_Error;
+            }
+
+            num_points = top[1] - 13 + ( top[1] == 18 );
+            if ( top[0] != num_points * blend->num_designs )
+            {
+              FT_ERROR(( "CID_Parse_CharStrings:" ));
+              FT_ERROR(( " incorrect number of mm arguments\n" ));
+              goto Syntax_Error;
+            }
+
+            top -= blend->num_designs * num_points;
+            if ( top < decoder->stack )
+              goto Stack_Underflow;
+
+            /* We want to compute:                                   */
+            /*                                                       */
+            /*  a0*w0 + a1*w1 + ... + ak*wk                          */
+            /*                                                       */
+            /* but we only have the a0, a1-a0, a2-a0, .. ak-a0.      */
+            /* However, given that w0 + w1 + ... + wk == 1, we can   */
+            /* rewrite it easily as:                                 */
+            /*                                                       */
+            /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
+            /*                                                       */
+            /* where k == num_designs-1                              */
+            /*                                                       */
+            /* I guess that's why it's written in this `compact'     */
+            /* form...                                               */
+            /*                                                       */
+            delta  = top + num_points;
+            values = top;
+            for ( nn = 0; nn < num_points; nn++ )
+            {
+              FT_Int  x = values[0];
+
+
+              for ( mm = 1; mm < blend->num_designs; mm++ )
+                x += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+              *values++ = x;
+            }
+            /* note that `top' will be incremented later by calls to `pop' */
+          }
+          break;
+
+#endif
+
+        default:
+        Unexpected_OtherSubr:
+          FT_ERROR(( "CID_Parse_CharStrings: invalid othersubr [%d %d]!\n",
+                     top[0], top[1] ));
+          goto Syntax_Error;
+        }
+        decoder->top = top;
+      }
+      else  /* general operator */
+      {
+        FT_Int  num_args = t1_args_count[op];
+
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch ( op )
+        {
+        case op_endchar:
+          FT_TRACE4(( " endchar" ));
+
+          close_contour( builder );
+
+          /* add current outline to the glyph slot */
+          FT_GlyphLoader_Add( builder->loader );
+
+          /* return now! */
+          FT_TRACE4(( "\n\n" ));
+          return T1_Err_Ok;
+
+        case op_hsbw:
+          FT_TRACE4(( " hsbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->advance.x       = top[1];
+          builder->advance.y       = 0;
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = 0;
+
+          /* The `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it.  So exit immediately.                         */
+          if ( builder->metrics_only )
+            return T1_Err_Ok;
+
+          break;
+
+        case op_seac:
+          /* return immediately after processing */
+          return t1operator_seac( decoder, top[0], top[1],
+                                           top[2], top[3], top[4] );
+
+        case op_sbw:
+          FT_TRACE4(( " sbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->left_bearing.y += top[1];
+          builder->advance.x       = top[2];
+          builder->advance.y       = top[3];
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = top[1];
+
+          /* The `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it.  So exit immediately.                         */
+          if ( builder->metrics_only )
+            return T1_Err_Ok;
+
+          break;
+
+        case op_closepath:
+          FT_TRACE4(( " closepath" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          break;
+
+        case op_hlineto:
+          FT_TRACE4(( " hlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          goto Add_Line;
+
+        case op_hmoveto:
+          FT_TRACE4(( " hmoveto" ));
+
+          x += top[0];
+          break;
+
+        case op_hvcurveto:
+          FT_TRACE4(( " hvcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          add_point( builder, x, y, 0 );
+
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+
+          y += top[3];
+          add_point( builder, x, y, 1 );
+
+          break;
+
+        case op_rlineto:
+          FT_TRACE4(( " rlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+
+        Add_Line:
+          if ( add_point1( builder, x, y ) )
+            goto Memory_Error;
+          break;
+
+        case op_rmoveto:
+          FT_TRACE4(( " rmoveto" ));
+
+          x += top[0];
+          y += top[1];
+          break;
+
+        case op_rrcurveto:
+          FT_TRACE4(( " rcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+          add_point( builder, x, y, 0 );
+
+          x += top[2];
+          y += top[3];
+          add_point( builder, x, y, 0 );
+
+          x += top[4];
+          y += top[5];
+          add_point( builder, x, y, 1 );
+
+          break;
+
+        case op_vhcurveto:
+          FT_TRACE4(( " vhcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          y += top[0];
+          add_point( builder, x, y, 0 );
+
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+
+          x += top[3];
+          add_point( builder, x, y, 1 );
+
+          break;
+
+        case op_vlineto:
+          FT_TRACE4(( " vlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          y += top[0];
+          goto Add_Line;
+
+        case op_vmoveto:
+          FT_TRACE4(( " vmoveto" ));
+
+          y += top[0];
+          break;
+
+        case op_div:
+          FT_TRACE4(( " div" ));
+
+          if ( top[1] )
+          {
+            *top = top[0] / top[1];
+            top++;
+          }
+          else
+          {
+            FT_ERROR(( "CID_Parse_CharStrings: division by 0\n" ));
+            goto Syntax_Error;
+          }
+          break;
+
+        case op_callsubr:
+          {
+            FT_Int  index;
+
+
+            FT_TRACE4(( " callsubr" ));
+
+            index = top[0];
+            if ( index < 0 || index >= (FT_Int)decoder->subrs->num_subrs )
+            {
+              FT_ERROR(( "CID_Parse_CharStrings: invalid subrs index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "CID_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = decoder->subrs->code[index] + decoder->lenIV;
+            zone->limit  = decoder->subrs->code[index + 1];
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "CID_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+          }
+          break;
+
+        case op_pop:
+          FT_TRACE4(( " pop" ));
+
+          /* theoretically, the arguments are already on the stack */
+          top++;
+          break;
+
+        case op_return:
+          FT_TRACE4(( " return" ));
+
+          if ( zone <= decoder->zones )
+          {
+            FT_ERROR(( "CID_Parse_CharStrings: unexpected return\n" ));
+            goto Syntax_Error;
+          }
+
+          zone--;
+          ip            = zone->cursor;
+          limit         = zone->limit;
+          decoder->zone = zone;
+
+          break;
+
+        case op_dotsection:
+          FT_TRACE4(( " dotsection" ));
+
+          break;
+
+        case op_hstem:
+          FT_TRACE4(( " hstem" ));
+
+          break;
+
+        case op_hstem3:
+          FT_TRACE4(( " hstem3" ));
+
+          break;
+
+        case op_vstem:
+          FT_TRACE4(( " vstem" ));
+
+          break;
+
+        case op_vstem3:
+          FT_TRACE4(( " vstem3" ));
+
+          break;
+
+        case op_setcurrentpoint:
+          FT_TRACE4(( " setcurrentpoint" ));
+
+          FT_ERROR(( "CID_Parse_CharStrings:" ));
+          FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
+          goto Syntax_Error;
+
+        default:
+          FT_ERROR(( "CID_Parse_CharStrings: unhandled opcode %d\n", op ));
+          goto Syntax_Error;
+        }
+
+        decoder->top = top;
+
+      } /* general operator processing */
+
+    } /* while ip < limit */
+
+    FT_TRACE4(( "..end..\n\n" ));
+
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return T1_Err_Stack_Underflow;
+
+  Memory_Error:
+    return builder->error;
+  }
+
+
+#if 0
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC
+  FT_Error  CID_Compute_Max_Advance( CID_Face  face,
+                                     FT_Int*   max_advance )
+  {
+    FT_Error     error;
+    CID_Decoder  decoder;
+    FT_Int       glyph_index;
+
+
+    *max_advance = 0;
+
+    /* Initialize load decoder */
+    CID_Init_Decoder( &decoder );
+    CID_Init_Builder( &decoder.builder, face, 0, 0 );
+
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    /* for each glyph, parse the glyph charstring and extract */
+    /* the advance width                                      */
+    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+          glyph_index++ )
+    {
+      /* now get load the unscaled outline */
+      error = cid_load_glyph( &decoder, glyph_index );
+      /* ignore the error if one occurred - skip to next glyph */
+    }
+
+    *max_advance = decoder.builder.advance.x;
+
+    return T1_Err_Ok;
+  }
+
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********               UNHINTED GLYPH LOADER                  *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of loading a      *********/
+  /**********    single outline.  It completely ignores hinting    *********/
+  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  cid_load_glyph( CID_Decoder*  decoder,
+                            FT_UInt       glyph_index )
+  {
+    CID_Face   face = decoder->builder.face;
+    CID_Info*  cid  = &face->cid;
+    FT_Byte*   p;
+    FT_UInt    entry_len = cid->fd_bytes + cid->gd_bytes;
+    FT_UInt    fd_select;
+    FT_ULong   off1, glyph_len;
+    FT_Stream  stream = face->root.stream;
+    FT_Error   error  = 0;
+
+
+    /* read the CID font dict index and charstring offset from the CIDMap */
+    if ( FILE_Seek( cid->data_offset + cid->cidmap_offset +
+                    glyph_index * entry_len) ||
+         ACCESS_Frame( 2 * entry_len )       )
+      goto Exit;
+
+    p = (FT_Byte*)stream->cursor;
+    fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
+    off1      = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
+    p        += cid->fd_bytes;
+    glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;
+
+    FORGET_Frame();
+
+    /* now, if the glyph is not empty, set up the subrs array, and parse */
+    /* the charstrings                                                   */
+    if ( glyph_len > 0 )
+    {
+      CID_FontDict*  dict;
+      FT_Byte*       charstring;
+      FT_UInt        lenIV;
+      FT_Memory      memory = face->root.memory;
+
+
+      /* setup subrs */
+      decoder->subrs = face->subrs + fd_select;
+
+      /* setup font matrix */
+      dict                 = cid->font_dicts + fd_select;
+      decoder->font_matrix = dict->font_matrix;
+      lenIV                = dict->private_dict.lenIV;
+      decoder->lenIV       = lenIV;
+
+      /* the charstrings are encoded (stupid!)  */
+      /* load the charstrings, then execute it  */
+
+      if ( ALLOC( charstring, glyph_len ) )
+        goto Exit;
+
+      if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) )
+      {
+        cid_decrypt( charstring, glyph_len, 4330 );
+        error = CID_Parse_CharStrings( decoder,
+                                       charstring + lenIV,
+                                       glyph_len  - lenIV );
+      }
+
+      FREE( charstring );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  CID_Load_Glyph( CID_GlyphSlot  glyph,
+                            CID_Size       size,
+                            FT_Int         glyph_index,
+                            FT_Int         load_flags )
+  {
+    FT_Error     error;
+    CID_Decoder  decoder;
+    CID_Face     face = (CID_Face)glyph->root.face;
+    FT_Bool      hinting;
+
+
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = size->root.metrics.x_scale;
+    glyph->y_scale = size->root.metrics.y_scale;
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+              ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+    glyph->root.format = ft_glyph_format_outline;
+
+    {
+      CID_Init_Decoder( &decoder );
+      CID_Init_Builder( &decoder.builder, face, size, glyph );
+
+      /* set up the decoder */
+      decoder.builder.no_recurse =
+        (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
+
+      error = cid_load_glyph( &decoder, glyph_index );
+
+      /* save new glyph tables */
+      CID_Done_Builder( &decoder.builder );
+    }
+
+    /* Now, set the metrics - this is rather simple, as    */
+    /* the left side bearing is the xMin, and the top side */
+    /* bearing the yMax.                                   */
+    if ( !error )
+    {
+      /* for composite glyphs, return only the left side bearing and the */
+      /* advance width                                                   */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
+      {
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
+      }
+      else
+      {
+        FT_BBox            cbox;
+        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
+
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance = decoder.builder.advance.x;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        glyph->root.outline.flags &= ft_outline_owner;
+        if ( size && size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+#if 0
+        glyph->root.outline.second_pass    = TRUE;
+        glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+        glyph->root.outline.dropout_mode   = 2;
+#endif
+
+        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur     = &glyph->root.outline;
+          FT_Vector*   vec     = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_Fixed     y_scale = glyph->y_scale;
+
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+          /* Then scale the metrics */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        }
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline, &decoder.font_matrix );
+
+        /* compute the other metrics */
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if ( hinting )
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+      }
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/cid/cidgload.h b/src/freetype/cid/cidgload.h
new file mode 100644 (file)
index 0000000..5f3913d
--- /dev/null
@@ -0,0 +1,198 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidgload.h                                                             */
+/*                                                                         */
+/*    OpenType Glyph Loader (specification).                               */
+/*                                                                         */
+/*  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 CIDGLOAD_H
+#define CIDGLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidobjs.h"
+
+#else
+
+#include <cid/cidobjs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    CID_Builder                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*     A structure used during glyph loading to store its outline.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory       :: The current memory object.                         */
+  /*                                                                       */
+  /*    face         :: The current face object.                           */
+  /*                                                                       */
+  /*    glyph        :: The current glyph slot.                            */
+  /*                                                                       */
+  /*    current      :: The current glyph outline.                         */
+  /*                                                                       */
+  /*    base         :: The base glyph outline.                            */
+  /*                                                                       */
+  /*    max_points   :: maximum points in builder outline                  */
+  /*                                                                       */
+  /*    max_contours :: Maximal number of contours in builder outline.     */
+  /*                                                                       */
+  /*    last         :: The last point position.                           */
+  /*                                                                       */
+  /*    scale_x      :: The horizontal scale (FUnits to sub-pixels).       */
+  /*                                                                       */
+  /*    scale_y      :: The vertical scale (FUnits to sub-pixels).         */
+  /*                                                                       */
+  /*    pos_x        :: The horizontal translation (if composite glyph).   */
+  /*                                                                       */
+  /*    pos_y        :: The vertical translation (if composite glyph).     */
+  /*                                                                       */
+  /*    left_bearing :: The left side bearing point.                       */
+  /*                                                                       */
+  /*    advance      :: The horizontal advance vector.                     */
+  /*                                                                       */
+  /*    bbox         :: Unused.                                            */
+  /*                                                                       */
+  /*    path_begun   :: A flag which indicates that a new path has begun.  */
+  /*                                                                       */
+  /*    load_points  :: If this flag is not set, no points are loaded.     */
+  /*                                                                       */
+  /*    no_recurse   :: Set but not used.                                  */
+  /*                                                                       */
+  /*    error        :: An error code that is only used to report memory   */
+  /*                    allocation problems.                               */
+  /*                                                                       */
+  /*    metrics_only :: A boolean indicating that we only want to compute  */
+  /*                    the metrics of a given glyph, not load all of its  */
+  /*                    points.                                            */
+  /*                                                                       */
+  typedef struct  CID_Builder_
+  {
+    FT_Memory        memory;
+    CID_Face         face;
+    CID_GlyphSlot    glyph;
+    FT_GlyphLoader*  loader;
+    FT_Outline*      base;
+    FT_Outline*      current;
+
+    FT_Vector        last;
+
+    FT_Fixed         scale_x;
+    FT_Fixed         scale_y;
+
+    FT_Pos           pos_x;
+    FT_Pos           pos_y;
+
+    FT_Vector        left_bearing;
+    FT_Vector        advance;
+
+    FT_BBox          bbox;          /* bounding box */
+    FT_Bool          path_begun;
+    FT_Bool          load_points;
+    FT_Bool          no_recurse;
+
+    FT_Error         error;         /* only used for memory errors */
+    FT_Bool          metrics_only;
+
+  } CID_Builder;
+
+
+  /* execution context charstring zone */
+
+  typedef struct  CID_Decoder_Zone_
+  {
+    FT_Byte*  base;
+    FT_Byte*  limit;
+    FT_Byte*  cursor;
+
+  } CID_Decoder_Zone;
+
+
+  typedef struct  CID_Decoder_
+  {
+    CID_Builder        builder;
+
+    FT_Int             stack[T1_MAX_CHARSTRINGS_OPERANDS];
+    FT_Int*            top;
+
+    CID_Decoder_Zone   zones[T1_MAX_SUBRS_CALLS + 1];
+    CID_Decoder_Zone*  zone;
+
+    FT_Matrix          font_matrix;
+    CID_Subrs*         subrs;
+    FT_UInt            lenIV;
+
+    FT_Int             flex_state;
+    FT_Int             num_flex_vectors;
+    FT_Vector          flex_vectors[7];
+
+  } CID_Decoder;
+
+
+  LOCAL_DEF
+  void  CID_Init_Builder( CID_Builder*   builder,
+                          CID_Face       face,
+                          CID_Size       size,
+                          CID_GlyphSlot  glyph );
+
+  LOCAL_DEF
+  void CID_Done_Builder( CID_Builder*  builder );
+
+
+  LOCAL_DEF
+  void CID_Init_Decoder( CID_Decoder*  decoder );
+
+
+#if 0
+
+  /* Compute the maximum advance width of a font through quick parsing */
+  LOCAL_DEF
+  FT_Error  CID_Compute_Max_Advance( CID_Face  face,
+                                     FT_Int*   max_advance );
+
+#endif
+
+  /* This function is exported, because it is used by the T1Dump utility */
+  LOCAL_DEF
+  FT_Error  CID_Parse_CharStrings( CID_Decoder*  decoder,
+                                   FT_Byte*      charstring_base,
+                                   FT_Int        charstring_len );
+
+  LOCAL_DEF
+  FT_Error  CID_Load_Glyph( CID_GlyphSlot  glyph,
+                            CID_Size       size,
+                            FT_Int         glyph_index,
+                            FT_Int         load_flags );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* CIDGLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/cid/cidload.c b/src/freetype/cid/cidload.c
new file mode 100644 (file)
index 0000000..1f7c7ae
--- /dev/null
@@ -0,0 +1,537 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidload.c                                                              */
+/*                                                                         */
+/*    CID-keyed Type1 font loader (body).                                  */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/ftmm.h>
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidload.h"
+
+#else
+
+#include <cid/cidload.h>
+
+#endif
+
+
+#include <stdio.h>
+#include <ctype.h>  /* for isspace(), isalnum() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cidload
+
+
+  /* read a single offset */
+  LOCAL_FUNC
+  FT_Long  cid_get_offset( FT_Byte**  start,
+                           FT_Byte    offsize )
+  {
+    FT_Long   result;
+    FT_Byte*  p = *start;
+
+
+    for ( result = 0; offsize > 0; offsize-- )
+    {
+      result <<= 8;
+      result  |= *p++;
+    }
+
+    *start = p;
+    return result;
+  }
+
+
+  LOCAL_FUNC
+  void  cid_decrypt( FT_Byte*   buffer,
+                     FT_Int     length,
+                     FT_UShort  seed )
+  {
+    while ( length > 0 )
+    {
+      FT_Byte  plain;
+
+
+      plain     = ( *buffer ^ ( seed >> 8 ) );
+      seed      = ( *buffer + seed ) * 52845 + 22719;
+      *buffer++ = plain;
+      length--;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    TYPE 1 SYMBOL PARSING                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  cid_load_keyword( CID_Face              face,
+                              CID_Loader*           loader,
+                              const CID_Field_Rec*  keyword )
+  {
+    FT_Error     error;
+    CID_Parser*  parser = &loader->parser;
+    FT_Byte*     object;
+    CID_Info*    cid = &face->cid;
+
+
+    /* if the keyword has a dedicated callback, call it */
+    if ( keyword->type == t1_field_callback )
+    {
+      error = keyword->reader( face, parser );
+      goto Exit;
+    }
+
+    /* we must now compute the address of our target object */
+    switch ( keyword->location )
+    {
+    case t1_field_cid_info:
+      object = (FT_Byte*)cid;
+      break;
+
+    case t1_field_font_info:
+      object = (FT_Byte*)&cid->font_info;
+      break;
+
+    default:
+      {
+        CID_FontDict*  dict;
+
+
+        if ( parser->num_dict < 0 )
+        {
+          FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
+                     keyword->ident ));
+          error = T1_Err_Syntax_Error;
+          goto Exit;
+        }
+
+        dict = cid->font_dicts + parser->num_dict;
+        switch ( keyword->location )
+        {
+        case t1_field_private:
+          object = (FT_Byte*)&dict->private_dict;
+          break;
+
+        default:
+          object = (FT_Byte*)dict;
+        }
+      }
+    }
+
+    /* now, load the keyword data in the object's field(s) */
+    if ( keyword->type == t1_field_integer_array ||
+         keyword->type == t1_field_fixed_array   )
+      error = CID_Load_Field_Table( parser, keyword, object );
+    else
+      error = CID_Load_Field( parser, keyword, object );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error  parse_font_bbox( CID_Face     face,
+                             CID_Parser*  parser )
+  {
+    FT_Short  temp[4];
+    FT_BBox*  bbox = &face->cid.font_bbox;
+
+
+    (void)CID_ToCoordArray( parser, 4, temp );
+    bbox->xMin = temp[0];
+    bbox->yMin = temp[1];
+    bbox->xMax = temp[2];
+    bbox->yMax = temp[3];
+
+    return T1_Err_Ok;       /* this is a callback function; */
+                            /* we must return an error code */
+  }
+
+
+  static
+  FT_Error  parse_font_matrix( CID_Face     face,
+                               CID_Parser*  parser )
+  {
+    FT_Matrix*     matrix;
+    CID_FontDict*  dict;
+    FT_Fixed       temp[4];
+
+
+    if ( parser->num_dict >= 0 )
+    {
+      dict   = face->cid.font_dicts + parser->num_dict;
+      matrix = &dict->font_matrix;
+
+      (void)CID_ToFixedArray( parser, 4, temp, 3 );
+      matrix->xx = temp[0];
+      matrix->yx = temp[1];
+      matrix->xy = temp[2];
+      matrix->yy = temp[3];
+    }
+
+    return T1_Err_Ok;       /* this is a callback function; */
+                            /* we must return an error code */
+  }
+
+
+  static
+  FT_Error  parse_fd_array( CID_Face     face,
+                            CID_Parser*  parser )
+  {
+    CID_Info*  cid    = &face->cid;
+    FT_Memory  memory = face->root.memory;
+    FT_Error   error  = T1_Err_Ok;
+    FT_Long    num_dicts;
+
+
+    num_dicts = CID_ToInt( parser );
+
+    if ( !cid->font_dicts )
+    {
+      FT_Int  n;
+
+
+      if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) )
+        goto Exit;
+
+      cid->num_dicts = (FT_UInt)num_dicts;
+
+      /* don't forget to set a few defaults */
+      for ( n = 0; n < cid->num_dicts; n++ )
+      {
+        CID_FontDict*  dict = cid->font_dicts + n;
+
+
+        /* default value for lenIV */
+        dict->private_dict.lenIV = 4;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  const CID_Field_Rec  t1_field_records[] =
+  {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidtokens.h"
+
+#else
+
+#include <cid/cidtokens.h>
+
+#endif
+
+    { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
+  };
+
+
+  static
+  int  is_alpha( char  c )
+  {
+    return ( isalnum( c ) ||
+             c == '.'     ||
+             c == '_'     );
+  }
+
+
+  static
+  void  skip_whitespace( CID_Parser*  parser )
+  {
+    FT_Byte*  cur = parser->cursor;
+
+
+    while ( cur < parser->limit && isspace( *cur ) )
+      cur++;
+
+    parser->cursor = cur;
+  }
+
+
+  static
+  FT_Error  parse_dict( CID_Face     face,
+                        CID_Loader*  loader,
+                        FT_Byte*     base,
+                        FT_Long      size )
+  {
+    CID_Parser*  parser = &loader->parser;
+
+
+    parser->cursor = base;
+    parser->limit  = base + size;
+    parser->error  = 0;
+
+    {
+      FT_Byte*  cur   = base;
+      FT_Byte*  limit = cur + size;
+
+
+      for ( ;cur < limit; cur++ )
+      {
+        /* look for `%ADOBeginFontDict' */
+        if ( *cur == '%' && cur + 20 < limit &&
+             strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+        {
+          cur += 17;
+
+          /* if /FDArray was found, then cid->num_dicts is > 0, and */
+          /* we can start increasing parser->num_dict               */
+          if ( face->cid.num_dicts > 0 )
+            parser->num_dict++;
+        }
+        /* look for immediates */
+        else if ( *cur == '/' && cur + 2 < limit )
+        {
+          FT_Byte*  cur2;
+          FT_Int    len;
+
+
+          cur++;
+
+          cur2 = cur;
+          while ( cur2 < limit && is_alpha( *cur2 ) )
+            cur2++;
+
+          len = cur2 - cur;
+          if ( len > 0 && len < 22 )
+          {
+            /* now compare the immediate name to the keyword table */
+            const CID_Field_Rec*  keyword = t1_field_records;
+
+
+            for (;;)
+            {
+              FT_Byte*  name;
+
+
+              name = (FT_Byte*)keyword->ident;
+              if ( !name )
+                break;
+
+              if ( cur[0] == name[0]                          &&
+                   len == (FT_Int)strlen( (const char*)name ) )
+              {
+                FT_Int  n;
+
+
+                for ( n = 1; n < len; n++ )
+                  if ( cur[n] != name[n] )
+                    break;
+
+                if ( n >= len )
+                {
+                  /* we found it - run the parsing callback */
+                  parser->cursor = cur2;
+                  skip_whitespace( parser );
+                  parser->error = cid_load_keyword( face, loader, keyword );
+                  if ( parser->error )
+                    return parser->error;
+
+                  cur = parser->cursor;
+                  break;
+                }
+              }
+              keyword++;
+            }
+          }
+        }
+      }
+    }
+    return parser->error;
+  }
+
+
+  /* read the subrmap and the subrs of each font dict */
+  static
+  FT_Error  cid_read_subrs( CID_Face  face )
+  {
+    CID_Info*   cid    = &face->cid;
+    FT_Memory   memory = face->root.memory;
+    FT_Stream   stream = face->root.stream;
+    FT_Error    error;
+    FT_Int      n;
+    CID_Subrs*  subr;
+    FT_UInt     max_offsets = 0;
+    FT_ULong*   offsets = 0;
+
+
+    if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) )
+      goto Exit;
+
+    subr = face->subrs;
+    for ( n = 0; n < cid->num_dicts; n++, subr++ )
+    {
+      CID_FontDict*  dict = cid->font_dicts + n;
+      FT_UInt        count, num_subrs = dict->num_subrs;
+      FT_ULong       data_len;
+      FT_Byte*       p;
+
+
+      /* reallocate offsets array if needed */
+      if ( num_subrs + 1 > max_offsets )
+      {
+        FT_UInt  new_max = ( num_subrs + 1 + 3 ) & -4;
+
+
+        if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) )
+          goto Fail;
+
+        max_offsets = new_max;
+      }
+
+      /* read the subrmap's offsets */
+      if ( FILE_Seek( cid->data_offset + dict->subrmap_offset ) ||
+           ACCESS_Frame( ( num_subrs + 1 ) * dict->sd_bytes )   )
+        goto Fail;
+
+      p = (FT_Byte*)stream->cursor;
+      for ( count = 0; count <= num_subrs; count++ )
+        offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
+
+      FORGET_Frame();
+
+      /* now, compute the size of subrs charstrings, */
+      /* allocate, and read them                     */
+      data_len = offsets[num_subrs] - offsets[0];
+
+      if ( ALLOC_ARRAY( subr->code, num_subrs + 1, FT_Byte* ) ||
+           ALLOC( subr->code[0], data_len )                   )
+        goto Fail;
+
+      if ( FILE_Seek( cid->data_offset + offsets[0] ) ||
+           FILE_Read( subr->code[0], data_len )  )
+        goto Exit;
+
+      /* set up pointers */
+      for ( count = 1; count <= num_subrs; count++ )
+      {
+        FT_UInt  len;
+
+
+        len               = offsets[count] - offsets[count - 1];
+        subr->code[count] = subr->code[count - 1] + len;
+      }
+
+      /* decrypt subroutines */
+      for ( count = 0; count < num_subrs; count++ )
+      {
+        FT_UInt  len;
+
+
+        len = offsets[count + 1] - offsets[count];
+        cid_decrypt( subr->code[count], len, 4330 );
+      }
+
+      subr->num_subrs = num_subrs;
+    }
+
+  Exit:
+    FREE( offsets );
+    return error;
+
+  Fail:
+    if ( face->subrs )
+    {
+      for ( n = 0; n < cid->num_dicts; n++ )
+      {
+        if ( face->subrs[n].code )
+          FREE( face->subrs[n].code[0] );
+
+        FREE( face->subrs[n].code );
+      }
+      FREE( face->subrs );
+    }
+    goto Exit;
+  }
+
+
+  static
+  void t1_init_loader( CID_Loader*  loader,
+                       CID_Face     face )
+  {
+    FT_UNUSED( face );
+
+    MEM_Set( loader, 0, sizeof ( *loader ) );
+  }
+
+
+  static
+  void t1_done_loader( CID_Loader*  loader )
+  {
+    CID_Parser*  parser = &loader->parser;
+
+
+    /* finalize parser */
+    CID_Done_Parser( parser );
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  CID_Open_Face( CID_Face  face )
+  {
+    CID_Loader  loader;
+    CID_Parser* parser;
+    FT_Error   error;
+
+
+    t1_init_loader( &loader, face );
+
+    parser = &loader.parser;
+    error = CID_New_Parser( parser, face->root.stream, face->root.memory );
+    if ( error )
+      goto Exit;
+
+    error = parse_dict( face, &loader,
+                        parser->postscript,
+                        parser->postscript_len );
+    if ( error )
+      goto Exit;
+
+    face->cid.data_offset = loader.parser.data_offset;
+    error = cid_read_subrs( face );
+
+  Exit:
+    t1_done_loader( &loader );
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/cid/cidload.h b/src/freetype/cid/cidload.h
new file mode 100644 (file)
index 0000000..7495da0
--- /dev/null
@@ -0,0 +1,70 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidload.h                                                              */
+/*                                                                         */
+/*    CID-keyed Type1 font loader (specification).                         */
+/*                                                                         */
+/*  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 CIDLOAD_H
+#define CIDLOAD_H
+
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidparse.h"
+
+#else
+
+#include <cid/cidparse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  typedef struct  CID_Loader_
+  {
+    CID_Parser  parser;          /* parser used to read the stream */
+    FT_Int      num_chars;       /* number of characters in encoding */
+
+  } CID_Loader;
+
+
+  LOCAL_DEF
+  FT_Long  cid_get_offset( FT_Byte**  start,
+                           FT_Byte    offsize );
+
+  LOCAL_DEF
+  void  cid_decrypt( FT_Byte*   buffer,
+                     FT_Int     length,
+                     FT_UShort  seed );
+
+  LOCAL_DEF
+  FT_Error  CID_Open_Face( CID_Face  face );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* CIDLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/cid/cidobjs.c b/src/freetype/cid/cidobjs.c
new file mode 100644 (file)
index 0000000..a75567b
--- /dev/null
@@ -0,0 +1,380 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidobjs.c                                                              */
+/*                                                                         */
+/*    CID objects manager (body).                                          */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidgload.h"
+#include "cidload.h"
+
+#else
+
+#include <cid/cidgload.h>
+#include <cid/cidload.h>
+
+#endif
+
+
+#include <freetype/internal/psnames.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef   FT_COMPONENT
+#define  FT_COMPONENT  trace_cidobjs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           FACE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Done_Face                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given face object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A pointer to the face object to destroy.                   */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  CID_Done_Face( CID_Face  face )
+  {
+    FT_Memory  memory;
+
+
+    if ( face )
+    {
+      CID_Info*     cid  = &face->cid;
+      T1_FontInfo*  info = &cid->font_info;
+
+
+      memory = face->root.memory;
+
+      /* release FontInfo strings */
+      FREE( info->version );
+      FREE( info->notice );
+      FREE( info->full_name );
+      FREE( info->family_name );
+      FREE( info->weight );
+
+      /* release font dictionaries */
+      FREE( cid->font_dicts );
+      cid->num_dicts = 0;
+
+      /* release other strings */
+      FREE( cid->cid_font_name );
+      FREE( cid->registry );
+      FREE( cid->ordering );
+
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Init_Face                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given CID face object.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The source font stream.                              */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The newly built face object.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  CID_Init_Face( FT_Stream      stream,
+                           CID_Face       face,
+                           FT_Int         face_index,
+                           FT_Int         num_params,
+                           FT_Parameter*  params )
+  {
+    FT_Error            error;
+    PSNames_Interface*  psnames;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+    FT_UNUSED( stream );
+
+
+    face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+    {
+      psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                  FT_FACE_LIBRARY( face ), "psnames" );
+
+      face->psnames = psnames;
+    }
+
+    /* open the tokenizer; this will also check the font format */
+    if ( FILE_Seek( 0 ) )
+      goto Exit;
+
+    error = CID_Open_Face( face );
+    if ( error )
+      goto Exit;
+
+    /* if we just wanted to check the format, leave successfully now */
+    if ( face_index < 0 )
+      goto Exit;
+
+    /* check the face index */
+    if ( face_index != 0 )
+    {
+      FT_ERROR(( "CID_Init_Face: invalid face index\n" ));
+      error = T1_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* Now, load the font program into the face object */
+    {
+      /* Init the face object fields */
+      /* Now set up root face fields */
+      {
+        FT_Face  root = (FT_Face)&face->root;
+
+
+        root->num_glyphs   = face->cid.cid_count;
+        root->num_charmaps = 0;
+
+        root->face_index = face_index;
+        root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+        root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+        if ( face->cid.font_info.is_fixed_pitch )
+          root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+        /* XXX: TODO: add kerning with .afm support */
+
+        /* get style name -- be careful, some broken fonts only */
+        /* have a /FontName dictionary entry!                   */
+        root->family_name = face->cid.font_info.family_name;
+        if ( root->family_name )
+        {
+          char*  full   = face->cid.font_info.full_name;
+          char*  family = root->family_name;
+
+          while ( *family && *full == *family )
+          {
+            family++;
+            full++;
+          }
+
+          root->style_name = ( *full == ' ' ) ? full + 1
+                                              : (char *)"Regular";
+        }
+        else
+        {
+          /* do we have a `/FontName'? */
+          if ( face->cid.cid_font_name )
+          {
+            root->family_name = face->cid.cid_font_name;
+            root->style_name  = "Regular";
+          }
+        }
+
+        /* no embedded bitmap support */
+        root->num_fixed_sizes = 0;
+        root->available_sizes = 0;
+
+        root->bbox         = face->cid.font_bbox;
+        root->units_per_EM = 1000;
+        root->ascender     =  (FT_Short)face->cid.font_bbox.yMax;
+        root->descender    = -(FT_Short)face->cid.font_bbox.yMin;
+        root->height       = ( ( root->ascender + root->descender ) * 12 )
+                             / 10;
+
+
+#if 0
+
+        /* now compute the maximum advance width */
+
+        root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+        /* compute max advance width for proportional fonts */
+        if ( !face->type1.font_info.is_fixed_pitch )
+        {
+          FT_Int  max_advance;
+
+
+          error = CID_Compute_Max_Advance( face, &max_advance );
+
+          /* in case of error, keep the standard width */
+          if ( !error )
+            root->max_advance_width = max_advance;
+          else
+            error = 0;   /* clear error */
+        }
+
+        root->max_advance_height = root->height;
+
+#endif /* 0 */
+
+        root->underline_position  = face->cid.font_info.underline_position;
+        root->underline_thickness = face->cid.font_info.underline_thickness;
+
+        root->max_points   = 0;
+        root->max_contours = 0;
+      }
+    }
+
+#if 0
+
+    /* charmap support - synthetize unicode charmap when possible */
+    {
+      FT_Face      root    = &face->root;
+      FT_CharMap   charmap = face->charmaprecs;
+
+
+      /* synthesize a Unicode charmap if there is support in the `psnames' */
+      /* module                                                            */
+      if ( face->psnames )
+      {
+        PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+
+        if ( psnames->unicode_value )
+        {
+          error = psnames->build_unicodes(
+                             root->memory,
+                             face->type1.num_glyphs,
+                             (const char**)face->type1.glyph_names,
+                             &face->unicode_map );
+          if ( !error )
+          {
+            root->charmap        = charmap;
+            charmap->face        = (FT_Face)face;
+            charmap->encoding    = ft_encoding_unicode;
+            charmap->platform_id = 3;
+            charmap->encoding_id = 1;
+            charmap++;
+          }
+
+          /* simply clear the error in case of failure (which really */
+          /* means that out of memory or no unicode glyph names)     */
+          error = 0;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encodings */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
+
+      switch ( face->type1.encoding_type )
+      {
+      case t1_encoding_standard:
+        charmap->encoding    = ft_encoding_adobe_standard;
+        charmap->encoding_id = 0;
+        break;
+
+      case t1_encoding_expert:
+        charmap->encoding    = ft_encoding_adobe_expert;
+        charmap->encoding_id = 1;
+        break;
+
+      default:
+        charmap->encoding    = ft_encoding_adobe_custom;
+        charmap->encoding_id = 2;
+        break;
+      }
+
+      root->charmaps     = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0]  = &face->charmaprecs[0];
+      face->charmaps[1]  = &face->charmaprecs[1];
+    }
+
+#endif /* 0 */
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Init_Driver                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given CID driver object.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  CID_Init_Driver( CID_Driver  driver )
+  {
+    FT_UNUSED( driver );
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Done_Driver                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given CID driver.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target CID driver.                       */
+  /*                                                                       */
+  LOCAL_DEF
+  void  CID_Done_Driver( CID_Driver  driver )
+  {
+    FT_UNUSED( driver );
+  }
+
+
+/* END */
diff --git a/src/freetype/cid/cidobjs.h b/src/freetype/cid/cidobjs.h
new file mode 100644 (file)
index 0000000..c28c59b
--- /dev/null
@@ -0,0 +1,141 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidobjs.h                                                              */
+/*                                                                         */
+/*    CID objects manager (specification).                                 */
+/*                                                                         */
+/*  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 CIDOBJS_H
+#define CIDOBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/t1types.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* The following structures must be defined by the hinter */
+  typedef struct CID_Size_Hints_   CID_Size_Hints;
+  typedef struct CID_Glyph_Hints_  CID_Glyph_Hints;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_Driver                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 driver object.                                */
+  /*                                                                       */
+  typedef struct CID_DriverRec_*  CID_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_Size                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 size object.                                  */
+  /*                                                                       */
+  typedef struct CID_SizeRec_*  CID_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_GlyphSlot                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 glyph slot object.                            */
+  /*                                                                       */
+  typedef struct CID_GlyphSlotRec_*  CID_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_CharMap                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 character mapping object.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The Type 1 format doesn't use a charmap but an encoding table.     */
+  /*    The driver is responsible for making up charmap objects            */
+  /*    corresponding to these tables.                                     */
+  /*                                                                       */
+  typedef struct CID_CharMapRec_*  CID_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  typedef struct  CID_SizeRec_
+  {
+    FT_SizeRec  root;
+    FT_Bool     valid;
+
+  } CID_SizeRec;
+
+
+  typedef struct  CID_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+  } CID_GlyphSlotRec;
+
+
+  LOCAL_DEF
+  FT_Error  CID_Init_Face( FT_Stream      stream,
+                           CID_Face       face,
+                           FT_Int         face_index,
+                           FT_Int         num_params,
+                           FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  CID_Done_Face( CID_Face  face );
+
+
+  LOCAL_DEF
+  FT_Error  CID_Init_Driver( CID_Driver  driver );
+
+  LOCAL_DEF
+  void  CID_Done_Driver( CID_Driver  driver );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* CIDOBJS_H */
+
+
+/* END */
diff --git a/src/freetype/cid/cidparse.c b/src/freetype/cid/cidparse.c
new file mode 100644 (file)
index 0000000..33d3d8a
--- /dev/null
@@ -0,0 +1,1024 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidparse.c                                                             */
+/*                                                                         */
+/*    CID-keyed Type1 parser (body).                                       */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidparse.h"
+
+#else
+
+#include <cid/cidparse.h>
+
+#endif
+
+
+#include <string.h>     /* for strncmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef FT_COMPONENT
+#define FT_COMPONENT  trace_cidparse
+
+
+#if 0
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****           IMPLEMENTATION OF CID_TABLE OBJECT                  *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_New_Table                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a CID_Table.                                           */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The address of the target table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    count  :: The table size, i.e., the maximal number of elements.    */
+  /*                                                                       */
+  /*    memory :: The memory object to be used for all subsequent          */
+  /*              reallocations.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  CID_New_Table( CID_Table*  table,
+                           FT_Int      count,
+                           FT_Memory   memory )
+  {
+    FT_Error  error;
+
+
+    table->memory = memory;
+    if ( ALLOC_ARRAY( table->elements, count, FT_Byte*  ) ||
+         ALLOC_ARRAY( table->lengths, count, FT_Byte* )   )
+      goto Exit;
+
+    table->max_elems = count;
+    table->init      = 0xDEADBEEFL;
+    table->num_elems = 0;
+    table->block     = 0;
+    table->capacity  = 0;
+    table->cursor    = 0;
+
+  Exit:
+    if ( error )
+      FREE( table->elements );
+
+    return error;
+  }
+
+
+  static
+  void  shift_elements( CID_Table*  table,
+                        FT_Byte*    old_base )
+  {
+    FT_Long    delta  = table->block - old_base;
+    FT_Byte**  offset = table->elements;
+    FT_Byte**  limit  = offset + table->max_elems;
+
+
+    if ( delta )
+      for ( ; offset < limit; offset++ )
+      {
+        if ( offset[0] )
+          offset[0] += delta;
+      }
+  }
+
+
+  static
+  FT_Error  reallocate_t1_table( CID_Table*  table,
+                                 FT_Int      new_size )
+  {
+    FT_Memory  memory   = table->memory;
+    FT_Byte*   old_base = table->block;
+    FT_Error   error;
+
+
+    /* realloc the base block */
+    if ( REALLOC( table->block, table->capacity, new_size ) )
+      return error;
+
+    table->capacity = new_size;
+
+    /* shift all offsets when needed */
+    if ( old_base )
+      shift_elements( table, old_base );
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Add_Table                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds an object to a CID_Table, possibly growing its memory block.  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The target table.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    index  :: The index of the object in the table.                    */
+  /*                                                                       */
+  /*    object :: The address of the object to copy in the memory.         */
+  /*                                                                       */
+  /*    length :: The length in bytes of the source object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  An error is returned if    */
+  /*    reallocation fails.                                                */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  CID_Add_Table( CID_Table*  table,
+                           FT_Int      index,
+                           void*       object,
+                           FT_Int      length )
+  {
+    if ( index < 0 || index > table->max_elems )
+    {
+      FT_ERROR(( "CID_Add_Table: invalid index\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* grow the base block if needed */
+    if ( table->cursor + length > table->capacity )
+    {
+      FT_Error  error;
+      FT_Int    new_size = table->capacity;
+
+
+      while ( new_size < table->cursor + length )
+        new_size += 1024;
+
+      error = reallocate_t1_table( table, new_size );
+      if ( error )
+        return error;
+    }
+
+    /* add the object to the base block and adjust offset */
+    table->elements[index] = table->block + table->cursor;
+    table->lengths [index] = length;
+
+    MEM_Copy( table->block + table->cursor, object, length );
+
+    table->cursor += length;
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Done_Table                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a CID_Table (reallocate it to its current cursor).       */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table :: The target table.                                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT release the heap's memory block.  It is up  */
+  /*    to the caller to clean it, or reference it in its own structures.  */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  CID_Done_Table( CID_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+    FT_Error   error;
+    FT_Byte*   old_base;
+
+
+    /* should never fail, as rec.cursor <= rec.size */
+    old_base = table->block;
+    if ( !old_base )
+      return;
+
+    (void)REALLOC( table->block, table->capacity, table->cursor );
+    table->capacity = table->cursor;
+
+    if ( old_base != table->block )
+      shift_elements( table, old_base );
+  }
+
+
+  LOCAL_FUNC
+  void  CID_Release_Table( CID_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+
+
+    if ( table->init == 0xDEADBEEFL )
+    {
+      FREE( table->block );
+      FREE( table->elements );
+      FREE( table->lengths );
+      table->init = 0;
+    }
+  }
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    INPUT STREAM PARSER                        *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define IS_CID_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
+#define IS_CID_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
+
+#define IS_CID_SPACE( c )  ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) )
+
+
+  LOCAL_FUNC
+  void  CID_Skip_Spaces( CID_Parser*  parser )
+  {
+    FT_Byte* cur   = parser->cursor;
+    FT_Byte* limit = parser->limit;
+
+
+    while ( cur < limit )
+    {
+      FT_Byte  c = *cur;
+
+
+      if ( !IS_CID_SPACE( c ) )
+        break;
+      cur++;
+    }
+
+    parser->cursor = cur;
+  }
+
+
+  LOCAL_FUNC
+  void  CID_ToToken( CID_Parser*     parser,
+                     CID_Token_Rec*  token )
+  {
+    FT_Byte*  cur;
+    FT_Byte*  limit;
+    FT_Byte   starter, ender;
+    FT_Int    embed;
+
+
+    token->type  = t1_token_none;
+    token->start = 0;
+    token->limit = 0;
+
+    /* first of all, skip space */
+    CID_Skip_Spaces( parser );
+
+    cur   = parser->cursor;
+    limit = parser->limit;
+
+    if ( cur < limit )
+    {
+      switch ( *cur )
+      {
+        /************* check for strings ***********************/
+      case '(':
+        token->type = t1_token_string;
+        ender = ')';
+        goto Lookup_Ender;
+
+        /************* check for programs/array ****************/
+      case '{':
+        token->type = t1_token_array;
+        ender = '}';
+        goto Lookup_Ender;
+
+        /************* check for table/array ******************/
+      case '[':
+        token->type = t1_token_array;
+        ender = ']';
+
+      Lookup_Ender:
+        embed   = 1;
+        starter = *cur++;
+        token->start = cur;
+
+        while ( cur < limit )
+        {
+          if ( *cur == starter )
+            embed++;
+          else if ( *cur == ender )
+          {
+            embed--;
+            if ( embed <= 0 )
+            {
+              token->limit = cur++;
+              break;
+            }
+          }
+          cur++;
+        }
+        break;
+
+        /* **************** otherwise, it is any token **********/
+      default:
+        token->start = cur++;
+        token->type  = t1_token_any;
+        while ( cur < limit && !IS_CID_SPACE( *cur ) )
+          cur++;
+
+        token->limit = cur;
+      }
+
+      if ( !token->limit )
+      {
+        token->start = 0;
+        token->type  = t1_token_none;
+      }
+
+      parser->cursor = cur;
+    }
+  }
+
+
+  LOCAL_FUNC
+  void  CID_ToTokenArray( CID_Parser*     parser,
+                          CID_Token_Rec*  tokens,
+                          FT_UInt         max_tokens,
+                          FT_Int*         pnum_tokens )
+  {
+    CID_Token_Rec  master;
+
+
+    *pnum_tokens = -1;
+
+    CID_ToToken( parser, &master );
+
+    if ( master.type == t1_token_array )
+    {
+      FT_Byte*        old_cursor = parser->cursor;
+      FT_Byte*        old_limit  = parser->limit;
+      CID_Token_Rec*  cur        = tokens;
+      CID_Token_Rec*  limit      = cur + max_tokens;
+
+
+      parser->cursor = master.start;
+      parser->limit  = master.limit;
+
+      while ( parser->cursor < parser->limit )
+      {
+        CID_Token_Rec  token;
+
+
+        CID_ToToken( parser, &token );
+        if ( !token.type )
+          break;
+
+        if ( cur < limit )
+          *cur = token;
+
+        cur++;
+      }
+
+      *pnum_tokens = cur - tokens;
+
+      parser->cursor = old_cursor;
+      parser->limit  = old_limit;
+    }
+  }
+
+
+  static
+  FT_Long  t1_toint( FT_Byte**  cursor,
+                     FT_Byte*   limit )
+  {
+    FT_Long   result = 0;
+    FT_Byte*  cur    = *cursor;
+    FT_Byte   c, d;
+
+
+    for ( ; cur < limit; cur++ )
+    {
+      c = *cur;
+      d = (FT_Byte)( c - '0' );
+      if ( d < 10 )
+        break;
+
+      if ( c == '-' )
+      {
+        cur++;
+        break;
+      }
+    }
+
+    if ( cur < limit )
+    {
+      do
+      {
+        d = (FT_Byte)( cur[0] - '0' );
+        if ( d >= 10 )
+          break;
+
+        result = result * 10 + d;
+        cur++;
+
+      } while ( cur < limit );
+
+      if ( c == '-' )
+        result = -result;
+    }
+
+    *cursor = cur;
+
+    return result;
+  }
+
+
+  static
+  FT_Long  t1_tofixed( FT_Byte**  cursor,
+                       FT_Byte*   limit,
+                       FT_Long    power_ten )
+  {
+    FT_Byte*  cur = *cursor;
+    FT_Long   num, divider, result;
+    FT_Int    sign = 0;
+    FT_Byte   d;
+
+
+    if ( cur >= limit )
+      return 0;
+
+    /* first of all, read the integer part */
+    result  = t1_toint( &cur, limit ) << 16;
+    num     = 0;
+    divider = 1;
+
+    if ( result < 0 )
+    {
+      sign   = 1;
+      result = -result;
+    }
+
+    if ( cur >= limit )
+      goto Exit;
+
+    /* read decimal part, if any */
+    if ( *cur == '.' && cur + 1 < limit )
+    {
+      cur++;
+
+      for (;;)
+      {
+        d = (FT_Byte)( *cur - '0' );
+        if ( d >= 10 )
+          break;
+
+        if ( divider < 10000000L )
+        {
+          num      = num * 10 + d;
+          divider *= 10;
+        }
+
+        cur++;
+        if ( cur >= limit )
+          break;
+      }
+    }
+
+    /* read exponent, if any */
+    if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
+    {
+      cur++;
+      power_ten += t1_toint( &cur, limit );
+    }
+
+  Exit:
+    /* raise to power of ten if needed */
+    while ( power_ten > 0 )
+    {
+      result = result * 10;
+      num    = num * 10;
+      power_ten--;
+    }
+
+    while ( power_ten < 0 )
+    {
+      result  = result / 10;
+      divider = divider * 10;
+      power_ten++;
+    }
+
+    if ( num )
+      result += FT_DivFix( num, divider );
+
+    if ( sign )
+      result = -result;
+
+    *cursor = cur;
+
+    return result;
+  }
+
+
+  static
+  int  t1_tobool( FT_Byte**  cursor,
+                  FT_Byte*   limit )
+  {
+    FT_Byte*  cur    = *cursor;
+    FT_Bool   result = 0;
+
+
+    /* return 1 if we find a "true", 0 otherwise */
+    if ( cur + 3 < limit &&
+         cur[0] == 't'   &&
+         cur[1] == 'r'   &&
+         cur[2] == 'u'   &&
+         cur[3] == 'e'   )
+    {
+      result = 1;
+      cur   += 5;
+    }
+    else if ( cur + 4 < limit &&
+              cur[0] == 'f'   &&
+              cur[1] == 'a'   &&
+              cur[2] == 'l'   &&
+              cur[3] == 's'   &&
+              cur[4] == 'e'   )
+    {
+      result = 0;
+      cur   += 6;
+    }
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  FT_Int  t1_tocoordarray( FT_Byte**  cursor,
+                           FT_Byte*   limit,
+                           FT_Int     max_coords,
+                           FT_Short*  coords )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+
+    if ( cur >= limit )
+      goto Exit;
+
+    /* check for the beginning of an array. */
+    /* If not, only one number will be read */
+    c     = *cur;
+    ender = 0;
+
+    if ( c == '[' )
+      ender = ']';
+
+    if ( c == '{' )
+      ender = '}';
+
+    if ( ender )
+      cur++;
+
+    /* now, read the coordinates */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' )
+          break;
+
+        cur++;
+        if ( cur >= limit )
+          goto Exit;
+      }
+
+      if ( count >= max_coords || c == ender )
+        break;
+
+      coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
+      count++;
+
+      if ( !ender )
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+  static
+  FT_Int  t1_tofixedarray( FT_Byte**  cursor,
+                           FT_Byte*   limit,
+                           FT_Int     max_values,
+                           FT_Fixed*  values,
+                           FT_Int     power_ten )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+
+    if ( cur >= limit )
+      goto Exit;
+
+    /* check for the beginning of an array. */
+    /* If not, only one number will be read */
+    c     = *cur;
+    ender = 0;
+
+    if ( c == '[' )
+      ender = ']';
+
+    if ( c == '{' )
+      ender = '}';
+
+    if ( ender )
+      cur++;
+
+    /* now, read the values */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' )
+          break;
+
+        cur++;
+        if ( cur >= limit )
+          goto Exit;
+      }
+
+      if ( count >= max_values || c == ender )
+        break;
+
+      values[count] = t1_tofixed( &cur, limit, power_ten );
+      count++;
+
+      if ( !ender )
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+
+    return count;
+  }
+
+
+  /* Loads a simple field (i.e. non-table) into the current */
+  /* list of objects                                        */
+  LOCAL_FUNC
+  FT_Error  CID_Load_Field( CID_Parser*           parser,
+                            const CID_Field_Rec*  field,
+                            void*                 object )
+  {
+    CID_Token_Rec  token;
+    FT_Byte*      cur;
+    FT_Byte*      limit;
+    FT_UInt       count;
+    FT_UInt       index;
+    FT_Error      error;
+
+
+    CID_ToToken( parser, &token );
+    if ( !token.type )
+      goto Fail;
+
+    count = 1;
+    index = 0;
+    cur   = token.start;
+    limit = token.limit;
+
+    {
+      FT_Byte*   q = (FT_Byte*)object + field->offset;
+      FT_Long    val;
+      FT_String* string;
+
+
+      switch ( field->type )
+      {
+      case t1_field_bool:
+        val = t1_tobool( &cur, limit );
+        goto Store_Integer;
+
+      case t1_field_fixed:
+        val = t1_tofixed( &cur, limit, 0 );
+        goto Store_Integer;
+
+      case t1_field_integer:
+        val = t1_toint( &cur, limit );
+
+      Store_Integer:
+        switch ( field->size )
+        {
+          case 1:
+            *(FT_Byte*)q = (FT_Byte)val;
+            break;
+
+          case 2:
+            *(FT_UShort*)q = (FT_UShort)val;
+            break;
+
+          case 4:
+            *(FT_Int32*)q = (FT_Int)val;
+            break;
+
+          default:  /* for 64-bit systems */
+            *(FT_Long*)q = val;
+        }
+        break;
+
+      case t1_field_string:
+        {
+          FT_Memory  memory = parser->memory;
+          FT_UInt    len    = limit-cur;
+
+
+          if ( ALLOC( string, len + 1 ) )
+            goto Exit;
+
+          MEM_Copy( string, cur, len );
+          string[len] = 0;
+
+          *(FT_String**)q = string;
+        }
+        break;
+
+      default:
+        /* an error occurred */
+        goto Fail;
+      }
+    }
+
+    error = 0;
+
+  Exit:
+    return error;
+
+  Fail:
+    error = T1_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+#define T1_MAX_TABLE_ELEMENTS  32
+
+
+  LOCAL_FUNC
+  FT_Error  CID_Load_Field_Table( CID_Parser*           parser,
+                                  const CID_Field_Rec*  field,
+                                  void*                 object )
+  {
+    CID_Token_Rec   elements[T1_MAX_TABLE_ELEMENTS];
+    CID_Token_Rec*  token;
+    FT_Int          num_elements;
+    FT_Error        error = 0;
+    FT_Byte*        old_cursor;
+    FT_Byte*        old_limit;
+    CID_Field_Rec   fieldrec = *(CID_Field_Rec*)field;
+
+
+    fieldrec.type = t1_field_integer;
+    if ( field->type == t1_field_fixed_array )
+      fieldrec.type = t1_field_fixed;
+
+    CID_ToTokenArray( parser, elements, 32, &num_elements );
+    if ( num_elements < 0 )
+      goto Fail;
+
+    if ( num_elements > T1_MAX_TABLE_ELEMENTS )
+      num_elements = T1_MAX_TABLE_ELEMENTS;
+
+    old_cursor = parser->cursor;
+    old_limit  = parser->limit;
+
+    /* we store the elements count */
+    if ( field->count_offset )
+      *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = num_elements;
+
+    /* we now load each element, adjusting the field.offset on each one */
+    token = elements;
+    for ( ; num_elements > 0; num_elements--, token++ )
+    {
+      parser->cursor = token->start;
+      parser->limit  = token->limit;
+      CID_Load_Field( parser, &fieldrec, object );
+      fieldrec.offset += fieldrec.size;
+    }
+
+    parser->cursor = old_cursor;
+    parser->limit  = old_limit;
+
+  Exit:
+    return error;
+
+  Fail:
+    error = T1_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+  LOCAL_FUNC
+  FT_Long  CID_ToInt( CID_Parser*  parser )
+  {
+    return t1_toint( &parser->cursor, parser->limit );
+  }
+
+
+  LOCAL_FUNC
+  FT_Int  CID_ToCoordArray( CID_Parser*  parser,
+                            FT_Int       max_coords,
+                            FT_Short*    coords )
+  {
+    return t1_tocoordarray( &parser->cursor, parser->limit,
+                            max_coords, coords );
+  }
+
+
+  LOCAL_FUNC
+  FT_Int  CID_ToFixedArray( CID_Parser*  parser,
+                            FT_Int       max_values,
+                            FT_Fixed*    values,
+                            FT_Int       power_ten )
+  {
+    return t1_tofixedarray( &parser->cursor, parser->limit,
+                            max_values, values, power_ten );
+  }
+
+
+#if 0
+
+  /* return the value of an hexadecimal digit */
+  static
+  int  hexa_value( char  c )
+  {
+    unsigned int  d;
+
+
+    d = (unsigned int)( c - '0' );
+    if ( d <= 9 )
+      return (int)d;
+
+    d = (unsigned int)( c - 'a' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    d = (unsigned int)( c - 'A' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    return -1;
+  }
+
+#endif /* 0 */
+
+
+  LOCAL_FUNC
+  FT_Error  CID_New_Parser( CID_Parser*  parser,
+                            FT_Stream    stream,
+                            FT_Memory    memory )
+  {
+    FT_Error  error;
+    FT_ULong  base_offset, offset, ps_len;
+    FT_Byte   buffer[256 + 10];
+    FT_Int    buff_len;
+
+
+    MEM_Set( parser, 0, sizeof ( *parser ) );
+    parser->stream = stream;
+    parser->memory = memory;
+
+    base_offset = FILE_Pos();
+
+    /* first of all, check the font format in the  header */
+    if ( ACCESS_Frame( 31 ) )
+      goto Exit;
+
+    if ( strncmp( (char *)stream->cursor,
+                  "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
+    {
+      FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
+      error = FT_Err_Unknown_File_Format;
+    }
+
+    FORGET_Frame();
+    if ( error )
+      goto Exit;
+
+    /* now, read the rest of the file, until we find a `StartData' */
+    buff_len = 256;
+    for (;;)
+    {
+      FT_Byte  *p, *limit = buffer + 256;
+
+      /* fill input buffer */
+      buff_len -= 256;
+      if ( buff_len > 0 )
+        MEM_Move( buffer, limit, buff_len );
+
+      if ( FILE_Read( buffer, 256 + 10 - buff_len ) )
+        goto Exit;
+
+      buff_len = 256 + 10;
+
+      /* look for `StartData' */
+      for ( p = buffer; p < limit; p++ )
+      {
+        if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 )
+        {
+          /* save offset of binary data after `StartData' */
+          offset = FILE_Pos() - ( limit - p ) + 10;
+          goto Found;
+        }
+      }
+    }
+
+  Found:
+    /* we have found the start of the binary data.  We will now        */
+    /* rewind and extract the frame of corresponding to the Postscript */
+    /* section                                                         */
+
+    ps_len = offset - base_offset;
+    if ( FILE_Seek( base_offset )                    ||
+         EXTRACT_Frame( ps_len, parser->postscript ) )
+      goto Exit;
+
+    parser->data_offset    = offset;
+    parser->postscript_len = ps_len;
+    parser->cursor         = parser->postscript;
+    parser->limit          = parser->cursor + ps_len;
+    parser->num_dict       = -1;
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  CID_Done_Parser( CID_Parser*  parser )
+  {
+    /* always free the private dictionary */
+    if ( parser->postscript )
+    {
+      FT_Stream  stream = parser->stream;
+
+
+      RELEASE_Frame( parser->postscript );
+    }
+  }
+
+
+/* END */
diff --git a/src/freetype/cid/cidparse.h b/src/freetype/cid/cidparse.h
new file mode 100644 (file)
index 0000000..7a8211a
--- /dev/null
@@ -0,0 +1,353 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidparse.h                                                             */
+/*                                                                         */
+/*    CID-keyed Type1 parser (specification).                              */
+/*                                                                         */
+/*  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 CIDPARSE_H
+#define CIDPARSE_H
+
+#include <freetype/internal/t1types.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+#if 0
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    CID_Table                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A CID_Table is a simple object used to store an array of objects   */
+  /*    in a single memory block.                                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    block     :: The address in memory of the growheap's block.  This  */
+  /*                 can change between two object adds, due to the use    */
+  /*                 of `realloc()'.                                       */
+  /*                                                                       */
+  /*    cursor    :: The current top of the growheap within its block.     */
+  /*                                                                       */
+  /*    capacity  :: The current size of the heap block.  Increments by    */
+  /*                 blocks of 1 kByte.                                    */
+  /*                                                                       */
+  /*    init      :: A boolean.  Set when the table has been initialized   */
+  /*                 (the table user should set this field).               */
+  /*                                                                       */
+  /*    max_elems :: The maximal number of elements in the table.          */
+  /*                                                                       */
+  /*    num_elems :: The current number of elements (in use) in the table. */
+  /*                                                                       */
+  /*    elements  :: A table of element addresses within the block.        */
+  /*                                                                       */
+  /*    lengths   :: A table of element sizes within the block.            */
+  /*                                                                       */
+  /*    memory    :: The memory object used for memory operations          */
+  /*                 (allocation resp. reallocation).                      */
+  /*                                                                       */
+  typedef struct  CID_Table_
+  {
+    FT_Byte*   block;          /* current memory block           */
+    FT_Int     cursor;         /* current cursor in memory block */
+    FT_Int     capacity;       /* current size of memory block   */
+    FT_Long    init;
+
+    FT_Int     max_elems;
+    FT_Int     num_elems;
+    FT_Byte**  elements;       /* addresses of table elements */
+    FT_Int*    lengths;        /* lengths of table elements   */
+
+    FT_Memory  memory;
+
+  } CID_Table;
+
+
+  LOCAL_DEF
+  FT_Error  CID_New_Table( CID_Table*  table,
+                           FT_Int      count,
+                           CID_Memory  memory );
+
+  LOCAL_DEF
+  FT_Error  CID_Add_Table( CID_Table*  table,
+                           FT_Int      index,
+                           void*       object,
+                           FT_Int      length );
+
+  LOCAL_DEF
+  void  CID_Release_Table( CID_Table*  table );
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    CID_Parser                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A CID_Parser is an object used to parse a Type 1 fonts very        */
+  /*    quickly.                                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    stream         :: The current input stream.                        */
+  /*                                                                       */
+  /*    memory         :: The current memory object.                       */
+  /*                                                                       */
+  /*    postscript     :: A pointer to the data to be parsed.              */
+  /*                                                                       */
+  /*    postscript_len :: The length of the data to be parsed.             */
+  /*                                                                       */
+  /*    data_offset    :: The start position of the binary data (i.e., the */
+  /*                      end of the data to be parsed.                    */
+  /*                                                                       */
+  /*    cursor         :: The current parser cursor.                       */
+  /*                                                                       */
+  /*    limit          :: The current parser limit (i.e., the first byte   */
+  /*                      after the current dictionary).                   */
+  /*                                                                       */
+  /*    error          :: The current parsing error.                       */
+  /*                                                                       */
+  /*    cid            :: A structure which holds the information about    */
+  /*                      the current font.                                */
+  /*                                                                       */
+  /*    num_dict       :: The number of font dictionaries.                 */
+  /*                                                                       */
+  typedef struct CID_Parser_
+  {
+    FT_Stream  stream;
+    FT_Memory  memory;
+
+    FT_Byte*   postscript;
+    FT_Int     postscript_len;
+
+    FT_ULong   data_offset;
+
+    FT_Byte*   cursor;
+    FT_Byte*   limit;
+    FT_Error   error;
+
+    CID_Info*  cid;
+    FT_Int     num_dict;
+
+  } CID_Parser;
+
+
+  LOCAL_DEF
+  FT_Error  CID_New_Parser( CID_Parser*  parser,
+                            FT_Stream    stream,
+                            FT_Memory    memory );
+
+  LOCAL_DEF
+  void  CID_Done_Parser( CID_Parser*  parser );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                            PARSING ROUTINES                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+  LOCAL_DEF
+  FT_Long  CID_ToInt( CID_Parser*  parser );
+
+  LOCAL_DEF
+  FT_Int  CID_ToCoordArray( CID_Parser*  parser,
+                            FT_Int       max_coords,
+                            FT_Short*    coords );
+
+  LOCAL_DEF
+  FT_Int  CID_ToFixedArray( CID_Parser*  parser,
+                            FT_Int       max_values,
+                            FT_Fixed*    values,
+                            FT_Int       power_ten );
+
+  LOCAL_DEF
+  void  CID_Skip_Spaces( CID_Parser*  parser );
+
+
+  /* simple enumeration type used to identify token types */
+  typedef enum  CID_Token_Type_
+  {
+    t1_token_none = 0,
+    t1_token_any,
+    t1_token_string,
+    t1_token_array,
+
+    /* do not remove */
+    t1_token_max
+
+  } CID_Token_Type;
+
+
+  /* a simple structure used to identify tokens */
+  typedef struct  CID_Token_Rec_
+  {
+    FT_Byte*        start;   /* first character of token in input stream */
+    FT_Byte*        limit;   /* first character after the token          */
+    CID_Token_Type  type;    /* type of token                            */
+
+  } CID_Token_Rec;
+
+
+  LOCAL_DEF
+  void  CID_ToToken( CID_Parser*     parser,
+                     CID_Token_Rec*  token );
+
+
+  /* enumeration type used to identify object fields */
+  typedef enum  CID_Field_Type_
+  {
+    t1_field_none = 0,
+    t1_field_bool,
+    t1_field_integer,
+    t1_field_fixed,
+    t1_field_string,
+    t1_field_integer_array,
+    t1_field_fixed_array,
+    t1_field_callback,
+
+    /* do not remove */
+    t1_field_max
+
+  } CID_Field_Type;
+
+  typedef enum  CID_Field_Location_
+  {
+    t1_field_cid_info,
+    t1_field_font_dict,
+    t1_field_font_info,
+    t1_field_private,
+
+    /* do not remove */
+    t1_field_location_max
+
+  } CID_Field_Location;
+
+
+  typedef FT_Error  (*CID_Field_Parser)( CID_Face     face,
+                                         CID_Parser*  parser );
+
+  /* structure type used to model object fields */
+  typedef struct  CID_Field_Rec_
+  {
+    const char*         ident;        /* field identifier                  */
+    CID_Field_Location  location;
+    CID_Field_Type      type;         /* type of field                     */
+    CID_Field_Parser    reader;
+    FT_UInt             offset;       /* offset of field in object         */
+    FT_UInt             size;         /* size of field in bytes            */
+    FT_UInt             array_max;    /* maximal number of elements for    */
+                                      /* array                             */
+    FT_UInt             count_offset; /* offset of element count for       */
+                                      /* arrays                            */
+  } CID_Field_Rec;
+
+
+#define CID_FIELD_REF( s, f )  ( ((s*)0)->f )
+
+#define CID_NEW_SIMPLE_FIELD( _ident, _type, _fname )         \
+          {                                                   \
+            _ident, T1CODE, _type,                            \
+            0,                                                \
+            (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \
+            sizeof ( CID_FIELD_REF( T1TYPE, _fname ) ),       \
+            0, 0                                              \
+          },
+
+#define CID_NEW_CALLBACK_FIELD( _ident, _reader ) \
+          {                                       \
+            _ident, T1CODE, t1_field_callback,    \
+            _reader,                              \
+            0, 0,                                 \
+            0, 0                                  \
+          },
+
+#define CID_NEW_TABLE_FIELD( _ident, _type, _fname, _max )           \
+          {                                                          \
+            _ident, T1CODE, _type,                                   \
+            0,                                                       \
+            (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ),        \
+            sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ),           \
+            _max,                                                    \
+            (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, num_ ## _fname ) \
+          },
+
+#define CID_NEW_TABLE_FIELD2( _ident, _type, _fname, _max )   \
+          {                                                   \
+            _ident, T1CODE, _type,                            \
+            0,                                                \
+            (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \
+            sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ),    \
+            _max, 0                                           \
+          },
+
+
+#define CID_FIELD_BOOL( _ident, _fname )                           \
+          CID_NEW_SIMPLE_FIELD( _ident, t1_field_bool, _fname )
+
+#define CID_FIELD_NUM( _ident, _fname )                            \
+          CID_NEW_SIMPLE_FIELD( _ident, t1_field_integer, _fname )
+
+#define CID_FIELD_FIXED( _ident, _fname )                          \
+          CID_NEW_SIMPLE_FIELD( _ident, t1_field_fixed, _fname )
+
+#define CID_FIELD_STRING( _ident, _fname )                         \
+          CID_NEW_SIMPLE_FIELD( _ident, t1_field_string, _fname )
+
+#define CID_FIELD_NUM_TABLE( _ident, _fname, _fmax )               \
+          CID_NEW_TABLE_FIELD( _ident, t1_field_integer_array,     \
+                               _fname, _fmax )
+
+#define CID_FIELD_FIXED_TABLE( _ident, _fname, _fmax )             \
+          CID_NEW_TABLE_FIELD( _ident, t1_field_fixed_array,       \
+                               _fname, _fmax )
+
+#define CID_FIELD_NUM_TABLE2( _ident, _fname, _fmax )              \
+          CID_NEW_TABLE_FIELD2( _ident, t1_field_integer_array,    \
+                                _fname, _fmax )
+
+#define CID_FIELD_FIXED_TABLE2( _ident, _fname, _fmax )            \
+          CID_NEW_TABLE_FIELD2( _ident, t1_field_fixed_array,      \
+                                _fname, _fmax )
+
+#define CID_FIELD_CALLBACK( _ident, _name )                        \
+          CID_NEW_CALLBACK_FIELD( _ident, parse_ ## _name )
+
+
+  LOCAL_DEF
+  FT_Error  CID_Load_Field( CID_Parser*           parser,
+                            const CID_Field_Rec*  field,
+                            void*                 object );
+
+  LOCAL_DEF
+  FT_Error  CID_Load_Field_Table( CID_Parser*           parser,
+                                  const CID_Field_Rec*  field,
+                                  void*                 object );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* CIDPARSE_H */
+
+
+/* END */
diff --git a/src/freetype/cid/cidriver.c b/src/freetype/cid/cidriver.c
new file mode 100644 (file)
index 0000000..f1c6b6a
--- /dev/null
@@ -0,0 +1,259 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidriver.c                                                             */
+/*                                                                         */
+/*    CID driver interface (body).                                         */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidriver.h"
+#include "cidgload.h"
+
+#else
+
+#include <cid/cidriver.h>
+#include <cid/cidgload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h>         /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ciddriver
+
+
+  static
+  FT_Module_Interface  CID_Get_Interface( FT_Driver         driver,
+                                          const FT_String*  interface )
+  {
+    FT_UNUSED( driver );
+    FT_UNUSED( interface );
+
+    return 0;
+  }
+
+
+#if 0 /* unimplemented yet */
+
+  static
+  FT_Error  cid_Get_Kerning( T1_Face     face,
+                             FT_UInt     left_glyph,
+                             FT_UInt     right_glyph,
+                             FT_Vector*  kerning )
+  {
+    CID_AFM*  afm;
+
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (CID_AFM*)face->afm_data;
+    if ( afm )
+      CID_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return T1_Err_Ok;
+  }
+
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Cid_Get_Char_Index                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*                                                                       */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  FT_UInt  CID_Get_Char_Index( FT_CharMap  charmap,
+                               FT_Long     charcode )
+  {
+    T1_Face             face;
+    FT_UInt             result = 0;
+    PSNames_Interface*  psnames;
+
+
+    face = (T1_Face)charmap->face;
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( psnames )
+      switch ( charmap->encoding )
+      {
+        /*******************************************************************/
+        /*                                                                 */
+        /* Unicode encoding support                                        */
+        /*                                                                 */
+      case ft_encoding_unicode:
+        /* use the `PSNames' module to synthetize the Unicode charmap */
+        result = psnames->lookup_unicode( &face->unicode_map,
+                                          (FT_ULong)charcode );
+
+        /* the function returns 0xFFFF if the Unicode charcode has */
+        /* no corresponding glyph.                                 */
+        if ( result == 0xFFFF )
+          result = 0;
+        goto Exit;
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Custom Type 1 encoding                                          */
+        /*                                                                 */
+      case ft_encoding_adobe_custom:
+        {
+          T1_Encoding*  encoding = &face->type1.encoding;
+
+
+          if ( charcode >= encoding->code_first &&
+               charcode <= encoding->code_last  )
+            result = encoding->char_index[charcode];
+          goto Exit;
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Adobe Standard & Expert encoding support                        */
+        /*                                                                 */
+      default:
+        if ( charcode < 256 )
+        {
+          FT_UInt      code;
+          FT_Int       n;
+          const char*  glyph_name;
+
+
+          code = psnames->adobe_std_encoding[charcode];
+          if ( charmap->encoding == ft_encoding_adobe_expert )
+            code = psnames->adobe_expert_encoding[charcode];
+
+          glyph_name = psnames->adobe_std_strings( code );
+          if ( !glyph_name )
+            break;
+
+          for ( n = 0; n < face->type1.num_glyphs; n++ )
+          {
+            const char*  gname = face->type1.glyph_names[n];
+
+
+            if ( gname && gname[0] == glyph_name[0] &&
+                 strcmp( gname, glyph_name ) == 0   )
+            {
+              result = n;
+              break;
+            }
+          }
+        }
+      }
+
+  Exit:
+    return result;
+  }
+
+
+  const FT_Driver_Class  t1cid_driver_class =
+  {
+    /* first of all, the FT_Module_Class fields */
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( FT_DriverRec ),
+      "t1cid",   /* module name           */
+      0x10000L,  /* version 1.0 of driver */
+      0x20000L,  /* requires FreeType 2.0 */
+
+      0,
+
+      (FT_Module_Constructor)CID_Init_Driver,
+      (FT_Module_Destructor) CID_Done_Driver,
+      (FT_Module_Requester)  CID_Get_Interface
+    },
+
+    /* then the other font drivers fields */
+    sizeof( CID_FaceRec ),
+    sizeof( CID_SizeRec ),
+    sizeof( CID_GlyphSlotRec ),
+
+    (FTDriver_initFace)     CID_Init_Face,
+    (FTDriver_doneFace)     CID_Done_Face,
+
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) 0,
+    (FTDriver_setPixelSizes)0,
+
+    (FTDriver_loadGlyph)    CID_Load_Glyph,
+    (FTDriver_getCharIndex) CID_Get_Char_Index,
+
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  EXPORT_FUNC( FT_Driver_Class* )  getDriverClass( void )
+  {
+    return &t1cid_driver_class;
+  }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/src/freetype/cid/cidriver.h b/src/freetype/cid/cidriver.h
new file mode 100644 (file)
index 0000000..a9674ee
--- /dev/null
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidriver.h                                                             */
+/*                                                                         */
+/*    High-level CID driver interface (specification).                     */
+/*                                                                         */
+/*  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 CIDRIVER_H
+#define CIDRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+  FT_EXPORT_VAR( const  FT_Driver_Class )  t1cid_driver_class;
+
+#endif /* CIDRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/cid/cidtokens.h b/src/freetype/cid/cidtokens.h
new file mode 100644 (file)
index 0000000..a916cea
--- /dev/null
@@ -0,0 +1,99 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidtokens.h                                                            */
+/*                                                                         */
+/*    CID token definitions (specification only).                          */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#undef  T1TYPE
+#undef  T1CODE
+#define T1TYPE  CID_Info
+#define T1CODE  t1_field_cid_info
+
+  CID_FIELD_STRING  ( "CIDFontName", cid_font_name )
+  CID_FIELD_NUM     ( "CIDFontVersion", cid_version )
+  CID_FIELD_NUM     ( "CIDFontType", cid_font_type )
+  CID_FIELD_STRING  ( "Registry", registry )
+  CID_FIELD_STRING  ( "Ordering", ordering )
+  CID_FIELD_NUM     ( "Supplement", supplement )
+  CID_FIELD_CALLBACK( "FontBBox", font_bbox )
+  CID_FIELD_NUM     ( "UIDBase", uid_base )
+  CID_FIELD_CALLBACK( "FDArray", fd_array )
+  CID_FIELD_NUM     ( "CIDMapOffset", cidmap_offset )
+  CID_FIELD_NUM     ( "FDBytes", fd_bytes )
+  CID_FIELD_NUM     ( "GDBytes", gd_bytes )
+  CID_FIELD_NUM     ( "CIDCount", cid_count )
+
+
+#undef  T1TYPE
+#undef  T1CODE
+#define T1TYPE  T1_FontInfo
+#define T1CODE  t1_field_font_info
+
+  CID_FIELD_STRING( "version", version )
+  CID_FIELD_STRING( "Notice", notice )
+  CID_FIELD_STRING( "FullName", full_name )
+  CID_FIELD_STRING( "FamilyName", family_name )
+  CID_FIELD_STRING( "Weight", weight )
+  CID_FIELD_FIXED ( "ItalicAngle", italic_angle )
+  CID_FIELD_BOOL  ( "isFixedPitch", is_fixed_pitch )
+  CID_FIELD_NUM   ( "UnderlinePosition", underline_position )
+  CID_FIELD_NUM   ( "UnderlineThickness", underline_thickness )
+
+
+#undef  T1TYPE
+#undef  T1CODE
+#define T1TYPE CID_FontDict
+#define T1CODE t1_field_font_dict
+
+  CID_FIELD_CALLBACK( "FontMatrix", font_matrix )
+  CID_FIELD_NUM     ( "PaintType", paint_type )
+  CID_FIELD_NUM     ( "FontType", font_type )
+  CID_FIELD_NUM     ( "SubrMapOffset", subrmap_offset )
+  CID_FIELD_NUM     ( "SDBytes", sd_bytes )
+  CID_FIELD_NUM     ( "SubrCount", num_subrs )
+  CID_FIELD_NUM     ( "lenBuildCharArray", len_buildchar )
+  CID_FIELD_FIXED   ( "ForceBoldThreshold", forcebold_threshold )
+  CID_FIELD_FIXED   ( "ExpansionFactor", expansion_factor )
+  CID_FIELD_NUM     ( "StrokeWidth", stroke_width )
+
+
+#undef  T1TYPE
+#undef  T1CODE
+#define T1TYPE  T1_Private
+#define T1CODE  t1_field_private
+
+  CID_FIELD_NUM       ( "UniqueID", unique_id )
+  CID_FIELD_NUM       ( "lenIV", lenIV )
+  CID_FIELD_NUM       ( "LanguageGroup", language_group )
+  CID_FIELD_NUM       ( "password", password )
+
+  CID_FIELD_FIXED     ( "BlueScale", blue_scale )
+  CID_FIELD_NUM       ( "BlueShift", blue_shift )
+  CID_FIELD_NUM       ( "BlueFuzz",  blue_fuzz )
+
+  CID_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 )
+  CID_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 )
+  CID_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 )
+  CID_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 )
+
+  CID_FIELD_NUM_TABLE2( "StdHW", standard_width,  1 )
+  CID_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
+  CID_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+  CID_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
+  CID_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
+
+
+/* END */
diff --git a/src/freetype/cid/module.mk b/src/freetype/cid/module.mk
new file mode 100644 (file)
index 0000000..3d13c9c
--- /dev/null
@@ -0,0 +1,6 @@
+make_module_list: add_type1cid_driver
+
+add_type1cid_driver:
+       $(OPEN_DRIVER)t1cid_driver_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)cid       $(ECHO_DRIVER_DESC)Postscript CID-keyed fonts, no known extension$(ECHO_DRIVER_DONE)
+# EOF
diff --git a/src/freetype/cid/rules.mk b/src/freetype/cid/rules.mk
new file mode 100644 (file)
index 0000000..cbaaec7
--- /dev/null
@@ -0,0 +1,69 @@
+#
+# FreeType 2 CID driver configuration rules
+#
+
+
+# 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.
+
+
+# CID driver directory
+#
+CID_DIR  := $(SRC_)cid
+CID_DIR_ := $(CID_DIR)$(SEP)
+
+
+CID_COMPILE := $(FT_COMPILE)
+
+
+# CID driver sources (i.e., C files)
+#
+CID_DRV_SRC := $(CID_DIR_)cidparse.c \
+               $(CID_DIR_)cidload.c  \
+               $(CID_DIR_)cidriver.c \
+               $(CID_DIR_)cidgload.c \
+               $(CID_DIR_)cidobjs.c
+
+# CID driver headers
+#
+CID_DRV_H := $(CID_DRV_SRC:%.c=%.h) \
+             $(CID_DIR_)cidtokens.h
+
+
+# CID driver object(s)
+#
+#   CID_DRV_OBJ_M is used during `multi' builds
+#   CID_DRV_OBJ_S is used during `single' builds
+#
+CID_DRV_OBJ_M := $(CID_DRV_SRC:$(CID_DIR_)%.c=$(OBJ_)%.$O)
+CID_DRV_OBJ_S := $(OBJ_)type1cid.$O
+
+# CID driver source file for single build
+#
+CID_DRV_SRC_S := $(CID_DIR_)type1cid.c
+
+
+# CID driver - single object
+#
+$(CID_DRV_OBJ_S): $(CID_DRV_SRC_S) $(CID_DRV_SRC) $(FREETYPE_H) $(CID_DRV_H)
+       $(CID_COMPILE) $T$@ $(CID_DRV_SRC_S)
+
+
+# CID driver - multiple objects
+#
+$(OBJ_)%.$O: $(CID_DIR_)%.c $(FREETYPE_H) $(CID_DRV_H)
+       $(CID_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(CID_DRV_OBJ_S)
+DRV_OBJS_M += $(CID_DRV_OBJ_M)
+
+# EOF
diff --git a/src/freetype/cid/type1cid.c b/src/freetype/cid/type1cid.c
new file mode 100644 (file)
index 0000000..d26aee2
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cff.c                                                                  */
+/*                                                                         */
+/*    FreeType OpenType driver component (body only).                      */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef FT_FLAT_COMPILE
+
+#include "cidparse.c"
+#include "cidload.c"
+#include "cidobjs.c"
+#include "cidriver.c"
+#include "cidgload.c"
+
+#else
+
+#include <cid/cidparse.c>
+#include <cid/cidload.c>
+#include <cid/cidobjs.c>
+#include <cid/cidriver.c>
+#include <cid/cidgload.c>
+
+#endif
+
+
+/* END */
diff --git a/src/freetype/freetype/config/ftconfig.h b/src/freetype/freetype/config/ftconfig.h
new file mode 100644 (file)
index 0000000..338e22c
--- /dev/null
@@ -0,0 +1,187 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftconfig.h                                                             */
+/*                                                                         */
+/*    ANSI-specific configuration file (specification only).               */
+/*                                                                         */
+/*  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 header file contains a number of macro definitions that are used */
+  /* by the rest of the engine.  Most of the macros here are automatically */
+  /* determined at compile time, and you should not need to change it to   */
+  /* port FreeType, except to compile the library with a non-ANSI          */
+  /* compiler.                                                             */
+  /*                                                                       */
+  /* Note however that if some specific modifications are needed, we       */
+  /* advise you to place a modified copy in your build directory.          */
+  /*                                                                       */
+  /* The build directory is usually `freetype/builds/<system>', and        */
+  /* contains system-specific files that are always included first when    */
+  /* building the library.                                                 */
+  /*                                                                       */
+  /* This ANSI version should stay in `include/freetype/config'.           */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTCONFIG_H
+#define FTCONFIG_H
+
+
+  /* Include the header file containing all developer build options */
+#include <freetype/config/ftoption.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*               PLATFORM-SPECIFIC CONFIGURATION MACROS                  */
+  /*                                                                       */
+  /* These macros can be toggled to suit a specific system.  The current   */
+  /* ones are defaults used to compile FreeType in an ANSI C environment   */
+  /* (16bit compilers are also supported).  Copy this file to your own     */
+  /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* We use <limits.h> values to know the sizes of the types.  */
+#include <limits.h>
+
+  /* The number of bytes in an `int' type.  */
+#if   UINT_MAX == 0xFFFFFFFF
+#define FT_SIZEOF_INT  4
+#elif UINT_MAX == 0xFFFF
+#define FT_SIZEOF_INT  2
+#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF
+#define FT_SIZEOF_INT  8
+#else
+#error "Unsupported number of bytes in `int' type!"
+#endif
+
+  /* The number of bytes in a `long' type.  */
+#if   ULONG_MAX == 0xFFFFFFFF
+#define FT_SIZEOF_LONG  4
+#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF
+#define FT_SIZEOF_LONG  8
+#else
+#error "Unsupported number of bytes in `long' type!"
+#endif
+
+
+  /* Preferred alignment of data */
+#define FT_ALIGNMENT  8
+
+
+  /* UNUSED is a macro used to indicate that a given parameter is not used */
+  /* -- this is only used to get rid of unpleasant compiler warnings       */
+#ifndef FT_UNUSED
+#define FT_UNUSED( arg )  ( (arg) = (arg) )
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     AUTOMATIC CONFIGURATION MACROS                    */
+  /*                                                                       */
+  /* These macros are computed from the ones defined above.  Don't touch   */
+  /* their definition, unless you know precisely what you are doing.  No   */
+  /* porter should need to mess with them.                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IntN types                                                            */
+  /*                                                                       */
+  /*   Used to guarantee the size of some specific integers.               */
+  /*                                                                       */
+  typedef signed short    FT_Int16;
+  typedef unsigned short  FT_UInt16;
+
+#if FT_SIZEOF_INT == 4
+
+  typedef signed int      FT_Int32;
+  typedef unsigned int    FT_UInt32;
+
+#elif FT_SIZEOF_LONG == 4
+
+  typedef signed long     FT_Int32;
+  typedef unsigned long   FT_UInt32;
+
+#else
+#error "no 32bit type found -- please check your configuration files"
+#endif
+
+#if FT_SIZEOF_LONG == 8
+
+  /* FT_LONG64 must be defined if a 64-bit type is available */
+#define FT_LONG64
+#define FT_INT64   long
+
+#else
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Many compilers provide the non-ANSI `long long' 64-bit type.  You can */
+  /* activate it by defining the FTCALC_USE_LONG_LONG macro in             */
+  /* `ftoption.h'.                                                         */
+  /*                                                                       */
+  /* Note that this will produce many -ansi warnings during library        */
+  /* compilation, and that in many cases,  the generated code will be      */
+  /* neither smaller nor faster!                                           */
+  /*                                                                       */
+#ifdef FTCALC_USE_LONG_LONG
+
+#define FT_LONG64
+#define FT_INT64   long long
+
+#endif /* FTCALC_USE_LONG_LONG */
+#endif /* FT_SIZEOF_LONG == 8 */
+
+
+#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+#define  LOCAL_DEF   static
+#define  LOCAL_FUNC  static
+#else
+#define  LOCAL_DEF   extern
+#define  LOCAL_FUNC  /* nothing */
+#endif
+
+#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT
+#define  BASE_DEF( x )   static  x
+#define  BASE_FUNC( x )  static  x
+#else
+#define  BASE_DEF( x )   extern  x
+#define  BASE_FUNC( x )  extern  x
+#endif
+
+#ifndef  FT_EXPORT_DEF
+#define  FT_EXPORT_DEF( x )   extern  x
+#endif
+
+#ifndef  FT_EXPORT_FUNC
+#define  FT_EXPORT_FUNC( x )  extern  x
+#endif
+
+#ifndef  FT_EXPORT_VAR
+#define  FT_EXPORT_VAR( x )   extern  x
+#endif
+
+#endif /* FTCONFIG_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/config/ftmodule.h b/src/freetype/freetype/config/ftmodule.h
new file mode 100644 (file)
index 0000000..50cc46b
--- /dev/null
@@ -0,0 +1,10 @@
+FT_USE_MODULE(autohint_module_class)
+FT_USE_MODULE(cff_driver_class)
+FT_USE_MODULE(t1cid_driver_class)
+FT_USE_MODULE(psnames_module_class)
+FT_USE_MODULE(ft_raster1_renderer_class)
+FT_USE_MODULE(sfnt_module_class)
+FT_USE_MODULE(ft_smooth_renderer_class)
+FT_USE_MODULE(tt_driver_class)
+FT_USE_MODULE(t1_driver_class)
+FT_USE_MODULE(winfnt_driver_class)
diff --git a/src/freetype/freetype/config/ftoption.h b/src/freetype/freetype/config/ftoption.h
new file mode 100644 (file)
index 0000000..a7e1f40
--- /dev/null
@@ -0,0 +1,395 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftoption.h                                                             */
+/*                                                                         */
+/*    User-selectable configuration macros (specification only).           */
+/*                                                                         */
+/*  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 FTOPTION_H
+#define FTOPTION_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                 USER-SELECTABLE CONFIGURATION MACROS                  */
+  /*                                                                       */
+  /* These macros can be toggled by developers to enable or disable        */
+  /* certain aspects of FreeType.  This is a default file, where all major */
+  /* options are enabled.                                                  */
+  /*                                                                       */
+  /* Note that if some modifications are required for your build, we       */
+  /* advise you to put a modified copy of this file in your build          */
+  /* directory, rather than modifying it in-place.                         */
+  /*                                                                       */
+  /* The build directory is normally `freetype/builds/<system>' and        */
+  /* contains build or system-specific files that are included in          */
+  /* priority when building the library.                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /**** G E N E R A L   F R E E T Y P E   2   C O N F I G U R A T I O N ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Convenience functions support                                         */
+  /*                                                                       */
+  /*   Some functions of the FreeType 2 API are provided as a convenience  */
+  /*   for client applications and developers. However,  they are not      */
+  /*   required to build and run the library itself.                       */
+  /*                                                                       */
+  /*   By defining this configuration macro, you'll disable the            */
+  /*   compilation of these functions at build time.  This can be useful   */
+  /*   to reduce the library's code size when you don't need any of        */
+  /*   these functions.                                                    */
+  /*                                                                       */
+  /*   All convenience functions are declared as such in their             */
+  /*   documentation.                                                      */
+  /*                                                                       */
+#undef FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Alternate Glyph Image Format support                                  */
+  /*                                                                       */
+  /*   By default, the glyph images returned by the FreeType glyph loader  */
+  /*   can either be a pixmap or a vectorial outline defined through       */
+  /*   Bezier control points.  When defining the following configuration   */
+  /*   macro, some font drivers will be able to register alternate         */
+  /*   glyph image formats.                                                */
+  /*                                                                       */
+  /*   Unset this macro if you are sure that you will never use a font     */
+  /*   driver with an alternate glyph format; this will reduce the size of */
+  /*   the base layer code.                                                */
+  /*                                                                       */
+  /*   Note that a few Type 1 fonts, as well as Windows `vector' fonts     */
+  /*   use a vector `plotter' format that isn't supported when this        */
+  /*   macro is undefined.                                                 */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Glyph Postscript Names handling                                       */
+  /*                                                                       */
+  /*   By default, FreeType 2 is compiled with the `PSNames' module.  This */
+  /*   This module is in charge of converting a glyph name string into a   */
+  /*   Unicode value, or return a Macintosh standard glyph name for the    */
+  /*   use with the TrueType `post' table.                                 */
+  /*                                                                       */
+  /*   Undefine this macro if you do not want `PSNames' compiled in your   */
+  /*   build of FreeType.  This has the following effects:                 */
+  /*                                                                       */
+  /*   - The TrueType driver will provide its own set of glyph names,      */
+  /*     if you build it to support postscript names in the TrueType       */
+  /*     `post' table.                                                     */
+  /*                                                                       */
+  /*   - The Type 1 driver will not be able to synthetize a Unicode        */
+  /*     charmap out of the glyphs found in the fonts.                     */
+  /*                                                                       */
+  /*   You would normally undefine this configuration macro when building  */
+  /*   a version of FreeType that doesn't contain a Type 1 or CFF driver.  */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Postscript Names to Unicode Values support                            */
+  /*                                                                       */
+  /*   By default, FreeType 2 is built with the `PSNames' module compiled  */
+  /*   in.  Among other things, the module is used to convert a glyph name */
+  /*   into a Unicode value.  This is especially useful in order to        */
+  /*   synthetize on the fly a Unicode charmap from the CFF/Type 1 driver  */
+  /*   through a big table named the `Adobe Glyph List' (AGL).             */
+  /*                                                                       */
+  /*   Undefine this macro if you do not want the Adobe Glyph List         */
+  /*   compiled in your `PSNames' module.  The Type 1 driver will not be   */
+  /*   able to synthetize a Unicode charmap out of the glyphs found in the */
+  /*   fonts.                                                              */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Many compilers provide the non-ANSI `long long' 64-bit type.  You can */
+  /* activate it by defining the FTCALC_USE_LONG_LONG macro.  Note that    */
+  /* this will produce many -ansi warnings during library compilation, and */
+  /* that in many cases the generated code will not be smaller or faster!  */
+  /*                                                                       */
+#undef FTCALC_USE_LONG_LONG
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DLL export compilation                                                */
+  /*                                                                       */
+  /*   When compiling FreeType as a DLL, some systems/compilers need a     */
+  /*   special keyword in front OR after the return type of function       */
+  /*   declarations.                                                       */
+  /*                                                                       */
+  /*   Two macros are used within the FreeType source code to define       */
+  /*   exported library functions: FT_EXPORT_DEF and FT_EXPORT_FUNC.       */
+  /*                                                                       */
+  /*     FT_EXPORT_DEF( return_type )                                      */
+  /*                                                                       */
+  /*       is used in a function declaration, as in                        */
+  /*                                                                       */
+  /*         FT_EXPORT_DEF( FT_Error )                                     */
+  /*         FT_Init_FreeType( FT_Library*  alibrary );                    */
+  /*                                                                       */
+  /*                                                                       */
+  /*     FT_EXPORT_FUNC( return_type )                                     */
+  /*                                                                       */
+  /*       is used in a function definition, as in                         */
+  /*                                                                       */
+  /*         FT_EXPORT_FUNC( FT_Error )                                    */
+  /*         FT_Init_FreeType( FT_Library*  alibrary )                     */
+  /*         {                                                             */
+  /*           ... some code ...                                           */
+  /*           return FT_Err_Ok;                                           */
+  /*         }                                                             */
+  /*                                                                       */
+  /*   You can provide your own implementation of FT_EXPORT_DEF and        */
+  /*   FT_EXPORT_FUNC here if you want.  If you leave them undefined, they */
+  /*   will be later automatically defined as `extern return_type' to      */
+  /*   allow normal compilation.                                           */
+  /*                                                                       */
+#undef FT_EXPORT_DEF
+#undef FT_EXPORT_FUNC
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Debug level                                                           */
+  /*                                                                       */
+  /*   FreeType can be compiled in debug or trace mode.  In debug mode,    */
+  /*   errors are reported through the `ftdebug' component.  In trace      */
+  /*   mode, additional messages are sent to the standard output during    */
+  /*   execution.                                                          */
+  /*                                                                       */
+  /*   Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode.     */
+  /*   Define FT_DEBUG_LEVEL_TRACE to build it in trace mode.              */
+  /*                                                                       */
+  /*   Don't define any of these macros to compile in `release' mode!      */
+  /*                                                                       */
+#define FT_DEBUG_LEVEL_ERROR
+#define FT_DEBUG_LEVEL_TRACE
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Computation Algorithms                                                */
+  /*                                                                       */
+  /*   Used for debugging, this configuration macro should disappear       */
+  /*   soon.                                                               */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_OLD_CALCS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The size in bytes of the render pool used by the scan-line converter  */
+  /* to do all of its work.                                                */
+  /*                                                                       */
+  /* This must be greater than 4kByte.                                     */
+  /*                                                                       */
+#define FT_RENDER_POOL_SIZE  16384
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FT_MAX_MODULES                                                        */
+  /*                                                                       */
+  /*   The maximum number of modules that can be registered in a single    */
+  /*   FreeType library object.  16 is the default.                        */
+  /*                                                                       */
+#define FT_MAX_MODULES  16
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FT_MAX_EXTENSIONS                                                     */
+  /*                                                                       */
+  /*   The maximum number of extensions that can be registered in a single */
+  /*   font driver.  8 is the default.                                     */
+  /*                                                                       */
+  /*   If you don't know what this means, you certainly do not need to     */
+  /*   change this value.                                                  */
+  /*                                                                       */
+#define FT_MAX_EXTENSIONS  8
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****        S F N T   D R I V E R    C O N F I G U R A T I O N       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support       */
+  /* embedded bitmaps in all formats using the SFNT module (namely         */
+  /* TrueType & OpenType).                                                 */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to    */
+  /* load and enumerate the glyph Postscript names in a TrueType or        */
+  /* OpenType file.                                                        */
+  /*                                                                       */
+  /* Note that when you do not compile the `PSNames' module by undefining  */
+  /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will   */
+  /* contain additional code used to read the PS Names table from a font.  */
+  /*                                                                       */
+  /* (By default, the module uses `PSNames' to extract glyph names.)       */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to       */
+  /* access the internal name table in a SFNT-based format like TrueType   */
+  /* or OpenType.  The name table contains various strings used to         */
+  /* describe the font, like family name, copyright, version, etc.  It     */
+  /* does not contain any glyph name though.                               */
+  /*                                                                       */
+  /* Accessing SFNT names is done through the functions declared in        */
+  /* `freetype/ftnames.h'.                                                 */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_SFNT_NAMES
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****    T R U E T Y P E   D R I V E R    C O N F I G U R A T I O N   ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile   */
+  /* a bytecode interpreter in the TrueType driver.  Note that there are   */
+  /* important patent issues related to the use of the interpreter.        */
+  /*                                                                       */
+  /* By undefining this, you will only compile the code necessary to load  */
+  /* TrueType glyphs without hinting.                                      */
+  /*                                                                       */
+#undef  TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType    */
+  /* bytecode interpreter with a huge switch statement, rather than a call */
+  /* table.  This results in smaller and faster code for a number of       */
+  /* architectures.                                                        */
+  /*                                                                       */
+  /* Note however that on some compiler/processor combinations, undefining */
+  /* this macro will generate faster, though larger, code.                 */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****      T Y P E 1   D R I V E R    C O N F I G U R A T I O N       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_STACK_DEPTH is the maximal depth of the token stack used by    */
+  /* the Type 1 parser (see t1load.c).  A minimum of 16 is required.       */
+  /*                                                                       */
+#define T1_MAX_STACK_DEPTH  16
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and       */
+  /* arrays in the Type 1 stream (see t1load.c).  A minimum of 4 is        */
+  /* required.                                                             */
+  /*                                                                       */
+#define T1_MAX_DICT_DEPTH  5
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine   */
+  /* calls during glyph loading.                                           */
+  /*                                                                       */
+#define T1_MAX_SUBRS_CALLS  8
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity.        */
+  /*                                                                       */
+#define T1_MAX_CHARSTRINGS_OPERANDS  32
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define T1_CONFIG_OPTION_DISABLE_HINTER if you want to generate a      */
+  /* driver with no hinter.  This can be useful to debug the parser.       */
+  /*                                                                       */
+#undef T1_CONFIG_OPTION_DISABLE_HINTER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define this configuration macro if you want to prevent the            */
+  /* compilation of `t1afm', which is in charge of reading Type 1 AFM      */
+  /* files into an existing face.  Note that if set, the T1 driver will be */
+  /* unable to produce kerning distances.                                  */
+  /*                                                                       */
+#undef T1_CONFIG_OPTION_NO_AFM
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define this configuration macro if you want to prevent the            */
+  /* compilation of the Multiple Masters font support in the Type 1        */
+  /* driver.                                                               */
+  /*                                                                       */
+#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+#endif /* FTOPTION_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/freetype.h b/src/freetype/freetype/freetype.h
new file mode 100644 (file)
index 0000000..29316c6
--- /dev/null
@@ -0,0 +1,2286 @@
+/***************************************************************************/
+/*                                                                         */
+/*  freetype.h                                                             */
+/*                                                                         */
+/*    FreeType high-level API and common types (specification only).       */
+/*                                                                         */
+/*  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 FREETYPE_H
+#define FREETYPE_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The `raster' component duplicates some of the declarations in         */
+  /* freetype.h for stand-alone use if _FREETYPE_ isn't defined.           */
+  /*                                                                       */
+#define _FREETYPE_
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The FREETYPE_MAJOR and FREETYPE_MINOR macros are used to version the  */
+  /* new FreeType design, which is able to host several kinds of font      */
+  /* drivers.  It starts at 2.0.                                           */
+  /*                                                                       */
+#define FREETYPE_MAJOR 2
+#define FREETYPE_MINOR 0
+
+
+#include <freetype/config/ftconfig.h>   /* read configuration information */
+#include <freetype/fterrors.h>
+#include <freetype/fttypes.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                        B A S I C   T Y P E S                          */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Glyph_Metrics                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model the metrics of a single glyph.  Note     */
+  /*    that values are expressed in 26.6 fractional pixel format or in    */
+  /*    font units, depending on context.                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    width        :: The glyph's width.                                 */
+  /*                                                                       */
+  /*    height       :: The glyph's height.                                */
+  /*                                                                       */
+  /*    horiBearingX :: Horizontal left side bearing.                      */
+  /*                                                                       */
+  /*    horiBearingY :: Horizontal top side bearing.                       */
+  /*                                                                       */
+  /*    horiAdvance  :: Horizontal advance width.                          */
+  /*                                                                       */
+  /*    vertBearingX :: Vertical left side bearing.                        */
+  /*                                                                       */
+  /*    vertBearingY :: Vertical top side bearing.                         */
+  /*                                                                       */
+  /*    vertAdvance  :: Vertical advance height.                           */
+  /*                                                                       */
+  typedef struct  FT_Glyph_Metrics_
+  {
+    FT_Pos  width;         /* glyph width  */
+    FT_Pos  height;        /* glyph height */
+
+    FT_Pos  horiBearingX;  /* left side bearing in horizontal layouts */
+    FT_Pos  horiBearingY;  /* top side bearing in horizontal layouts  */
+    FT_Pos  horiAdvance;   /* advance width for horizontal layout     */
+
+    FT_Pos  vertBearingX;  /* left side bearing in vertical layouts */
+    FT_Pos  vertBearingY;  /* top side bearing in vertical layouts  */
+    FT_Pos  vertAdvance;   /* advance height for vertical layout    */
+
+  } FT_Glyph_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Generic_Finalizer                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Describes a function used to destroy the `client' data of any      */
+  /*    FreeType object.  See the description of the FT_Generic type for   */
+  /*    details of usage.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    The address of the FreeType object which is under finalization.    */
+  /*    Its client data is accessed through its `generic' field.           */
+  /*                                                                       */
+  typedef void  (*FT_Generic_Finalizer)(void*  object);
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Generic                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Client applications often need to associate their own data to a    */
+  /*    variety of FreeType core objects.  For example, a text layout API  */
+  /*    might want to associate a glyph cache to a given size object.      */
+  /*                                                                       */
+  /*    Most FreeType object contains a `generic' field, of type           */
+  /*    FT_Generic, which usage is left to client applications and font    */
+  /*    servers.                                                           */
+  /*                                                                       */
+  /*    It can be used to store a pointer to client-specific data, as well */
+  /*    as the address of a `finalizer' function, which will be called by  */
+  /*    FreeType when the object is destroyed (for example, the previous   */
+  /*    client example would put the address of the glyph cache destructor */
+  /*    in the `finalizer' field).                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    data      :: A typeless pointer to any client-specified data. This */
+  /*                 field is completely ignored by the FreeType library.  */
+  /*                                                                       */
+  /*    finalizer :: A pointer to a `generic finalizer' function, which    */
+  /*                 will be called when the object is destroyed.  If this */
+  /*                 field is set to NULL, no code will be called.         */
+  /*                                                                       */
+  typedef struct  FT_Generic_
+  {
+    void*                 data;
+    FT_Generic_Finalizer  finalizer;
+
+  } FT_Generic;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Bitmap_Size                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An extremely simple structure used to model the size of a bitmap   */
+  /*    strike (i.e., a bitmap instance of the font for a given            */
+  /*    resolution) in a fixed-size font face.  This is used for the       */
+  /*    `available_sizes' field of the FT_Face_Properties structure.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    height :: The character height in pixels.                          */
+  /*                                                                       */
+  /*    width  :: The character width in pixels.                           */
+  /*                                                                       */
+  typedef struct  FT_Bitmap_Size_
+  {
+    FT_Short  height;
+    FT_Short  width;
+
+  } FT_Bitmap_Size;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     O B J E C T   C L A S S E S                       */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Library                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a FreeType library instance.  Each `library' is        */
+  /*    completely independent from the others; it is the `root' of a set  */
+  /*    of objects like fonts, faces, sizes, etc.                          */
+  /*                                                                       */
+  /*    It also embeds a system object (see FT_System), as well as a       */
+  /*    scan-line converter object (see FT_Raster).                        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Library objects are created through FT_Init_FreeType().            */
+  /*                                                                       */
+  typedef struct FT_LibraryRec_  *FT_Library;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Module                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given FreeType module object.  Each module can be a  */
+  /*    font driver, a renderer, or anything else that provides services   */
+  /*    to the formers.                                                    */
+  /*                                                                       */
+  typedef struct FT_ModuleRec_*  FT_Module;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given FreeType font driver object.  Each font driver */
+  /*    is able to create faces, sizes, glyph slots, and charmaps from the */
+  /*    resources whose format it supports.                                */
+  /*                                                                       */
+  /*    A driver can support either bitmap, graymap, or scalable font      */
+  /*    formats.                                                           */
+  /*                                                                       */
+  typedef struct FT_DriverRec_*  FT_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Renderer                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given FreeType renderer.  A renderer is in charge of */
+  /*    converting a glyph image to a bitmap, when necessary.  Each        */
+  /*    supports a given glyph image format, and one or more target        */
+  /*    surface depths.                                                    */
+  /*                                                                       */
+  typedef struct FT_RendererRec_*  FT_Renderer;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Face                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given driver face object.  A face object contains    */
+  /*    all the instance and glyph independent data of a font file         */
+  /*    typeface.                                                          */
+  /*                                                                       */
+  /*    A face object is created from a resource object through the        */
+  /*    new_face() method of a given driver.                               */
+  /*                                                                       */
+  typedef struct FT_FaceRec_*  FT_Face;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given driver size object.  Such an object models the */
+  /*    _resolution_ AND _size_ dependent state of a given driver face     */
+  /*    size.                                                              */
+  /*                                                                       */
+  /*    A size object is always created from a given face object.  It is   */
+  /*    discarded automatically by its parent face.                        */
+  /*                                                                       */
+  typedef struct FT_SizeRec_*  FT_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given `glyph slot'.  A slot is a container where it  */
+  /*    is possible to load any of the glyphs contained within its parent  */
+  /*    face.                                                              */
+  /*                                                                       */
+  /*    A glyph slot is created from a given face object.  It is discarded */
+  /*    automatically by its parent face.                                  */
+  /*                                                                       */
+  typedef struct FT_GlyphSlotRec_*  FT_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_CharMap                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given character map.  A charmap is used to translate */
+  /*    character codes in a given encoding into glyph indexes for its     */
+  /*    parent's face.  Some font formats may provide several charmaps per */
+  /*    font.                                                              */
+  /*                                                                       */
+  /*    A charmap is created from a given face object.  It is discarded    */
+  /*    automatically by its parent face.                                  */
+  /*                                                                       */
+  typedef struct FT_CharMapRec_*  FT_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Encoding                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration used to specify encodings supported by charmaps.    */
+  /*    Used in the FT_Select_CharMap() API function.                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */
+  /*    all character codes must be expressed as FT_Longs.                 */
+  /*                                                                       */
+  typedef enum  FT_Encoding_
+  {
+    ft_encoding_none    = 0,
+    ft_encoding_symbol  = FT_MAKE_TAG( 's', 'y', 'm', 'b' ),
+    ft_encoding_unicode = FT_MAKE_TAG( 'u', 'n', 'i', 'c' ),
+    ft_encoding_latin_2 = FT_MAKE_TAG( 'l', 'a', 't', '2' ),
+    ft_encoding_sjis    = FT_MAKE_TAG( 's', 'j', 'i', 's' ),
+    ft_encoding_gb2312  = FT_MAKE_TAG( 'g', 'b', ' ', ' ' ),
+    ft_encoding_big5    = FT_MAKE_TAG( 'b', 'i', 'g', '5' ),
+    ft_encoding_wansung = FT_MAKE_TAG( 'w', 'a', 'n', 's' ),
+    ft_encoding_johab   = FT_MAKE_TAG( 'j', 'o', 'h', 'a' ),
+
+    ft_encoding_adobe_standard = FT_MAKE_TAG( 'A', 'D', 'O', 'B' ),
+    ft_encoding_adobe_expert   = FT_MAKE_TAG( 'A', 'D', 'B', 'E' ),
+    ft_encoding_adobe_custom   = FT_MAKE_TAG( 'A', 'D', 'B', 'C' ),
+
+    ft_encoding_apple_roman    = FT_MAKE_TAG( 'a', 'r', 'm', 'n' )
+
+    /* other encodings might be defined in the future */
+
+  } FT_Encoding;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_CharMapRec                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The base charmap class.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    face        :: A handle to the parent face object.                 */
+  /*                                                                       */
+  /*    flags       :: A set of bit flags used to describe the charmap.    */
+  /*                   Each bit indicates that a given encoding is         */
+  /*                   supported.                                          */
+  /*                                                                       */
+  /*    platform_id :: An ID number describing the platform for the        */
+  /*                   following encoding ID.  This comes directly from    */
+  /*                   the TrueType specification and should be emulated   */
+  /*                   for other formats.                                  */
+  /*                                                                       */
+  /*    encoding_id :: A platform specific encoding number.  This also     */
+  /*                   comes from the TrueType specification and should be */
+  /*                   emulated similarly.                                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    We STRONGLY recommmend emulating a Unicode charmap for drivers     */
+  /*    that do not support TrueType or OpenType.                          */
+  /*                                                                       */
+  typedef struct  FT_CharMapRec_
+  {
+    FT_Face      face;
+    FT_Encoding  encoding;
+    FT_UShort    platform_id;
+    FT_UShort    encoding_id;
+
+  } FT_CharMapRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                 B A S E   O B J E C T   C L A S S E S                 */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       FreeType base face class                        */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_FaceRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType root face class structure.  A face object models the      */
+  /*    resolution and point-size independent data found in a font file.   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_faces           :: In the case where the face is located in a  */
+  /*                           collection (i.e., a resource which embeds   */
+  /*                           several faces), this is the total number of */
+  /*                           faces found in the resource.  1 by default. */
+  /*                                                                       */
+  /*    face_index          :: The index of the face in its resource.      */
+  /*                           Usually, this is 0 for all normal font      */
+  /*                           formats.  It can be more in the case of     */
+  /*                           collections (which embed several fonts in a */
+  /*                           single resource/file).                      */
+  /*                                                                       */
+  /*    face_flags          :: A set of bit flags that give important      */
+  /*                           information about the face; see the         */
+  /*                           FT_FACE_FLAG_XXX macros for details.        */
+  /*                                                                       */
+  /*    style_flags         :: A set of bit flags indicating the style of  */
+  /*                           the face (i.e., italic, bold, underline,    */
+  /*                           etc).                                       */
+  /*                                                                       */
+  /*    num_glyphs          :: The total number of glyphs in the face.     */
+  /*                                                                       */
+  /*    family_name         :: The face's family name.  This is an ASCII   */
+  /*                           string, usually in English, which describes */
+  /*                           the typeface's family (like `Times New      */
+  /*                           Roman', `Bodoni', `Garamond', etc).  This   */
+  /*                           is a least common denominator used to list  */
+  /*                           fonts.  Some formats (TrueType & OpenType)  */
+  /*                           provide localized and Unicode versions of   */
+  /*                           this string.  Applications should use the   */
+  /*                           format specific interface to access them.   */
+  /*                                                                       */
+  /*    style_name          :: The face's style name.  This is an ASCII    */
+  /*                           string, usually in English, which describes */
+  /*                           the typeface's style (like `Italic',        */
+  /*                           `Bold', `Condensed', etc).  Not all font    */
+  /*                           formats provide a style name, so this field */
+  /*                           is optional, and can be set to NULL.  As    */
+  /*                           for `family_name', some formats provide     */
+  /*                           localized/Unicode versions of this string.  */
+  /*                           Applications should use the format specific */
+  /*                           interface to access them.                   */
+  /*                                                                       */
+  /*    num_fixed_sizes     :: The number of fixed sizes available in this */
+  /*                           face.  This should be set to 0 for scalable */
+  /*                           fonts, unless its resource includes a       */
+  /*                           complete set of glyphs (called a `strike')  */
+  /*                           for the specified size.                     */
+  /*                                                                       */
+  /*    available_sizes     :: An array of sizes specifying the available  */
+  /*                           bitmap/graymap sizes that are contained in  */
+  /*                           in the font resource.  Should be set to     */
+  /*                           NULL if the field `num_fixed_sizes' is set  */
+  /*                           to 0.                                       */
+  /*                                                                       */
+  /*    num_charmaps        :: The total number of character maps in the   */
+  /*                           face.                                       */
+  /*                                                                       */
+  /*    charmaps            :: A table of pointers to the face's charmaps  */
+  /*                           Used to scan the list of available charmaps */
+  /*                           this table might change after a call to     */
+  /*                           FT_Attach_File/Stream (e.g. when it used    */
+  /*                           to hook and additional encoding/CMap to     */
+  /*                           the face object).                           */
+  /*                                                                       */
+  /*    generic             :: A field reserved for client uses.  See the  */
+  /*                           FT_Generic type description.                */
+  /*                                                                       */
+  /*    bbox                :: The font bounding box.  Coordinates are     */
+  /*                           expressed in font units (see units_per_EM). */
+  /*                           The box is large enough to contain any      */
+  /*                           glyph from the font.  Thus, bbox.yMax can   */
+  /*                           be seen as the `maximal ascender',          */
+  /*                           bbox.yMin as the `minimal descender', and   */
+  /*                           the maximal glyph width is given by         */
+  /*                           `bbox.xMax-bbox.xMin' (not to be confused   */
+  /*                           with the maximal _advance_width_).  Only    */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    units_per_EM        :: The number of font units per EM square for  */
+  /*                           this face.  This is typically 2048 for      */
+  /*                           TrueType fonts, 1000 for Type1 fonts, and   */
+  /*                           should be set to the (unrealistic) value 1  */
+  /*                           for fixed-sizes fonts.  Only relevant for   */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    ascender            :: The face's ascender is the vertical         */
+  /*                           distance from the baseline to the topmost   */
+  /*                           point of any glyph in the face.  This       */
+  /*                           field's value is positive, expressed in     */
+  /*                           font units.  Some font designs use a value  */
+  /*                           different from `bbox.yMax'.  Only relevant  */
+  /*                           for scalable formats.                       */
+  /*                                                                       */
+  /*    descender           :: The face's descender is the vertical        */
+  /*                           distance from the baseline to the           */
+  /*                           bottommost point of any glyph in the face.  */
+  /*                           This field's value is positive, expressed   */
+  /*                           in font units.  Some font designs use a     */
+  /*                           value different from `-bbox.yMin'.  Only    */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    height              :: The face's height is the vertical distance  */
+  /*                           from one baseline to the next when writing  */
+  /*                           several lines of text.  Its value is always */
+  /*                           positive, expressed in font units.  The     */
+  /*                           value can be computed as                    */
+  /*                           `ascender+descender+line_gap' where the     */
+  /*                           value of `line_gap' is also called          */
+  /*                           `external leading'.  Only relevant for      */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    max_advance_width   :: The maximal advance width, in font units,   */
+  /*                           for all glyphs in this face.  This can be   */
+  /*                           used to make word wrapping computations     */
+  /*                           faster.  Only relevant for scalable         */
+  /*                           formats.                                    */
+  /*                                                                       */
+  /*    max_advance_height  :: The maximal advance height, in font units,  */
+  /*                           for all glyphs in this face.  This is only  */
+  /*                           relevant for vertical layouts, and should   */
+  /*                           be set to the `height' for fonts that do    */
+  /*                           not provide vertical metrics.  Only         */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    underline_position  :: The position, in font units, of the         */
+  /*                           underline line for this face.  It's the     */
+  /*                           center of the underlining stem.  Only       */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    underline_thickness :: The thickness, in font units, of the        */
+  /*                           underline for this face.  Only relevant for */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    driver              :: A handle to the face's parent driver        */
+  /*                           object.                                     */
+  /*                                                                       */
+  /*    memory              :: A handle to the face's parent memory        */
+  /*                           object.  Used for the allocation of         */
+  /*                           subsequent objects.                         */
+  /*                                                                       */
+  /*    stream              :: A handle to the face's stream.              */
+  /*                                                                       */
+  /*    glyph               :: The face's associated glyph slot(s).  This  */
+  /*                           object is created automatically with a new  */
+  /*                           face object.  However, certain kinds of     */
+  /*                           applications (mainly tools like converters) */
+  /*                           can need more than one slot to ease their   */
+  /*                           task.                                       */
+  /*                                                                       */
+  /*    sizes_list          :: The list of child sizes for this face.      */
+  /*                                                                       */
+  /*    max_points          :: The maximal number of points used to store  */
+  /*                           the vectorial outline of any glyph in this  */
+  /*                           face.  If this value cannot be known in     */
+  /*                           advance, or if the face isn't scalable,     */
+  /*                           this should be set to 0.  Only relevant for */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    max_contours        :: The maximal number of contours used to      */
+  /*                           store the vectorial outline of any glyph in */
+  /*                           this face.  If this value cannot be known   */
+  /*                           in advance, or if the face isn't scalable,  */
+  /*                           this should be set to 0.  Only relevant for */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    transform_matrix    :: A 2x2 matrix of 16.16 coefficients used     */
+  /*                           to transform glyph outlines after they are  */
+  /*                           loaded from the font.  Only used by the     */
+  /*                           convenience functions.                      */
+  /*                                                                       */
+  /*    transform_delta     :: A translation vector used to transform      */
+  /*                           glyph outlines after they are loaded from   */
+  /*                           the font.  Only used by the convenience     */
+  /*                           functions.                                  */
+  /*                                                                       */
+  /*    transform_flags     :: Some flags used to classify the transform.  */
+  /*                           Only used by the convenience functions.     */
+  /*                                                                       */
+  typedef struct  FT_FaceRec_
+  {
+    FT_Long          num_faces;
+    FT_Long          face_index;
+
+    FT_Long          face_flags;
+    FT_Long          style_flags;
+
+    FT_Long          num_glyphs;
+
+    FT_String*       family_name;
+    FT_String*       style_name;
+
+    FT_Int           num_fixed_sizes;
+    FT_Bitmap_Size*  available_sizes;
+
+    /* the face's table of available charmaps */
+    FT_Int           num_charmaps;
+    FT_CharMap*      charmaps;
+
+    FT_Generic       generic;
+
+    /* the following are only relevant for scalable outlines */
+    FT_BBox          bbox;
+
+    FT_UShort        units_per_EM;
+    FT_Short         ascender;
+    FT_Short         descender;
+    FT_Short         height;
+
+    FT_Short         max_advance_width;
+    FT_Short         max_advance_height;
+
+    FT_Short         underline_position;
+    FT_Short         underline_thickness;
+
+    FT_GlyphSlot     glyph;
+    FT_Size          size;
+
+    /************************************************************/
+    /* The following fields should be considered private and    */
+    /* rarely, if ever, used directly by client applications.   */
+
+    FT_Driver        driver;
+    FT_Memory        memory;
+    FT_Stream        stream;
+
+    FT_CharMap       charmap;
+    FT_ListRec       sizes_list;
+
+    FT_Generic       autohint;
+    void*            extensions;
+
+    FT_UShort        max_points;
+    FT_Short         max_contours;
+
+    FT_Matrix        transform_matrix;
+    FT_Vector        transform_delta;
+    FT_Int           transform_flags;
+
+  } FT_FaceRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_SCALABLE                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face provides  */
+  /*    vectorial outlines (i.e., TrueType or Type1).  This doesn't        */
+  /*    prevent embedding of bitmap strikes though, i.e., a given face can */
+  /*    have both this bit set, and a `num_fixed_sizes' property > 0.      */
+  /*                                                                       */
+#define FT_FACE_FLAG_SCALABLE  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_FIXED_SIZES                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    `fixed sizes', i.e., bitmap strikes for some given pixel sizes.    */
+  /*    See the `num_fixed_sizes' and `available_sizes' face properties    */
+  /*    for more information.                                              */
+  /*                                                                       */
+#define FT_FACE_FLAG_FIXED_SIZES  2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_FIXED_WIDTH                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    fixed-width characters (like Courier, Lucida, MonoType, etc.).     */
+  /*                                                                       */
+#define FT_FACE_FLAG_FIXED_WIDTH  4
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_SFNT                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face uses the  */
+  /*    `sfnt' storage fomat.  For now, this means TrueType or OpenType.   */
+  /*                                                                       */
+#define FT_FACE_FLAG_SFNT  8
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_HORIZONTAL                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    horizontal glyph metrics.  This should be set for all common       */
+  /*    formats, but who knows.                                            */
+  /*                                                                       */
+#define FT_FACE_FLAG_HORIZONTAL  0x10
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_VERTICAL                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    vertical glyph metrics.  If not set, the glyph loader will         */
+  /*    synthetize vertical metrics itself to help display vertical text   */
+  /*    correctly.                                                         */
+  /*                                                                       */
+#define FT_FACE_FLAG_VERTICAL  0x20
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_KERNING                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    kerning information.  When set, this information can be retrieved  */
+  /*    through the function FT_Get_Kerning().  Note that when unset, this */
+  /*    function will always return the kerning vector (0,0).              */
+  /*                                                                       */
+#define FT_FACE_FLAG_KERNING  0x40
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_FAST_GLYPHS                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that the glyphs in a given  */
+  /*    font can be retrieved very quickly, and that a glyph cache is thus */
+  /*    not necessary for any of its child size objects.                   */
+  /*                                                                       */
+  /*    This flag should really be set for fixed-size formats like FNT,    */
+  /*    where each glyph bitmap is available directly in binary form       */
+  /*    without any kind of compression.                                   */
+  /*                                                                       */
+#define FT_FACE_FLAG_FAST_GLYPHS  0x80
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_MULTIPLE_MASTERS                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that the font contains      */
+  /*    multiple masters and is capable of interpolating between them.     */
+  /*                                                                       */
+#define FT_FACE_FLAG_MULTIPLE_MASTERS  0x100
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_GLYPH_NAMES                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that the font contains      */
+  /*    glyph names that can be retrieved through FT_Get_Glyph_Name().     */
+  /*                                                                       */
+#define FT_FACE_FLAG_GLYPH_NAMES       0x200
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_EXTERNAL_STREAM                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This bit field is used internally by FreeType to indicate that     */
+  /*    a face's stream was provided by the client application and should  */
+  /*    not be destroyed by FT_Done_Face().                                */
+  /*                                                                       */
+#define FT_FACE_FLAG_EXTERNAL_STREAM   0x4000
+
+
+#define FT_HAS_HORIZONTAL( face ) \
+          ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )
+#define FT_HAS_VERTICAL( face ) \
+          ( face->face_flags & FT_FACE_FLAG_VERTICAL )
+#define FT_HAS_KERNING( face ) \
+          ( face->face_flags & FT_FACE_FLAG_KERNING )
+#define FT_IS_SCALABLE( face ) \
+          ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+#define FT_IS_SFNT( face ) \
+          ( face->face_flags & FT_FACE_FLAG_SFNT )
+#define FT_IS_FIXED_WIDTH( face ) \
+          ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
+#define FT_HAS_FIXED_SIZES( face ) \
+          ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+#define FT_HAS_FAST_GLYPHS( face ) \
+          ( face->face_flags & FT_FACE_FLAG_FAST_GLYPHS )
+#define FT_HAS_GLYPH_NAMES( face ) \
+          ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
+
+#define FT_HAS_MULTIPLE_MASTERS( face ) \
+          ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_STYLE_FLAG_ITALIC                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face is        */
+  /*    italicized.                                                        */
+  /*                                                                       */
+#define FT_STYLE_FLAG_ITALIC  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_STYLE_FLAG_BOLD                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face is        */
+  /*    emboldened.                                                        */
+  /*                                                                       */
+#define FT_STYLE_FLAG_BOLD  2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                    FreeType base size metrics                         */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Size_Metrics                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The size metrics structure returned scaled important distances for */
+  /*    a given size object.                                               */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x_ppem       :: The character width, expressed in integer pixels.  */
+  /*                    This is the width of the EM square expressed in    */
+  /*                    pixels, hence the term `ppem' (pixels per EM).     */
+  /*                                                                       */
+  /*    y_ppem       :: The character height, expressed in integer pixels. */
+  /*                    This is the height of the EM square expressed in   */
+  /*                    pixels, hence the term `ppem' (pixels per EM).     */
+  /*                                                                       */
+  /*    x_scale      :: A simple 16.16 fixed point format coefficient used */
+  /*                    to scale horizontal distances expressed in font    */
+  /*                    units to fractional (26.6) pixel coordinates.      */
+  /*                                                                       */
+  /*    y_scale      :: A simple 16.16 fixed point format coefficient used */
+  /*                    to scale vertical distances expressed in font      */
+  /*                    units to fractional (26.6) pixel coordinates.      */
+  /*                                                                       */
+  /*    x_resolution :: The horizontal device resolution for this size     */
+  /*                    object, expressed in integer dots per inches       */
+  /*                    (dpi).  As a convention, fixed font formats set    */
+  /*                    this value to 72.                                  */
+  /*                                                                       */
+  /*    y_resolution :: The vertical device resolution for this size       */
+  /*                    object, expressed in integer dots per inches       */
+  /*                    (dpi).  As a convention, fixed font formats set    */
+  /*                    this value to 72.                                  */
+  /*                                                                       */
+  /*    ascender     :: The ascender, expressed in 26.6 fixed point        */
+  /*                    pixels.  Always positive.                          */
+  /*                                                                       */
+  /*    descender    :: The descender, expressed in 26.6 fixed point       */
+  /*                    pixels.  Always positive.                          */
+  /*                                                                       */
+  /*    height       :: The text height, expressed in 26.6 fixed point     */
+  /*                    pixels.  Always positive.                          */
+  /*                                                                       */
+  /*    max_advance  :: Maximum horizontal advance, expressed in 26.6      */
+  /*                    fixed point pixels.  Always positive.              */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The values of `ascender', `descender', and `height' are only the   */
+  /*    scaled versions of `face->ascender', `face->descender', and        */
+  /*    `face->height'.                                                    */
+  /*                                                                       */
+  /*    Unfortunately, due to glyph hinting, these values might not be     */
+  /*    exact for certain fonts, they thus must be treated as unreliable   */
+  /*    with an error margin of at least one pixel!                        */
+  /*                                                                       */
+  /*    Indeed, the only way to get the exact pixel ascender and descender */
+  /*    is to render _all_ glyphs.  As this would be a definite            */
+  /*    performance hit, it is up to client applications to perform such   */
+  /*    computations.                                                      */
+  /*                                                                       */
+  typedef struct  FT_Size_Metrics_
+  {
+    FT_UShort   x_ppem;        /* horizontal pixels per EM               */
+    FT_UShort   y_ppem;        /* vertical pixels per EM                 */
+
+    FT_Fixed    x_scale;       /* two scales used to convert font units  */
+    FT_Fixed    y_scale;       /* to 26.6 frac. pixel coordinates..      */
+
+    FT_Pos      ascender;      /* ascender in 26.6 frac. pixels          */
+    FT_Pos      descender;     /* descender in 26.6 frac. pixels         */
+    FT_Pos      height;        /* text height in 26.6 frac. pixels       */
+    FT_Pos      max_advance;   /* max horizontal advance, in 26.6 pixels */
+
+  } FT_Size_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       FreeType base size class                        */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_SizeRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType root size class structure.  A size object models the      */
+  /*    resolution and pointsize dependent data of a given face.           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    face    :: Handle to the parent face object.                       */
+  /*                                                                       */
+  /*    generic :: A typeless pointer, which is unused by the FreeType     */
+  /*               library or any of its drivers.  It can be used by       */
+  /*               client applications to link their own data to each size */
+  /*               object.                                                 */
+  /*                                                                       */
+  /*    metrics :: Metrics for this size object.  This field is read-only. */
+  /*                                                                       */
+  typedef struct  FT_SizeRec_
+  {
+    FT_Face          face;      /* parent face object              */
+    FT_Generic       generic;   /* generic pointer for client uses */
+    FT_Size_Metrics  metrics;   /* size metrics                    */
+
+  } FT_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_SubGlyph                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The subglyph structure is an internal object used to describe      */
+  /*    subglyphs (for example, in the case of composites).                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The subglyph implementation is not part of the high-level API,     */
+  /*    hence the forward structure declaration.                           */
+  /*                                                                       */
+  typedef struct FT_SubGlyph_  FT_SubGlyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_GlyphLoader                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The glyph loader is an internal object used to load several glyphs */
+  /*    together (for example, in the case of composites).                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The glyph loader implementation is not part of the high-level API, */
+  /*    hence the forward structure declaration.                           */
+  /*                                                                       */
+  typedef struct FT_GlyphLoader_  FT_GlyphLoader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  FreeType Glyph Slot base class                       */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_GlyphSlotRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType root glyph slot class structure.  A glyph slot is a       */
+  /*    container where individual glyphs can be loaded, be they           */
+  /*    vectorial or bitmap/graymaps.                                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    library           :: A handle to the FreeType library instance     */
+  /*                         this slot belongs to.                         */
+  /*                                                                       */
+  /*    face              :: A handle to the parent face object.           */
+  /*                                                                       */
+  /*    next              :: In some cases (like some font tools), several */
+  /*                         glyph slots per face object can be a good     */
+  /*                         thing.  As this is rare, the glyph slots are  */
+  /*                         listed through a direct, single-linked list   */
+  /*                         using its `next' field.                       */
+  /*                                                                       */
+  /*    generic           :: A typeless pointer which is unused by the     */
+  /*                         FreeType library or any of its drivers.  It   */
+  /*                         can be used by client applications to link    */
+  /*                         their own data to each size object.           */
+  /*                                                                       */
+  /*    metrics           :: The metrics of the last loaded glyph in the   */
+  /*                         slot.  The returned values depend on the last */
+  /*                         load flags (see the FT_Load_Glyph() API       */
+  /*                         function) and can be expressed either in 26.6 */
+  /*                         fractional pixels or font units.              */
+  /*                                                                       */
+  /*                         Note that even when the glyph image is        */
+  /*                         transformed, the metrics are not.             */
+  /*                                                                       */
+  /*    linearHoriAdvance :: For scalable formats only, this field holds   */
+  /*                         the linearly scaled horizontal advance width  */
+  /*                         for the glyph (i.e. the scaled and unhinted   */
+  /*                         value of the hori advance). This can be       */
+  /*                         important to perform correct WYSIWYG layout   */
+  /*                                                                       */
+  /*                         Note that this value is expressed by default  */
+  /*                         in 16.16 pixels. However, when the glyph is   */
+  /*                         loaded with the FT_LOAD_UNSCALED_LINEAR flag, */
+  /*                         this field contains simply the value of the   */
+  /*                         advance in original font units.               */
+  /*                                                                       */
+  /*    linearVertAdvance :: For scalable formats only, this field holds   */
+  /*                         the linearly scaled vertical advance height   */
+  /*                         for the glyph.  See linearHoriAdvance for     */
+  /*                         comments.                                     */
+  /*                                                                       */
+  /*    advance           :: This is the transformed advance width for the */
+  /*                         glyph.                                        */
+  /*                                                                       */
+  /*    format            :: This field indicates the format of the image  */
+  /*                         contained in the glyph slot.  Typically       */
+  /*                         ft_glyph_format_bitmap,                       */
+  /*                         ft_glyph_format_outline, and                  */
+  /*                         ft_glyph_format_composite, but others are     */
+  /*                         possible.                                     */
+  /*                                                                       */
+  /*    bitmap            :: This field is used as a bitmap descriptor     */
+  /*                         when the slot format is                       */
+  /*                         ft_glyph_format_bitmap.  Note that the        */
+  /*                         address and content of the bitmap buffer can  */
+  /*                         change between calls of FT_Load_Glyph() and a */
+  /*                         few other functions.                          */
+  /*                                                                       */
+  /*    bitmap_left       :: This is the bitmap's left bearing expressed   */
+  /*                         in integer pixels.  Of course, this is only   */
+  /*                         valid if the format is                        */
+  /*                         ft_glyph_format_bitmap.                       */
+  /*                                                                       */
+  /*    bitmap_top        :: This is the bitmap's top bearing expressed in */
+  /*                         integer pixels.  Remember that this is the    */
+  /*                         distance from the baseline to the top-most    */
+  /*                         glyph scanline, upwards y-coordinates being   */
+  /*                         *positive*.                                   */
+  /*                                                                       */
+  /*    outline           :: The outline descriptor for the current glyph  */
+  /*                         image if its format is                        */
+  /*                         ft_glyph_bitmap_outline.                      */
+  /*                                                                       */
+  /*    num_subglyphs     :: The number of subglyphs in a composite glyph. */
+  /*                         This format is only valid for the composite   */
+  /*                         glyph format, that should normally only be    */
+  /*                         loaded with the FT_LOAD_NO_RECURSE flag.      */
+  /*                                                                       */
+  /*    subglyphs         :: An array of subglyph descriptors for          */
+  /*                         composite glyphs.  There are `num_subglyphs'  */
+  /*                         elements in there.                            */
+  /*                                                                       */
+  /*    control_data      :: Certain font drivers can also return the      */
+  /*                         control data for a given glyph image (e.g.    */
+  /*                         TrueType bytecode, Type 1 charstrings, etc.). */
+  /*                         This field is a pointer to such data.         */
+  /*                                                                       */
+  /*    control_len       :: This is the length in bytes of the control    */
+  /*                         data.                                         */
+  /*                                                                       */
+  /*    other             :: Really wicked formats can use this pointer to */
+  /*                         present their own glyph image to client apps. */
+  /*                         Note that the app will need to know about the */
+  /*                         image format.                                 */
+  /*                                                                       */
+  /*    loader            :: This is a private object for the glyph slot.  */
+  /*                         Do not touch this.                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If FT_Load_Glyph() is called with default flags (FT_LOAD_DEFAULT), */
+  /*    the glyph image is loaded in the glyph slot in its native format   */
+  /*    (e.g. a vectorial outline for TrueType and Type 1 formats).        */
+  /*                                                                       */
+  /*    This image can later be converted into a bitmap by calling         */
+  /*    FT_Render_Glyph().  This function finds the current renderer for   */
+  /*    the native image's format then invokes it.                         */
+  /*                                                                       */
+  /*    The renderer is in charge of transforming the native image through */
+  /*    the slot's face transformation fields, then convert it into a      */
+  /*    bitmap that is returned in `slot->bitmap'.                         */
+  /*                                                                       */
+  /*    Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */
+  /*    to specify the position of the bitmap relative to the current pen  */
+  /*    position (e.g. coordinates [0,0] on the baseline).  Of course,     */
+  /*    `slot->format' is also changed to `ft_glyph_format_bitmap' .       */
+  /*                                                                       */
+  typedef struct  FT_GlyphSlotRec_
+  {
+    FT_Library        library;
+    FT_Face           face;
+    FT_GlyphSlot      next;
+    FT_UInt           flags;
+    FT_Generic        generic;
+
+    FT_Glyph_Metrics  metrics;
+    FT_Fixed          linearHoriAdvance;
+    FT_Fixed          linearVertAdvance;
+    FT_Vector         advance;
+
+    FT_Glyph_Format   format;
+
+    FT_Bitmap         bitmap;
+    FT_Int            bitmap_left;
+    FT_Int            bitmap_top;
+
+    FT_Outline        outline;
+
+    FT_UInt           num_subglyphs;
+    FT_SubGlyph*      subglyphs;
+
+    void*             control_data;
+    long              control_len;
+
+    void*             other;
+
+    /* private fields */
+    FT_GlyphLoader*   loader;
+
+  } FT_GlyphSlotRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                         F U N C T I O N S                             */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Init_FreeType                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a new FreeType library object.  The set of drivers     */
+  /*    that are registered by this function is determined at build time.  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    library :: A handle to a new library object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Init_FreeType( FT_Library*  library );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_FreeType                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given FreeType library object and all of its childs,    */
+  /*    including resources, drivers, faces, sizes, etc.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the target library object.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Done_FreeType( FT_Library  library );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Open_Flags                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration used to list the bit flags used within              */
+  /*    FT_Open_Args().                                                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_open_memory   :: This is a memory-based stream.                 */
+  /*                                                                       */
+  /*    ft_open_stream   :: Copy the stream from the `stream' field.       */
+  /*                                                                       */
+  /*    ft_open_pathname :: Create a new input stream from a C pathname.   */
+  /*                                                                       */
+  /*    ft_open_driver   :: Use the `driver' field.                        */
+  /*                                                                       */
+  /*    ft_open_params   :: Use the `num_params' & `params' field.         */
+  /*                                                                       */
+  typedef enum
+  {
+    ft_open_memory   = 1,
+    ft_open_stream   = 2,
+    ft_open_pathname = 4,
+    ft_open_driver   = 8,
+    ft_open_params   = 16
+
+  } FT_Open_Flags;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Parameter                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to pass more or less generic parameters    */
+  /*    to FT_Open_Face().                                                 */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    tag  :: A 4-byte identification tag.                               */
+  /*                                                                       */
+  /*    data :: A pointer to the parameter data.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The id and function of parameters are driver-specific.             */
+  /*                                                                       */
+  typedef struct  FT_Parameter_
+  {
+    FT_ULong    tag;
+    FT_Pointer  data;
+
+  } FT_Parameter;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Open_Args                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to indicate how to open a new font file/stream.   */
+  /*    A pointer to such a structure can be used as a parameter for the   */
+  /*    functions FT_Open_Face() & FT_Attach_Stream().                     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags       :: A set of bit flags indicating how to use the        */
+  /*                   structure.                                          */
+  /*                                                                       */
+  /*    memory_base :: The first byte of the file in memory.               */
+  /*                                                                       */
+  /*    memory_size :: The size in bytes of the file in memory.            */
+  /*                                                                       */
+  /*    pathname    :: A pointer to an 8-bit file pathname.                */
+  /*                                                                       */
+  /*    stream      :: A handle to a source stream object.                 */
+  /*                                                                       */
+  /*    driver      :: This field is exclusively used by FT_Open_Face();   */
+  /*                   it simply specifies the font driver to use to open  */
+  /*                   the face.  If set to 0, FreeType will try to load   */
+  /*                   the face with each one of the drivers in its list.  */
+  /*                                                                       */
+  /*    num_params  :: The number of extra parameters.                     */
+  /*                                                                       */
+  /*    params      :: Extra parameters passed to the font driver when     */
+  /*                   opening a new face.                                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    `stream_type' determines which fields are used to create a new     */
+  /*    input stream.                                                      */
+  /*                                                                       */
+  /*    If it is `ft_stream_memory', a new memory-based stream will be     */
+  /*    created using the memory block specified by `memory_base' and      */
+  /*    `memory_size'.                                                     */
+  /*                                                                       */
+  /*    If it is `ft_stream_pathname', a new stream will be created with   */
+  /*    the `pathname' field, calling the system-specific FT_New_Stream()  */
+  /*    function.                                                          */
+  /*                                                                       */
+  /*    If is is `ft_stream_copy', then the content of `stream' will be    */
+  /*    copied to a new input stream object.  The object will be closed    */
+  /*    and destroyed when the face is destroyed itself.  Note that this   */
+  /*    means that you should not close the stream before the library      */
+  /*    does!                                                              */
+  /*                                                                       */
+  typedef struct  FT_Open_Args_
+  {
+    FT_Open_Flags  flags;
+    FT_Byte*       memory_base;
+    FT_Long        memory_size;
+    FT_String*     pathname;
+    FT_Stream      stream;
+    FT_Module      driver;
+    FT_Int         num_params;
+    FT_Parameter*  params;
+
+  } FT_Open_Args;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Face                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new face object from a given resource and typeface index */
+  /*    using a pathname to the font file.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pathname   :: A path to the font file.                             */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    Note that additional slots can be added to each face with the      */
+  /*    FT_New_GlyphSlot() API function.  Slots are linked in a single     */
+  /*    list through their `next' field.                                   */
+  /*                                                                       */
+  /*    FT_New_Face() can be used to determine and/or check the font       */
+  /*    format of a given font resource.  If the `face_index' field is     */
+  /*    negative, the function will _not_ return any face handle in        */
+  /*    `*face'.  Its return value should be 0 if the resource is          */
+  /*    recognized, or non-zero if not.                                    */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_New_Face( FT_Library   library,
+                                          const char*  filepathname,
+                                          FT_Long      face_index,
+                                          FT_Face*     face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Memory_Face                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new face object from a given resource and typeface index */
+  /*    using a font file already loaded into memory.                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    file_base  :: A pointer to the beginning of the font data.         */
+  /*                                                                       */
+  /*    file_size  :: The size of the memory chunk used by the font data.  */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    face       :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    Note that additional slots can be added to each face with the      */
+  /*    FT_New_GlyphSlot() API function.  Slots are linked in a single     */
+  /*    list through their `next' field.                                   */
+  /*                                                                       */
+  /*    FT_New_Memory_Face() can be used to determine and/or check the     */
+  /*    font format of a given font resource.  If the `face_index' field   */
+  /*    is negative, the function will _not_ return any face handle in     */
+  /*    `*face'.  Its return value should be 0 if the resource is          */
+  /*    recognized, or non-zero if not.                                    */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_New_Memory_Face( FT_Library  library,
+                                                 FT_Byte*    file_base,
+                                                 FT_Long     file_size,
+                                                 FT_Long     face_index,
+                                                 FT_Face*    face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Open_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Opens a face object from a given resource and typeface index using */
+  /*    an `FT_Open_Args' structure.  If the face object doesn't exist, it */
+  /*    will be created.                                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    args       :: A pointer to an `FT_Open_Args' structure which must  */
+  /*                  be filled by the caller.                             */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    Note that additional slots can be added to each face with the      */
+  /*    FT_New_GlyphSlot() API function.  Slots are linked in a single     */
+  /*    list through their `next' field.                                   */
+  /*                                                                       */
+  /*    FT_Open_Face() can be used to determine and/or check the font      */
+  /*    format of a given font resource.  If the `face_index' field is     */
+  /*    negative, the function will _not_ return any face handle in        */
+  /*    `*face'.  Its return value should be 0 if the resource is          */
+  /*    recognized, or non-zero if not.                                    */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Open_Face( FT_Library     library,
+                                           FT_Open_Args*  args,
+                                           FT_Long        face_index,
+                                           FT_Face*       face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Attach_File                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    `Attaches' a given font file to an existing face.  This is usually */
+  /*    to read additional information for a single face object.  For      */
+  /*    example, it is used to read the AFM files that come with Type 1    */
+  /*    fonts in order to add kerning data and other metrics.              */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face         :: The target face object.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    filepathname :: An 8-bit pathname naming the `metrics' file.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If your font file is in memory, or if you want to provide your     */
+  /*    own input stream object, use FT_Attach_Stream().                   */
+  /*                                                                       */
+  /*    The meaning of the `attach' action (i.e., what really happens when */
+  /*    the new file is read) is not fixed by FreeType itself.  It really  */
+  /*    depends on the font format (and thus the font driver).             */
+  /*                                                                       */
+  /*    Client applications are expected to know what they are doing       */
+  /*    when invoking this function.  Most drivers simply do not implement */
+  /*    file attachments.                                                  */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Attach_File( FT_Face      face,
+                                             const char*  filepathname );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Attach_Stream                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is similar to FT_Attach_File() with the exception    */
+  /*    that it reads the attachment from an arbitrary stream.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: The target face object.                              */
+  /*                                                                       */
+  /*    parameters :: A pointer to an FT_Open_Args structure used to       */
+  /*                  describe the input stream to FreeType.               */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The meaning of the `attach' (i.e. what really happens when the     */
+  /*    new file is read) is not fixed by FreeType itself.  It really      */
+  /*    depends on the font format (and thus the font driver).             */
+  /*                                                                       */
+  /*    Client applications are expected to know what they are doing       */
+  /*    when invoking this function.  Most drivers simply do not implement */
+  /*    file attachments.                                                  */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Attach_Stream( FT_Face        face,
+                                               FT_Open_Args*  parameters );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given face object, as well as all of its child slots    */
+  /*    and sizes.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to a target face object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Done_Face( FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Char_Size                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the character dimensions of a given face object.  The         */
+  /*    `char_width' and `char_height' values are used for the width and   */
+  /*    height, respectively, expressed in 26.6 fractional points.         */
+  /*                                                                       */
+  /*    If the horizontal or vertical resolution values are zero, a        */
+  /*    default value of 72dpi is used.  Similarly, if one of the          */
+  /*    character dimensions is zero, its value is set equal to the other. */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size            :: A handle to a target size object.               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_width      :: The character width, in 26.6 fractional points. */
+  /*                                                                       */
+  /*    char_height     :: The character height, in 26.6 fractional        */
+  /*                       points.                                         */
+  /*                                                                       */
+  /*    horz_resolution :: The horizontal resolution.                      */
+  /*                                                                       */
+  /*    vert_resolution :: The vertical resolution.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    When dealing with fixed-size faces (i.e., non-scalable formats),   */
+  /*    use the function FT_Set_Pixel_Sizes().                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Set_Char_Size( FT_Face     face,
+                                               FT_F26Dot6  char_width,
+                                               FT_F26Dot6  char_height,
+                                               FT_UInt     horz_resolution,
+                                               FT_UInt     vert_resolution );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Pixel_Sizes                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the character dimensions of a given face object.  The width   */
+  /*    and height are expressed in integer pixels.                        */
+  /*                                                                       */
+  /*    If one of the character dimensions is zero, its value is set equal */
+  /*    to the other.                                                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face         :: A handle to the target face object.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pixel_width  :: The character width, in integer pixels.            */
+  /*                                                                       */
+  /*    pixel_height :: The character height, in integer pixels.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Set_Pixel_Sizes( FT_Face  face,
+                                                 FT_UInt  pixel_width,
+                                                 FT_UInt  pixel_height );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Load_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the target face object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the glyph image is not a bitmap, and if the bit flag            */
+  /*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         */
+  /*    transformed with the information passed to a previous call to      */
+  /*    FT_Set_Transform.                                                  */
+  /*                                                                       */
+  /*    Note that this also transforms the `face.glyph.advance' field, but */
+  /*    *not* the values in `face.glyph.metrics'.                          */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Load_Glyph( FT_Face  face,
+                                            FT_UInt  glyph_index,
+                                            FT_Int   load_flags );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Load_Char                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size, according to its character code.                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a target face object where the glyph    */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    char_code   :: The glyph's character code, according to the        */
+  /*                   current charmap used in the face.                   */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the face has no current charmap, or if the character code       */
+  /*    is not defined in the charmap, this function will return an        */
+  /*    error.                                                             */
+  /*                                                                       */
+  /*    If the glyph image is not a bitmap, and if the bit flag            */
+  /*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         */
+  /*    transformed with the information passed to a previous call to      */
+  /*    FT_Set_Transform().                                                */
+  /*                                                                       */
+  /*    Note that this also transforms the `face.glyph.advance' field, but */
+  /*    *not* the values in `face.glyph.metrics'.                          */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Load_Char( FT_Face   face,
+                                           FT_ULong  char_code,
+                                           FT_Int    load_flags );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_SCALE                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the vector outline being loaded should not be scaled to 26.6       */
+  /*    fractional pixels, but kept in notional units.                     */
+  /*                                                                       */
+#define FT_LOAD_NO_SCALE  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_HINTING                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the vector outline being loaded should not be fitted to the pixel  */
+  /*    grid but simply scaled to 26.6 fractional pixels.                  */
+  /*                                                                       */
+  /*    This flag is ignored if FT_LOAD_NO_SCALE is set.                   */
+  /*                                                                       */
+#define FT_LOAD_NO_HINTING  2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_RENDER                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should load the glyph and immediately convert it into */
+  /*    a bitmap, if necessary, by calling FT_Render_Glyph().              */
+  /*                                                                       */
+  /*    Note that by default, FT_Load_Glyph() loads the glyph image in its */
+  /*    native format.                                                     */
+  /*                                                                       */
+#define FT_LOAD_RENDER  4
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_BITMAP                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should not load the bitmap or pixmap of a given       */
+  /*    glyph.  This is useful when you do not want to load the embedded   */
+  /*    bitmaps of scalable formats, as the native glyph image will be     */
+  /*    loaded, and can then be rendered through FT_Render_Glyph().        */
+  /*                                                                       */
+#define FT_LOAD_NO_BITMAP  8
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_VERTICAL_LAYOUT                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph image should be prepared for vertical layout.  This      */
+  /*    basically means that `face.glyph.advance' will correspond to the   */
+  /*    vertical advance height (instead of the default horizontal         */
+  /*    advance width), and that the glyph image will translated to match  */
+  /*    the vertical bearings positions.                                   */
+  /*                                                                       */
+#define FT_LOAD_VERTICAL_LAYOUT  16
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_FORCE_AUTOHINT                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should try to auto-hint the glyphs, even if a driver  */
+  /*    specific hinter is available.                                      */
+  /*                                                                       */
+#define FT_LOAD_FORCE_AUTOHINT  32
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_CROP_BITMAP                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the font driver should try to crop the bitmap (i.e. remove all     */
+  /*    space around its black bits) when loading it.  For now, this       */
+  /*    really only works with embedded bitmaps in TrueType fonts.         */
+  /*                                                                       */
+#define FT_LOAD_CROP_BITMAP  64
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_PEDANTIC                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should perform a pedantic bytecode                */
+  /*    interpretation.  Many popular fonts come with broken glyph         */
+  /*    programs.  When this flag is set, loading them will return an      */
+  /*    error.  Otherwise, errors are ignored by the loader, sometimes     */
+  /*    resulting in ugly glyphs.                                          */
+  /*                                                                       */
+#define FT_LOAD_PEDANTIC  128
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should ignore the global advance width defined    */
+  /*    in the font.  As far as we know, this is only used by the          */
+  /*    X-TrueType font server, in order to deal correctly with the        */
+  /*    incorrect metrics contained in DynaLab's TrueType CJK fonts.       */
+  /*                                                                       */
+#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH  512
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_RECURSE                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should not load composite glyph recursively.      */
+  /*    Rather, when a composite glyph is encountered, it should set       */
+  /*    the values of `num_subglyphs' and `subglyphs', as well as set      */
+  /*    `face->glyph.format' to ft_glyph_format_composite.                 */
+  /*                                                                       */
+  /*    This is for use by the auto-hinter and possibly other tools.       */
+  /*    For nearly all applications, this flags should be left unset       */
+  /*    when invoking FT_Load_Glyph().                                     */
+  /*                                                                       */
+  /*    Note that the flag forces the load of unscaled glyphs.             */
+  /*                                                                       */
+#define FT_LOAD_NO_RECURSE  1024
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_IGNORE_TRANSFORM                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should not try to transform the loaded glyph      */
+  /*    image.                                                             */
+  /*                                                                       */
+#define FT_LOAD_IGNORE_TRANSFORM 2048
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_MONOCHROME                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Only used with FT_LOAD_RENDER set, it indicates that the returned  */
+  /*    glyph image should be 1-bit monochrome.  This really tells the     */
+  /*    glyph loader to use `ft_render_mode_mono' when calling             */
+  /*    FT_Render_Glyph().                                                 */
+  /*                                                                       */
+#define FT_LOAD_MONOCHROME  4096
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_LINEAR_DESIGN                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should return the linearly scaled metrics expressed   */
+  /*    in original font units, instead of the default 16.16 pixel values. */
+  /*                                                                       */
+#define FT_LOAD_LINEAR_DESIGN 8192
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_DEFAULT                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should try to load the glyph normally, i.e.,          */
+  /*    embedded bitmaps are favored over outlines, vectors are always     */
+  /*    scaled and grid-fitted.                                            */
+  /*                                                                       */
+#define FT_LOAD_DEFAULT  0
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Transform                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to set the transformation that is applied to glyph */
+  /*    images just before they are converted to bitmaps in a glyph slot   */
+  /*    when FT_Render_Glyph() is called.                                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the source face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to the transformation's 2x2 matrix.  Use 0 for */
+  /*              the identity matrix.                                     */
+  /*    delta  :: A pointer to the translation vector.  Use 0 for the null */
+  /*              vector.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The transformation is only applied to scalable image formats after */
+  /*    the glyph has been loaded.  It means that hinting is unaltered by  */
+  /*    the transformation and is performed on the character size given in */
+  /*    the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes().      */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Set_Transform( FT_Face     face,
+                                           FT_Matrix*  matrix,
+                                           FT_Vector*  delta );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Render_Mode                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type that lists the render modes supported by the   */
+  /*    FreeType 2 renderer(s).  A renderer is in charge of converting a   */
+  /*    glyph image into a bitmap.                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_render_mode_normal :: This is the default render mode; it       */
+  /*                             corresponds to 8-bit anti-aliased         */
+  /*                             bitmaps, using 256 levels of gray.        */
+  /*                                                                       */
+  /*    ft_render_mode_mono   :: This render mode is used to produce 1-bit */
+  /*                             monochrome bitmaps.                       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    There is no render mode to produce 8-bit `monochrome' bitmaps --   */
+  /*    you have to make the conversion yourself if you need such things   */
+  /*    (besides, FreeType is not a graphics library).                     */
+  /*                                                                       */
+  /*    More modes might appear later for specific display modes (e.g. TV, */
+  /*    LCDs, etc.).  They will be supported through the simple addition   */
+  /*    of a renderer module, with no changes to the rest of the engine.   */
+  /*                                                                       */
+  typedef enum  FT_Render_Mode_
+  {
+    ft_render_mode_normal = 0,
+    ft_render_mode_mono   = 1
+
+  } FT_Render_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Render_Glyph                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a given glyph image to a bitmap.  It does so by           */
+  /*    inspecting the glyph image format, find the relevant renderer, and */
+  /*    invoke it.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot        :: A handle to the glyph slot containing the image to  */
+  /*                   convert.                                            */
+  /*                                                                       */
+  /*    render_mode :: This is the render mode used to render the glyph    */
+  /*                   image into a bitmap.  See FT_Render_Mode for a list */
+  /*                   of possible values.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Render_Glyph( FT_GlyphSlot  slot,
+                                              FT_UInt       render_mode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Kerning_Mode                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration used to specify which kerning values to return in   */
+  /*    FT_Get_Kerning().                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_kerning_default  :: Return scaled and grid-fitted kerning       */
+  /*                           distances (value is 0).                     */
+  /*                                                                       */
+  /*    ft_kerning_unfitted :: Return scaled but un-grid-fitted kerning    */
+  /*                           distances.                                  */
+  /*                                                                       */
+  /*    ft_kerning_unscaled :: Return the kerning vector in original font  */
+  /*                           units.                                      */
+  /*                                                                       */
+  typedef enum  FT_Kerning_Mode_
+  {
+    ft_kerning_default  = 0,
+    ft_kerning_unfitted,
+    ft_kerning_unscaled
+
+  } FT_Kerning_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Kerning                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the kerning vector between two glyphs of a same face.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a source face object.                   */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /*    kern_mode   :: See FT_Kerning_Mode() for more information.         */
+  /*                   Determines the scale/dimension of the returned      */
+  /*                   kerning vector.                                     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this method.  Other layouts, or more sophisticated    */
+  /*    kernings, are out of the scope of this API function -- they can be */
+  /*    implemented through format-specific interfaces.                    */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Get_Kerning( FT_Face     face,
+                                             FT_UInt     left_glyph,
+                                             FT_UInt     right_glyph,
+                                             FT_UInt     kern_mode,
+                                             FT_Vector*  kerning );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Glyph_Name                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the ASCII name of a given glyph in a face.  This only    */
+  /*    works for those faces where FT_HAS_GLYPH_NAME(face) returns true.  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a source face object.                   */
+  /*                                                                       */
+  /*    glyph_index :: The glyph index.                                    */
+  /*                                                                       */
+  /*    buffer      :: A pointer to a target buffer where the name will be */
+  /*                   copied to.                                          */
+  /*                                                                       */
+  /*    buffer_max  :: The maximal number of bytes available in the        */
+  /*                   buffer.                                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error is returned if the face doesn't provide glyph names or if */
+  /*    the glyph index is invalid.  In all cases of failure, the first    */
+  /*    byte of `buffer' will be set to 0 to indicate an empty name.       */
+  /*                                                                       */
+  /*    The glyph name is truncated to fit within the buffer if it is too  */
+  /*    long.  The returned string is always zero-terminated.              */
+  /*                                                                       */
+  /*    This function is not compiled within the library if the config     */
+  /*    macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in                */
+  /*    `include/freetype/config/ftoptions.h'                              */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Get_Glyph_Name( FT_Face     face,
+                                                FT_UInt     glyph_index,
+                                                FT_Pointer  buffer,
+                                                FT_UInt     buffer_max );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Select_Charmap                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Selects a given charmap by its encoding tag (as listed in          */
+  /*    `freetype.h').                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*                                                                       */
+  /*    encoding :: A handle to the selected charmap.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will return an error if no charmap in the face       */
+  /*    corresponds to the encoding queried here.                          */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Select_Charmap( FT_Face      face,
+                                                FT_Encoding  encoding );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Charmap                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Selects a given charmap for character code to glyph index          */
+  /*    decoding.                                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*    charmap  :: A handle to the selected charmap.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will return an error if the charmap is not part of   */
+  /*    the face (i.e., if it is not listed in the face->charmaps[]        */
+  /*    table).                                                            */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Set_Charmap( FT_Face     face,
+                                             FT_CharMap  charmap );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Char_Index                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the glyph index of a given character code.  This function  */
+  /*    uses a charmap object to do the translation.                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*                                                                       */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph index.  0 means `undefined character code'.              */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_UInt )  FT_Get_Char_Index( FT_Face   face,
+                                               FT_ULong  charcode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulDiv                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation `(a*b)/c'   */
+  /*    with maximal accuracy (it uses a 64-bit intermediate integer       */
+  /*    whenever necessary).                                               */
+  /*                                                                       */
+  /*    This function isn't necessarily as fast as some processor specific */
+  /*    operations, but is at least completely portable.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.                                        */
+  /*    c :: The divisor.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/c'.  This function never traps when trying to */
+  /*    divide by zero; it simply returns `MaxInt' or `MinInt' depending   */
+  /*    on the signs of `a' and `b'.                                       */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Long )  FT_MulDiv( FT_Long  a,
+                                       FT_Long  b,
+                                       FT_Long  c );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*b)/0x10000' with maximal accuracy.  Most of the time this is   */
+  /*    used to multiply a given value by a 16.16 fixed float factor.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/0x10000'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function has been optimized for the case where the absolute   */
+  /*    value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
+  /*    As this happens mainly when scaling from notional units to         */
+  /*    fractional pixels in FreeType, it resulted in noticeable speed     */
+  /*    improvements between versions 2.x and 1.x.                         */
+  /*                                                                       */
+  /*    As a conclusion, always try to place a 16.16 factor as the         */
+  /*    _second_ argument of this function; this can make a great          */
+  /*    difference.                                                        */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Long )  FT_MulFix( FT_Long  a,
+                                       FT_Long  b );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_DivFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*0x10000)/b' with maximal accuracy.  Most of the time, this is  */
+  /*    used to divide a given value by a 16.16 fixed float factor.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*0x10000)/b'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The optimization for FT_DivFix() is simple: If (a << 16) fits in   */
+  /*    32 bits, then the division is computed directly.  Otherwise, we    */
+  /*    use a specialized version of the old FT_MulDiv64().                */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Long )  FT_DivFix( FT_Long  a,
+                                       FT_Long  b );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Vector_Transform                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Transforms a single vector through a 2x2 matrix.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    vector :: The target vector to transform.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to the source 2x2 matrix.                      */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The result is undefined if either `vector' or `matrix' is invalid. */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Vector_Transform( FT_Vector*  vec,
+                                              FT_Matrix*  matrix );
+
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FREETYPE_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftbbox.h b/src/freetype/freetype/ftbbox.h
new file mode 100644 (file)
index 0000000..e144664
--- /dev/null
@@ -0,0 +1,72 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftbbox.h                                                               */
+/*                                                                         */
+/*    FreeType bbox computation (specification).                           */
+/*                                                                         */
+/*  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 component has a _single_ role: to compute exact outline bounding */
+  /* boxes.                                                                */
+  /*                                                                       */
+  /* It is separated from the rest of the engine for various technical     */
+  /* reasons.  It may well be integrated in `ftoutln' later.               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTBBOX_H
+#define FTBBOX_H
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Raster_GetBBox                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the exact bounding box of an outline.  This is slower     */
+  /*    than computing the control box.  However, it uses an advanced      */
+  /*    algorithm which returns _very_ quickly when the two boxes          */
+  /*    coincide.  Otherwise, the outline Bezier arcs are walked over to   */
+  /*    extract their extrema.                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the source outline.                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    bbox    :: The outline's exact bounding box.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  FT_EXPORT_DEF(FT_Error)  FT_Raster_GetBBox( FT_Outline*  outline,
+                                              FT_BBox*     abbox );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* FTBBOX_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/fterrors.h b/src/freetype/freetype/fterrors.h
new file mode 100644 (file)
index 0000000..9fb8099
--- /dev/null
@@ -0,0 +1,166 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fterrors.h                                                             */
+/*                                                                         */
+/*    FreeType error codes (specification).                                */
+/*                                                                         */
+/*  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 is used to define the FreeType error enumeration constants  */
+  /* It can also be used to create an error message table easily with      */
+  /* something like:                                                       */
+  /*                                                                       */
+  /*   {                                                                   */
+  /*     #undef FTERRORS_H                                                 */
+  /*     #define FT_ERRORDEF( e, v, s )  { e, s },                         */
+  /*     #define FT_ERROR_START_LIST  {                                    */
+  /*     #define FT_ERROR_END_LIST    { 0, 0 } };                          */
+  /*                                                                       */
+  /*     const struct                                                      */
+  /*     {                                                                 */
+  /*       int          err_code;                                          */
+  /*       const char*  err_msg                                            */
+  /*     } ft_errors[] =                                                   */
+  /*                                                                       */
+  /*     #include <freetype/fterrors.h>                                    */
+  /*   }                                                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTERRORS_H
+#define FTERRORS_H
+
+
+#ifndef FT_ERRORDEF
+
+#define FT_ERRORDEF( e, v, s )  e = v,
+#define FT_ERROR_START_LIST     enum {
+#define FT_ERROR_END_LIST       FT_Err_Max };
+
+#endif /* !FT_ERRORDEF */
+
+
+#ifdef FT_ERROR_START_LIST
+  FT_ERROR_START_LIST
+#endif
+
+  FT_ERRORDEF( FT_Err_Ok,                           0x0000, \
+               "no error" )
+  FT_ERRORDEF( FT_Err_Cannot_Open_Resource,         0x0001, \
+               "can't open stream"   )
+  FT_ERRORDEF( FT_Err_Unknown_File_Format,          0x0002, \
+               "unknown file format" )
+  FT_ERRORDEF( FT_Err_Invalid_File_Format,          0x0003, \
+               "broken file" )
+
+  FT_ERRORDEF( FT_Err_Invalid_Argument,             0x0010, \
+               "invalid argument" )
+  FT_ERRORDEF( FT_Err_Invalid_Handle,               0x0011, \
+               "invalid object handle" )
+  FT_ERRORDEF( FT_Err_Invalid_Glyph_Index,          0x0012, \
+               "invalid glyph index" )
+  FT_ERRORDEF( FT_Err_Invalid_Character_Code,       0x0013, \
+               "invalid character code" )
+
+  FT_ERRORDEF( FT_Err_Unimplemented_Feature,        0x0020, \
+               "unimplemented feature" )
+  FT_ERRORDEF( FT_Err_Invalid_Glyph_Format,         0x0021, \
+               "unsupported glyph image format" )
+  FT_ERRORDEF( FT_Err_Cannot_Render_Glyph,          0x0022, \
+               "cannot render this glyph format" )
+
+  FT_ERRORDEF( FT_Err_Invalid_Library_Handle,       0x0030, \
+               "invalid library handle" )
+  FT_ERRORDEF( FT_Err_Invalid_Driver_Handle,        0x0031, \
+               "invalid module handle" )
+  FT_ERRORDEF( FT_Err_Invalid_Face_Handle,          0x0032, \
+               "invalid face handle" )
+  FT_ERRORDEF( FT_Err_Invalid_Size_Handle,          0x0033, \
+               "invalid size handle" )
+  FT_ERRORDEF( FT_Err_Invalid_Slot_Handle,          0x0034, \
+               "invalid glyph slot handle" )
+  FT_ERRORDEF( FT_Err_Invalid_CharMap_Handle,       0x0035, \
+               "invalid charmap handle" )
+  FT_ERRORDEF( FT_Err_Invalid_Outline,              0x0036, \
+               "invalid outline" )
+  FT_ERRORDEF( FT_Err_Invalid_Version,              0x0037, \
+               "invalid FreeType version" )
+  FT_ERRORDEF( FT_Err_Lower_Module_Version,         0x0038, \
+               "module version is too low" )
+
+  FT_ERRORDEF( FT_Err_Too_Many_Drivers,             0x0040, \
+               "too many modules" )
+  FT_ERRORDEF( FT_Err_Too_Many_Extensions,          0x0041, \
+               "too many extensions" )
+
+  FT_ERRORDEF( FT_Err_Out_Of_Memory,                0x0050, \
+               "out of memory" )
+  FT_ERRORDEF( FT_Err_Unlisted_Object,              0x0051, \
+               "unlisted object" )
+
+  FT_ERRORDEF( FT_Err_Invalid_Stream_Handle,        0x0060, \
+               "invalid stream handle" )
+  FT_ERRORDEF( FT_Err_Cannot_Open_Stream,           0x0061, \
+               "cannot open stream" )
+  FT_ERRORDEF( FT_Err_Invalid_Stream_Seek,          0x0062, \
+               "invalid stream seek" )
+  FT_ERRORDEF( FT_Err_Invalid_Stream_Skip,          0x0063, \
+               "invalid stream skip" )
+  FT_ERRORDEF( FT_Err_Invalid_Stream_Read,          0x0064, \
+               "invalid stream read" )
+  FT_ERRORDEF( FT_Err_Invalid_Stream_Operation,     0x0065, \
+               "invalid stream operation" )
+  FT_ERRORDEF( FT_Err_Invalid_Frame_Operation,      0x0066, \
+               "invalid frame operation" )
+  FT_ERRORDEF( FT_Err_Nested_Frame_Access,          0x0067, \
+               "nested frame access" )
+  FT_ERRORDEF( FT_Err_Invalid_Frame_Read,           0x0068, \
+               "invalid frame read" )
+
+  FT_ERRORDEF( FT_Err_Invalid_Composite,            0x0070, \
+               "invalid composite glyph" )
+  FT_ERRORDEF( FT_Err_Too_Many_Hints,               0x0071, \
+               "too many hints" )
+
+  FT_ERRORDEF( FT_Err_Raster_Uninitialized,         0x0080, \
+               "raster uninitialized" )
+  FT_ERRORDEF( FT_Err_Raster_Corrupted,             0x0081, \
+               "raster corrupted" )
+  FT_ERRORDEF( FT_Err_Raster_Overflow,              0x0082, \
+               "raster overflow" )
+  FT_ERRORDEF( FT_Err_Raster_Negative_Height,       0x0083, \
+               "negative height while rastering" )
+
+  /* range 0x400 - 0x4FF is reserved for TrueType specific stuff */
+
+  /* range 0x500 - 0x5FF is reserved for CFF specific stuff */
+
+  /* range 0x600 - 0x6FF is reserved for Type1 specific stuff */
+
+#ifdef FT_ERROR_END_LIST
+  FT_ERROR_END_LIST
+#endif
+
+
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+#undef FT_ERRORDEF
+
+
+#endif /* FTERRORS_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftglyph.h b/src/freetype/freetype/ftglyph.h
new file mode 100644 (file)
index 0000000..0647c88
--- /dev/null
@@ -0,0 +1,422 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftglyph.h                                                              */
+/*                                                                         */
+/*    FreeType convenience functions to handle glyphs (specification).     */
+/*                                                                         */
+/*  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 contains the definition of several convenience functions    */
+  /* that can be used by client applications to easily retrieve glyph      */
+  /* bitmaps and outlines from a given face.                               */
+  /*                                                                       */
+  /* These functions should be optional if you are writing a font server   */
+  /* or text layout engine on top of FreeType.  However, they are pretty   */
+  /* handy for many other simple uses of the library.                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTGLYPH_H
+#define FTGLYPH_H
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  /* forward declaration to a private type */
+  typedef struct FT_Glyph_Class_  FT_Glyph_Class;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_GlyphRec                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The root glyph structure contains a given glyph image plus its     */
+  /*    advance width in 16.16 fixed float format.                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    library :: A handle to the FreeType library object.                */
+  /*                                                                       */
+  /*    clazz   :: A pointer to the glyph's class.  Private.               */
+  /*                                                                       */
+  /*    format  :: The format of the glyph's image.                        */
+  /*                                                                       */
+  /*    advance :: A 16.16 vector that gives the glyph's advance width.    */
+  /*                                                                       */
+  typedef struct  FT_GlyphRec_
+  {
+    FT_Library             library;
+    const FT_Glyph_Class*  clazz;
+    FT_Glyph_Format        format;
+    FT_Vector              advance;
+
+  } FT_GlyphRec, *FT_Glyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_BitmapGlyphRec                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used for bitmap glyph images.  This really is a        */
+  /*    `sub-class' of `FT_GlyphRec'.                                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root   :: The root FT_Glyph fields.                                */
+  /*                                                                       */
+  /*    left   :: The left-side bearing, i.e., the horizontal distance     */
+  /*              from the current pen position to the left border of the  */
+  /*              glyph bitmap.                                            */
+  /*                                                                       */
+  /*    top    :: The top-side bearing, i.e., the vertical distance from   */
+  /*              the current pen position to the top border of the glyph  */
+  /*              bitmap.  This distance is positive for upwards-y!        */
+  /*                                                                       */
+  /*    bitmap :: A descriptor for the bitmap.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You can typecast FT_Glyph to FT_BitmapGlyph if you have            */
+  /*    glyph->format == ft_glyph_format_bitmap.  This lets you access     */
+  /*    the bitmap's contents easily.                                      */
+  /*                                                                       */
+  /*    The corresponding pixel buffer is always owned by the BitmapGlyph  */
+  /*    and is thus created and destroyed with it.                         */
+  /*                                                                       */
+  typedef struct  FT_BitmapGlyphRec_
+  {
+    FT_GlyphRec  root;
+    FT_Int       left;
+    FT_Int       top;
+    FT_Bitmap    bitmap;
+
+  } FT_BitmapGlyphRec, *FT_BitmapGlyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_OutlineGlyphRec                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used for outline (vectorial) glyph images.  This       */
+  /*    really is a `sub-class' of `FT_GlyphRec'.                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root    :: The root FT_Glyph fields.                               */
+  /*                                                                       */
+  /*    outline :: A descriptor for the outline.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You can typecast FT_Glyph to FT_OutlineGlyph if you have           */
+  /*    glyph->format == ft_glyph_format_outline.  This lets you access    */
+  /*    the outline's content easily.                                      */
+  /*                                                                       */
+  /*    As the outline is extracted from a glyph slot, its coordinates are */
+  /*    expressed normally in 26.6 pixels, unless the flag                 */
+  /*    FT_LOAD_NO_SCALE was used in FT_Load_Glyph() or FT_Load_Char().    */
+  /*                                                                       */
+  /*    The outline's tables are always owned by the object and are        */
+  /*    destroyed with it.                                                 */
+  /*                                                                       */
+  typedef struct  FT_OutlineGlyphRec_
+  {
+    FT_GlyphRec  root;
+    FT_Outline   outline;
+
+  } FT_OutlineGlyphRec, *FT_OutlineGlyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Glyph                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to extract a glyph image from a slot.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot   :: A handle to the source glyph slot.                       */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aglyph :: A handle to the glyph object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Get_Glyph( FT_GlyphSlot  slot,
+                                           FT_Glyph*     aglyph );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Copy                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to copy a glyph image.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    source :: A handle to the source glyph object.                     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    target :: A handle to the target glyph object.  0 in case of       */
+  /*              error.                                                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Glyph_Copy( FT_Glyph   source,
+                                            FT_Glyph*  target );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Transform                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Transforms a glyph image if its format is scalable.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph  :: A handle to the target glyph object.                     */
+  /*                                                                       */
+  /*    matrix :: A pointer to a 2x2 matrix to apply.                      */
+  /*                                                                       */
+  /*    delta  :: A pointer to a 2d vector to apply.  Coordinates are      */
+  /*              expressed in 1/64th of a pixel.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code (the glyph format is not scalable if it is     */
+  /*    not zero).                                                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The 2x2 transformation matrix is also applied to the glyph's       */
+  /*    advance vector.                                                    */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Glyph_Transform( FT_Glyph    glyph,
+                                                 FT_Matrix*  matrix,
+                                                 FT_Vector*  delta );
+
+
+  enum
+  {
+    ft_glyph_bbox_pixels    = 0,
+    ft_glyph_bbox_subpixels = 1,
+    ft_glyph_bbox_gridfit   = 2
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Get_CBox                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the glyph image's bounding box.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: A handle to the source glyph object.                      */
+  /*                                                                       */
+  /*    mode  :: A set of bit flags that indicate how to interpret the     */
+  /*             returned bounding box values.                             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    box   :: The glyph bounding box.  Coordinates are expressed in     */
+  /*             1/64th of pixels if it is grid-fitted.                    */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Coordinates are relative to the glyph origin, using the Y-upwards  */
+  /*    convention.                                                        */
+  /*                                                                       */
+  /*    If `ft_glyph_bbox_subpixels' is set in `mode', the bbox            */
+  /*    coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels).   */
+  /*    Otherwise, coordinates are expressed in integer pixels.            */
+  /*                                                                       */
+  /*    Note that the maximum coordinates are exclusive, which means that  */
+  /*    one can compute the width and height of the glyph image (be it in  */
+  /*    integer or 26.6 pixels) as:                                        */
+  /*                                                                       */
+  /*      width  = bbox.xMax - bbox.xMin;                                  */
+  /*      height = bbox.yMax - bbox.yMin;                                  */
+  /*                                                                       */
+  /*    Note also that for 26.6 coordinates, if the                        */
+  /*    `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates     */
+  /*    will also be grid-fitted, which corresponds to:                    */
+  /*                                                                       */
+  /*      bbox.xMin = FLOOR(bbox.xMin);                                    */
+  /*      bbox.yMin = FLOOR(bbox.yMin);                                    */
+  /*      bbox.xMax = CEILING(bbox.xMax);                                  */
+  /*      bbox.yMax = CEILING(bbox.yMax);                                  */
+  /*                                                                       */
+  /*    The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'.   */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Glyph_Get_CBox( FT_Glyph  glyph,
+                                            FT_UInt   bbox_mode,
+                                            FT_BBox*  cbox );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_To_Bitmap                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a given glyph object to a bitmap glyph object.            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    glyph       :: A pointer to a handle to the target glyph.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    render_mode :: A set of bit flags that describe how the data is    */
+  /*                                                                       */
+  /*                                                                       */
+  /*    origin      :: A pointer to a vector used to translate the glyph   */
+  /*                   image before rendering.  Can be 0 (if no            */
+  /*                   translation).  The origin is expressed in           */
+  /*                   26.6 pixels.                                        */
+  /*                                                                       */
+  /*    destroy     :: A boolean that indicates that the original glyph    */
+  /*                   image should be destroyed by this function.  It is  */
+  /*                   never destroyed in case of error.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The glyph image is translated with the `origin' vector before      */
+  /*    rendering.  In case of error, it it translated back to its         */
+  /*    original position and the glyph is left untouched.                 */
+  /*                                                                       */
+  /*    The first parameter is a pointer to a FT_Glyph handle, that will   */
+  /*    be replaced by this function.  Typically, you would use (omitting  */
+  /*    error handling):                                                   */
+  /*                                                                       */
+  /*                                                                       */
+  /*      {                                                                */
+  /*        FT_Glyph        glyph;                                         */
+  /*        FT_BitmapGlyph  glyph_bitmap;                                  */
+  /*                                                                       */
+  /*                                                                       */
+  /*        // load glyph                                                  */
+  /*        error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT );     */
+  /*                                                                       */
+  /*        // extract glyph image                                         */
+  /*        error = FT_Get_Glyph( face->glyph, &glyph );                   */
+  /*                                                                       */
+  /*        // convert to a bitmap (default render mode + destroy old)     */
+  /*        if ( glyph->format != ft_glyph_format_bitmap )                 */
+  /*        {                                                              */
+  /*          error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default,  */
+  /*                                      0, 1 );                          */
+  /*          if ( error ) // glyph unchanged                              */
+  /*            ...                                                        */
+  /*        }                                                              */
+  /*                                                                       */
+  /*        // access bitmap content by typecasting                        */
+  /*        glyph_bitmap = (FT_BitmapGlyph)glyph;                          */
+  /*                                                                       */
+  /*        // do funny stuff with it, like blitting/drawing               */
+  /*        ...                                                            */
+  /*                                                                       */
+  /*        // discard glyph image (bitmap or not)                         */
+  /*        FT_Done_Glyph( glyph );                                        */
+  /*      }                                                                */
+  /*                                                                       */
+  /*                                                                       */
+  /*    This function will always fail if the glyph's format isn't         */
+  /*    scalable.                                                          */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Glyph_To_Bitmap( FT_Glyph*   the_glyph,
+                                                 FT_ULong    render_mode,
+                                                 FT_Vector*  origin,
+                                                 FT_Bool     destroy );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given glyph.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: A handle to the target glyph object.                      */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Done_Glyph( FT_Glyph  glyph );
+
+
+  /* other helpful functions */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Matrix_Multiply                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs the matrix operation `b = a*b'.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: A pointer to matrix `a'.                                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    b :: A pointer to matrix `b'.                                      */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The result is undefined if either `a' or `b' is zero.              */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Matrix_Multiply( FT_Matrix*  a,
+                                             FT_Matrix*  b );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Matrix_Invert                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inverts a 2x2 matrix.  Returns an error if it can't be inverted.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    matrix :: A pointer to the target matrix.  Remains untouched in    */
+  /*              case of error.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Matrix_Invert( FT_Matrix*  matrix );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* FTGLYPH_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftimage.h b/src/freetype/freetype/ftimage.h
new file mode 100644 (file)
index 0000000..4dd1c3d
--- /dev/null
@@ -0,0 +1,1003 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftimage.h                                                              */
+/*                                                                         */
+/*    FreeType glyph image formats and default raster interface            */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Note: A `raster' is simply a scan-line converter, used to render      */
+  /*       FT_Outlines into FT_Bitmaps.                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTIMAGE_H
+#define FTIMAGE_H
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Pos                                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The type FT_Pos is a 32-bit integer used to store vectorial        */
+  /*    coordinates.  Depending on the context, these can represent        */
+  /*    distances in integer font units, or 26.6 fixed float pixel         */
+  /*    coordinates.                                                       */
+  /*                                                                       */
+  typedef signed long  FT_Pos;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Vector                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to store a 2D vector; coordinates are of   */
+  /*    the FT_Pos type.                                                   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x :: The horizontal coordinate.                                    */
+  /*    y :: The vertical coordinate.                                      */
+  /*                                                                       */
+  typedef struct  FT_Vector_
+  {
+    FT_Pos  x;
+    FT_Pos  y;
+
+  } FT_Vector;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Pixel_Mode                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type used to describe the format of pixels in a     */
+  /*    given bitmap.  Note that additional formats may be added in the    */
+  /*    future.                                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_pixel_mode_mono  :: A monochrome bitmap (1 bit/pixel).          */
+  /*                                                                       */
+  /*    ft_pixel_mode_grays :: An 8-bit gray-levels bitmap.  Note that the */
+  /*                           total number of gray levels is given in the */
+  /*                           `num_grays' field of the FT_Bitmap          */
+  /*                           structure.                                  */
+  /*                                                                       */
+  /*    ft_pixel_mode_pal2  :: A 2-bit paletted bitmap.                    */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_pal4  :: A 4-bit paletted bitmap.                    */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_pal8  :: An 8-bit paletted bitmap.                   */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb15 :: A 15-bit RGB bitmap.  Uses 5:5:5 encoding.  */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb16 :: A 16-bit RGB bitmap.  Uses 5:6:5 encoding.  */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb24 :: A 24-bit RGB bitmap.                        */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb32 :: A 32-bit RGB bitmap.                        */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Some anti-aliased bitmaps might be embedded in TrueType fonts      */
+  /*    using formats pal2 or pal4, though no fonts presenting those have  */
+  /*    been found to date.                                                */
+  /*                                                                       */
+  typedef enum  FT_Pixel_Mode_
+  {
+    ft_pixel_mode_none = 0,
+    ft_pixel_mode_mono,
+    ft_pixel_mode_grays,
+    ft_pixel_mode_pal2,
+    ft_pixel_mode_pal4,
+    ft_pixel_mode_pal8,
+    ft_pixel_mode_rgb15,
+    ft_pixel_mode_rgb16,
+    ft_pixel_mode_rgb24,
+    ft_pixel_mode_rgb32,
+
+    ft_pixel_mode_max      /* do not remove */
+
+  } FT_Pixel_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Palette_Mode                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type used to describe the format of a bitmap        */
+  /*    palette, used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8.      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_palette_mode_rgb  :: The palette is an array of 3-bytes RGB     */
+  /*                            records.                                   */
+  /*                                                                       */
+  /*    ft_palette_mode_rgba :: The palette is an array of 4-bytes RGBA    */
+  /*                            records.                                   */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by       */
+  /*    FreeType, these types are not handled by the library itself.       */
+  /*                                                                       */
+  typedef enum  FT_Palette_Mode_
+  {
+    ft_palette_mode_rgb = 0,
+    ft_palette_mode_rgba,
+
+    ft_palettte_mode_max   /* do not remove */
+
+  } FT_Palette_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Bitmap                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe a bitmap or pixmap to the raster.     */
+  /*    Note that we now manage pixmaps of various depths through the      */
+  /*    `pixel_mode' field.                                                */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    rows         :: The number of bitmap rows.                         */
+  /*                                                                       */
+  /*    width        :: The number of pixels in bitmap row.                */
+  /*                                                                       */
+  /*    pitch        :: The pitch's absolute value is the number of bytes  */
+  /*                    taken by one bitmap row, including padding.        */
+  /*                    However, the pitch is positive when the bitmap has */
+  /*                    a `down' flow, and negative when it has an `up'    */
+  /*                    flow.  In all cases, the pitch is an offset to add */
+  /*                    to a bitmap pointer in order to go down one row.   */
+  /*                                                                       */
+  /*    buffer       :: A typeless pointer to the bitmap buffer.  This     */
+  /*                    value should be aligned on 32-bit boundaries in    */
+  /*                    most cases.                                        */
+  /*                                                                       */
+  /*    num_grays    :: This field is only used with                       */
+  /*                    `ft_pixel_mode_grays'; it gives the number of gray */
+  /*                    levels used in the bitmap.                         */
+  /*                                                                       */
+  /*    pixel_mode   :: The pixel_mode, i.e., how pixel bits are stored.   */
+  /*                                                                       */
+  /*    palette_mode :: This field is only used with paletted pixel modes; */
+  /*                    it indicates how the palette is stored.            */
+  /*                                                                       */
+  /*    palette      :: A typeless pointer to the bitmap palette; only     */
+  /*                    used for paletted pixel modes.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*   For now, the only pixel mode supported by FreeType are mono and     */
+  /*   grays.  However, drivers might be added in the future to support    */
+  /*   more `colorful' options.                                            */
+  /*                                                                       */
+  /*   When using pixel modes pal2, pal4 and pal8 with a void `palette'    */
+  /*   field, a gray pixmap with respectively 4, 16, and 256 levels of     */
+  /*   gray is assumed.  This, in order to be compatible with some         */
+  /*   embedded bitmap formats defined in the TrueType specification.      */
+  /*                                                                       */
+  /*   Note that no font was found presenting such embedded bitmaps, so    */
+  /*   this is currently completely unhandled by the library.              */
+  /*                                                                       */
+  typedef struct  FT_Bitmap_
+  {
+    int             rows;
+    int             width;
+    int             pitch;
+    unsigned char*  buffer;
+    short           num_grays;
+    char            pixel_mode;
+    char            palette_mode;
+    void*           palette;
+
+  } FT_Bitmap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Outline                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure is used to describe an outline to the scan-line     */
+  /*    converter.                                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    n_contours :: The number of contours in the outline.               */
+  /*                                                                       */
+  /*    n_points   :: The number of points in the outline.                 */
+  /*                                                                       */
+  /*    points     :: A pointer to an array of `n_points' FT_Vector        */
+  /*                  elements, giving the outline's point coordinates.    */
+  /*                                                                       */
+  /*    tags       :: A pointer to an array of `n_points' chars, giving    */
+  /*                  giving each outline point's type.  If bit 0 is       */
+  /*                  unset, the point is 'off' the curve, i.e. a Bezier   */
+  /*                  control point, while it is `on' when unset.          */
+  /*                                                                       */
+  /*                  Bit 1 is meaningful for `off' points only.  If set,  */
+  /*                  it indicates a third-order Bezier arc control point; */
+  /*                  and a second-order control point if unset.           */
+  /*                                                                       */
+  /*    contours   :: An array of `n_contours' shorts, giving the end      */
+  /*                  point of each contour within the outline.  For       */
+  /*                  example, the first contour is defined by the points  */
+  /*                  `0' to `contours[0]', the second one is defined by   */
+  /*                  the points `contours[0]+1' to `contours[1]', etc.    */
+  /*                                                                       */
+  /*    flags      :: A set of bit flags used to characterize the outline  */
+  /*                  and give hints to the scan-converter and hinter on   */
+  /*                  how to convert/grid-fit it.  See FT_Outline_Flags.   */
+  /*                                                                       */
+  typedef struct  FT_Outline_
+  {
+    short       n_contours;      /* number of contours in glyph        */
+    short       n_points;        /* number of points in the glyph      */
+
+    FT_Vector*  points;          /* the outline's points               */
+    char*       tags;            /* the points flags                   */
+    short*      contours;        /* the contour end points             */
+
+    int         flags;           /* outline masks                      */
+
+  } FT_Outline;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*   FT_Outline_Flags                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple type used to enumerates the flags in an outline's         */
+  /*    `outline_flags' field.                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_outline_owner          :: If set, this flag indicates that the  */
+  /*                                 outline's field arrays (i.e.          */
+  /*                                 `points', `flags' & `contours') are   */
+  /*                                 `owned' by the outline object, and    */
+  /*                                 should thus be freed when it is       */
+  /*                                 destroyed.                            */
+  /*                                                                       */
+  /*   ft_outline_even_odd_fill   :: By default, outlines are filled using */
+  /*                                 the non-zero winding rule.  If set to */
+  /*                                 1, the outline will be filled using   */
+  /*                                 the even-odd fill rule (only works    */
+  /*                                 with the smooth raster).              */
+  /*                                                                       */
+  /*   ft_outline_reverse_fill    :: By default, outside contours of an    */
+  /*                                 outline are oriented in clock-wise    */
+  /*                                 direction, as defined in the TrueType */
+  /*                                 specification.  This flag is set if   */
+  /*                                 the outline uses the opposite         */
+  /*                                 direction (typically for Type 1       */
+  /*                                 fonts).  This flag is ignored by the  */
+  /*                                 scan-converter.  However, it is very  */
+  /*                                 important for the auto-hinter.        */
+  /*                                                                       */
+  /*   ft_outline_ignore_dropouts :: By default, the scan converter will   */
+  /*                                 try to detect drop-outs in an outline */
+  /*                                 and correct the glyph bitmap to       */
+  /*                                 ensure consistent shape continuity.   */
+  /*                                 If set, this flag hints the scan-line */
+  /*                                 converter to ignore such cases.       */
+  /*                                                                       */
+  /*   ft_outline_high_precision  :: This flag indicates that the          */
+  /*                                 scan-line converter should try to     */
+  /*                                 convert this outline to bitmaps with  */
+  /*                                 the highest possible quality.  It is  */
+  /*                                 typically set for small character     */
+  /*                                 sizes.  Note that this is only a      */
+  /*                                 hint, that might be completely        */
+  /*                                 ignored by a given scan-converter.    */
+  /*                                                                       */
+  /*   ft_outline_single_pass     :: This flag is set to force a given     */
+  /*                                 scan-converter to only use a single   */
+  /*                                 pass over the outline to render a     */
+  /*                                 bitmap glyph image.  Normally, it is  */
+  /*                                 set for very large character sizes.   */
+  /*                                 It is only a hint, that might be      */
+  /*                                 completely ignored by a given         */
+  /*                                 scan-converter.                       */
+  /*                                                                       */
+  typedef enum  FT_Outline_Flags_
+  {
+    ft_outline_none            = 0,
+    ft_outline_owner           = 1,
+    ft_outline_even_odd_fill   = 2,
+    ft_outline_reverse_fill    = 4,
+    ft_outline_ignore_dropouts = 8,
+    ft_outline_high_precision  = 256,
+    ft_outline_single_pass     = 512
+
+  } FT_Outline_Flags;
+
+
+#define FT_CURVE_TAG( flag )  ( flag & 3 )
+
+#define FT_Curve_Tag_On           1
+#define FT_Curve_Tag_Conic        0
+#define FT_Curve_Tag_Cubic        2
+
+#define FT_Curve_Tag_Touch_X      8  /* reserved for the TrueType hinter */
+#define FT_Curve_Tag_Touch_Y     16  /* reserved for the TrueType hinter */
+
+#define FT_Curve_Tag_Touch_Both  ( FT_Curve_Tag_Touch_X | \
+                                   FT_Curve_Tag_Touch_Y )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_MoveTo_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type used to describe the signature of a `move  */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `move to' is emitted to start a new contour in an outline.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    to   :: A pointer to the target point of the `move to'.            */
+  /*                                                                       */
+  /*    user :: A typeless pointer which is passed from the caller of the  */
+  /*            decomposition function.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int  (*FT_Outline_MoveTo_Func)( FT_Vector*  to,
+                                          void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_LineTo_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type used to describe the signature of a `line  */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `line to' is emitted to indicate a segment in the outline.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    to   :: A pointer to the target point of the `line to'.            */
+  /*                                                                       */
+  /*    user :: A typeless pointer which is passed from the caller of the  */
+  /*            decomposition function.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int  (*FT_Outline_LineTo_Func)( FT_Vector*  to,
+                                          void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_ConicTo_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type use to describe the signature of a `conic  */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `conic to' is emitted to indicate a second-order Bezier arc in   */
+  /*    the outline.                                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    control :: An intermediate control point between the last position */
+  /*               and the new target in `to'.                             */
+  /*                                                                       */
+  /*    to      :: A pointer to the target end point of the conic arc.     */
+  /*                                                                       */
+  /*    user    :: A typeless pointer which is passed from the caller of   */
+  /*               the decomposition function.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int  (*FT_Outline_ConicTo_Func)( FT_Vector*  control,
+                                           FT_Vector*  to,
+                                           void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_CubicTo_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type used to describe the signature of a `cubic */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `cubic to' is emitted to indicate a third-order Bezier arc.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    control1 :: A pointer to the first Bezier control point.           */
+  /*                                                                       */
+  /*    control2 :: A pointer to the second Bezier control point.          */
+  /*                                                                       */
+  /*    to       :: A pointer to the target end point.                     */
+  /*                                                                       */
+  /*    user     :: A typeless pointer which is passed from the caller of  */
+  /*                the decomposition function.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int  (*FT_Outline_CubicTo_Func)( FT_Vector*  control1,
+                                           FT_Vector*  control2,
+                                           FT_Vector*  to,
+                                           void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Outline_Funcs                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure to hold various function pointers used during outline  */
+  /*    decomposition in order to emit segments, conic, and cubic Beziers, */
+  /*    as well as `move to' and `close to' operations.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    move_to  :: The `move to' emitter.                                 */
+  /*                                                                       */
+  /*    line_to  :: The segment emitter.                                   */
+  /*                                                                       */
+  /*    conic_to :: The second-order Bezier arc emitter.                   */
+  /*                                                                       */
+  /*    cubic_to :: The third-order Bezier arc emitter.                    */
+  /*                                                                       */
+  /*    shift    :: The shift that is applied to coordinates before they   */
+  /*                are sent to the emitter.                               */
+  /*                                                                       */
+  /*    delta    :: The delta that is applied to coordinates before they   */
+  /*                are sent to the emitter, but after the shift.          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The point coordinates sent to the emitters are the transformed     */
+  /*    version of the original coordinates (this is important for high    */
+  /*    accuracy during scan-conversion).  The transformation is simple:   */
+  /*                                                                       */
+  /*      x' = (x << shift) - delta                                        */
+  /*      y' = (x << shift) - delta                                        */
+  /*                                                                       */
+  /*    Set the value of `shift' and `delta' to 0 to get the original      */
+  /*    point coordinates.                                                 */
+  /*                                                                       */
+  typedef struct  FT_Outline_Funcs_
+  {
+    FT_Outline_MoveTo_Func   move_to;
+    FT_Outline_LineTo_Func   line_to;
+    FT_Outline_ConicTo_Func  conic_to;
+    FT_Outline_CubicTo_Func  cubic_to;
+
+    int                      shift;
+    FT_Pos                   delta;
+
+  } FT_Outline_Funcs;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_IMAGE_TAG                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro converts four letter tags into an unsigned long.        */
+  /*                                                                       */
+#define FT_IMAGE_TAG( _x1, _x2, _x3, _x4 ) \
+          ( ( (unsigned long)_x1 << 24 ) | \
+            ( (unsigned long)_x2 << 16 ) | \
+            ( (unsigned long)_x3 << 8  ) | \
+              (unsigned long)_x4         )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Glyph_Format                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type used to describe the format of a given glyph   */
+  /*    image.  Note that this version of FreeType only supports two image */
+  /*    formats, even though future font drivers will be able to register  */
+  /*    their own format.                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_glyph_format_composite :: The glyph image is a composite of     */
+  /*                                 several other images.  This glyph     */
+  /*                                 format is _only_ used with the        */
+  /*                                 FT_LOAD_FLAG_NO_RECURSE flag (XXX:    */
+  /*                                 Which is currently unimplemented).    */
+  /*                                                                       */
+  /*    ft_glyph_format_bitmap    :: The glyph image is a bitmap, and can  */
+  /*                                 be described as a FT_Bitmap.          */
+  /*                                                                       */
+  /*    ft_glyph_format_outline   :: The glyph image is a vectorial image  */
+  /*                                 made of bezier control points, and    */
+  /*                                 can be described as a FT_Outline.     */
+  /*                                                                       */
+  /*    ft_glyph_format_plotter   :: The glyph image is a vectorial image  */
+  /*                                 made of plotter lines (some T1 fonts  */
+  /*                                 like Hershey contain glyph in this    */
+  /*                                 format).                              */
+  /*                                                                       */
+  typedef enum  FT_Glyph_Format_
+  {
+    ft_glyph_format_none      = 0,
+    ft_glyph_format_composite = FT_IMAGE_TAG( 'c', 'o', 'm', 'p' ),
+    ft_glyph_format_bitmap    = FT_IMAGE_TAG( 'b', 'i', 't', 's' ),
+    ft_glyph_format_outline   = FT_IMAGE_TAG( 'o', 'u', 't', 'l' ),
+    ft_glyph_format_plotter   = FT_IMAGE_TAG( 'p', 'l', 'o', 't' )
+
+  } FT_Glyph_Format;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****            R A S T E R   D E F I N I T I O N S                *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A raster is a scan converter, in charge of rendering an outline into  */
+  /* a a bitmap.  This section contains the public API for rasters.        */
+  /*                                                                       */
+  /* Note that in FreeType 2, all rasters are now encapsulated within      */
+  /* specific modules called `renderers'.  See `freetype/ftrender.h' for   */
+  /* more details on renderers.                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Raster                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle (pointer) to a raster object.  Each object can be used    */
+  /*    independently to convert an outline into a bitmap or pixmap.       */
+  /*                                                                       */
+  typedef struct FT_RasterRec_*  FT_Raster;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Span                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a single span of gray (or black) pixels  */
+  /*    when rendering a monochrome or anti-aliased bitmap.                */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x        :: The span's horizontal start position.                  */
+  /*                                                                       */
+  /*    len      :: The span's length in pixels.                           */
+  /*                                                                       */
+  /*    coverage :: The span color/coverage, ranging from 0 (background)   */
+  /*                to 255 (foreground).  Only used for anti-aliased       */
+  /*                rendering.                                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is used by the span drawing callback type named     */
+  /*    FT_Raster_Span_Func(), which takes the y-coordinate of the span as */
+  /*    a parameter.                                                       */
+  /*                                                                       */
+  /*    The coverage value is always between 0 and 255, even if the number */
+  /*    of gray levels have been set through FT_Set_Gray_Levels().         */
+  /*                                                                       */
+  typedef struct  FT_Span_
+  {
+    short          x;
+    unsigned short len;
+    unsigned char  coverage;
+
+  } FT_Span;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Span_Func                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used as a call-back by the anti-aliased renderer in     */
+  /*    order to let client applications draw themselves the gray pixel    */
+  /*    spans on each scan line.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    y     :: The scanline's y-coordinate.                              */
+  /*                                                                       */
+  /*    count :: The number of spans to draw on this scanline.             */
+  /*                                                                       */
+  /*    spans :: A table of `count' spans to draw on the scanline.         */
+  /*                                                                       */
+  /*    user  :: User-supplied data that is passed to the callback.        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This callback allows client applications to directly render the    */
+  /*    gray spans of the anti-aliased bitmap to any kind of surfaces.     */
+  /*                                                                       */
+  /*    This can be used to write anti-aliased outlines directly to a      */
+  /*    given background bitmap, and even perform translucency.            */
+  /*                                                                       */
+  /*    Note that the `count' field cannot be greater than a fixed value   */
+  /*    defined by the FT_MAX_GRAY_SPANS configuration macro in            */
+  /*    ftoption.h.  By default, this value is set to 32, which means that */
+  /*    if there are more than 32 spans on a given scanline, the callback  */
+  /*    will be called several times with the same `y' parameter in order  */
+  /*    to draw all callbacks.                                             */
+  /*                                                                       */
+  /*    Otherwise, the callback is only called once per scan-line, and     */
+  /*    only for those scanlines that do have `gray' pixels on them.       */
+  /*                                                                       */
+  typedef void  (*FT_Raster_Span_Func)( int       y,
+                                        int       count,
+                                        FT_Span*  spans,
+                                        void*     user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_BitTest_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used as a call-back by the monochrome scan-converter    */
+  /*    to test whether a given target pixel is already set to the drawing */
+  /*    `color'.  These tests are crucial to implement drop-out control    */
+  /*    per-se the TrueType spec.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    y     :: The pixel's y-coordinate.                                 */
+  /*                                                                       */
+  /*    x     :: The pixel's x-coordinate.                                 */
+  /*                                                                       */
+  /*    user  :: User-supplied data that is passed to the callback.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   1 if the pixel is `set', 0 otherwise.                               */
+  /*                                                                       */
+  typedef int  (*FT_Raster_BitTest_Func)( int    y,
+                                          int    x,
+                                          void*  user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_BitSet_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used as a call-back by the monochrome scan-converter    */
+  /*    to set an individual target pixel.  This is crucial to implement   */
+  /*    drop-out control according to the TrueType specification.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    y     :: The pixel's y-coordinate.                                 */
+  /*                                                                       */
+  /*    x     :: The pixel's x-coordinate.                                 */
+  /*                                                                       */
+  /*    user  :: User-supplied data that is passed to the callback.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    1 if the pixel is `set', 0 otherwise.                              */
+  /*                                                                       */
+  typedef void  (*FT_Raster_BitSet_Func)( int    y,
+                                          int    x,
+                                          void*  user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Raster_Flag                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration to list the bit flags as used in the `flags' field  */
+  /*    of a FT_Raster_Params structure.                                   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_raster_flag_default :: This value is 0.                         */
+  /*                                                                       */
+  /*    ft_raster_flag_aa      :: Requests the rendering of an             */
+  /*                              anti-aliased glyph bitmap.  If unset, a  */
+  /*                              monchrome bitmap will be rendered.       */
+  /*                                                                       */
+  /*    ft_raster_flag_direct  :: Requests direct rendering over the       */
+  /*                              target bitmap.  Direct rendering uses    */
+  /*                              user-provided callbacks in order to      */
+  /*                              perform direct drawing or composition    */
+  /*                              over an existing bitmap.  If this bit is */
+  /*                              unset, the content of the target bitmap  */
+  /*                              *must be zeroed*!                        */
+  /*                                                                       */
+  typedef  enum
+  {
+    ft_raster_flag_default = 0,
+    ft_raster_flag_aa      = 1,
+    ft_raster_flag_direct  = 2
+
+  } FT_Raster_Flag;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Raster_Params                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure to hold the arguments used by a raster's render        */
+  /*    function.                                                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    target      :: The target bitmap.                                  */
+  /*                                                                       */
+  /*    source      :: A pointer to the source glyph image (e.g. an        */
+  /*                   FT_Outline).                                        */
+  /*                                                                       */
+  /*    flags       :: The rendering flags.                                */
+  /*                                                                       */
+  /*    gray_spans  :: The gray span drawing callback.                     */
+  /*                                                                       */
+  /*    black_spans :: The black span drawing callback.                    */
+  /*                                                                       */
+  /*    bit_test    :: The bit test callback.                              */
+  /*                                                                       */
+  /*    bit_set     :: The bit set callback.                               */
+  /*                                                                       */
+  /*    user        :: User-supplied data that is passed to each drawing   */
+  /*                   callback.                                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An anti-aliased glyph bitmap is drawn if the ft_raster_flag_aa bit */
+  /*    flag is set in the `flags' field, otherwise a monochrome bitmap    */
+  /*    will be generated.                                                 */
+  /*                                                                       */
+  /*    If the ft_raster_flag_direct bit flag is set in `flags', the       */
+  /*    raster will call the `gray_spans' callback to draw gray pixel      */
+  /*    spans, in the case of an aa glyph bitmap, it will call             */
+  /*    `black_spans', and `bit_test' and `bit_set' in the case of a       */
+  /*    monochrome bitmap.  This allows direct composition over a          */
+  /*    pre-existing bitmap through user-provided callbacks to perform the */
+  /*    span drawing/composition.                                          */
+  /*                                                                       */
+  /*    Note that the `bit_test' and `bit_set' callbacks are required when */
+  /*    rendering a monochrome bitmap, as they are crucial to implement    */
+  /*    correct drop-out control as defined in the TrueType specification. */
+  /*                                                                       */
+  typedef struct  FT_Raster_Params_
+  {
+    FT_Bitmap*              target;
+    void*                   source;
+    int                     flags;
+    FT_Raster_Span_Func     gray_spans;
+    FT_Raster_Span_Func     black_spans;
+    FT_Raster_BitTest_Func  bit_test;
+    FT_Raster_BitSet_Func   bit_set;
+    void*                   user;
+
+  } FT_Raster_Params;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_New_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to create a new raster object.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to the memory allocator.                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    raster :: A handle to the new raster object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The `memory' parameter is a typeless pointer in order to avoid     */
+  /*    un-wanted dependencies on the rest of the FreeType code.  In       */
+  /*    practice, it is a FT_Memory, i.e., a handle to the standard        */
+  /*    FreeType memory allocator.  However, this field can be completely  */
+  /*    ignored by a given raster implementation.                          */
+  /*                                                                       */
+  typedef int  (*FT_Raster_New_Func)( void*       memory,
+                                      FT_Raster*  raster );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Done_Func                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to destroy a given raster object.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster :: A handle to the raster object.                           */
+  /*                                                                       */
+  typedef void  (*FT_Raster_Done_Func)( FT_Raster  raster );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Reset_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType provides an area of memory called the `render pool',      */
+  /*    available to all registered rasters.  This pool can be freely used */
+  /*    during a given scan-conversion but is shared by all rasters.  Its  */
+  /*    content is thus transient.                                         */
+  /*                                                                       */
+  /*    This function is called each time the render pool changes, or just */
+  /*    after a new raster object is created.                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster    :: A handle to the new raster object.                    */
+  /*                                                                       */
+  /*    pool_base :: The address in memory of the render pool.             */
+  /*                                                                       */
+  /*    pool_size :: The size in bytes of the render pool.                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Rasters can ignore the render pool and rely on dynamic memory      */
+  /*    allocation if they want to (a handle to the memory allocator is    */
+  /*    passed to the raster constructor).  However, this is not           */
+  /*    recommended for efficiency purposes.                               */
+  /*                                                                       */
+  typedef void  (*FT_Raster_Reset_Func)( FT_Raster       raster,
+                                         unsigned char*  pool_base,
+                                         unsigned long   pool_size );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Set_Mode_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is a generic facility to change modes or attributes  */
+  /*    in a given raster.  This can be used for debugging purposes, or    */
+  /*    simply to allow implementation-specific `features' in a given      */
+  /*    raster module.                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster :: A handle to the new raster object.                       */
+  /*                                                                       */
+  /*    mode   :: A 4-byte tag used to name the mode or property.          */
+  /*                                                                       */
+  /*    args   :: A pointer to the new mode/property to use.               */
+  /*                                                                       */
+  typedef int  (*FT_Raster_Set_Mode_Func)( FT_Raster      raster,
+                                           unsigned long  mode,
+                                           void*          args );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Render_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   Invokes a given raster to scan-convert a given glyph image into a   */
+  /*   target bitmap.                                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster :: A handle to the raster object.                           */
+  /*                                                                       */
+  /*    params :: A pointer to a FT_Raster_Params structure used to store  */
+  /*              the rendering parameters.                                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The exact format of the source image depends on the raster's glyph */
+  /*    format defined in its FT_Raster_Funcs structure.  It can be an     */
+  /*    FT_Outline or anything else in order to support a large array of   */
+  /*    glyph formats.                                                     */
+  /*                                                                       */
+  /*    Note also that the render function can fail and return a           */
+  /*    FT_Err_Unimplemented_Feature error code if the raster used does    */
+  /*    not support direct composition.                                    */
+  /*                                                                       */
+  /*    XXX: For now, the standard raster doesn't support direct           */
+  /*         composition but this should change for the final release (see */
+  /*         the files demos/src/ftgrays.c and demos/src/ftgrays2.c for    */
+  /*         examples of distinct implementations which support direct     */
+  /*         composition).                                                 */
+  /*                                                                       */
+  typedef int  (*FT_Raster_Render_Func)( FT_Raster          raster,
+                                         FT_Raster_Params*  params );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Raster_Funcs                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   A structure used to describe a given raster class to the library.   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    glyph_format  :: The supported glyph format for this raster.       */
+  /*                                                                       */
+  /*    raster_new    :: The raster constructor.                           */
+  /*                                                                       */
+  /*    raster_reset  :: Used to reset the render pool within the raster.  */
+  /*                                                                       */
+  /*    raster_render :: A function to render a glyph into a given bitmap. */
+  /*                                                                       */
+  /*    raster_done   :: The raster destructor.                            */
+  /*                                                                       */
+  typedef struct  FT_Raster_Funcs_
+  {
+    FT_Glyph_Format          glyph_format;
+    FT_Raster_New_Func       raster_new;
+    FT_Raster_Reset_Func     raster_reset;
+    FT_Raster_Set_Mode_Func  raster_set_mode;
+    FT_Raster_Render_Func    raster_render;
+    FT_Raster_Done_Func      raster_done;
+
+  } FT_Raster_Funcs;
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTIMAGE_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftmm.h b/src/freetype/freetype/ftmm.h
new file mode 100644 (file)
index 0000000..db5db04
--- /dev/null
@@ -0,0 +1,175 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmm.h                                                                 */
+/*                                                                         */
+/*    FreeType Multiple Master font interface (specification).             */
+/*                                                                         */
+/*  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 FTMM_H
+#define FTMM_H
+
+#include <freetype/t1tables.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_MM_Axis                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to model a given axis in design space for  */
+  /*    Multiple Masters fonts.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    name    :: The axis's name.                                        */
+  /*                                                                       */
+  /*    minimum :: The axis's minimum design coordinate.                   */
+  /*                                                                       */
+  /*    maximum :: The axis's maximum design coordinate.                   */
+  /*                                                                       */
+  typedef struct  FT_MM_Axis_
+  {
+    FT_String*  name;
+    FT_Long     minimum;
+    FT_Long     maximum;
+
+  } FT_MM_Axis;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Multi_Master                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model the axes and space of a Multiple Masters */
+  /*    font.                                                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_axis    :: Number of axes.  Cannot exceed 4.                   */
+  /*                                                                       */
+  /*    num_designs :: Number of designs; should ne normally 2^num_axis    */
+  /*                   even though the Type 1 specification strangely      */
+  /*                   allows for intermediate designs to be present. This */
+  /*                   number cannot exceed 16.                            */
+  /*                                                                       */
+  /*    axis        :: A table of axis descriptors.                        */
+  /*                                                                       */
+  typedef struct  FT_Multi_Master_
+  {
+    FT_UInt     num_axis;
+    FT_UInt     num_designs;
+    FT_MM_Axis  axis[T1_MAX_MM_AXIS];
+
+  } FT_Multi_Master;
+
+
+  typedef FT_Error  (*FT_Get_MM_Func)( FT_Face           face,
+                                       FT_Multi_Master*  master );
+
+  typedef FT_Error  (*FT_Set_MM_Design_Func)( FT_Face   face,
+                                              FT_UInt   num_coords,
+                                              FT_Long*  coords );
+
+  typedef FT_Error  (*FT_Set_MM_Blend_Func)( FT_Face   face,
+                                             FT_UInt   num_coords,
+                                             FT_Long*  coords );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Multi_Master                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the Multiple Master descriptor of a given font.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the source face.                             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    master :: The Multiple Masters descriptor.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Get_Multi_Master( FT_Face           face,
+                                                  FT_Multi_Master*  master );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_MM_Design_Coordinates                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Masters fonts, choose an interpolated font design     */
+  /*    through design coordinates.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /*    num_coords :: The number of design coordinates (must be equal to   */
+  /*                  the number of axes in the font).                     */
+  /*                                                                       */
+  /*    coords     :: The design coordinates.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Set_MM_Design_Coordinates(
+                               FT_Face   face,
+                               FT_UInt   num_coords,
+                               FT_Long*  coords );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_MM_Blend_Coordinates                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Masters fonts, choose an interpolated font design     */
+  /*    through normalized blend coordinates.                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /*    num_coords :: The number of design coordinates (must be equal to   */
+  /*                  the number of axes in the font).                     */
+  /*                                                                       */
+  /*    coords     :: The design coordinates (each one must be between 0   */
+  /*                  and 1.0).                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Set_MM_Blend_Coordinates(
+                               FT_Face    face,
+                               FT_UInt    num_coords,
+                               FT_Fixed*  coords );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* FTMM_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftmodule.h b/src/freetype/freetype/ftmodule.h
new file mode 100644 (file)
index 0000000..3c09aa2
--- /dev/null
@@ -0,0 +1,274 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmodule.h                                                             */
+/*                                                                         */
+/*    FreeType modules public interface (specification).                   */
+/*                                                                         */
+/*  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 FTMODULE_H
+#define FTMODULE_H
+
+#include <freetype/freetype.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* module bit flags */
+  typedef enum  FT_Module_Flags_
+  {
+    ft_module_font_driver         = 1,     /* this module is a font driver  */
+    ft_module_renderer            = 2,     /* this module is a renderer     */
+    ft_module_hinter              = 4,     /* this module is a glyph hinter */
+    ft_module_styler              = 8,     /* this module is a styler       */
+
+    ft_module_driver_scalable     = 0x100, /* the driver supports scalable  */
+                                           /* fonts                         */
+    ft_module_driver_no_outlines  = 0x200, /* the driver does not support   */
+                                           /* vector outlines               */
+    ft_module_driver_has_hinter   = 0x400  /* the driver provides its own   */
+                                           /* hinter                        */
+
+  } FT_Module_Flags;
+
+
+  typedef void  (*FT_Module_Interface)( void );
+
+  typedef FT_Error  (*FT_Module_Constructor)( FT_Module  module );
+
+  typedef void  (*FT_Module_Destructor)( FT_Module  module );
+
+  typedef FT_Module_Interface (*FT_Module_Requester)( FT_Module    module,
+                                                      const char*  name );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Module_Class                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The module class descriptor.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    module_flags      :: Bit flags describing the module.              */
+  /*                                                                       */
+  /*    module_size       :: The size of one module object/instance in     */
+  /*                         bytes.                                        */
+  /*                                                                       */
+  /*    module_name       :: The name of the module.                       */
+  /*                                                                       */
+  /*    module_version    :: The version, as a 16.16 fixed number          */
+  /*                         (major.minor).                                */
+  /*                                                                       */
+  /*    module_requires   :: The version of FreeType this module requires  */
+  /*                         (starts at version 2.0, i.e 0x20000)          */
+  /*                                                                       */
+  /*    module_init       :: A function used to initialize (not create) a  */
+  /*                         new module object.                            */
+  /*                                                                       */
+  /*    module_done       :: A function used to finalize (not destroy) a   */
+  /*                         given module object                           */
+  /*                                                                       */
+  /*    get_interface     :: Queries a given module for a specific         */
+  /*                         interface by name.                            */
+  /*                                                                       */
+  typedef struct  FT_Module_Class_
+  {
+    FT_ULong               module_flags;
+    FT_Int                 module_size;
+    const FT_String*       module_name;
+    FT_Fixed               module_version;
+    FT_Fixed               module_requires;
+
+    const void*            module_interface;
+
+    FT_Module_Constructor  module_init;
+    FT_Module_Destructor   module_done;
+    FT_Module_Requester    get_interface;
+
+  } FT_Module_Class;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add_Module                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds a new module to a given library instance.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the library object.                         */
+  /*                                                                       */
+  /*    clazz   :: A pointer to class descriptor for the module.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error will be returned if a module already exists by that name, */
+  /*    or if the module requires a version of FreeType that is too great. */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Add_Module( FT_Library              library,
+                                            const FT_Module_Class*  clazz );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Module                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds a module by its name.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object.                     */
+  /*                                                                       */
+  /*    module_name :: The module's name (as an ASCII string).             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A module handle.  0 if none was found.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should better be familiar with FreeType internals to know      */
+  /*    which module to look for :-)                                       */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Module )  FT_Get_Module( FT_Library   library,
+                                             const char*  module_name );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Remove_Module                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Removes a given module from a library instance.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a library object.                           */
+  /*                                                                       */
+  /*    module  :: A handle to a module object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The module object is destroyed by the function in case of success. */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Remove_Module( FT_Library  library,
+                                               FT_Module   module );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Library                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to create a new FreeType library instance    */
+  /*    from a given memory object.  It is thus possible to use libraries  */
+  /*    with distinct memory allocators within the same program.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory   :: A handle to the original memory object.                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    alibrary :: A pointer to handle of a new library object.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_New_Library( FT_Memory    memory,
+                                             FT_Library*  library );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Library                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given library object.  This closes all drivers and      */
+  /*    discards all resource objects.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the target library.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Done_Library( FT_Library  library );
+
+
+
+  typedef void  (*FT_DebugHook_Func)( void*  arg );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Debug_Hook                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets a debug hook function for debugging the interpreter of a font */
+  /*    format.                                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library    :: A handle to the library object.                      */
+  /*                                                                       */
+  /*    hook_index :: The index of the debug hook.  You should use the     */
+  /*                  values defined in ftobjs.h, e.g.                     */
+  /*                  FT_DEBUG_HOOK_TRUETYPE                               */
+  /*                                                                       */
+  /*    debug_hook :: The function used to debug the interpreter.          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Currently, four debug hook slots are available, but only two (for  */
+  /*    the TrueType and the Type 1 interpreter) are defined.              */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Set_Debug_Hook( FT_Library         library,
+                                            FT_UInt            hook_index,
+                                            FT_DebugHook_Func  debug_hook );
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add_Default_Modules                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds the set of default drivers to a given library object.         */
+  /*    This is only useful when you create a library object with          */
+  /*    FT_New_Library() (usually to plug a custom memory manager).        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library :: A handle to a new library object.                       */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Add_Default_Modules( FT_Library  library );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTMODULE_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftnames.h b/src/freetype/freetype/ftnames.h
new file mode 100644 (file)
index 0000000..2969214
--- /dev/null
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftnames.h                                                              */
+/*                                                                         */
+/*    Simple interface to access SFNT name tables (which are used          */
+/*    to hold font names, copyright info, notices, etc.).                  */
+/*                                                                         */
+/*    This is _not_ used to retrieve glyph names!                          */
+/*                                                                         */
+/*  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 FTNAMES_H
+#define FTNAMES_H
+
+
+#include <freetype/freetype.h>
+
+
+  typedef struct  FT_SfntName_
+  {
+    FT_UShort  platform_id;
+    FT_UShort  encoding_id;
+    FT_UShort  language_id;
+    FT_UShort  name_id;
+  
+    FT_Byte*   string;
+    FT_UInt    string_len;  /* in bytes */
+  
+  } FT_SfntName;
+
+
+  FT_EXPORT_DEF( FT_UInt )  FT_Get_Sfnt_Name_Count( FT_Face  face );
+  
+  FT_EXPORT_DEF( FT_Error )  FT_Get_Sfnt_Name( FT_Face       face,
+                                               FT_UInt       index,
+                                               FT_SfntName*  aname );
+                                               
+
+#endif /* FTNAMES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftoutln.h b/src/freetype/freetype/ftoutln.h
new file mode 100644 (file)
index 0000000..1e448bd
--- /dev/null
@@ -0,0 +1,344 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftoutln.h                                                              */
+/*                                                                         */
+/*    Support for the FT_Outline type used to store glyph shapes of        */
+/*    most scalable font formats (specification).                          */
+/*                                                                         */
+/*  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 FTOUTLN_H
+#define FTOUTLN_H
+
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Decompose                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Walks over an outline's structure to decompose it into individual  */
+  /*    segments and Bezier arcs.  This function is also able to emit      */
+  /*    `move to' and `close to' operations to indicate the start and end  */
+  /*    of new contours in the outline.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline   :: A pointer to the source target.                       */
+  /*                                                                       */
+  /*    interface :: A table of `emitters', i.e,. function pointers called */
+  /*                 during decomposition to indicate path operations.     */
+  /*                                                                       */
+  /*    user      :: A typeless pointer which is passed to each emitter    */
+  /*                 during the decomposition.  It can be used to store    */
+  /*                 the state during the decomposition.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means sucess.                              */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_Decompose(
+                               FT_Outline*        outline,
+                               FT_Outline_Funcs*  interface,
+                               void*              user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_New                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new outline of a given size.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object from where the       */
+  /*                   outline is allocated.  Note however that the new    */
+  /*                   outline will NOT necessarily be FREED, when         */
+  /*                   destroying the library, by FT_Done_FreeType().      */
+  /*                                                                       */
+  /*    numPoints   :: The maximal number of points within the outline.    */
+  /*                                                                       */
+  /*    numContours :: The maximal number of contours within the outline.  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    outline     :: A handle to the new outline.  NULL in case of       */
+  /*                   error.                                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    No.                                                                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The reason why this function takes a `library' parameter is simply */
+  /*    to use the library's memory allocator.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_New( FT_Library   library,
+                                             FT_UInt      numPoints,
+                                             FT_Int       numContours,
+                                             FT_Outline*  outline );
+
+
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_New_Internal(
+                               FT_Memory    memory,
+                               FT_UInt      numPoints,
+                               FT_Int       numContours,
+                               FT_Outline*  outline );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Done                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys an outline created with FT_Outline_New().                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle of the library object used to allocate the     */
+  /*               outline.                                                */
+  /*                                                                       */
+  /*    outline :: A pointer to the outline object to be discarded.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    No.                                                                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the outline's `owner' field is not set, only the outline        */
+  /*    descriptor will be released.                                       */
+  /*                                                                       */
+  /*    The reason why this function takes an `outline' parameter is       */
+  /*    simply to use FT_Free().                                           */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_Done( FT_Library   library,
+                                              FT_Outline*  outline );
+
+
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_Done_Internal( FT_Memory    memory,
+                                                       FT_Outline*  outline );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_CBox                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns an outline's `control box'.  The control box encloses all  */
+  /*    the outline's points, including Bezier control points.  Though it  */
+  /*    coincides with the exact bounding box for most glyphs, it can be   */
+  /*    slightly larger in some situations (like when rotating an outline  */
+  /*    which contains Bezier outside arcs).                               */
+  /*                                                                       */
+  /*    Computing the control box is very fast, while getting the bounding */
+  /*    box can take much more time as it needs to walk over all segments  */
+  /*    and arcs in the outline.  To get the latter, you can use the       */
+  /*    `ftbbox' component which is dedicated to this single task.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    cbox    :: The outline's control box.                              */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Outline_Get_CBox( FT_Outline*  outline,
+                                              FT_BBox*     cbox );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Translate                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Applies a simple translation to the points of an outline.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /*    xOffset :: The horizontal offset.                                  */
+  /*                                                                       */
+  /*    yOffset :: The vertical offset.                                    */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Outline_Translate( FT_Outline*  outline,
+                                               FT_Pos       xOffset,
+                                               FT_Pos       yOffset );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Copy                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Copies an outline into another one.  Both objects must have the    */
+  /*    same sizes (number of points & number of contours) when this       */
+  /*    function is called.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    source :: A handle to the source outline.                          */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    target :: A handle to the target outline.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_Copy( FT_Outline*  source,
+                                              FT_Outline*  target );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Vector_Transform                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Transforms a single vector through a 2x2 matrix.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    vector :: The target vector to transform.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to the source 2x2 matrix.                      */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    Yes.                                                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The result is undefined if either `vector' or `matrix' is invalid. */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Outline_Transform( FT_Outline*  outline,
+                                               FT_Matrix*   matrix );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Reverse                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reverses the drawing direction of an outline.  This is used to     */
+  /*    ensure consistent fill conventions for mirrored glyphs.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This functions toggles the bit flag `ft_outline_reverse_fill' in   */
+  /*    the outline's `flags' field.                                       */
+  /*                                                                       */
+  /*    It shouldn't be used by a normal client application, unless it     */
+  /*    knows what it is doing.                                            */
+  /*                                                                       */
+  FT_EXPORT_DEF( void )  FT_Outline_Reverse( FT_Outline*  outline );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_Bitmap                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders an outline within a bitmap.  The outline's image is simply */
+  /*    OR-ed to the target bitmap.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a FreeType library object.                  */
+  /*                                                                       */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /*    map     :: A pointer to the target bitmap descriptor.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    YES.  Rendering is synchronized, so that concurrent calls to the   */
+  /*    scan-line converter will be serialized.                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT CREATE the bitmap, it only renders an       */
+  /*    outline image within the one you pass to it!                       */
+  /*                                                                       */
+  /*    It will use the raster correponding to the default glyph format.   */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_Get_Bitmap( FT_Library   library,
+                                                    FT_Outline*  outline,
+                                                    FT_Bitmap*   bitmap );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Render                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders an outline within a bitmap using the current scan-convert. */
+  /*    This functions uses an FT_Raster_Params structure as an argument,  */
+  /*    allowing advanced features like direct composition, translucency,  */
+  /*    etc.                                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a FreeType library object.                  */
+  /*                                                                       */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /*    params  :: A pointer to a FT_Raster_Params structure used to       */
+  /*               describe the rendering operation.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <MT-Note>                                                             */
+  /*    YES.  Rendering is synchronized, so that concurrent calls to the   */
+  /*    scan-line converter will be serialized.                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should know what you are doing and how FT_Raster_Params works  */
+  /*    to use this function.                                              */
+  /*                                                                       */
+  /*    The field `params.source' will be set to `outline' before the scan */
+  /*    converter is called, which means that the value you give to it is  */
+  /*    actually ignored.                                                  */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )  FT_Outline_Render( FT_Library         library,
+                                                FT_Outline*        outline,
+                                                FT_Raster_Params*  params );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTOUTLN_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftrender.h b/src/freetype/freetype/ftrender.h
new file mode 100644 (file)
index 0000000..fe5acd2
--- /dev/null
@@ -0,0 +1,191 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrender.h                                                             */
+/*                                                                         */
+/*    FreeType renderer modules public interface (specification).          */
+/*                                                                         */
+/*  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 FTRENDER_H
+#define FTRENDER_H
+
+#include <freetype/ftmodule.h>
+#include <freetype/ftglyph.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* create a new glyph object */
+  typedef FT_Error  (*FT_Glyph_Init_Func)( FT_Glyph      glyph,
+                                           FT_GlyphSlot  slot );
+
+  /* destroys a given glyph object */
+  typedef void  (*FT_Glyph_Done_Func)( FT_Glyph  glyph );
+
+  typedef void  (*FT_Glyph_Transform_Func)( FT_Glyph    glyph,
+                                            FT_Matrix*  matrix,
+                                            FT_Vector*  delta );
+
+  typedef void  (*FT_Glyph_BBox_Func)( FT_Glyph  glyph,
+                                       FT_BBox*  abbox );
+
+  typedef FT_Error  (*FT_Glyph_Copy_Func)( FT_Glyph   source,
+                                           FT_Glyph   target );
+
+  typedef FT_Error  (*FT_Glyph_Prepare_Func)( FT_Glyph      glyph,
+                                              FT_GlyphSlot  slot );
+
+  struct  FT_Glyph_Class_
+  {
+    FT_UInt                  glyph_size;
+    FT_Glyph_Format          glyph_format;
+    FT_Glyph_Init_Func       glyph_init;
+    FT_Glyph_Done_Func       glyph_done;
+    FT_Glyph_Copy_Func       glyph_copy;
+    FT_Glyph_Transform_Func  glyph_transform;
+    FT_Glyph_BBox_Func       glyph_bbox;
+    FT_Glyph_Prepare_Func    glyph_prepare;
+  };
+
+
+  typedef FT_Error  (*FTRenderer_render)( FT_Renderer   renderer,
+                                          FT_GlyphSlot  slot,
+                                          FT_UInt       mode,
+                                          FT_Vector*    origin );
+
+  typedef FT_Error  (*FTRenderer_transform)( FT_Renderer   renderer,
+                                             FT_GlyphSlot  slot,
+                                             FT_Matrix*    matrix,
+                                             FT_Vector*    delta );
+
+  typedef void  (*FTRenderer_getCBox)( FT_Renderer   renderer,
+                                       FT_GlyphSlot  slot,
+                                       FT_BBox*      cbox );
+
+  typedef FT_Error  (*FTRenderer_setMode)( FT_Renderer  renderer,
+                                           FT_ULong     mode_tag,
+                                           FT_Pointer   mode_ptr );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Renderer_Class                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The renderer module class descriptor.                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root         :: The root FT_Module_Class fields.                   */
+  /*                                                                       */
+  /*    glyph_format :: The glyph image format this renderer handles.      */
+  /*                                                                       */
+  /*    render_glyph :: A method used to render the image that is in a     */
+  /*                    given glyph slot into a bitmap.                    */
+  /*                                                                       */
+  /*    set_mode     :: A method used to pass additional parameters.       */
+  /*                                                                       */
+  /*    raster_class :: For `ft_glyph_format_outline' renderers only, this */
+  /*                    is a pointer to its raster's class.                */
+  /*                                                                       */
+  /*    raster       :: For `ft_glyph_format_outline' renderers only. this */
+  /*                    is a pointer to the corresponding raster object,   */
+  /*                    if any.                                            */
+  /*                                                                       */
+  typedef struct  FT_Renderer_Class_
+  {
+    FT_Module_Class       root;
+
+    FT_Glyph_Format       glyph_format;
+
+    FTRenderer_render     render_glyph;
+    FTRenderer_transform  transform_glyph;
+    FTRenderer_getCBox    get_glyph_cbox;
+    FTRenderer_setMode    set_mode;
+
+    FT_Raster_Funcs*      raster_class;
+
+  } FT_Renderer_Class;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Renderer                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the current renderer for a given glyph format.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the library object.                         */
+  /*                                                                       */
+  /*    format  :: The glyph format.                                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A renderer handle.  0 if none found.                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error will be returned if a module already exists by that name, */
+  /*    or if the module requires a version of FreeType that is too great. */
+  /*                                                                       */
+  /*    To add a new renderer, simply use FT_Add_Module().  To retrieve a  */
+  /*    renderer by its name, use FT_Get_Module().                         */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Renderer )  FT_Get_Renderer( FT_Library       library,
+                                                 FT_Glyph_Format  format );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Renderer                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the current renderer to use, and set additional mode.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library    :: A handle to the library object.                      */
+  /*                                                                       */
+  /*    renderer   :: A handle to the renderer object.                     */
+  /*                                                                       */
+  /*    num_params :: The number of additional parameters.                 */
+  /*                                                                       */
+  /*    parameters :: Additional parameters.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In case of success, the renderer will be used to convert glyph     */
+  /*    images in the renderer's known format into bitmaps.                */
+  /*                                                                       */
+  /*    This doesn't change the current renderer for other formats.        */
+  /*                                                                       */
+  FT_EXPORT_DEF(FT_Error) FT_Set_Renderer( FT_Library     library,
+                                           FT_Renderer    renderer,
+                                           FT_UInt        num_params,
+                                           FT_Parameter*  parameters );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTRENDER_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ftsystem.h b/src/freetype/freetype/ftsystem.h
new file mode 100644 (file)
index 0000000..bc74bce
--- /dev/null
@@ -0,0 +1,101 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsystem.h                                                             */
+/*                                                                         */
+/*    FreeType low-level system interface definition (specification).      */
+/*                                                                         */
+/*  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 FTSYSTEM_H
+#define FTSYSTEM_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  M E M O R Y   M A N A G E M E N T                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  typedef struct FT_MemoryRec_*  FT_Memory;
+
+
+  typedef void*  (*FT_Alloc_Func)( FT_Memory  memory,
+                                   long       size );
+
+  typedef void  (*FT_Free_Func)( FT_Memory  memory,
+                                 void*      block );
+
+  typedef void*  (*FT_Realloc_Func)( FT_Memory  memory,
+                                     long       cur_size,
+                                     long       new_size,
+                                     void*      block );
+
+
+  struct FT_MemoryRec_
+  {
+    void*            user;
+    FT_Alloc_Func    alloc;
+    FT_Free_Func     free;
+    FT_Realloc_Func  realloc;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       I / O   M A N A G E M E N T                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  typedef union  FT_StreamDesc_
+  {
+    long   value;
+    void*  pointer;
+
+  } FT_StreamDesc;
+
+
+  typedef struct FT_StreamRec_*  FT_Stream;
+
+
+  typedef unsigned long  (*FT_Stream_IO)( FT_Stream       stream,
+                                          unsigned long   offset,
+                                          unsigned char*  buffer,
+                                          unsigned long   count );
+
+  typedef void  (*FT_Stream_Close)( FT_Stream  stream );
+
+
+  struct  FT_StreamRec_
+  {
+    unsigned char*   base;
+    unsigned long    size;
+    unsigned long    pos;
+
+    FT_StreamDesc    descriptor;
+    FT_StreamDesc    pathname;    /* ignored by FreeType -- */
+                                  /* useful for debugging   */
+    FT_Stream_IO     read;
+    FT_Stream_Close  close;
+
+    FT_Memory        memory;
+    unsigned char*   cursor;
+    unsigned char*   limit;
+  };
+
+
+#endif /* FTSYSTEM_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/fttypes.h b/src/freetype/freetype/fttypes.h
new file mode 100644 (file)
index 0000000..ec90906
--- /dev/null
@@ -0,0 +1,400 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fttypes.h                                                              */
+/*                                                                         */
+/*    FreeType simple types definitions (specification only).              */
+/*                                                                         */
+/*  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 FTTYPES_H
+#define FTTYPES_H
+
+
+#include <freetype/ftsystem.h>
+#include <freetype/ftimage.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Bool                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef of unsigned char, used for simple booleans.              */
+  /*                                                                       */
+  typedef unsigned char  FT_Bool;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_FWord                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A signed 16-bit integer used to store a distance in original font  */
+  /*    units.                                                             */
+  /*                                                                       */
+  typedef signed short  FT_FWord;   /* distance in FUnits */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_UFWord                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An unsigned 16-bit integer used to store a distance in original    */
+  /*    font units.                                                        */
+  /*                                                                       */
+  typedef unsigned short  FT_UFWord;  /* unsigned distance */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Char                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for the _signed_ char type.                       */
+  /*                                                                       */
+  typedef signed char  FT_Char;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Byte                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for the _unsigned_ char type.                     */
+  /*                                                                       */
+  typedef unsigned char  FT_Byte;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_String                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for the char type, usually used for strings.      */
+  /*                                                                       */
+  typedef char  FT_String;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Short                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for signed short.                                        */
+  /*                                                                       */
+  typedef signed short  FT_Short;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_UShort                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for unsigned short.                                      */
+  /*                                                                       */
+  typedef unsigned short  FT_UShort;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Int                                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for the int type.                                        */
+  /*                                                                       */
+  typedef int  FT_Int;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_UInt                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for the unsigned int type.                               */
+  /*                                                                       */
+  typedef unsigned int  FT_UInt;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Long                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for signed long.                                         */
+  /*                                                                       */
+  typedef signed long  FT_Long;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_ULong                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for unsigned long.                                       */
+  /*                                                                       */
+  typedef unsigned long  FT_ULong;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_F2Dot14                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A signed 2.14 fixed float type used for unit vectors.              */
+  /*                                                                       */
+  typedef signed short  FT_F2Dot14;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_F26Dot6                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A signed 26.6 fixed float type used for vectorial pixel            */
+  /*    coordinates.                                                       */
+  /*                                                                       */
+  typedef signed long  FT_F26Dot6;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Fixed                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This type is used to store 16.16 fixed float values, like scales   */
+  /*    or matrix coefficients.                                            */
+  /*                                                                       */
+  typedef signed long  FT_Fixed;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Error                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The FreeType error code type.  A value of 0 is always interpreted  */
+  /*    as a successful operation.                                         */
+  /*                                                                       */
+  typedef int  FT_Error;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Pointer                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for a typeless pointer.                           */
+  /*                                                                       */
+  typedef void*  FT_Pointer;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_UnitVector                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to store a 2D vector unit vector.  Uses    */
+  /*    FT_F2Dot14 types.                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x :: Horizontal coordinate.                                        */
+  /*                                                                       */
+  /*    y :: Vertical coordinate.                                          */
+  /*                                                                       */
+  typedef struct  FT_UnitVector_
+  {
+    FT_F2Dot14  x;
+    FT_F2Dot14  y;
+
+  } FT_UnitVector;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Matrix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to store a 2x2 matrix.  Coefficients are   */
+  /*    in 16.16 fixed float format.  The computation performed is:        */
+  /*                                                                       */
+  /*       {                                                               */
+  /*          x' = x*xx + y*xy                                             */
+  /*          y' = x*yx + y*yy                                             */
+  /*       }                                                               */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    xx :: Matrix coefficient.                                          */
+  /*                                                                       */
+  /*    xy :: Matrix coefficient.                                          */
+  /*                                                                       */
+  /*    yx :: Matrix coefficient.                                          */
+  /*                                                                       */
+  /*    yy :: Matrix coefficient.                                          */
+  /*                                                                       */
+  typedef struct  FT_Matrix_
+  {
+    FT_Fixed  xx, xy;
+    FT_Fixed  yx, yy;
+
+  } FT_Matrix;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_BBox                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold an outline's bounding box, i.e., the      */
+  /*    coordinates of its extrema in the horizontal and vertical          */
+  /*    directions.                                                        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    xMin :: The horizontal minimum (left-most).                        */
+  /*                                                                       */
+  /*    yMin :: The vertical minimum (bottom-most).                        */
+  /*                                                                       */
+  /*    xMax :: The horizontal maximum (right-most).                       */
+  /*                                                                       */
+  /*    yMax :: The vertical maximum (top-most).                           */
+  /*                                                                       */
+  typedef struct  FT_BBox_
+  {
+    FT_Pos  xMin, yMin;
+    FT_Pos  xMax, yMax;
+
+  } FT_BBox;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_MAKE_TAG                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro converts four letter tags which are used to label       */
+  /*    TrueType tables into an unsigned long to be used within FreeType.  */
+  /*                                                                       */
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
+          ( ( (FT_ULong)_x1 << 24 ) |     \
+            ( (FT_ULong)_x2 << 16 ) |     \
+            ( (FT_ULong)_x3 <<  8 ) |     \
+              (FT_ULong)_x4         )
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                    L I S T   M A N A G E M E N T                      */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_ListNode                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*     Many elements and objects in FreeType are listed through a        */
+  /*     FT_List record (see FT_ListRec).  As its name suggests, a         */
+  /*     FT_ListNode is a handle to a single list element.                 */
+  /*                                                                       */
+  typedef struct FT_ListNodeRec_*  FT_ListNode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_List                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a list record (see FT_ListRec).                        */
+  /*                                                                       */
+  typedef struct FT_ListRec_*  FT_List;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_ListNodeRec                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold a single list element.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    prev :: The previous element in the list.  NULL if first.          */
+  /*                                                                       */
+  /*    next :: The next element in the list.  NULL if last.               */
+  /*                                                                       */
+  /*    data :: A typeless pointer to the listed object.                   */
+  /*                                                                       */
+  typedef struct  FT_ListNodeRec_
+  {
+    FT_ListNode  prev;
+    FT_ListNode  next;
+    void*        data;
+
+  } FT_ListNodeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_ListRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold a simple doubly-linked list.  These are   */
+  /*    used in many parts of FreeType.                                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    head :: The head (first element) of doubly-linked list.            */
+  /*                                                                       */
+  /*    tail :: The tail (last element) of doubly-linked list.             */
+  /*                                                                       */
+  typedef struct  FT_ListRec_
+  {
+    FT_ListNode  head;
+    FT_ListNode  tail;
+
+  } FT_ListRec;
+
+
+#define FT_IS_EMPTY( list )  ( (list).head == 0 )
+
+
+#endif /* FTTYPES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/autohint.h b/src/freetype/freetype/internal/autohint.h
new file mode 100644 (file)
index 0000000..5d35a5d
--- /dev/null
@@ -0,0 +1,195 @@
+/***************************************************************************/
+/*                                                                         */
+/*  autohint.h                                                             */
+/*                                                                         */
+/*    High-level `autohint' module-specific interface (specification).     */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The auto-hinter is used to load and automatically hint glyphs if a    */
+  /* format-specific hinter isn't available.                               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef AUTOHINT_H
+#define AUTOHINT_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A small technical note regarding automatic hinting in order to        */
+  /* clarify this module interface.                                        */
+  /*                                                                       */
+  /* An automatic hinter might compute two kinds of data for a given face: */
+  /*                                                                       */
+  /* - global hints: Usually some metrics that describe global properties  */
+  /*                 of the face.  It is computed by scanning more or less */
+  /*                 agressively the glyphs in the face, and thus can be   */
+  /*                 very slow to compute (even if the size of global      */
+  /*                 hints is really small).                               */
+  /*                                                                       */
+  /* - glyph hints:  These describe some important features of the glyph   */
+  /*                 outline, as well as how to align them.  They are      */
+  /*                 generally much faster to compute than global hints.   */
+  /*                                                                       */
+  /* The current FreeType auto-hinter does a pretty good job while         */
+  /* performing fast computations for both global and glyph hints.         */
+  /* However, we might be interested in introducing more complex and       */
+  /* powerful algorithms in the future, like the one described in the John */
+  /* D. Hobby paper, which unfortunately requires a lot more horsepower.   */
+  /*                                                                       */
+  /* Because a sufficiently sophisticated font management system would     */
+  /* typically implement an LRU cache of opened face objects to reduce     */
+  /* memory usage, it is a good idea to be able to avoid recomputing       */
+  /* global hints every time the same face is re-opened.                   */
+  /*                                                                       */
+  /* We thus provide the ability to cache global hints outside of the face */
+  /* object, in order to speed up font re-opening time.  Of course, this   */
+  /* feature is purely optional, so most client programs won't even notice */
+  /* it.                                                                   */
+  /*                                                                       */
+  /* I initially thought that it would be a good idea to cache the glyph   */
+  /* hints too.  However, my general idea now is that if you really need   */
+  /* to cache these too, you are simply in need of a new font format,      */
+  /* where all this information could be stored within the font file and   */ 
+  /* decoded on the fly.                                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/freetype.h>
+
+
+  typedef struct FT_AutoHinterRec_  *FT_AutoHinter;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Get_Global_Func                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the global hints computed for a given face object the    */
+  /*    resulting data is dissociated from the face and will survive a     */
+  /*    call to FT_Done_Face(). It must be discarded through the API       */
+  /*    FT_AutoHinter_Done_Global_Func().                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    hinter        :: A handle to the source auto-hinter.               */
+  /*                                                                       */
+  /*    face          :: A handle to the source face object.               */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    global_hints  :: A typeless pointer to the global hints.           */
+  /*                                                                       */
+  /*    global_len    :: The size in bytes of the global hints.            */
+  /*                                                                       */
+  typedef void  (*FT_AutoHinter_Get_Global_Func)(
+                  FT_AutoHinter  hinter,
+                  FT_Face        face,
+                  void**         global_hints,
+                  long*          global_len );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Done_Global_Func                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards the global hints retrieved through                        */
+  /*    FT_AutoHinter_Get_Global_Func().  This is the only way these hints */
+  /*    are freed from memory.                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    hinter :: A handle to the auto-hinter module.                      */
+  /*                                                                       */
+  /*    global :: A pointer to retrieved global hints to discard.          */
+  /*                                                                       */
+  typedef void  (*FT_AutoHinter_Done_Global_Func)( FT_AutoHinter  hinter,
+                                                   void*          global );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Reset_Func                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to recompute the global metrics in a given   */
+  /*    font.  This is useful when global font data changes (e.g. Multiple */
+  /*    Masters fonts where blend coordinates change).                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    hinter :: A handle to the source auto-hinter.                      */
+  /*                                                                       */
+  /*    face   :: A handle to the face.                                    */
+  /*                                                                       */
+  typedef void  (*FT_AutoHinter_Reset_Func)( FT_AutoHinter  hinter,
+                                             FT_Face        face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Load_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to load, scale, and automatically hint a     */
+  /*    glyph from a given face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the face.                               */
+  /*    glyph_index :: The glyph index.                                    */
+  /*    load_flags  :: The load flags.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is capable of loading composite glyphs by hinting    */
+  /*    each sub-glyph independently (which improves quality).             */
+  /*                                                                       */
+  /*    It will call the font driver with FT_Load_Glyph(), with            */
+  /*    FT_LOAD_NO_SCALE set.                                              */
+  /*                                                                       */
+  typedef FT_Error  (*FT_AutoHinter_Load_Func)( FT_AutoHinter  hinter,
+                                                FT_GlyphSlot   slot,
+                                                FT_Size        size,
+                                                FT_UInt        glyph_index,
+                                                FT_ULong       load_flags );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_AutoHinter_Interface                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The auto-hinter module's interface.                                */
+  /*                                                                       */
+  typedef struct  FT_AutoHinter_Interface
+  {
+    FT_AutoHinter_Reset_Func        reset_face;
+    FT_AutoHinter_Load_Func         load_glyph;
+
+    FT_AutoHinter_Get_Global_Func   get_global_hints;
+    FT_AutoHinter_Done_Global_Func  done_global_hints;
+
+  } FT_AutoHinter_Interface;
+
+
+#endif /* AUTOHINT_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftcalc.h b/src/freetype/freetype/internal/ftcalc.h
new file mode 100644 (file)
index 0000000..99b6cfa
--- /dev/null
@@ -0,0 +1,123 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcalc.h                                                               */
+/*                                                                         */
+/*    Arithmetic computations (specification).                             */
+/*                                                                         */
+/*  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 FTCALC_H
+#define FTCALC_H
+
+#include <freetype/freetype.h>
+#include <freetype/config/ftconfig.h>   /* for LONG64 */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+#ifdef LONG64
+
+
+  typedef INT64  FT_Int64;
+
+#define ADD_64( x, y, z )  z = (x) + (y)
+#define MUL_64( x, y, z )  z = (FT_Int64)(x) * (y)
+
+#define DIV_64( x, y )     ( (x) / (y) )
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+#define SQRT_64( z )  FT_Sqrt64( z )
+
+  FT_EXPORT_DEF( FT_Int32 )  FT_Sqrt64( FT_Int64  l );
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#else /* LONG64 */
+
+
+  typedef struct  FT_Int64_
+  {
+    FT_UInt32  lo;
+    FT_UInt32  hi;
+
+  } FT_Int64;
+
+
+#define ADD_64( x, y, z )  FT_Add64( &x, &y, &z )
+#define MUL_64( x, y, z )  FT_MulTo64( x, y, &z )
+#define DIV_64( x, y )     FT_Div64by32( &x, y )
+
+
+  FT_EXPORT_DEF( void )  FT_Add64( FT_Int64*  x,
+                                   FT_Int64*  y,
+                                   FT_Int64*  z );
+
+  FT_EXPORT_DEF( void )  FT_MulTo64( FT_Int32   x,
+                                     FT_Int32   y,
+                                     FT_Int64*  z );
+
+  FT_EXPORT_DEF( FT_Int32 )  FT_Div64by32( FT_Int64*  x,
+                                           FT_Int32   y );
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+#define SQRT_64( z )  FT_Sqrt64( &z )
+
+  FT_EXPORT_DEF( FT_Int32 )  FT_Sqrt64( FT_Int64*  x );
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#endif /* LONG64 */
+
+
+#ifndef FT_CONFIG_OPTION_OLD_CALCS
+
+#define SQRT_32( x )  FT_Sqrt32( x )
+
+  BASE_DEF( FT_Int32 )  FT_Sqrt32( FT_Int32  x );
+
+#endif /* !FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FT_MulDiv() and FT_MulFix() are declared in freetype.h.               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define INT_TO_F26DOT6( x )    ( (FT_Long)(x) << 6  )
+#define INT_TO_F2DOT14( x )    ( (FT_Long)(x) << 14 )
+#define INT_TO_FIXED( x )      ( (FT_Long)(x) << 16 )
+#define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) << 2  )
+#define FLOAT_TO_FIXED( x )    ( (FT_Long)( x * 65536.0 ) )
+
+#define ROUND_F26DOT6( x )     ( x >= 0 ? (    ( (x) + 32 ) & -64 )     \
+                                        : ( -( ( 32 - (x) ) & -64 ) ) )
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* FTCALC_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftdebug.h b/src/freetype/freetype/internal/ftdebug.h
new file mode 100644 (file)
index 0000000..8b1e4dd
--- /dev/null
@@ -0,0 +1,225 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftdebug.h                                                              */
+/*                                                                         */
+/*    Debugging and logging component (specification).                     */
+/*                                                                         */
+/*  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 FTDEBUG_H
+#define FTDEBUG_H
+
+#include <freetype/config/ftconfig.h>   /* for FT_DEBUG_LEVEL_TRACE, */
+                                        /* FT_DEBUG_LEVEL_ERROR      */
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* A very stupid pre-processor trick.  See K&R version 2 */
+  /* section A12.3 for details...                          */
+  /*                                                       */
+  /* It is also described in the section `Separate         */
+  /* Expansion of Macro Arguments' in the info file        */
+  /* `cpp.info', describing GNU cpp.                       */
+  /*                                                       */
+#define FT_CAT( x, y )   x ## y
+#define FT_XCAT( x, y )  FT_CAT( x, y )
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+
+  /* note that not all levels are used currently */
+
+  typedef enum  FT_Trace_
+  {
+    /* the first level must always be `trace_any' */
+    trace_any = 0,
+
+    /* base components */
+    trace_aaraster,  /* anti-aliasing raster    (ftgrays.c)  */
+    trace_calc,      /* calculations            (ftcalc.c)   */
+    trace_extend,    /* extension manager       (ftextend.c) */
+    trace_glyph,     /* glyph manager           (ftglyph.c)  */
+    trace_io,        /* i/o monitoring          (ftsystem.c) */
+    trace_init,      /* initialization          (ftinit.c)   */
+    trace_list,      /* list manager            (ftlist.c)   */
+    trace_memory,    /* memory manager          (ftobjs.c)   */
+    trace_mm,        /* MM interface            (ftmm.c)     */
+    trace_objs,      /* base objects            (ftobjs.c)   */
+    trace_outline,   /* outline management      (ftoutln.c)  */
+    trace_raster,    /* rasterizer              (ftraster.c) */
+    trace_stream,    /* stream manager          (ftstream.c) */
+
+    /* SFNT driver components */
+    trace_sfobjs,    /* SFNT object handler     (sfobjs.c)   */
+    trace_ttcmap,    /* charmap handler         (ttcmap.c)   */
+    trace_ttload,    /* basic TrueType tables   (ttload.c)   */
+    trace_ttpost,    /* PS table processing     (ttpost.c)   */
+    trace_ttsbit,    /* TrueType sbit handling  (ttsbit.c)   */
+
+    /* TrueType driver components */
+    trace_ttdriver,  /* TT font driver          (ttdriver.c) */
+    trace_ttgload,   /* TT glyph loader         (ttgload.c)  */
+    trace_ttinterp,  /* bytecode interpreter    (ttinterp.c) */
+    trace_ttobjs,    /* TT objects manager      (ttobjs.c)   */
+    trace_ttpload,   /* TT data/program loader  (ttpload.c)  */
+
+    /* Type 1 driver components */
+    trace_t1driver,
+    trace_t1gload,
+    trace_t1hint,
+    trace_t1load,
+    trace_t1objs,
+
+    /* experimental Type 1 driver components */
+    trace_z1driver,
+    trace_z1gload,
+    trace_z1hint,
+    trace_z1load,
+    trace_z1objs,
+    trace_z1parse,
+
+    /* Type 2 driver components */
+    trace_t2driver,
+    trace_t2gload,
+    trace_t2load,
+    trace_t2objs,
+    trace_t2parse,
+
+    /* CID driver components */
+    trace_cidafm,
+    trace_ciddriver,
+    trace_cidgload,
+    trace_cidload,
+    trace_cidobjs,
+    trace_cidparse,
+
+    /* Windows fonts component */
+    trace_winfnt,
+
+    /* the last level must always be `trace_max' */
+    trace_max
+
+  } FT_Trace;
+
+
+  /* declared in ftdebug.c */
+  extern char  ft_trace_levels[trace_max];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IMPORTANT!                                                            */
+  /*                                                                       */
+  /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */
+  /* value before using any TRACE macro.                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define FT_TRACE( level, varformat )                      \
+          do                                              \
+          {                                               \
+            if ( ft_trace_levels[FT_COMPONENT] >= level ) \
+              FT_XCAT( FT_Message, varformat );           \
+          } while ( 0 )
+
+
+  FT_EXPORT_DEF( void )  FT_SetTraceLevel( FT_Trace  component,
+                                           char      level );
+
+
+#elif defined( FT_DEBUG_LEVEL_ERROR )
+
+
+#define FT_TRACE( level, varformat )  do ; while ( 0 )      /* nothing */
+
+
+#else  /* release mode */
+
+
+#define FT_Assert( condition )        do ; while ( 0 )      /* nothing */
+
+#define FT_TRACE( level, varformat )  do ; while ( 0 )      /* nothing */
+#define FT_ERROR( varformat )         do ; while ( 0 )      /* nothing */
+
+
+#endif /* FT_DEBUG_LEVEL_TRACE, FT_DEBUG_LEVEL_ERROR */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define macros and functions that are common to the debug and trace    */
+  /* modes.                                                                */
+  /*                                                                       */
+  /* You need vprintf() to be able to compile ftdebug.c.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#if defined( FT_DEBUG_LEVEL_TRACE ) || defined( FT_DEBUG_LEVEL_ERROR )
+
+
+#include "stdio.h"  /* for vprintf() */
+
+
+#define FT_Assert( condition )                                      \
+          do                                                        \
+          {                                                         \
+            if ( !( condition ) )                                   \
+              FT_Panic( "assertion failed on line %d of file %s\n", \
+                        __LINE__, __FILE__ );                       \
+          } while ( 0 )
+
+  /* print a message */
+  FT_EXPORT_DEF( void )  FT_Message( const char*  fmt, ... );
+
+  /* print a message and exit */
+  FT_EXPORT_DEF( void )  FT_Panic( const char*  fmt, ... );
+
+#define FT_ERROR( varformat )  FT_XCAT( FT_Message, varformat )
+
+
+#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* You need two opening resp. closing parentheses!                       */
+  /*                                                                       */
+  /* Example: FT_TRACE0(( "Value is %i", foo ))                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#define FT_TRACE0( varformat )  FT_TRACE( 0, varformat )
+#define FT_TRACE1( varformat )  FT_TRACE( 1, varformat )
+#define FT_TRACE2( varformat )  FT_TRACE( 2, varformat )
+#define FT_TRACE3( varformat )  FT_TRACE( 3, varformat )
+#define FT_TRACE4( varformat )  FT_TRACE( 4, varformat )
+#define FT_TRACE5( varformat )  FT_TRACE( 5, varformat )
+#define FT_TRACE6( varformat )  FT_TRACE( 6, varformat )
+#define FT_TRACE7( varformat )  FT_TRACE( 7, varformat )
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTDEBUG_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftdriver.h b/src/freetype/freetype/internal/ftdriver.h
new file mode 100644 (file)
index 0000000..592de49
--- /dev/null
@@ -0,0 +1,182 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftdriver.h                                                             */
+/*                                                                         */
+/*    FreeType font driver interface (specification).                      */
+/*                                                                         */
+/*  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 FTDRIVER_H
+#define FTDRIVER_H
+
+
+#include <freetype/ftmodule.h>
+#include <freetype/config/ftconfig.h>
+
+
+  typedef FT_Error  (*FTDriver_initFace)( FT_Stream      stream,
+                                          FT_Face        face,
+                                          FT_Int         typeface_index,
+                                          FT_Int         num_params,
+                                          FT_Parameter*  parameters );
+
+  typedef void  (*FTDriver_doneFace)( FT_Face  face );
+
+
+  typedef FT_Error  (*FTDriver_initSize)( FT_Size  size );
+
+  typedef void  (*FTDriver_doneSize)( FT_Size  size );
+
+
+  typedef FT_Error  (*FTDriver_initGlyphSlot)( FT_GlyphSlot  slot );
+
+  typedef void  (*FTDriver_doneGlyphSlot)( FT_GlyphSlot  slot );
+
+
+  typedef FT_Error  (*FTDriver_setCharSizes)( FT_Size     size,
+                                              FT_F26Dot6  char_width,
+                                              FT_F26Dot6  char_height,
+                                              FT_UInt     horz_resolution,
+                                              FT_UInt     vert_resolution );
+
+  typedef FT_Error  (*FTDriver_setPixelSizes)( FT_Size  size,
+                                               FT_UInt  pixel_width,
+                                               FT_UInt  pixel_height );
+
+  typedef FT_Error  (*FTDriver_loadGlyph)( FT_GlyphSlot  slot,
+                                           FT_Size       size,
+                                           FT_UInt       glyph_index,
+                                           FT_Int        load_flags );
+
+
+  typedef FT_UInt  (*FTDriver_getCharIndex)( FT_CharMap  charmap,
+                                             FT_Long     charcode );
+
+  typedef FT_Error  (*FTDriver_getKerning)( FT_Face      face,
+                                            FT_UInt      left_glyph,
+                                            FT_UInt      right_glyph,
+                                            FT_Vector*   kerning );
+
+
+  typedef FT_Error  (*FTDriver_attachFile)( FT_Face    face,
+                                            FT_Stream  stream );
+
+
+  typedef FT_Error  (*FTDriver_getAdvances)( FT_Face     face,
+                                             FT_UInt     first,
+                                             FT_UInt     count,
+                                             FT_Bool     vertical,
+                                             FT_UShort*  advances );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Driver_Class                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The font driver class.  This structure mostly contains pointers to */
+  /*    driver methods.                                                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root             :: The parent module.                             */
+  /*                                                                       */
+  /*    face_object_size :: The size of a face object in bytes.            */
+  /*                                                                       */
+  /*    size_object_size :: The size of a size object in bytes.            */
+  /*                                                                       */
+  /*    slot_object_size :: The size of a glyph object in bytes.           */
+  /*                                                                       */
+  /*    init_face        :: The format-specific face constructor.          */
+  /*                                                                       */
+  /*    done_face        :: The format-specific face destructor.           */
+  /*                                                                       */
+  /*    init_size        :: The format-specific size constructor.          */
+  /*                                                                       */
+  /*    done_size        :: The format-specific size destructor.           */
+  /*                                                                       */
+  /*    init_slot        :: The format-specific slot constructor.          */
+  /*                                                                       */
+  /*    done_slot        :: The format-specific slot destructor.           */
+  /*                                                                       */
+  /*    set_char_sizes   :: A handle to a function used to set the new     */
+  /*                        character size in points + resolution.  Can be */
+  /*                        set to 0 to indicate default behaviour.        */
+  /*                                                                       */
+  /*    set_pixel_sizes  :: A handle to a function used to set the new     */
+  /*                        character size in pixels.  Can be set to 0 to  */
+  /*                        indicate default behaviour.                    */
+  /*                                                                       */
+  /*    load_glyph       :: A function handle to load a given glyph image  */
+  /*                        in a slot.  This field is mandatory!           */
+  /*                                                                       */
+  /*    get_char_index   :: A function handle to return the glyph index of */
+  /*                        a given character for a given charmap.  This   */
+  /*                        field is mandatory!                            */
+  /*                                                                       */
+  /*    get_kerning      :: A function handle to return the unscaled       */
+  /*                        kerning for a given pair of glyphs.  Can be    */
+  /*                        set to 0 if the format doesn't support         */
+  /*                        kerning.                                       */
+  /*                                                                       */
+  /*    attach_file      :: This function handle is used to read           */
+  /*                        additional data for a face from another        */
+  /*                        file/stream.  For example, this can be used to */
+  /*                        add data from AFM or PFM files on a Type 1     */
+  /*                        face, or a CIDMap on a CID-keyed face.         */
+  /*                                                                       */
+  /*    get_advances     :: A function handle used to return the advances  */
+  /*                        of 'count' glyphs, starting at `index'.  the   */
+  /*                        `vertical' flags must be set when vertical     */
+  /*                        advances are queried.  The advances buffer is  */
+  /*                        caller-allocated.                              */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Most function pointers, with the exception of `load_glyph' and     */
+  /*    `get_char_index' can be set to 0 to indicate a default behaviour.  */
+  /*                                                                       */
+  typedef struct  FT_Driver_Class_
+  {
+    FT_Module_Class         root;
+
+    FT_Int                  face_object_size;
+    FT_Int                  size_object_size;
+    FT_Int                  slot_object_size;
+
+    FTDriver_initFace       init_face;
+    FTDriver_doneFace       done_face;
+
+    FTDriver_initSize       init_size;
+    FTDriver_doneSize       done_size;
+
+    FTDriver_initGlyphSlot  init_slot;
+    FTDriver_doneGlyphSlot  done_slot;
+
+    FTDriver_setCharSizes   set_char_sizes;
+    FTDriver_setPixelSizes  set_pixel_sizes;
+
+    FTDriver_loadGlyph      load_glyph;
+    FTDriver_getCharIndex   get_char_index;
+
+    FTDriver_getKerning     get_kerning;
+    FTDriver_attachFile     attach_file;
+
+    FTDriver_getAdvances    get_advances;
+
+  } FT_Driver_Class;
+
+
+#endif /* FTDRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftextend.h b/src/freetype/freetype/internal/ftextend.h
new file mode 100644 (file)
index 0000000..fdd2c6e
--- /dev/null
@@ -0,0 +1,178 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftextend.h                                                             */
+/*                                                                         */
+/*    FreeType extensions implementation (specification).                  */
+/*                                                                         */
+/*  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 FTEXTEND_H
+#define FTEXTEND_H
+
+
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The extensions don't need to be integrated at compile time into the   */
+  /* engine, only at link time.                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Extension_Initializer                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each new face object can have several extensions associated with   */
+  /*    it at creation time.  This function is used to initialize given    */
+  /*    extension data for a given face.                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    ext  :: A typeless pointer to the extension data.                  */
+  /*                                                                       */
+  /*    face :: A handle to the source face object the extension is        */
+  /*            associated with.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In case of error, the initializer should not destroy the extension */
+  /*    data, as the finalizer will get called later by the function's     */
+  /*    caller.                                                            */
+  /*                                                                       */
+  typedef FT_Error  (*FT_Extension_Initializer)( void*    ext,
+                                                 FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Extension_Finalizer                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each new face object can have several extensions associated with   */
+  /*    it at creation time.  This function is used to finalize given      */
+  /*    extension data for a given face; it occurs before the face object  */
+  /*    itself is finalized.                                               */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*   ext  :: A typeless pointer to the extension data.                   */
+  /*                                                                       */
+  /*   face :: A handle to the source face object the extension is         */
+  /*           associated with.                                            */
+  /*                                                                       */
+  typedef void  (*FT_Extension_Finalizer)( void*    ext,
+                                           FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Extension_Class                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to describe a given extension to the       */
+  /*    FreeType base layer.  An FT_Extension_Class is used as a parameter */
+  /*    for FT_Register_Extension().                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    id        :: The extension's ID.  This is a normal C string that   */
+  /*                 is used to uniquely reference the extension's         */
+  /*                 interface.                                            */
+  /*                                                                       */
+  /*    size      :: The size in bytes of the extension data that must be  */
+  /*                 associated with each face object.                     */
+  /*                                                                       */
+  /*    init      :: A pointer to the extension data's initializer.        */
+  /*                                                                       */
+  /*    finalize  :: A pointer to the extension data's finalizer.          */
+  /*                                                                       */
+  /*    interface :: This pointer can be anything, but should usually      */
+  /*                 point to a table of function pointers which implement */
+  /*                 the extension's interface.                            */
+  /*                                                                       */
+  /*    offset    :: This field is set and used within the base layer and  */
+  /*                 should be set to 0 when registering an extension      */
+  /*                 through FT_Register_Extension().  It contains an      */
+  /*                 offset within the face's extension block for the      */
+  /*                 current extension's data.                             */
+  /*                                                                       */
+  typedef struct  FT_Extension_Class_
+  {
+    const char*               id;
+    FT_ULong                  size;
+    FT_Extension_Initializer  init;
+    FT_Extension_Finalizer    finalize;
+    void*                     interface;
+
+    FT_ULong                  offset;
+
+  } FT_Extension_Class;
+
+
+  FT_EXPORT_DEF( FT_Error )  FT_Register_Extension(
+                               FT_Driver            driver,
+                               FT_Extension_Class*  clazz );
+
+
+#ifdef FT_CONFIG_OPTION_EXTEND_ENGINE
+
+
+  /* Initialize the extension component */
+  LOCAL_DEF
+  FT_Error  FT_Init_Extensions( FT_Library  library );
+
+  /* Finalize the extension component */
+  LOCAL_DEF
+  FT_Error  FT_Done_Extensions( FT_Library  library );
+
+  /* Create an extension within a face object.  Called by the */
+  /* face object constructor.                                 */
+  LOCAL_DEF
+  FT_Error  FT_Create_Extensions( FT_Face  face );
+
+  /* Destroy all extensions within a face object.  Called by the */
+  /* face object destructor.                                     */
+  LOCAL_DEF
+  FT_Error  FT_Destroy_Extensions( FT_Face  face );
+
+
+#endif
+
+
+  /* return an extension's data & interface according to its ID */
+  FT_EXPORT_DEF( void* )  FT_Get_Extension(
+                            FT_Face      face,
+                            const char*  extension_id,
+                            void**       extension_interface );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTEXTEND_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftlist.h b/src/freetype/freetype/internal/ftlist.h
new file mode 100644 (file)
index 0000000..7c6d8ed
--- /dev/null
@@ -0,0 +1,113 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftlist.c                                                               */
+/*                                                                         */
+/*    Generic list support for FreeType (specification).                   */
+/*                                                                         */
+/*  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 implements functions relative to list processing.  Its     */
+  /*  data structures are defined in `freetype.h'.                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTLIST_H
+#define FTLIST_H
+
+#include <freetype/freetype.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  FT_EXPORT_DEF( FT_ListNode )  FT_List_Find( FT_List  list,
+                                              void*    data );
+
+  FT_EXPORT_DEF( void )  FT_List_Add( FT_List      list,
+                                      FT_ListNode  node );
+
+  FT_EXPORT_DEF( void )  FT_List_Insert( FT_List      list,
+                                         FT_ListNode  node );
+
+  FT_EXPORT_DEF( void )  FT_List_Remove( FT_List      list,
+                                         FT_ListNode  node );
+
+  FT_EXPORT_DEF( void )  FT_List_Up( FT_List      list,
+                                     FT_ListNode  node );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_List_Iterator                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An FT_List iterator function which is called during a list parse   */
+  /*    by FT_List_Iterate().                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    node :: The current iteration list node.                           */
+  /*                                                                       */
+  /*    user :: A typeless pointer passed to FT_List_Iterate().            */
+  /*            Can be used to point to the iteration's state.             */
+  /*                                                                       */
+  typedef FT_Error  (*FT_List_Iterator)( FT_ListNode  node,
+                                         void*        user );
+
+
+  FT_EXPORT_DEF( FT_Error )  FT_List_Iterate( FT_List           list,
+                                              FT_List_Iterator  iterator,
+                                              void*             user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_List_Destructor                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An FT_List iterator function which is called during a list         */
+  /*    finalization by FT_List_Finalize() to destroy all elements in a    */
+  /*    given list.                                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    system :: The current system object.                               */
+  /*                                                                       */
+  /*    data   :: The current object to destroy.                           */
+  /*                                                                       */
+  /*    user   :: A typeless pointer passed to FT_List_Iterate().  It can  */
+  /*              be used to point to the iteration's state.               */
+  /*                                                                       */
+  typedef void  (*FT_List_Destructor)( FT_Memory  memory,
+                                       void*      data,
+                                       void*      user );
+
+
+  FT_EXPORT_DEF( void )  FT_List_Finalize( FT_List             list,
+                                           FT_List_Destructor  destroy,
+                                           FT_Memory           memory,
+                                           void*               user );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* FTLIST_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftmemory.h b/src/freetype/freetype/internal/ftmemory.h
new file mode 100644 (file)
index 0000000..da8d3a4
--- /dev/null
@@ -0,0 +1,127 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmemory.h                                                             */
+/*                                                                         */
+/*    The FreeType memory management macros (specification).               */
+/*                                                                         */
+/*  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 FTMEMORY_H
+#define FTMEMORY_H
+
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/fttypes.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_SET_ERROR                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro is used to set an implicit `error' variable to a given  */
+  /*    expression's value (usually a function call), and convert it to a  */
+  /*    boolean which is set whenever the value is != 0.                   */
+  /*                                                                       */
+#undef  FT_SET_ERROR
+#define FT_SET_ERROR( expression ) \
+          ( ( error = (expression) ) != 0 )
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           M E M O R Y                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  BASE_DEF( FT_Error )  FT_Alloc( FT_Memory  memory,
+                                  FT_Long    size,
+                                  void**     P );
+
+  BASE_DEF( FT_Error )  FT_Realloc( FT_Memory  memory,
+                                    FT_Long    current,
+                                    FT_Long    size,
+                                    void**     P );
+
+  BASE_DEF( void )  FT_Free( FT_Memory  memory,
+                             void**     P );
+
+
+
+  /* This `#include' is needed by the MEM_xxx() macros; it should be */
+  /* available on all platforms we know of.                          */
+#include <string.h>
+
+#define MEM_Set( dest, byte, count )  memset( dest, byte, count )
+
+#define MEM_Copy( dest, source, count )  memcpy( dest, source, count )
+
+#define MEM_Move( dest, source, count )  memmove( dest, source, count )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* We now support closures to produce completely reentrant code.  This   */
+  /* means the allocation functions now takes an additional argument       */
+  /* (`memory').  It is a handle to a given memory object, responsible for */
+  /* all low-level operations, including memory management and             */
+  /* synchronisation.                                                      */
+  /*                                                                       */
+  /* In order to keep our code readable and use the same macros in the     */
+  /* font drivers and the rest of the library, MEM_Alloc(), ALLOC(), and   */
+  /* ALLOC_ARRAY() now use an implicit variable, `memory'.  It must be     */
+  /* defined at all locations where a memory operation is queried.         */
+  /*                                                                       */
+#define MEM_Alloc( _pointer_, _size_ )                     \
+          FT_Alloc( memory, _size_, (void**)&(_pointer_) )
+
+#define MEM_Alloc_Array( _pointer_, _count_, _type_ )    \
+          FT_Alloc( memory, (_count_)*sizeof ( _type_ ), \
+                    (void**)&(_pointer_) )
+
+#define MEM_Realloc( _pointer_, _current_, _size_ )                     \
+          FT_Realloc( memory, _current_, _size_, (void**)&(_pointer_) )
+
+#define MEM_Realloc_Array( _pointer_, _current_, _new_, _type_ )        \
+          FT_Realloc( memory, (_current_)*sizeof ( _type_ ),            \
+                      (_new_)*sizeof ( _type_ ), (void**)&(_pointer_) )
+
+#define ALLOC( _pointer_, _size_ )                       \
+          FT_SET_ERROR( MEM_Alloc( _pointer_, _size_ ) )
+
+#define REALLOC( _pointer_, _current_, _size_ )                       \
+          FT_SET_ERROR( MEM_Realloc( _pointer_, _current_, _size_ ) )
+
+#define ALLOC_ARRAY( _pointer_, _count_, _type_ )       \
+          FT_SET_ERROR( MEM_Alloc( _pointer_,           \
+                        (_count_)*sizeof ( _type_ ) ) )
+
+#define REALLOC_ARRAY( _pointer_, _current_, _count_, _type_ ) \
+          FT_SET_ERROR( MEM_Realloc( _pointer_,                \
+                        (_current_)*sizeof ( _type_ ),         \
+                        (_count_)*sizeof ( _type_ ) ) )
+
+#define FREE( _pointer_ )  FT_Free( memory, (void**)&(_pointer_) )
+
+
+#endif /* FTMEMORY_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftobjs.h b/src/freetype/freetype/internal/ftobjs.h
new file mode 100644 (file)
index 0000000..0d0f5d8
--- /dev/null
@@ -0,0 +1,532 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftobjs.h                                                               */
+/*                                                                         */
+/*    The FreeType private base classes (specification).                   */
+/*                                                                         */
+/*  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 contains the definition of all internal FreeType classes.  */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTOBJS_H
+#define FTOBJS_H
+
+#include <freetype/internal/ftmemory.h>
+#include <freetype/ftrender.h>
+#include <freetype/internal/ftdriver.h>
+#include <freetype/internal/autohint.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Some generic definitions.                                             */
+  /*                                                                       */
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef NULL
+#define NULL  (void*)0
+#endif
+
+#ifndef UNUSED
+#define UNUSED( arg )  ( (arg)=(arg) )
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The min and max functions missing in C.  As usual, be careful not to  */
+  /* write things like MIN( a++, b++ ) to avoid side effects.              */
+  /*                                                                       */
+#ifndef MIN
+#define MIN( a, b )  ( (a) < (b) ? (a) : (b) )
+#endif
+
+#ifndef MAX
+#define MAX( a, b )  ( (a) > (b) ? (a) : (b) )
+#endif
+
+#ifndef ABS
+#define ABS( a )     ( (a) < 0 ? -(a) : (a) )
+#endif
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                         M O D U L E S                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_ModuleRec                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A module object instance.                                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    clazz   :: A pointer to the module's class.                        */
+  /*                                                                       */
+  /*    library :: A handle to the parent library object.                  */
+  /*                                                                       */
+  /*    memory  :: A handle to the memory manager.                         */
+  /*                                                                       */
+  /*    generic :: A generic structure for user-level extensibility (?).   */
+  /*                                                                       */
+  typedef struct  FT_ModuleRec_
+  {
+    FT_Module_Class*  clazz;
+    FT_Library        library;
+    FT_Memory         memory;
+    FT_Generic        generic;
+    
+  } FT_ModuleRec;
+
+
+  /* typecast an object to a FT_Module */
+#define FT_MODULE( x )          ((FT_Module)(x))
+#define FT_MODULE_CLASS( x )    FT_MODULE(x)->clazz
+#define FT_MODULE_LIBRARY( x )  FT_MODULE(x)->library
+#define FT_MODULE_MEMORY( x )   FT_MODULE(x)->memory
+
+#define FT_MODULE_IS_DRIVER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                    ft_module_font_driver )
+
+#define FT_MODULE_IS_RENDERER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                      ft_module_renderer )
+
+#define FT_MODULE_IS_HINTER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                    ft_module_hinter )
+
+#define FT_MODULE_IS_STYLER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                    ft_module_styler )
+
+#define FT_DRIVER_IS_SCALABLE( x )  ( FT_MODULE_CLASS(x)->module_flags & \
+                                      ft_module_driver_scalable )
+
+#define FT_DRIVER_USES_OUTLINES( x )  !( FT_MODULE_CLASS(x)->module_flags & \
+                                         ft_module_driver_no_outlines )
+
+#define FT_DRIVER_HAS_HINTER( x )  ( FT_MODULE_CLASS(x)->module_flags & \
+                                     ft_module_driver_has_hinter )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Module_Interface                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds a module and returns its specific interface as a typeless    */
+  /*    pointer.                                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object.                     */
+  /*                                                                       */
+  /*    module_name :: The module's name (as an ASCII string).             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A module-specific interface if available, 0 otherwise.             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should better be familiar with FreeType internals to know      */
+  /*    which module to look for, and what its interface is :-)            */
+  /*                                                                       */
+  BASE_DEF( const void* )  FT_Get_Module_Interface( FT_Library   library,
+                                                    const char*  mod_name );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* a few macros used to perform easy typecasts with minimal brain damage */
+
+#define FT_FACE( x )          ((FT_Face)(x))
+#define FT_SIZE( x )          ((FT_Size)(x))
+#define FT_SLOT( x )          ((FT_GlyphSlot)(x))
+  
+#define FT_FACE_DRIVER( x )   FT_FACE( x )->driver
+#define FT_FACE_LIBRARY( x )  FT_FACE_DRIVER( x )->root.library
+#define FT_FACE_MEMORY( x )   FT_FACE( x )->memory
+
+#define FT_SIZE_FACE( x )     FT_SIZE( x )->face
+#define FT_SLOT_FACE( x )     FT_SLOT( x )->face
+
+#define FT_FACE_SLOT( x )     FT_FACE( x )->glyph
+#define FT_FACE_SIZE( x )     FT_FACE( x )->size
+
+
+  /* this must be kept exported -- tt will be used later in our own */
+  /* high-level caching font manager called SemTex (way after the   */
+  /* 2.0 release though                                             */
+  FT_EXPORT_DEF( FT_Error )  FT_New_Size( FT_Face   face,
+                                          FT_Size*  size );
+
+  FT_EXPORT_DEF( FT_Error )  FT_Done_Size( FT_Size  size );
+
+
+  FT_EXPORT_DEF( FT_Error )  FT_New_GlyphSlot( FT_Face        face,
+                                               FT_GlyphSlot*  aslot );
+
+  FT_EXPORT_DEF( void )      FT_Done_GlyphSlot( FT_GlyphSlot  slot );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                   G L Y P H   L O A D E R                       ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS          1
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES      2
+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID        4
+#define FT_SUBGLYPH_FLAG_SCALE                   8
+#define FT_SUBGLYPH_FLAG_XY_SCALE             0x40
+#define FT_SUBGLYPH_FLAG_2X2                  0x80
+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS      0x200
+
+
+  enum
+  {
+    ft_glyph_own_bitmap = 1
+  };
+
+
+  struct  FT_SubGlyph_
+  {
+    FT_Int     index;
+    FT_UShort  flags;
+    FT_Int     arg1;
+    FT_Int     arg2;
+    FT_Matrix  transform;
+  };
+
+
+  typedef struct  FT_GlyphLoad_
+  {
+    FT_Outline    outline;       /* outline             */
+    FT_UInt       num_subglyphs; /* number of subglyphs */
+    FT_SubGlyph*  subglyphs;     /* subglyphs           */
+    FT_Vector*    extra_points;  /* extra points table  */
+  
+  } FT_GlyphLoad;
+
+
+  struct  FT_GlyphLoader_
+  {
+    FT_Memory     memory;
+    FT_UInt       max_points;
+    FT_UInt       max_contours;
+    FT_UInt       max_subglyphs;
+    FT_Bool       use_extra;
+
+    FT_GlyphLoad  base;
+    FT_GlyphLoad  current;
+
+    void*         other;            /* for possible future extension? */
+    
+  };
+
+
+  BASE_DEF( FT_Error )  FT_GlyphLoader_New( FT_Memory         memory,
+                                            FT_GlyphLoader**  aloader );
+                                          
+  BASE_DEF( FT_Error )  FT_GlyphLoader_Create_Extra(
+                          FT_GlyphLoader*  loader );                                        
+  
+  BASE_DEF( void )  FT_GlyphLoader_Done( FT_GlyphLoader*  loader );
+  
+  BASE_DEF( void )  FT_GlyphLoader_Reset( FT_GlyphLoader*  loader );
+  
+  BASE_DEF( void )  FT_GlyphLoader_Rewind( FT_GlyphLoader*  loader );
+  
+  BASE_DEF( FT_Error )  FT_GlyphLoader_Check_Points(
+                          FT_GlyphLoader*  loader,
+                          FT_UInt          n_points,
+                          FT_UInt          n_contours );
+                               
+  BASE_DEF( FT_Error )  FT_GlyphLoader_Check_Subglyphs(
+                          FT_GlyphLoader*  loader,
+                          FT_UInt          n_subs );
+
+  BASE_DEF( void )  FT_GlyphLoader_Prepare( FT_GlyphLoader*  loader );
+
+  BASE_DEF( void )  FT_GlyphLoader_Add( FT_GlyphLoader*  loader );
+
+  BASE_DEF( FT_Error )  FT_GlyphLoader_Copy_Points( FT_GlyphLoader*  target,
+                                                    FT_GlyphLoader*  source );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                        R E N D E R E R S                        ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FT_RENDERER( x )      ((FT_Renderer)( x ))
+#define FT_GLYPH( x )         ((FT_Glyph)( x ))
+#define FT_BITMAP_GLYPH( x )  ((FT_BitmapGlyph)( x ))
+#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x ))
+
+
+  typedef struct  FT_RendererRec_
+  {
+    FT_ModuleRec           root;
+    FT_Renderer_Class*     clazz;
+    FT_Glyph_Format        glyph_format;
+    const FT_Glyph_Class   glyph_class;
+
+    FT_Raster              raster;
+    FT_Raster_Render_Func  raster_render;
+    FTRenderer_render      render;
+  
+  } FT_RendererRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                    F O N T   D R I V E R S                      ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* typecast a module into a driver easily */
+#define FT_DRIVER( x )        ((FT_Driver)(x))
+
+  /* typecast a module as a driver, and get its driver class */
+#define FT_DRIVER_CLASS( x )  FT_DRIVER( x )->clazz
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_DriverRec                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The root font driver class.  A font driver is responsible for      */
+  /*    managing and loading font files of a given format.                 */
+  /*                                                                       */
+  /*  <Fields>                                                             */
+  /*     root         :: Contains the fields of the root module class.     */
+  /*                                                                       */
+  /*     clazz        :: A pointer to the font driver's class.  Note that  */
+  /*                     this is NOT root.clazz.  `class' wasn't used      */
+  /*                     as it is a reserved word in C++.                  */
+  /*                                                                       */
+  /*     faces_list   :: The list of faces currently opened by this        */
+  /*                     driver.                                           */
+  /*                                                                       */
+  /*     extensions   :: A typeless pointer to the driver's extensions     */
+  /*                     registry, if they are supported through the       */
+  /*                     configuration macro FT_CONFIG_OPTION_EXTENSIONS.  */
+  /*                                                                       */
+  /*     glyph_loader :: The glyph loader for all faces managed by this    */
+  /*                     driver.  This object isn't defined for unscalable */
+  /*                     formats.                                          */
+  /*                                                                       */
+  typedef struct  FT_DriverRec_
+  {
+    FT_ModuleRec      root;
+    FT_Driver_Class*  clazz;
+    
+    FT_ListRec        faces_list;
+    void*             extensions;
+    
+    FT_GlyphLoader*   glyph_loader;
+
+  } FT_DriverRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                       L I B R A R I E S                         ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FT_DEBUG_HOOK_TRUETYPE   0
+#define FT_DEBUG_HOOK_TYPE1      1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_LibraryRec                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The FreeType library class.  This is the root of all FreeType      */
+  /*    data.  Use FT_New_Library() to create a library object, and        */
+  /*    FT_Done_Library() to discard it and all child objects.             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory           :: The library's memory object.  Manages memory   */
+  /*                        allocation.                                    */
+  /*                                                                       */
+  /*    generic          :: Client data variable.  Used to extend the      */
+  /*                        Library class by higher levels and clients.    */
+  /*                                                                       */
+  /*    num_modules      :: The number of modules currently registered     */
+  /*                        within this library.  This is set to 0 for new */
+  /*                        libraries.  New modules are added through the  */
+  /*                        FT_Add_Module() API function.                  */
+  /*                                                                       */
+  /*    modules          :: A table used to store handles to the currently */
+  /*                        registered modules. Note that each font driver */
+  /*                        contains a list of its opened faces.           */
+  /*                                                                       */
+  /*    renderers        :: The list of renderers currently registered     */
+  /*                        within the library.                            */
+  /*                                                                       */
+  /*    cur_renderer     :: The current outline renderer.  This is a       */
+  /*                        shortcut used to avoid parsing the list on     */
+  /*                        each call to FT_Outline_Render().  It is a     */
+  /*                        handle to the current renderer for the         */
+  /*                        ft_glyph_format_outline format.                */
+  /*                                                                       */
+  /*    auto_hinter      :: XXX                                            */
+  /*                                                                       */
+  /*    raster_pool      :: The raster object's render pool.  This can     */
+  /*                        ideally be changed dynamically at run-time.    */
+  /*                                                                       */
+  /*    raster_pool_size :: The size of the render pool in bytes.          */
+  /*                                                                       */
+  /*    debug_hooks      :: XXX                                            */
+  /*                                                                       */
+  typedef struct  FT_LibraryRec_
+  {
+    FT_Memory           memory;           /* library's memory manager */
+
+    FT_Generic          generic;
+
+    FT_UInt             num_modules;
+    FT_Module           modules[FT_MAX_MODULES];  /* module objects  */
+
+    FT_ListRec          renderers;        /* list of renderers        */
+    FT_Renderer         cur_renderer;     /* current outline renderer */
+    FT_Module           auto_hinter;
+
+    FT_Byte*            raster_pool;      /* scan-line conversion */
+                                          /* render pool          */
+    FT_ULong            raster_pool_size; /* size of render pool in bytes */
+
+    FT_DebugHook_Func   debug_hooks[4];
+
+  } FT_LibraryRec;
+
+
+  BASE_DEF( FT_Renderer )  FT_Lookup_Renderer( FT_Library       library,
+                                               FT_Glyph_Format  format,
+                                               FT_ListNode*     node );
+
+  BASE_DEF( FT_Error )  FT_Render_Glyph_Internal( FT_Library    library,
+                                                  FT_GlyphSlot  slot,
+                                                  FT_UInt       render_mode );
+
+  typedef FT_Error  (*FT_Glyph_Name_Requester)( FT_Face     face,
+                                                FT_UInt     glyph_index,
+                                                FT_Pointer  buffer,
+                                                FT_UInt     buffer_max );
+
+
+#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
+
+
+  FT_EXPORT_DEF( FT_Error )   FT_New_Stream( const char*  filepathname,
+                                             FT_Stream    astream );
+
+  FT_EXPORT_DEF( void )       FT_Done_Stream( FT_Stream  stream );
+
+  FT_EXPORT_DEF( FT_Memory )  FT_New_Memory( void );
+
+
+#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */
+
+
+  /* Define default raster's interface.  The default raster is located in  */
+  /* `src/base/ftraster.c'                                                 */
+  /*                                                                       */
+  /* Client applications can register new rasters through the              */
+  /* FT_Set_Raster() API.                                                  */
+
+#ifndef FT_NO_DEFAULT_RASTER
+  FT_EXPORT_VAR( FT_Raster_Funcs )  ft_default_raster;
+#endif
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTOBJS_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/ftstream.h b/src/freetype/freetype/internal/ftstream.h
new file mode 100644 (file)
index 0000000..365f479
--- /dev/null
@@ -0,0 +1,361 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftstream.h                                                             */
+/*                                                                         */
+/*    Stream handling(specification).                                      */
+/*                                                                         */
+/*  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 FTSTREAM_H
+#define FTSTREAM_H
+
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* format of an 8-bit frame_op value = [ xxxxx | e | s ] */
+  /* s is set to 1 if the value is signed,                 */
+  /* e is set to 1 if the value is little-endian           */
+  /* xxxxx is a command                                    */
+
+#define FT_FRAME_OP_SHIFT         2
+#define FT_FRAME_OP_SIGNED        1
+#define FT_FRAME_OP_LITTLE        2
+#define FT_FRAME_OP_COMMAND( x )  ( x >> FT_FRAME_OP_SHIFT )
+
+#define FT_MAKE_FRAME_OP( command, little, sign ) \
+          ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign )
+
+#define FT_FRAME_OP_END   0
+#define FT_FRAME_OP_START 1  /* start a new frame     */
+#define FT_FRAME_OP_BYTE  2  /* read 1-byte value     */
+#define FT_FRAME_OP_SHORT 3  /* read 2-byte value     */
+#define FT_FRAME_OP_LONG  4  /* read 4-byte value     */
+#define FT_FRAME_OP_OFF3  5  /* read 3-byte value     */
+#define FT_FRAME_OP_BYTES 6  /* read a bytes sequence */
+
+
+  typedef enum  FT_Frame_Op_
+  {
+    ft_frame_end       = 0,
+    ft_frame_start     = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ),
+
+    ft_frame_byte      = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE,  0, 0 ),
+    ft_frame_schar     = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE,  0, 1 ),
+
+    ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ),
+    ft_frame_short_be  = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ),
+    ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ),
+    ft_frame_short_le  = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ),
+
+    ft_frame_ulong_be  = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ),
+    ft_frame_ulong_le  = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ),
+    ft_frame_long_be   = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ),
+    ft_frame_long_le   = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ),
+
+    ft_frame_uoff3_be  = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ),
+    ft_frame_uoff3_le  = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ),
+    ft_frame_off3_be   = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ),
+    ft_frame_off3_le   = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ),
+  
+    ft_frame_bytes     = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ),
+    ft_frame_skip      = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 )
+
+  } FT_Frame_Op;
+
+
+  typedef struct  FT_Frame_Field_
+  {
+    FT_Frame_Op  value;
+    char         size;
+    FT_UShort    offset;
+
+  } FT_Frame_Field;
+
+
+  /* make-up a FT_Frame_Field out of a structure type and a field name */
+#define FT_FIELD_REF( s, f )  (((s*)0)->f)
+
+#define FT_FRAME_FIELD( frame_op, struct_type, field )            \
+          {                                                       \
+            frame_op,                                             \
+            sizeof ( FT_FIELD_REF( struct_type,field ) ),         \
+            (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \
+          }
+
+#define FT_MAKE_EMPTY_FIELD( frame_op )  { frame_op, 0, 0 }
+
+#define FT_FRAME_START( s )         { ft_frame_start, 0, s }
+#define FT_FRAME_END                { ft_frame_end, 0, 0 }
+
+#define FT_FRAME_LONG( s, f )       FT_FRAME_FIELD( ft_frame_long_be, s, f )
+#define FT_FRAME_ULONG( s, f )      FT_FRAME_FIELD( ft_frame_ulong_be, s, f )
+#define FT_FRAME_SHORT( s, f )      FT_FRAME_FIELD( ft_frame_short_be, s, f )
+#define FT_FRAME_USHORT( s, f )     FT_FRAME_FIELD( ft_frame_ushort_be, s, f )
+#define FT_FRAME_BYTE( s, f )       FT_FRAME_FIELD( ft_frame_byte, s, f )
+#define FT_FRAME_CHAR( s, f )       FT_FRAME_FIELD( ft_frame_schar, s, f )
+
+#define FT_FRAME_LONG_LE( s, f )    FT_FRAME_FIELD( ft_frame_long_le, s, f )
+#define FT_FRAME_ULONG_LE( s, f )   FT_FRAME_FIELD( ft_frame_ulong_le, s, f )
+#define FT_FRAME_SHORT_LE( s, f )   FT_FRAME_FIELD( ft_frame_short_le, s, f )
+#define FT_FRAME_USHORT_LE( s, f )  FT_FRAME_FIELD( ft_frame_ushort_le, s, f )
+
+#define FT_FRAME_SKIP_LONG          { ft_frame_long_be, 0, 0 }
+#define FT_FRAME_SKIP_SHORT         { ft_frame_short_be, 0, 0 }
+#define FT_FRAME_SKIP_BYTE          { ft_frame_byte, 0, 0 }
+
+#define FT_FRAME_BYTES( struct_type, field, count )               \
+          {                                                       \
+            ft_frame_bytes,                                       \
+            count,                                                \
+            (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \
+          }
+#define FT_FRAME_SKIP_BYTES( count )  { ft_frame_skip, count, 0 }
+            
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* integer extraction macros -- the `buffer' parameter must ALWAYS be of */
+  /* type `char*' or equivalent (1-byte elements).                         */
+  /*                                                                       */
+#define NEXT_Char( buffer )            \
+          ( (signed char)*buffer++ )
+#define NEXT_Byte( buffer )            \
+          ( (unsigned char)*buffer++ )
+
+#define NEXT_Short( buffer )                              \
+          ( buffer += 2,                                  \
+            ( (short)( (signed   char)buffer[-2] << 8 ) | \
+                       (unsigned char)buffer[-1]        ) )
+
+#define NEXT_UShort( buffer )                      \
+          ( (unsigned short)NEXT_Short( buffer ) )
+
+#define NEXT_Offset( buffer )                             \
+          ( buffer += 3,                                  \
+            ( ( (long)(signed   char)buffer[-3] << 16 ) | \
+              ( (long)(unsigned char)buffer[-2] <<  8 ) | \
+                (long)(unsigned char)buffer[-1]         ) )
+
+#define NEXT_UOffset( buffer )                     \
+          ( (unsigned long)NEXT_Offset( buffer ) )
+
+#define NEXT_Long( buffer )                               \
+          ( buffer += 4,                                  \
+            ( ( (long)(signed   char)buffer[-4] << 24 ) | \
+              ( (long)(unsigned char)buffer[-3] << 16 ) | \
+              ( (long)(unsigned char)buffer[-2] <<  8 ) | \
+                (long)(unsigned char)buffer[-1]         ) )
+
+#define NEXT_ULong( buffer )                     \
+          ( (unsigned long)NEXT_Long( buffer ) )
+
+
+#define NEXT_ShortLE( buffer )                            \
+          ( buffer += 2,                                  \
+            ( (short)( (signed   char)buffer[-1] << 8 ) | \
+                       (unsigned char)buffer[-2]        ) )
+
+#define NEXT_UShortLE( buffer )                      \
+          ( (unsigned short)NEXT_ShortLE( buffer ) )
+
+#define NEXT_OffsetLE( buffer )                           \
+          ( buffer += 3,                                  \
+            ( ( (long)(signed   char)buffer[-1] << 16 ) | \
+              ( (long)(unsigned char)buffer[-2] <<  8 ) | \
+                (long)(unsigned char)buffer[-3]         ) )
+
+#define NEXT_UOffsetLE( buffer )                     \
+          ( (unsigned long)NEXT_OffsetLE( buffer ) )
+
+
+#define NEXT_LongLE( buffer )                             \
+          ( buffer += 4,                                  \
+            ( ( (long)(signed   char)buffer[-1] << 24 ) | \
+              ( (long)(unsigned char)buffer[-2] << 16 ) | \
+              ( (long)(unsigned char)buffer[-3] <<  8 ) | \
+                (long)(unsigned char)buffer[-4]         ) )
+
+#define NEXT_ULongLE( buffer )                     \
+          ( (unsigned long)NEXT_LongLE( buffer ) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Each GET_xxxx() macro uses an implicit `stream' variable.             */
+  /*                                                                       */
+#define FT_GET_MACRO( func, type )        ( (type)func( stream ) )
+
+#define GET_Char()      FT_GET_MACRO( FT_Get_Char, FT_Char )
+#define GET_Byte()      FT_GET_MACRO( FT_Get_Char, FT_Byte )
+#define GET_Short()     FT_GET_MACRO( FT_Get_Short, FT_Short )
+#define GET_UShort()    FT_GET_MACRO( FT_Get_Short, FT_UShort )
+#define GET_Offset()    FT_GET_MACRO( FT_Get_Offset, FT_Long )
+#define GET_UOffset()   FT_GET_MACRO( FT_Get_Offset, FT_ULong )
+#define GET_Long()      FT_GET_MACRO( FT_Get_Long, FT_Long )
+#define GET_ULong()     FT_GET_MACRO( FT_Get_Long, FT_ULong )
+#define GET_Tag4()      FT_GET_MACRO( FT_Get_Long, FT_ULong )
+
+#define GET_ShortLE()   FT_GET_MACRO( FT_Get_ShortLE, FT_Short )
+#define GET_UShortLE()  FT_GET_MACRO( FT_Get_ShortLE, FT_UShort )
+#define GET_LongLE()    FT_GET_MACRO( FT_Get_LongLE, FT_Short )
+#define GET_ULongLE()   FT_GET_MACRO( FT_Get_LongLE, FT_Short )
+
+#define FT_READ_MACRO( func, type, var )        \
+          ( var = (type)func( stream, &error ), \
+            error != FT_Err_Ok )
+
+#define READ_Byte( var )      FT_READ_MACRO( FT_Read_Char, FT_Byte, var )
+#define READ_Char( var )      FT_READ_MACRO( FT_Read_Char, FT_Char, var )
+#define READ_Short( var )     FT_READ_MACRO( FT_Read_Short, FT_Short, var )
+#define READ_UShort( var )    FT_READ_MACRO( FT_Read_Short, FT_UShort, var )
+#define READ_Offset( var )    FT_READ_MACRO( FT_Read_Offset, FT_Long, var )
+#define READ_UOffset( var )   FT_READ_MACRO( FT_Read_Offset, FT_ULong, var )
+#define READ_Long( var )      FT_READ_MACRO( FT_Read_Long, FT_Long, var )
+#define READ_ULong( var )     FT_READ_MACRO( FT_Read_Long, FT_ULong, var )
+
+#define READ_ShortLE( var )   FT_READ_MACRO( FT_Read_ShortLE, FT_Short, var )
+#define READ_UShortLE( var )  FT_READ_MACRO( FT_Read_ShortLE, FT_UShort, var )
+#define READ_LongLE( var )    FT_READ_MACRO( FT_Read_LongLE, FT_Long, var )
+#define READ_ULongLE( var )   FT_READ_MACRO( FT_Read_LongLE, FT_ULong, var )
+
+
+  BASE_DEF( void )  FT_New_Memory_Stream( FT_Library  library,
+                                          FT_Byte*    base,
+                                          FT_ULong    size,
+                                          FT_Stream   stream );
+
+  BASE_DEF( FT_Error )  FT_Seek_Stream( FT_Stream  stream,
+                                        FT_ULong   pos );
+
+  BASE_DEF( FT_Error )  FT_Skip_Stream( FT_Stream  stream,
+                                        FT_Long    distance );
+
+  BASE_DEF( FT_Long )  FT_Stream_Pos( FT_Stream  stream );
+
+
+  BASE_DEF( FT_Error )  FT_Read_Stream( FT_Stream  stream,
+                                        FT_Byte*   buffer,
+                                        FT_ULong   count );
+
+  BASE_DEF( FT_Error )  FT_Read_Stream_At( FT_Stream  stream,
+                                           FT_ULong   pos,
+                                           FT_Byte*   buffer,
+                                           FT_ULong   count );
+
+  BASE_DEF( FT_Error )  FT_Access_Frame( FT_Stream  stream,
+                                         FT_ULong   count );
+
+  BASE_DEF( void )  FT_Forget_Frame( FT_Stream  stream );
+
+  BASE_DEF( FT_Error )  FT_Extract_Frame( FT_Stream  stream,
+                                          FT_ULong   count,
+                                          FT_Byte**  pbytes );
+
+  BASE_DEF( void )  FT_Release_Frame( FT_Stream  stream,
+                                      FT_Byte**  pbytes );
+
+  BASE_DEF( FT_Char )  FT_Get_Char( FT_Stream  stream );
+
+  BASE_DEF( FT_Short )  FT_Get_Short( FT_Stream  stream );
+
+  BASE_DEF( FT_Long )  FT_Get_Offset( FT_Stream  stream );
+
+  BASE_DEF( FT_Long )  FT_Get_Long( FT_Stream  stream );
+
+  BASE_DEF( FT_Short )  FT_Get_ShortLE( FT_Stream  stream );
+
+  BASE_DEF( FT_Long )  FT_Get_LongLE( FT_Stream  stream );
+
+
+  BASE_DEF( FT_Char )  FT_Read_Char( FT_Stream  stream,
+                                     FT_Error*  error );
+
+  BASE_DEF( FT_Short )  FT_Read_Short( FT_Stream  stream,
+                                       FT_Error*  error );
+
+  BASE_DEF( FT_Long )  FT_Read_Offset( FT_Stream  stream,
+                                       FT_Error*  error );
+
+  BASE_DEF( FT_Long )  FT_Read_Long( FT_Stream  stream,
+                                     FT_Error*  error );
+
+  BASE_DEF( FT_Short )  FT_Read_ShortLE( FT_Stream  stream,
+                                         FT_Error*  error );
+
+  BASE_DEF( FT_Long )  FT_Read_LongLE( FT_Stream  stream,
+                                       FT_Error*  error );
+
+  BASE_DEF( FT_Error )  FT_Read_Fields( FT_Stream              stream,
+                                        const FT_Frame_Field*  fields,
+                                        void*                  structure );
+
+
+#define USE_Stream( resource, stream )                       \
+          FT_SET_ERROR( FT_Open_Stream( resource, stream ) )
+
+#define DONE_Stream( stream )      \
+          FT_Done_Stream( stream )
+
+
+#define ACCESS_Frame( size )                              \
+          FT_SET_ERROR( FT_Access_Frame( stream, size ) )
+
+#define FORGET_Frame()              \
+          FT_Forget_Frame( stream )
+
+#define EXTRACT_Frame( size, bytes )                              \
+          FT_SET_ERROR( FT_Extract_Frame( stream, size,           \
+                                          (FT_Byte**)&(bytes) ) )
+          
+#define RELEASE_Frame( bytes )                            \
+          FT_Release_Frame( stream, (FT_Byte**)&(bytes) )
+
+#define FILE_Seek( position )                                \
+          FT_SET_ERROR( FT_Seek_Stream( stream, position ) )
+
+#define FILE_Skip( distance )                                \
+          FT_SET_ERROR( FT_Skip_Stream( stream, distance ) )
+
+#define FILE_Pos()                \
+          FT_Stream_Pos( stream )
+
+#define FILE_Read( buffer, count )                        \
+          FT_SET_ERROR( FT_Read_Stream( stream,           \
+                                        (FT_Byte*)buffer, \
+                                        count ) )
+
+#define FILE_Read_At( position, buffer, count )              \
+          FT_SET_ERROR( FT_Read_Stream_At( stream,           \
+                                           position,         \
+                                           (FT_Byte*)buffer, \
+                                           count ) )
+
+#define READ_Fields( fields, object )  \
+        ( ( error = FT_Read_Fields( stream, fields, object ) ) != FT_Err_Ok )
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTSTREAM_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/psnames.h b/src/freetype/freetype/internal/psnames.h
new file mode 100644 (file)
index 0000000..ed86235
--- /dev/null
@@ -0,0 +1,220 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psnames.h                                                              */
+/*                                                                         */
+/*    High-level interface for the `PSNames' module (in charge of          */
+/*    various functions related to Postscript glyph names conversion).     */
+/*                                                                         */
+/*  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 PSNAMES_H
+#define PSNAMES_H
+
+
+#include <freetype/freetype.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    PS_Unicode_Value_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to return the Unicode index corresponding to a     */
+  /*    given glyph name.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph_name :: The glyph name.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The Unicode character index resp. the non-Unicode value 0xFFFF if  */
+  /*    the glyph name has no known Unicode meaning.                       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is able to map several different glyph names to the  */
+  /*    same Unicode value, according to the rules defined in the Adobe    */
+  /*    Glyph List table.                                                  */
+  /*                                                                       */
+  /*    This function will not be compiled if the configuration macro      */
+  /*    FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined.                    */
+  /*                                                                       */
+  typedef FT_ULong  (*PS_Unicode_Value_Func)( const char*  glyph_name );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    PS_Unicode_Index_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to return the glyph index corresponding to a given */
+  /*    Unicode value.                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    num_glyphs  :: The number of glyphs in the face.                   */
+  /*                                                                       */
+  /*    glyph_names :: An array of glyph name pointers.                    */
+  /*                                                                       */
+  /*    unicode     :: The Unicode value.                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph index resp. 0xFFFF if no glyph corresponds to this       */
+  /*    Unicode value.                                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is able to recognize several glyph names per Unicode */
+  /*    value, according to the Adobe Glyph List.                          */
+  /*                                                                       */
+  /*    This function will not be compiled if the configuration macro      */
+  /*    FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined.                    */
+  /*                                                                       */
+  typedef FT_UInt  (*PS_Unicode_Index_Func)( FT_UInt       num_glyphs,
+                                             const char**  glyph_names,
+                                             FT_ULong      unicode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    PS_Macintosh_Name_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to return the glyph name corresponding to an Apple */
+  /*    glyph name index.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    name_index :: The index of the Mac name.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph name, or 0 if the index is invalid.                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will not be compiled if the configuration macro      */
+  /*    FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined.                    */ 
+  /*                                                                       */
+  typedef const char*  (*PS_Macintosh_Name_Func)( FT_UInt  name_index );
+
+
+  typedef const char*  (*PS_Adobe_Std_Strings_Func)( FT_UInt  string_index );
+
+
+  typedef struct  PS_UniMap_
+  {
+    FT_UInt  unicode;
+    FT_UInt  glyph_index;
+
+  } PS_UniMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    PS_Unicodes                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple table used to map Unicode values to glyph indices.  It is */
+  /*    built by the PS_Build_Unicodes table according to the glyphs       */
+  /*    present in a font file.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_codes :: The number of glyphs in the font that match a given   */
+  /*                 Unicode value.                                        */
+  /*                                                                       */
+  /*    unicodes  :: An array of unicode values, sorted in increasing      */
+  /*                 order.                                                */
+  /*                                                                       */
+  /*    gindex    :: An array of glyph indices, corresponding to each      */
+  /*                 Unicode value.                                        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Use the function PS_Lookup_Unicode() to retrieve the glyph index   */
+  /*    corresponding to a given Unicode character code.                   */
+  /*                                                                       */
+  typedef struct  PS_Unicodes_
+  {
+    FT_UInt     num_maps;
+    PS_UniMap*  maps;
+
+  } PS_Unicodes;
+
+
+  typedef FT_Error  (*PS_Build_Unicodes_Func)( FT_Memory     memory,
+                                               FT_UInt       num_glyphs,
+                                               const char**  glyph_names,
+                                               PS_Unicodes*  unicodes );
+
+  typedef FT_UInt  (*PS_Lookup_Unicode_Func)( PS_Unicodes*  unicodes,
+                                              FT_UInt       unicode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    PSNames_Interface                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure defines the PSNames interface.                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    unicode_value         :: A function used to convert a glyph name   */
+  /*                             into a Unicode character code.            */
+  /*                                                                       */
+  /*    build_unicodes        :: A function which builds up the Unicode    */
+  /*                             mapping table.                            */
+  /*                                                                       */
+  /*    lookup_unicode        :: A function used to return the glyph index */
+  /*                             corresponding to a given Unicode          */
+  /*                             character.                                */
+  /*                                                                       */
+  /*    macintosh_name        :: A function used to return the standard    */
+  /*                             Apple glyph Postscript name corresponding */
+  /*                             to a given string index (used by the      */
+  /*                             TrueType `post' table).                   */
+  /*                                                                       */
+  /*    adobe_std_strings     :: A function that returns a pointer to a    */
+  /*                             Adobe Standard String for a given SID.    */
+  /*                                                                       */
+  /*    adobe_std_encoding    :: A table of 256 unsigned shorts that maps  */
+  /*                             character codes in the Adobe Standard     */
+  /*                             Encoding to SIDs.                         */
+  /*                                                                       */
+  /*    adobe_expert_encoding :: A table of 256 unsigned shorts that maps  */
+  /*                             character codes in the Adobe Expert       */
+  /*                             Encoding to SIDs.                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    `unicode_value' and `unicode_index' will be set to 0 if the        */
+  /*    configuration macro FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is           */
+  /*    undefined.                                                         */
+  /*                                                                       */
+  /*    `macintosh_name' will be set to 0 if the configuration macro       */
+  /*    FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined.                    */
+  /*                                                                       */
+  typedef struct  PSNames_Interface_
+  {
+    PS_Unicode_Value_Func      unicode_value;
+    PS_Build_Unicodes_Func     build_unicodes;
+    PS_Lookup_Unicode_Func     lookup_unicode;
+    PS_Macintosh_Name_Func     macintosh_name;
+
+    PS_Adobe_Std_Strings_Func  adobe_std_strings;
+    const unsigned short*      adobe_std_encoding;
+    const unsigned short*      adobe_expert_encoding;
+
+  } PSNames_Interface;
+
+
+#endif /* PSNAMES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/sfnt.h b/src/freetype/freetype/internal/sfnt.h
new file mode 100644 (file)
index 0000000..380ee93
--- /dev/null
@@ -0,0 +1,492 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfnt.h                                                                 */
+/*                                                                         */
+/*    High-level `sfnt' driver interface (specification).                  */
+/*                                                                         */
+/*  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 SFNT_H
+#define SFNT_H
+
+
+#include <freetype/freetype.h>
+#include <freetype/internal/ftdriver.h>
+#include <freetype/internal/tttypes.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Init_Face_Func                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    First part of the SFNT face object initialization.  This will find */
+  /*    the face in a SFNT file or collection, and load its format tag in  */
+  /*    face->format_tag.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The input stream.                                    */
+  /*                                                                       */
+  /*    face       :: A handle to the target face object.                  */
+  /*                                                                       */
+  /*    face_index :: The index of the TrueType font, if we are opening a  */
+  /*                  collection.                                          */
+  /*                                                                       */
+  /*    num_params :: The number of additional parameters.                 */
+  /*                                                                       */
+  /*    params     :: Optional additional parameters.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  /*    This function recognizes fonts embedded in a `TrueType             */
+  /*    collection'.                                                       */
+  /*                                                                       */
+  /*    Once the format tag has been validated by the font driver, it      */
+  /*    should then call the TT_Load_Face_Func() callback to read the rest */
+  /*    of the SFNT tables in the object.                                  */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Init_Face_Func)( FT_Stream      stream,
+                                  TT_Face        face,
+                                  FT_Int         face_index,
+                                  FT_Int         num_params,
+                                  FT_Parameter*  params );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Face_Func                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Second part of the SFNT face object initialization.  This will     */
+  /*    load the common SFNT tables (head, OS/2, maxp, metrics, etc.) in   */
+  /*    the face object.                                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The input stream.                                    */
+  /*                                                                       */
+  /*    face       :: A handle to the target face object.                  */
+  /*                                                                       */
+  /*    face_index :: The index of the TrueType font, if we are opening a  */
+  /*                  collection.                                          */
+  /*                                                                       */
+  /*    num_params :: The number of additional parameters.                 */
+  /*                                                                       */
+  /*    params     :: Optional additional parameters.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function must be called after TT_Init_Face_Func().            */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_Face_Func)( FT_Stream      stream,
+                                  TT_Face        face,
+                                  FT_Int         face_index,
+                                  FT_Int         num_params,
+                                  FT_Parameter*  params );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Done_Face_Func                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A callback used to delete the common SFNT data from a face.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT destroy the face object.                    */
+  /*                                                                       */
+  typedef
+  void  (*TT_Done_Face_Func)( TT_Face  face );
+
+
+  typedef
+  FT_Module_Interface  (*SFNT_Get_Interface_Func)( FT_Module    module,
+                                                   const char*  interface );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_SFNT_Header_Func                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the header of a SFNT font file.  Supports collections.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the target face object.                  */
+  /*                                                                       */
+  /*    stream     :: The input stream.                                    */
+  /*                                                                       */
+  /*    face_index :: The index of the TrueType font, if we are opening a  */
+  /*                  collection.                                          */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    sfnt       :: The SFNT header.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  /*    This function recognizes fonts embedded in a `TrueType             */
+  /*    collection'.                                                       */
+  /*                                                                       */
+  /*    This function checks that the header is valid by looking at the    */
+  /*    values of `search_range', `entry_selector', and `range_shift'.     */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_SFNT_Header_Func)( TT_Face       face,
+                                         FT_Stream     stream,
+                                         FT_Long       face_index,
+                                         SFNT_Header*  sfnt );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Directory_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the table directory into a face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face      :: A handle to the target face object.                   */
+  /*                                                                       */
+  /*    stream    :: The input stream.                                     */
+  /*                                                                       */
+  /*    sfnt      :: The SFNT header.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be on the first byte after the 4-byte font  */
+  /*    format tag.  This is the case just after a call to                 */
+  /*    TT_Load_Format_Tag().                                              */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_Directory_Func)( TT_Face       face,
+                                       FT_Stream     stream,
+                                       SFNT_Header*  sfnt );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Any_Func                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads any font table into client memory.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: The face object to look for.                             */
+  /*                                                                       */
+  /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
+  /*              to access the whole font file, else set this parameter   */
+  /*              to a valid TrueType table tag that you can forge with    */
+  /*              the MAKE_TT_TAG macro.                                   */
+  /*                                                                       */
+  /*    offset :: The starting offset in the table (or the file if         */
+  /*              tag == 0).                                               */
+  /*                                                                       */
+  /*    length :: The address of the decision variable:                    */
+  /*                                                                       */
+  /*                If length == NULL:                                     */
+  /*                  Loads the whole table.  Returns an error if          */
+  /*                  `offset' == 0!                                       */
+  /*                                                                       */
+  /*                If *length == 0:                                       */
+  /*                  Exits immediately; returning the length of the given */
+  /*                  table or of the font file, depending on the value of */
+  /*                  `tag'.                                               */
+  /*                                                                       */
+  /*                If *length != 0:                                       */
+  /*                  Loads the next `length' bytes of table or font,      */
+  /*                  starting at offset `offset' (in table or font too).  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    buffer :: The address of target buffer.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    TrueType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_Any_Func)( TT_Face    face,
+                                 FT_ULong   tag,
+                                 FT_Long    offset,
+                                 FT_Byte*   buffer,
+                                 FT_ULong*  length );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_SBit_Image_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given glyph sbit image from the font resource.  This also  */
+  /*    returns its metrics.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: The target face object.                             */
+  /*                                                                       */
+  /*    x_ppem      :: The horizontal resolution in points per EM.         */
+  /*                                                                       */
+  /*    y_ppem      :: The vertical resolution in points per EM.           */
+  /*                                                                       */
+  /*    glyph_index :: The current glyph index.                            */
+  /*                                                                       */
+  /*    stream      :: The input stream.                                   */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    map         :: The target pixmap.                                  */
+  /*                                                                       */
+  /*    metrics     :: A big sbit metrics structure for the glyph image.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  Returns an error if no     */
+  /*    glyph sbit exists for the index.                                   */
+  /*                                                                       */
+  /*  <Note>                                                               */
+  /*    The `map.buffer' field is always freed before the glyph is loaded. */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_SBit_Image_Func)( TT_Face           face,
+                                        FT_Int            x_ppem,
+                                        FT_Int            y_ppem,
+                                        FT_UInt           glyph_index,
+                                        FT_UInt           load_flags,
+                                        FT_Stream         stream,
+                                        FT_Bitmap*        map,
+                                        TT_SBit_Metrics*  metrics );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Get_PS_Name_Func                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Gets the PostScript glyph name of a glyph.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    index  :: The glyph index.                                         */
+  /*                                                                       */
+  /*    PSname :: The address of a string pointer.  Will be NULL in case   */
+  /*              of error, otherwise it is a pointer to the glyph name.   */
+  /*                                                                       */
+  /*              You must not modify the returned string!                 */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Get_PS_Name_Func)( TT_Face      face,
+                                    FT_UInt      index,
+                                    FT_String**  PSname );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Metrics_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal or vertical header in a face object.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the target face object.                    */
+  /*                                                                       */
+  /*    stream   :: The input stream.                                      */
+  /*                                                                       */
+  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_Metrics_Func)( TT_Face    face,
+                                     FT_Stream  stream,
+                                     FT_Bool    vertical );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_CharMap_Load_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given TrueType character map into memory.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the parent face object.                      */
+  /*                                                                       */
+  /*    stream :: A handle to the current stream object.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    cmap   :: A pointer to a cmap object.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function assumes that the stream is already in use (i.e.,      */
+  /*    opened).  In case of error, all partially allocated tables are     */
+  /*    released.                                                          */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_CharMap_Load_Func)( TT_Face        face,
+                                     TT_CMapTable*  cmap,
+                                     FT_Stream      input );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_CharMap_Free_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a character mapping table.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the parent face object.                        */
+  /*                                                                       */
+  /*    cmap :: A handle to a cmap object.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_CharMap_Free_Func)( TT_Face        face,
+                                     TT_CMapTable*  cmap );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Table_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given TrueType table.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function will use `face->goto_table' to seek the stream to     */
+  /*    the start of the table.                                            */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_Table_Func)( TT_Face    face,
+                                   FT_Stream  stream );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Free_Table_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Frees a given TrueType table.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  typedef
+  void  (*TT_Free_Table_Func)( TT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    SFNT_Interface                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure holds pointers to the functions used to load and    */
+  /*    free the basic tables that are required in a `sfnt' font file.     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Check the various xxx_Func() descriptions for details.             */
+  /*                                                                       */
+  typedef struct  SFNT_Interface_
+  {
+    TT_Goto_Table_Func        goto_table;
+
+    TT_Init_Face_Func         init_face;
+    TT_Load_Face_Func         load_face;
+    TT_Done_Face_Func         done_face;
+    SFNT_Get_Interface_Func   get_interface;
+    
+    TT_Load_Any_Func          load_any;
+    TT_Load_SFNT_Header_Func  load_sfnt_header;
+    TT_Load_Directory_Func    load_directory;
+
+    /* these functions are called by `load_face' but they can also  */
+    /* be called from external modules, if there is a need to do so */
+    TT_Load_Table_Func        load_header;
+    TT_Load_Metrics_Func      load_metrics;
+    TT_Load_Table_Func        load_charmaps;
+    TT_Load_Table_Func        load_max_profile;
+    TT_Load_Table_Func        load_os2;
+    TT_Load_Table_Func        load_psnames;
+
+    TT_Load_Table_Func        load_names;
+    TT_Free_Table_Func        free_names;
+
+    /* optional tables */
+    TT_Load_Table_Func        load_hdmx;
+    TT_Free_Table_Func        free_hdmx;
+
+    TT_Load_Table_Func        load_kerning;
+    TT_Load_Table_Func        load_gasp;
+       TT_Load_Table_Func        load_pclt;
+
+    /* see `ttsbit.h' */
+    TT_Load_Table_Func        load_sbits;
+    TT_Load_SBit_Image_Func   load_sbit_image;
+    TT_Free_Table_Func        free_sbits;
+
+    /* see `ttpost.h' */
+    TT_Get_PS_Name_Func       get_psname;
+    TT_Free_Table_Func        free_psnames;
+
+    /* see `ttcmap.h' */
+    TT_CharMap_Load_Func      load_charmap;
+    TT_CharMap_Free_Func      free_charmap;
+
+  } SFNT_Interface;
+
+
+#endif /* SFNT_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/t1errors.h b/src/freetype/freetype/internal/t1errors.h
new file mode 100644 (file)
index 0000000..58566d8
--- /dev/null
@@ -0,0 +1,67 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1errors.h                                                             */
+/*                                                                         */
+/*    Type 1 error ID definitions (specification only).                    */
+/*                                                                         */
+/*  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 T1ERRORS_H
+#define T1ERRORS_H
+
+
+  /************************ error codes declaration **************/
+
+  /* The error codes are grouped into `classes' used to indicate the */
+  /* `level' at which the error happened.                            */
+  /*                                                                 */
+  /* The class is given by an error code's high byte.                */
+
+
+  /* ------------- Success is always 0 -------- */
+
+#define T1_Err_Ok                      FT_Err_Ok
+
+  /* ----------- high level API errors -------- */
+
+#define T1_Err_Invalid_File_Format     FT_Err_Invalid_File_Format
+#define T1_Err_Invalid_Argument        FT_Err_Invalid_Argument
+#define T1_Err_Invalid_Driver_Handle   FT_Err_Invalid_Driver_Handle
+#define T1_Err_Invalid_Face_Handle     FT_Err_Invalid_Face_Handle
+#define T1_Err_Invalid_Size_Handle     FT_Err_Invalid_Size_Handle
+#define T1_Err_Invalid_Glyph_Handle    FT_Err_Invalid_Slot_Handle
+#define T1_Err_Invalid_CharMap_Handle  FT_Err_Invalid_CharMap_Handle
+#define T1_Err_Invalid_Glyph_Index     FT_Err_Invalid_Glyph_Index
+
+#define T1_Err_Unimplemented_Feature   FT_Err_Unimplemented_Feature
+
+#define T1_Err_Invalid_Engine          FT_Err_Invalid_Driver_Handle
+
+  /* ------------- internal errors ------------ */
+
+#define T1_Err_Out_Of_Memory           FT_Err_Out_Of_Memory
+#define T1_Err_Unlisted_Object         FT_Err_Unlisted_Object
+
+  /* ------------ general glyph outline errors ------ */
+
+#define T1_Err_Invalid_Composite       FT_Err_Invalid_Composite
+
+#define T1_Err_Syntax_Error            FT_Err_Invalid_File_Format
+#define T1_Err_Stack_Underflow         FT_Err_Invalid_File_Format
+#define T1_Err_Stack_Overflow          FT_Err_Invalid_File_Format
+
+
+#endif /* T1ERRORS_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/t1types.h b/src/freetype/freetype/internal/t1types.h
new file mode 100644 (file)
index 0000000..4d41a6b
--- /dev/null
@@ -0,0 +1,188 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1types.h                                                              */
+/*                                                                         */
+/*    Basic Type1/Type2 type definitions and interface (specification      */
+/*    only).                                                               */
+/*                                                                         */
+/*  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 T1TYPES_H
+#define T1TYPES_H
+
+
+#include <freetype/t1tables.h>
+#include <freetype/internal/psnames.h>
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***              REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS              ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Encoding                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling a custom encoding                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_chars  :: The number of character codes in the encoding.       */
+  /*                  Usually 256.                                         */
+  /*                                                                       */
+  /*    code_first :: The lowest valid character code in the encoding.     */
+  /*                                                                       */
+  /*    code_last  :: The highest valid character code in the encoding.    */
+  /*                                                                       */
+  /*    char_index :: An array of corresponding glyph indices.             */
+  /*                                                                       */
+  /*    char_name  :: An array of corresponding glyph names.               */
+  /*                                                                       */
+  typedef struct  T1_Encoding_
+  {
+    FT_Int       num_chars;
+    FT_Int       code_first;
+    FT_Int       code_last;
+
+    FT_UShort*   char_index;
+    FT_String**  char_name;
+
+  } T1_Encoding;
+
+
+  typedef enum  T1_EncodingType_
+  {
+       t1_encoding_none = 0,
+       t1_encoding_array,
+       t1_encoding_standard,
+       t1_encoding_expert
+
+  } T1_EncodingType;
+
+
+  typedef struct  T1_Font_
+  {
+
+    /* font info dictionary */
+    T1_FontInfo      font_info;
+
+    /* private dictionary */
+    T1_Private       private_dict;
+
+    /* top-level dictionary */
+    FT_String*       font_name;
+
+    T1_EncodingType  encoding_type;
+    T1_Encoding      encoding;
+
+    FT_Byte*         subrs_block;
+    FT_Byte*         charstrings_block;
+    FT_Byte*         glyph_names_block;
+
+    FT_Int           num_subrs;
+    FT_Byte**        subrs;
+    FT_Int*          subrs_len;
+
+    FT_Int           num_glyphs;
+    FT_String**      glyph_names;       /* array of glyph names       */
+    FT_Byte**        charstrings;       /* array of glyph charstrings */
+    FT_Int*          charstrings_len;
+
+    FT_Byte          paint_type;
+    FT_Byte          font_type;
+    FT_Matrix        font_matrix;
+    FT_BBox          font_bbox;
+    FT_Long          font_id;
+
+    FT_Int           stroke_width;
+
+  } T1_Font;
+
+
+  typedef struct  CID_Subrs_
+  {
+    FT_UInt    num_subrs;
+    FT_Byte**  code;
+    
+  } CID_Subrs;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                ORIGINAL T1_FACE CLASS DEFINITION                  ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This structure/class is defined here because it is common to the      */
+  /* following formats: TTF, OpenType-TT, and OpenType-CFF.                */
+  /*                                                                       */
+  /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */
+  /* are not shared between font drivers, and are thus defined normally in */
+  /* `ttobjs.h'.                                                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+  typedef struct T1_FaceRec_*   T1_Face;
+  typedef struct CID_FaceRec_*  CID_Face;
+
+
+  typedef struct  T1_FaceRec_
+  {
+    FT_FaceRec     root;
+    T1_Font        type1;
+    void*          psnames;
+    void*          afm_data;
+    FT_CharMapRec  charmaprecs[2];
+    FT_CharMap     charmaps[2];
+    PS_Unicodes    unicode_map;
+
+    /* support for Multiple Masters fonts */
+    T1_Blend*      blend;
+
+  } T1_FaceRec;
+
+
+  typedef struct  CID_FaceRec_
+  {
+    FT_FaceRec  root;
+    void*       psnames;
+    CID_Info    cid;
+    void*       afm_data;
+    CID_Subrs*  subrs;
+  
+  } CID_FaceRec;
+
+
+#endif /* T1TYPES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/t2errors.h b/src/freetype/freetype/internal/t2errors.h
new file mode 100644 (file)
index 0000000..d685220
--- /dev/null
@@ -0,0 +1,121 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2errors.h                                                             */
+/*                                                                         */
+/*    OpenType error ID definitions (specification only).                  */
+/*                                                                         */
+/*  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 T2ERRORS_H
+#define T2ERRORS_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Error codes declaration                                               */
+  /*                                                                       */
+  /* The error codes are grouped in `classes' used to indicate the `level' */
+  /* at which the error happened.  The class is given by an error code's   */
+  /* high byte.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* Success is always 0. */
+
+#define T2_Err_Ok                         FT_Err_Ok
+
+  /* High level API errors. */
+
+#define T2_Err_Invalid_File_Format        FT_Err_Invalid_File_Format
+#define T2_Err_Invalid_Argument           FT_Err_Invalid_Argument
+#define T2_Err_Invalid_Driver_Handle      FT_Err_Invalid_Driver_Handle
+#define T2_Err_Invalid_Face_Handle        FT_Err_Invalid_Face_Handle
+#define T2_Err_Invalid_Instance_Handle    FT_Err_Invalid_Size_Handle
+#define T2_Err_Invalid_Glyph_Handle       FT_Err_Invalid_Slot_Handle
+#define T2_Err_Invalid_CharMap_Handle     FT_Err_Invalid_CharMap_Handle
+#define T2_Err_Invalid_Glyph_Index        FT_Err_Invalid_Glyph_Index
+
+#define T2_Err_Unimplemented_Feature      FT_Err_Unimplemented_Feature
+
+#define T2_Err_Invalid_Engine             FT_Err_Invalid_Driver_Handle
+
+  /* Internal errors. */
+
+#define T2_Err_Out_Of_Memory              FT_Err_Out_Of_Memory
+#define T2_Err_Unlisted_Object            FT_Err_Unlisted_Object
+
+  /* General glyph outline errors. */
+
+#define T2_Err_Invalid_Composite          FT_Err_Invalid_Composite
+
+  /* Bytecode interpreter error codes. */
+
+  /* These error codes are produced by the TrueType */
+  /* bytecode interpreter.  They usually indicate a */
+  /* broken font file, a broken glyph within a font */
+  /* file, or a bug in the interpreter!             */
+
+#define T2_Err_Invalid_Opcode             0x500
+#define T2_Err_Too_Few_Arguments          0x501
+#define T2_Err_Stack_Overflow             0x502
+#define T2_Err_Code_Overflow              0x503
+#define T2_Err_Bad_Argument               0x504
+#define T2_Err_Divide_By_Zero             0x505
+#define T2_Err_Storage_Overflow           0x506
+#define T2_Err_Cvt_Overflow               0x507
+#define T2_Err_Invalid_Reference          0x508
+#define T2_Err_Invalid_Distance           0x509
+#define T2_Err_Interpolate_Twilight       0x50A
+#define T2_Err_Debug_OpCode               0x50B
+#define T2_Err_ENDF_In_Exec_Stream        0x50C
+#define T2_Err_Out_Of_CodeRanges          0x50D
+#define T2_Err_Nested_DEFS                0x50E
+#define T2_Err_Invalid_CodeRange          0x50F
+#define T2_Err_Invalid_Displacement       0x510
+#define T2_Err_Execution_Too_Long         0x511
+
+#define T2_Err_Too_Many_Instruction_Defs  0x512
+#define T2_Err_Too_Many_Function_Defs     0x513
+
+  /* Other TrueType specific error codes. */
+
+#define T2_Err_Table_Missing              0x520
+#define T2_Err_Too_Many_Extensions        0x521
+#define T2_Err_Extensions_Unsupported     0x522
+#define T2_Err_Invalid_Extension_Id       0x523
+
+#define T2_Err_No_Vertical_Data           0x524
+
+#define T2_Err_Max_Profile_Missing        0x530
+#define T2_Err_Header_Table_Missing       0x531
+#define T2_Err_Horiz_Header_Missing       0x532
+#define T2_Err_Locations_Missing          0x533
+#define T2_Err_Name_Table_Missing         0x534
+#define T2_Err_CMap_Table_Missing         0x535
+#define T2_Err_Hmtx_Table_Missing         0x536
+#define T2_Err_OS2_Table_Missing          0x537
+#define T2_Err_Post_Table_Missing         0x538
+
+#define T2_Err_Invalid_Horiz_Metrics      0x540
+#define T2_Err_Invalid_CharMap_Format     0x541
+#define T2_Err_Invalid_PPem               0x542
+#define T2_Err_Invalid_Vert_Metrics       0x543
+
+#define T2_Err_Could_Not_Find_Context     0x550
+
+
+#endif /* T2ERRORS_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/t2types.h b/src/freetype/freetype/internal/t2types.h
new file mode 100644 (file)
index 0000000..033f315
--- /dev/null
@@ -0,0 +1,218 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t2types.h                                                              */
+/*                                                                         */
+/*    Basic OpenType/CFF type definitions and interface (specification     */
+/*    only).                                                               */
+/*                                                                         */
+/*  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 T2TYPES_H
+#define T2TYPES_H
+
+
+#include <freetype/freetype.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    CFF_Index                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a CFF Index table.                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    stream      :: XXX                                                 */
+  /*                                                                       */
+  /*    count       :: The number of elements in the index.                */
+  /*                                                                       */
+  /*    off_size    :: The size in bytes of object offsets in index.       */
+  /*                                                                       */
+  /*    data_offset :: The position of first data byte in the index's      */
+  /*                   bytes.                                              */
+  /*                                                                       */
+  /*    offsets     :: XXX                                                 */
+  /*                                                                       */
+  /*    bytes       :: If the index is loaded in memory, its bytes.        */
+  /*                                                                       */
+  typedef struct  CFF_Index_
+  {
+    FT_Stream  stream;
+    FT_UInt    count;
+    FT_Byte    off_size;
+    FT_ULong   data_offset;
+
+    FT_ULong*  offsets;
+    FT_Byte*   bytes;
+
+  } CFF_Index;
+
+
+  typedef struct  CFF_Font_Dict_
+  {
+    FT_UInt    version;
+    FT_UInt    notice;
+    FT_UInt    copyright;
+    FT_UInt    full_name;
+    FT_UInt    family_name;
+    FT_UInt    weight;
+    FT_Bool    is_fixed_pitch;
+    FT_Fixed   italic_angle;
+    FT_Pos     underline_position;
+    FT_Pos     underline_thickness;
+    FT_Int     paint_type;
+    FT_Int     charstring_type;
+    FT_Matrix  font_matrix;
+    FT_ULong   unique_id;
+    FT_BBox    font_bbox;
+    FT_Pos     stroke_width;
+    FT_ULong   charset_offset;
+    FT_ULong   encoding_offset;
+    FT_ULong   charstrings_offset;
+    FT_ULong   private_offset;
+    FT_ULong   private_size;
+    FT_Long    synthetic_base;
+    FT_UInt    embedded_postscript;
+    FT_UInt    base_font_name;       
+    FT_UInt    postscript;
+
+    /* these should only be used for the top-level font dictionary */
+    FT_UInt    cid_registry;
+    FT_UInt    cid_ordering;
+    FT_ULong   cid_supplement;
+
+    FT_Long    cid_font_version;
+    FT_Long    cid_font_revision;
+    FT_Long    cid_font_type;
+    FT_Long    cid_count;
+    FT_ULong   cid_uid_base;
+    FT_ULong   cid_fd_array_offset;
+    FT_ULong   cid_fd_select_offset;
+    FT_UInt    cid_font_name;
+
+  } CFF_Font_Dict;
+  
+  
+  typedef struct  CFF_Private_
+  {
+    FT_Byte   num_blue_values;
+    FT_Byte   num_other_blues;
+    FT_Byte   num_family_blues;
+    FT_Byte   num_family_other_blues;
+    
+    FT_Pos    blue_values[14];
+    FT_Pos    other_blues[10];
+    FT_Pos    family_blues[14];
+    FT_Pos    family_other_blues[10];
+    
+    FT_Fixed  blue_scale;
+    FT_Pos    blue_shift;
+    FT_Pos    blue_fuzz;
+    FT_Pos    standard_width;
+    FT_Pos    standard_height;
+    
+    FT_Byte   num_snap_widths;
+    FT_Byte   num_snap_heights;
+    FT_Pos    snap_widths[13];
+    FT_Pos    snap_heights[13];
+    FT_Bool   force_bold;
+    FT_Fixed  force_bold_threshold;
+    FT_Int    lenIV;
+    FT_Int    language_group;
+    FT_Fixed  expansion_factor;
+    FT_Long   initial_random_seed;
+    FT_ULong  local_subrs_offset;
+    FT_Pos    default_width;
+    FT_Pos    nominal_width;
+  
+  } CFF_Private;
+
+
+  typedef struct  CFF_FD_Select_
+  {
+    FT_Byte   format;
+    FT_UInt   range_count;
+
+    /* that's the table, taken from the file `as is' */
+    FT_Byte*  data;
+    FT_UInt   data_size;
+
+    /* small cache for format 3 only */
+    FT_UInt   cache_first;
+    FT_UInt   cache_count;
+    FT_Byte   cache_fd;
+    
+  } CFF_FD_Select;
+
+
+  /* A SubFont packs a font dict and a private dict together. They are */
+  /* needed to support CID-keyed CFF fonts.                            */
+  typedef struct  CFF_SubFont_
+  {
+    CFF_Font_Dict  font_dict;
+    CFF_Private    private_dict;
+    
+    CFF_Index      local_subrs_index;
+    FT_UInt        num_local_subrs;
+    FT_Byte**      local_subrs;
+
+  } CFF_SubFont;
+
+
+  /* maximum number of sub-fonts in a CID-keyed file */
+#define CFF_MAX_CID_FONTS  16
+  
+
+  typedef struct  CFF_Font_
+  {
+    FT_Stream      stream;
+    FT_Memory      memory;
+    FT_UInt        num_faces;
+    FT_UInt        num_glyphs;
+    
+    FT_Byte        version_major;
+    FT_Byte        version_minor;
+    FT_Byte        header_size;
+    FT_Byte        absolute_offsize;
+
+  
+    CFF_Index      name_index;
+    CFF_Index      top_dict_index;
+    CFF_Index      string_index;
+    CFF_Index      global_subrs_index;
+  
+    /* we don't load the Encoding and CharSet tables */
+  
+    CFF_Index      charstrings_index;
+    CFF_Index      font_dict_index;
+    CFF_Index      private_index;
+    CFF_Index      local_subrs_index;
+
+    FT_String*     font_name;
+    FT_UInt        num_global_subrs;
+    FT_Byte**      global_subrs;
+
+    CFF_SubFont    top_font;
+    FT_UInt        num_subfonts;
+    CFF_SubFont*   subfonts[CFF_MAX_CID_FONTS];
+
+    CFF_FD_Select  fd_select;
+
+  } CFF_Font;
+
+
+#endif /* T2TYPES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/tterrors.h b/src/freetype/freetype/internal/tterrors.h
new file mode 100644 (file)
index 0000000..b53e9f3
--- /dev/null
@@ -0,0 +1,121 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tterrors.h                                                             */
+/*                                                                         */
+/*    TrueType error ID definitions (specification only).                  */
+/*                                                                         */
+/*  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 TTERRORS_H
+#define TTERRORS_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Error codes declaration                                               */
+  /*                                                                       */
+  /* The error codes are grouped in `classes' used to indicate the `level' */
+  /* at which the error happened.  The class is given by an error code's   */
+  /* high byte.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* Success is always 0. */
+
+#define TT_Err_Ok                         FT_Err_Ok
+
+  /* High level API errors. */
+
+#define TT_Err_Invalid_File_Format        FT_Err_Invalid_File_Format
+#define TT_Err_Invalid_Argument           FT_Err_Invalid_Argument
+#define TT_Err_Invalid_Driver_Handle      FT_Err_Invalid_Driver_Handle
+#define TT_Err_Invalid_Face_Handle        FT_Err_Invalid_Face_Handle
+#define TT_Err_Invalid_Instance_Handle    FT_Err_Invalid_Size_Handle
+#define TT_Err_Invalid_Glyph_Handle       FT_Err_Invalid_Slot_Handle
+#define TT_Err_Invalid_CharMap_Handle     FT_Err_Invalid_CharMap_Handle
+#define TT_Err_Invalid_Glyph_Index        FT_Err_Invalid_Glyph_Index
+
+#define TT_Err_Unimplemented_Feature      FT_Err_Unimplemented_Feature
+
+#define TT_Err_Invalid_Engine             FT_Err_Invalid_Driver_Handle
+
+  /* Internal errors. */
+
+#define TT_Err_Out_Of_Memory              FT_Err_Out_Of_Memory
+#define TT_Err_Unlisted_Object            FT_Err_Unlisted_Object
+
+  /* General glyph outline errors. */
+
+#define TT_Err_Too_Many_Ins               FT_Err_Too_Many_Hints
+#define TT_Err_Invalid_Composite          FT_Err_Invalid_Composite
+
+  /* Bytecode interpreter error codes. */
+
+  /* These error codes are produced by the TrueType */
+  /* bytecode interpreter.  They usually indicate a */
+  /* broken font file, a broken glyph within a font */
+  /* file, or a bug in the interpreter!             */
+
+#define TT_Err_Invalid_Opcode             0x400
+#define TT_Err_Too_Few_Arguments          0x401
+#define TT_Err_Stack_Overflow             0x402
+#define TT_Err_Code_Overflow              0x403
+#define TT_Err_Bad_Argument               0x404
+#define TT_Err_Divide_By_Zero             0x405
+#define TT_Err_Storage_Overflow           0x406
+#define TT_Err_Cvt_Overflow               0x407
+#define TT_Err_Invalid_Reference          0x408
+#define TT_Err_Invalid_Distance           0x409
+#define TT_Err_Interpolate_Twilight       0x40A
+#define TT_Err_Debug_OpCode               0x40B
+#define TT_Err_ENDF_In_Exec_Stream        0x40C
+#define TT_Err_Out_Of_CodeRanges          0x40D
+#define TT_Err_Nested_DEFS                0x40E
+#define TT_Err_Invalid_CodeRange          0x40F
+#define TT_Err_Invalid_Displacement       0x410
+#define TT_Err_Execution_Too_Long         0x411
+#define TT_Err_Too_Many_Function_Defs     0x412
+#define TT_Err_Too_Many_Instruction_Defs  0x413
+
+  /* Other TrueType specific error codes. */
+
+#define TT_Err_Table_Missing              0x420
+#define TT_Err_Too_Many_Extensions        0x421
+#define TT_Err_Extensions_Unsupported     0x422
+#define TT_Err_Invalid_Extension_Id       0x423
+
+#define TT_Err_No_Vertical_Data           0x424
+
+#define TT_Err_Max_Profile_Missing        0x430
+#define TT_Err_Header_Table_Missing       0x431
+#define TT_Err_Horiz_Header_Missing       0x432
+#define TT_Err_Locations_Missing          0x433
+#define TT_Err_Name_Table_Missing         0x434
+#define TT_Err_CMap_Table_Missing         0x435
+#define TT_Err_Hmtx_Table_Missing         0x436
+#define TT_Err_OS2_Table_Missing          0x437
+#define TT_Err_Post_Table_Missing         0x438
+
+#define TT_Err_Invalid_Horiz_Metrics      0x440
+#define TT_Err_Invalid_CharMap_Format     0x441
+#define TT_Err_Invalid_PPem               0x442
+#define TT_Err_Invalid_Vert_Metrics       0x443
+
+#define TT_Err_Could_Not_Find_Context     0x450
+
+
+#endif /* TTERRORS_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/internal/tttypes.h b/src/freetype/freetype/internal/tttypes.h
new file mode 100644 (file)
index 0000000..1fd43ce
--- /dev/null
@@ -0,0 +1,1582 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tttypes.h                                                              */
+/*                                                                         */
+/*    Basic SFNT/TrueType type definitions and interface (specification    */
+/*    only).                                                               */
+/*                                                                         */
+/*  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 TTTYPES_H
+#define TTTYPES_H
+
+
+#include <freetype/tttables.h>
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***             REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS         ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TTC_Header                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    TrueType collection header.  This table contains the offsets of    */
+  /*    the font headers of each distinct TrueType face in the file.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    tag     :: Must be `ttc ' to indicate a TrueType collection.       */
+  /*                                                                       */
+  /*    version :: The version number.                                     */
+  /*                                                                       */
+  /*    count   :: The number of faces in the collection.  The             */
+  /*               specification says this should be an unsigned long, but */
+  /*               we use a signed long since we need the value -1 for     */
+  /*               specific purposes.                                      */
+  /*                                                                       */
+  /*    offsets :: The offsets of the font headers, one per face.          */
+  /*                                                                       */
+  typedef struct  TTC_Header_
+  {
+    FT_ULong   tag;
+    FT_Fixed   version;
+    FT_Long    count;
+    FT_ULong*  offsets;
+
+  } TTC_Header;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    SFNT_Header                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    SFNT file format header.                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    format_tag     :: The font format tag.                             */
+  /*                                                                       */
+  /*    num_tables     :: The number of tables in file.                    */
+  /*                                                                       */
+  /*    search_range   :: Must be 16*(max power of 2 <= num_tables).       */
+  /*                                                                       */
+  /*    entry_selector :: Must be log2 of search_range/16.                 */
+  /*                                                                       */
+  /*    range_shift    :: Must be num_tables*16 - search_range.            */
+  /*                                                                       */
+  typedef struct SFNT_Header_
+  {
+    FT_ULong   format_tag;
+    FT_UShort  num_tables;
+    FT_UShort  search_range;
+    FT_UShort  entry_selector;
+    FT_UShort  range_shift;
+  
+  } SFNT_Header;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_TableDir                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure models a TrueType table directory.  It is used to   */
+  /*    access the various tables of the font face.                        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version       :: The version number; starts with 0x00010000.       */
+  /*                                                                       */
+  /*    numTables     :: The number of tables.                             */
+  /*                                                                       */
+  /*    searchRange   :: Unused.                                           */
+  /*                                                                       */
+  /*    entrySelector :: Unused.                                           */
+  /*                                                                       */
+  /*    rangeShift    :: Unused.                                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font opening.                   */
+  /*                                                                       */
+  typedef struct  TT_TableDir_
+  {
+    FT_Fixed   version;        /* should be 0x10000 */
+    FT_UShort  numTables;      /* number of tables  */
+
+    FT_UShort  searchRange;    /* These parameters are only used  */
+    FT_UShort  entrySelector;  /* for a dichotomy search in the   */
+    FT_UShort  rangeShift;     /* directory.  We ignore them.     */
+
+  } TT_TableDir;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Table                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure describes a given table of a TrueType font.         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Tag      :: A four-bytes tag describing the table.                 */
+  /*                                                                       */
+  /*    CheckSum :: The table checksum.  This value can be ignored.        */
+  /*                                                                       */
+  /*    Offset   :: The offset of the table from the start of the TrueType */
+  /*                font in its resource.                                  */
+  /*                                                                       */
+  /*    Length   :: The table length (in bytes).                           */
+  /*                                                                       */
+  typedef struct  TT_Table_
+  {
+    FT_ULong  Tag;        /*        table type */
+    FT_ULong  CheckSum;   /*    table checksum */
+    FT_ULong  Offset;     /* table file offset */
+    FT_ULong  Length;     /*      table length */
+
+  } TT_Table;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_CMapDir                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure describes the directory of the `cmap' table,        */
+  /*    containing the font's character mappings table.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    tableVersionNumber :: The version number.                          */
+  /*                                                                       */
+  /*    numCMaps           :: The number of charmaps in the font.          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font loading.                   */
+  /*                                                                       */
+  typedef struct  TT_CMapDir_
+  {
+    FT_UShort  tableVersionNumber;
+    FT_UShort  numCMaps;
+
+  } TT_CMapDir;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_CMapDirEntry                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure describes a charmap in a TrueType font.             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    platformID :: An ID used to specify for which platform this        */
+  /*                  charmap is defined (FreeType manages all platforms). */
+  /*                                                                       */
+  /*    encodingID :: A platform-specific ID used to indicate which source */
+  /*                  encoding is used in this charmap.                    */
+  /*                                                                       */
+  /*    offset     :: The offset of the charmap relative to the start of   */
+  /*                  the `cmap' table.                                    */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font loading.                   */
+  /*                                                                       */
+  typedef struct  TT_CMapDirEntry_
+  {
+    FT_UShort  platformID;
+    FT_UShort  platformEncodingID;
+    FT_Long    offset;
+
+  } TT_CMapDirEntry;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_LongMetrics                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling the long metrics of the `hmtx' and `vmtx'     */
+  /*    TrueType tables.  The values are expressed in font units.          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    advance :: The advance width or height for the glyph.              */
+  /*                                                                       */
+  /*    bearing :: The left-side or top-side bearing for the glyph.        */
+  /*                                                                       */
+  typedef struct  TT_LongMetrics_
+  {
+    FT_UShort  advance;
+    FT_Short   bearing;
+
+  } TT_LongMetrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type> TT_ShortMetrics                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple type to model the short metrics of the `hmtx' and `vmtx'  */
+  /*    tables.                                                            */
+  /*                                                                       */
+  typedef FT_Short  TT_ShortMetrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_NameRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling TrueType name records.  Name records are used */
+  /*    to store important strings like family name, style name,           */
+  /*    copyright, etc. in _localized_ versions (i.e., language, encoding, */
+  /*    etc).                                                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    platformID   :: The ID of the name's encoding platform.            */
+  /*                                                                       */
+  /*    encodingID   :: The platform-specific ID for the name's encoding.  */
+  /*                                                                       */
+  /*    languageID   :: The platform-specific ID for the name's language.  */
+  /*                                                                       */
+  /*    nameID       :: The ID specifying what kind of name this is.       */
+  /*                                                                       */
+  /*    stringLength :: The length of the string in bytes.                 */
+  /*                                                                       */
+  /*    stringOffset :: The offset to the string in the `name' table.      */
+  /*                                                                       */
+  /*    string       :: A pointer to the string's bytes.  Note that these  */
+  /*                    are usually UTF-16 encoded characters.             */
+  /*                                                                       */
+  typedef struct  TT_NameRec_
+  {
+    FT_UShort  platformID;
+    FT_UShort  encodingID;
+    FT_UShort  languageID;
+    FT_UShort  nameID;
+    FT_UShort  stringLength;
+    FT_UShort  stringOffset;
+
+    /* this last field is not defined in the spec */
+    /* but used by the FreeType engine            */
+
+    FT_Byte*   string;
+
+  } TT_NameRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_NameTable                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling the TrueType name table.                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    format         :: The format of the name table.                    */
+  /*                                                                       */
+  /*    numNameRecords :: The number of names in table.                    */
+  /*                                                                       */
+  /*    storageOffset  :: The offset of the name table in the `name'       */
+  /*                      TrueType table.                                  */
+  /*                                                                       */
+  /*    names          :: An array of name records.                        */
+  /*                                                                       */
+  /*    storage        :: The names storage area.                          */
+  /*                                                                       */
+  typedef struct  TT_NameTable_
+  {
+    FT_UShort    format;
+    FT_UShort    numNameRecords;
+    FT_UShort    storageOffset;
+    TT_NameRec*  names;
+    FT_Byte*     storage;
+
+  } TT_NameTable;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***             OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS         ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_GaspRange                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A tiny structure used to model a gasp range according to the       */
+  /*    TrueType specification.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    maxPPEM  :: The maximum ppem value to which `gaspFlag' applies.    */
+  /*                                                                       */
+  /*    gaspFlag :: A flag describing the grid-fitting and anti-aliasing   */
+  /*                modes to be used.                                      */
+  /*                                                                       */
+  typedef struct  TT_GaspRange_
+  {
+    FT_UShort  maxPPEM;
+    FT_UShort  gaspFlag;
+
+  } TT_GaspRange;
+
+
+#define TT_GASP_GRIDFIT  0x01
+#define TT_GASP_DOGRAY   0x02
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Gasp                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling the TrueType `gasp' table used to specify     */
+  /*    grid-fitting and anti-aliasing behaviour.                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version    :: The version number.                                  */
+  /*                                                                       */
+  /*    numRanges  :: The number of gasp ranges in table.                  */
+  /*                                                                       */
+  /*    gaspRanges :: An array of gasp ranges.                             */
+  /*                                                                       */
+  typedef struct  TT_Gasp_
+  {
+    FT_UShort      version;
+    FT_UShort      numRanges;
+    TT_GaspRange*  gaspRanges;
+
+  } TT_Gasp;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_HdmxRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A small structure used to model the pre-computed widths of a given */
+  /*    size.  They are found in the `hdmx' table.                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ppem      :: The pixels per EM value at which these metrics apply. */
+  /*                                                                       */
+  /*    max_width :: The maximum advance width for this metric.            */
+  /*                                                                       */
+  /*    widths    :: An array of widths.  Note: These are 8-bit bytes.     */
+  /*                                                                       */
+  typedef struct  TT_HdmxRec_
+  {
+    FT_Byte   ppem;
+    FT_Byte   max_width;
+    FT_Byte*  widths;
+
+  } TT_HdmxRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Hdmx                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model the `hdmx' table, which contains         */
+  /*    pre-computed widths for a set of given sizes/dimensions.           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version     :: The version number.                                 */
+  /*                                                                       */
+  /*    num_records :: The number of hdmx records.                         */
+  /*                                                                       */
+  /*    records     :: An array of hdmx records.                           */
+  /*                                                                       */
+  typedef struct  TT_Hdmx_
+  {
+    FT_UShort    version;
+    FT_Short     num_records;
+    TT_HdmxRec*  records;
+
+  } TT_Hdmx;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Kern_0_Pair                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a kerning pair for the kerning table     */
+  /*    format 0.  The engine now loads this table if it finds one in the  */
+  /*    font file.                                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    left  :: The index of the left glyph in pair.                      */
+  /*                                                                       */
+  /*    right :: The index of the right glyph in pair.                     */
+  /*                                                                       */
+  /*    value :: The kerning distance.  A positive value spaces the        */
+  /*             glyphs, a negative one makes them closer.                 */
+  /*                                                                       */
+  typedef struct  TT_Kern_0_Pair_
+  {
+    FT_UShort  left;   /* index of left  glyph in pair */
+    FT_UShort  right;  /* index of right glyph in pair */
+    FT_FWord   value;  /* kerning value                */
+
+  } TT_Kern_0_Pair;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                    EMBEDDED BITMAPS SUPPORT                       ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Metrics                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold the big metrics of a given glyph bitmap   */
+  /*    in a TrueType or OpenType font.  These are usually found in the    */
+  /*    `EBDT' (Microsoft) or `bdat' (Apple) table.                        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    height       :: The glyph height in pixels.                        */
+  /*                                                                       */
+  /*    width        :: The glyph width in pixels.                         */
+  /*                                                                       */
+  /*    horiBearingX :: The horizontal left bearing.                       */
+  /*                                                                       */
+  /*    horiBearingY :: The horizontal top bearing.                        */
+  /*                                                                       */
+  /*    horiAdvance  :: The horizontal advance.                            */
+  /*                                                                       */
+  /*    vertBearingX :: The vertical left bearing.                         */
+  /*                                                                       */
+  /*    vertBearingY :: The vertical top bearing.                          */
+  /*                                                                       */
+  /*    vertAdvance  :: The vertical advance.                              */
+  /*                                                                       */
+  typedef struct  TT_SBit_Metrics_
+  {
+    FT_Byte  height;
+    FT_Byte  width;
+
+    FT_Char  horiBearingX;
+    FT_Char  horiBearingY;
+    FT_Byte  horiAdvance;
+
+    FT_Char  vertBearingX;
+    FT_Char  vertBearingY;
+    FT_Byte  vertAdvance;
+
+  } TT_SBit_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Small_Metrics                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold the small metrics of a given glyph bitmap */
+  /*    in a TrueType or OpenType font.  These are usually found in the    */
+  /*    `EBDT' (Microsoft) or the `bdat' (Apple) table.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    height   :: The glyph height in pixels.                            */
+  /*                                                                       */
+  /*    width    :: The glyph width in pixels.                             */
+  /*                                                                       */
+  /*    bearingX :: The left-side bearing.                                 */
+  /*                                                                       */
+  /*    bearingY :: The top-side bearing.                                  */
+  /*                                                                       */
+  /*    advance  :: The advance width or height.                           */
+  /*                                                                       */
+  typedef struct  TT_SBit_Small_Metrics_
+  {
+    FT_Byte  height;
+    FT_Byte  width;
+
+    FT_Char  bearingX;
+    FT_Char  bearingY;
+    FT_Byte  advance;
+
+  } TT_SBit_Small_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Line_Metrics                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe the text line metrics of a given      */
+  /*    bitmap strike, for either a horizontal or vertical layout.         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ascender                :: The ascender in pixels.                 */
+  /*                                                                       */
+  /*    descender               :: The descender in pixels.                */
+  /*                                                                       */
+  /*    max_width               :: The maximum glyph width in pixels.      */
+  /*                                                                       */
+  /*    caret_slope_enumerator  :: Rise of the caret slope, typically set  */
+  /*                               to 1 for non-italic fonts.              */
+  /*                                                                       */
+  /*    caret_slope_denominator :: Rise of the caret slope, typically set  */
+  /*                               to 0 for non-italic fonts.              */
+  /*                                                                       */
+  /*    caret_offset            :: Offset in pixels to move the caret for  */
+  /*                               proper positioning.                     */
+  /*                                                                       */
+  /*    min_origin_SB           :: Minimum of horiBearingX (resp.          */
+  /*                               vertBearingY).                          */
+  /*    min_advance_SB          :: Minimum of                              */
+  /*                                                                       */
+  /*                                 horizontal advance -                  */
+  /*                                   ( horiBearingX + width )            */
+  /*                                                                       */
+  /*                               resp.                                   */
+  /*                                                                       */
+  /*                                 vertical advance -                    */
+  /*                                   ( vertBearingY + height )           */
+  /*                                                                       */
+  /*    max_before_BL           :: Maximum of horiBearingY (resp.          */
+  /*                               vertBearingY).                          */
+  /*                                                                       */
+  /*    min_after_BL            :: Minimum of                              */
+  /*                                                                       */
+  /*                                 horiBearingY - height                 */
+  /*                                                                       */
+  /*                               resp.                                   */
+  /*                                                                       */
+  /*                                 vertBearingX - width                  */
+  /*                                                                       */
+  /*    pads                    :: Unused (to make the size of the record  */
+  /*                               a multiple of 32 bits.                  */
+  /*                                                                       */
+  typedef struct  TT_SBit_Line_Metrics_
+  {
+    FT_Char  ascender;
+    FT_Char  descender;
+    FT_Byte  max_width;
+    FT_Char  caret_slope_numerator;
+    FT_Char  caret_slope_denominator;
+    FT_Char  caret_offset;
+    FT_Char  min_origin_SB;
+    FT_Char  min_advance_SB;
+    FT_Char  max_before_BL;
+    FT_Char  min_after_BL;
+    FT_Char  pads[2];
+
+  } TT_SBit_Line_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Range                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A TrueType/OpenType subIndexTable as defined in the `EBLC'         */
+  /*    (Microsoft) or `bloc' (Apple) tables.                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    first_glyph   :: The first glyph index in the range.               */
+  /*                                                                       */
+  /*    last_glyph    :: The last glyph index in the range.                */
+  /*                                                                       */
+  /*    index_format  :: The format of index table.  Valid values are 1    */
+  /*                     to 5.                                             */
+  /*                                                                       */
+  /*    image_format  :: The format of `EBDT' image data.                  */
+  /*                                                                       */
+  /*    image_offset  :: The offset to image data in `EBDT'.               */
+  /*                                                                       */
+  /*    image_size    :: For index formats 2 and 5.  This is the size in   */
+  /*                     bytes of each glyph bitmap.                       */
+  /*                                                                       */
+  /*    big_metrics   :: For index formats 2 and 5.  This is the big       */
+  /*                     metrics for each glyph bitmap.                    */
+  /*                                                                       */
+  /*    num_glyphs    :: For index formats 4 and 5.  This is the number of */
+  /*                     glyphs in the code array.                         */
+  /*                                                                       */
+  /*    glyph_offsets :: For index formats 1 and 3.                        */
+  /*                                                                       */
+  /*    glyph_codes   :: For index formats 4 and 5.                        */
+  /*                                                                       */
+  /*    table_offset  :: The offset of the index table in the `EBLC'       */
+  /*                     table.  Only used during strike loading.          */
+  /*                                                                       */
+  typedef struct  TT_SBit_Range
+  {
+    FT_UShort        first_glyph;
+    FT_UShort        last_glyph;
+
+    FT_UShort        index_format;
+    FT_UShort        image_format;
+    FT_ULong         image_offset;
+
+    FT_ULong         image_size;
+    TT_SBit_Metrics  metrics;
+    FT_ULong         num_glyphs;
+
+    FT_ULong*        glyph_offsets;
+    FT_UShort*       glyph_codes;
+
+    FT_ULong         table_offset;
+
+  } TT_SBit_Range;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Strike                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used describe a given bitmap strike in the `EBLC'      */
+  /*    (Microsoft) or `bloc' (Apple) tables.                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*   num_index_ranges :: The number of index ranges.                     */
+  /*                                                                       */
+  /*   index_ranges     :: An array of glyph index ranges.                 */
+  /*                                                                       */
+  /*   color_ref        :: Unused.  A color reference?                     */
+  /*                                                                       */
+  /*   hori             :: The line metrics for horizontal layouts.        */
+  /*                                                                       */
+  /*   vert             :: The line metrics for vertical layouts.          */
+  /*                                                                       */
+  /*   start_glyph      :: The lowest glyph index for this strike.         */
+  /*                                                                       */
+  /*   end_glyph        :: The highest glyph index for this strike.        */
+  /*                                                                       */
+  /*   x_ppem           :: The number of horizontal pixels per EM.         */
+  /*                                                                       */
+  /*   y_ppem           :: The number of vertical pixels per EM.           */
+  /*                                                                       */
+  /*   bit_depth        :: The bit depth.  Valid values are 1, 2, 4,       */
+  /*                       and 8.                                          */
+  /*                                                                       */
+  /*   flags            :: Is this a vertical or horizontal strike?        */
+  /*                                                                       */
+  typedef struct  TT_SBit_Strike_
+  {
+    FT_Int                num_ranges;
+    TT_SBit_Range*        sbit_ranges;
+    FT_ULong              ranges_offset;
+
+    FT_ULong              color_ref;
+
+    TT_SBit_Line_Metrics  hori;
+    TT_SBit_Line_Metrics  vert;
+
+    FT_UShort             start_glyph;
+    FT_UShort             end_glyph;
+
+    FT_Byte               x_ppem;
+    FT_Byte               y_ppem;
+
+    FT_Byte               bit_depth;
+    FT_Char               flags;
+
+  } TT_SBit_Strike;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Component                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure to describe a compound sbit element.            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    glyph_code :: The element's glyph index.                           */
+  /*                                                                       */
+  /*    x_offset   :: The element's left bearing.                          */
+  /*                                                                       */
+  /*    y_offset   :: The element's top bearing.                           */
+  /*                                                                       */
+  typedef struct  TT_SBit_Component_
+  {
+    FT_UShort  glyph_code;
+
+    FT_Char    x_offset;
+    FT_Char    y_offset;
+
+  } TT_SBit_Component;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Scale                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used describe a given bitmap scaling table, as defined */
+  /*    in the `EBSC' table.                                               */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    hori              :: The horizontal line metrics.                  */
+  /*                                                                       */
+  /*    vert              :: The vertical line metrics.                    */
+  /*                                                                       */
+  /*    x_ppem            :: The number of horizontal pixels per EM.       */
+  /*                                                                       */
+  /*    y_ppem            :: The number of vertical pixels per EM.         */
+  /*                                                                       */
+  /*    x_ppem_substitute :: Substitution x_ppem value.                    */
+  /*                                                                       */
+  /*    y_ppem_substitute :: Substitution y_ppem value.                    */
+  /*                                                                       */
+  typedef struct  TT_SBit_Scale_
+  {
+    TT_SBit_Line_Metrics  hori;
+    TT_SBit_Line_Metrics  vert;
+
+    FT_Byte               x_ppem;
+    FT_Byte               y_ppem;
+
+    FT_Byte               x_ppem_substitute;
+    FT_Byte               y_ppem_substitute;
+
+  } TT_SBit_Scale;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                  POSTSCRIPT GLYPH NAMES SUPPORT                   ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Post_20                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Postscript names sub-table, format 2.0.  Stores the PS name of     */
+  /*    each glyph in the font face.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_glyphs    :: The number of named glyphs in the table.          */
+  /*                                                                       */
+  /*    num_names     :: The number of PS names stored in the table.       */
+  /*                                                                       */
+  /*    glyph_indices :: The indices of the glyphs in the names arrays.    */
+  /*                                                                       */
+  /*    glyph_names   :: The PS names not in Mac Encoding.                 */
+  /*                                                                       */
+  typedef struct  TT_Post_20_
+  {
+    FT_UShort   num_glyphs;
+    FT_UShort   num_names;
+    FT_UShort*  glyph_indices;
+    FT_Char**   glyph_names;
+
+  } TT_Post_20;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Post_25                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Postscript names sub-table, format 2.5.  Stores the PS name of     */
+  /*    each glyph in the font face.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_glyphs :: The number of glyphs in the table.                   */
+  /*                                                                       */
+  /*    offsets    :: An array of signed offsets in a normal Mac           */
+  /*                  Postscript name encoding.                            */
+  /*                                                                       */
+  typedef struct  TT_Post_25_
+  {
+    FT_UShort  num_glyphs;
+    FT_Char*   offsets;
+
+  } TT_Post_25;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Post_Names                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Postscript names table, either format 2.0 or 2.5.                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    loaded    :: A flag to indicate whether the PS names are loaded.   */
+  /*                                                                       */
+  /*    format_20 :: The sub-table used for format 2.0.                    */
+  /*                                                                       */
+  /*    format_25 :: The sub-table used for format 2.5.                    */
+  /*                                                                       */
+  typedef struct  TT_Post_Names_
+  {
+    FT_Bool       loaded;
+
+    union
+    {
+      TT_Post_20  format_20;
+      TT_Post_25  format_25;
+
+    } names;
+
+  } TT_Post_Names;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                  TRUETYPE CHARMAPS SUPPORT                        ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* format 0 */
+
+  typedef struct  TT_CMap0_
+  {
+    FT_Byte*  glyphIdArray;
+
+  } TT_CMap0;
+
+
+  /* format 2 */
+
+  typedef struct  TT_CMap2SubHeader_
+  {
+    FT_UShort  firstCode;      /* first valid low byte         */
+    FT_UShort  entryCount;     /* number of valid low bytes    */
+    FT_Short   idDelta;        /* delta value to glyphIndex    */
+    FT_UShort  idRangeOffset;  /* offset from here to 1st code */
+
+  } TT_CMap2SubHeader;
+
+
+  typedef struct  TT_CMap2_
+  {
+    FT_UShort*          subHeaderKeys;
+    /* high byte mapping table            */
+    /* value = subHeader index * 8        */
+
+    TT_CMap2SubHeader*  subHeaders;
+    FT_UShort*          glyphIdArray;
+    FT_UShort           numGlyphId;   /* control value */
+
+  } TT_CMap2;
+
+
+  /* format 4 */
+
+  typedef struct  TT_CMap4Segment_
+  {
+    FT_UShort  endCount;
+    FT_UShort  startCount;
+    FT_Short   idDelta;
+    FT_UShort  idRangeOffset;
+
+  } TT_CMap4Segment;
+
+
+  typedef struct  TT_CMap4_
+  {
+    FT_UShort         segCountX2;     /* number of segments * 2       */
+    FT_UShort         searchRange;    /* these parameters can be used */
+    FT_UShort         entrySelector;  /* for a binary search          */
+    FT_UShort         rangeShift;
+
+    TT_CMap4Segment*  segments;
+    FT_UShort*        glyphIdArray;
+    FT_UShort         numGlyphId;   /* control value */
+    
+    TT_CMap4Segment*  last_segment;  /* last used segment; this is a small  */
+                                     /* cache to potentially increase speed */
+  } TT_CMap4;
+
+
+  /* format 6 */
+
+  typedef struct  TT_CMap6_
+  {
+    FT_UShort   firstCode;      /* first character code of subrange      */
+    FT_UShort   entryCount;     /* number of character codes in subrange */
+
+    FT_UShort*  glyphIdArray;
+
+  } TT_CMap6;
+
+
+  typedef struct TT_CMapTable_  TT_CMapTable;
+
+
+  typedef
+  FT_UInt  (*TT_CharMap_Func)( TT_CMapTable*  charmap,
+                               FT_ULong       char_code );
+
+
+  /* charmap table */
+  struct  TT_CMapTable_
+  {
+    FT_UShort  platformID;
+    FT_UShort  platformEncodingID;
+    FT_UShort  format;
+    FT_UShort  length;
+    FT_UShort  version;
+
+    FT_Bool    loaded;
+    FT_ULong   offset;
+
+    union
+    {
+      TT_CMap0  cmap0;
+      TT_CMap2  cmap2;
+      TT_CMap4  cmap4;
+      TT_CMap6  cmap6;
+    } c;
+
+    TT_CharMap_Func  get_index;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_CharMapRec                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType character map object type.                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root :: The parent character map structure.                        */
+  /*                                                                       */
+  /*    cmap :: The used character map.                                    */
+  /*                                                                       */
+  typedef struct  TT_CharMapRec_
+  {
+    FT_CharMapRec  root;
+    TT_CMapTable   cmap;
+
+  } TT_CharMapRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                  ORIGINAL TT_FACE CLASS DEFINITION                ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This structure/class is defined here because it is common to the      */
+  /* following formats: TTF, OpenType-TT, and OpenType-CFF.                */
+  /*                                                                       */
+  /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */
+  /* are not shared between font drivers, and are thus defined normally in */
+  /* `ttobjs.h'.                                                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_Face                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType face/font object.  A TT_Face encapsulates   */
+  /*    the resolution and scaling independent parts of a TrueType font    */
+  /*    resource.                                                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The TT_Face structure is also used as a `parent class' for the     */
+  /*    OpenType-CFF class (T2_Face).                                      */
+  /*                                                                       */
+  typedef struct TT_FaceRec_*  TT_Face;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_CharMap                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType character mapping object.                   */
+  /*                                                                       */
+  typedef struct TT_CharMapRec_*  TT_CharMap;
+
+
+  /* a function type used for the truetype bytecode interpreter hooks */
+  typedef FT_Error  (*TT_Interpreter)( void*  exec_context );
+
+  /* forward declaration */
+  typedef struct TT_Loader_  TT_Loader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Goto_Table_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Seeks a stream to the start of a given TrueType table.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /*    tag    :: A 4-byte tag used to name the table.                     */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    length :: The length of the table in bytes.  Set to 0 if not       */
+  /*              needed.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Goto_Table_Func)( TT_Face    face,
+                                   FT_ULong   tag,
+                                   FT_Stream  stream,
+                                   FT_ULong*  length );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Access_Glyph_Frame_Func                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Seeks a stream to the start of a given glyph element, and opens a  */
+  /*    frame for it.                                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    loader      :: The current TrueType glyph loader object.           */
+  /*                                                                       */
+  /*    glyph index :: The index of the glyph to access.                   */
+  /*                                                                       */
+  /*    offset      :: The offset of the glyph according to the            */
+  /*                   `locations' table.                                  */
+  /*                                                                       */
+  /*    byte_count  :: The size of the frame in bytes.                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is normally equivalent to FILE_Seek(offset)          */
+  /*    followed by ACCESS_Frame(byte_count) with the loader's stream, but */
+  /*    alternative formats (e.g. compressed ones) might use something     */
+  /*    different.                                                         */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Access_Glyph_Frame_Func)( TT_Loader*  loader,
+                                           FT_UInt     glyph_index,
+                                           FT_ULong    offset,
+                                           FT_UInt     byte_count );
+
+  
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Glyph_Element_Func                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reads one glyph element (its header, a simple glyph, or a          */
+  /*    composite) from the loader's current stream frame.                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    loader :: The current TrueType glyph loader object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef
+  FT_Error  (*TT_Load_Glyph_Element_Func)( TT_Loader*  loader );
+  
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Forget_Glyph_Frame_Func                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Closes the current loader stream frame for the glyph.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    loader :: The current TrueType glyph loader object.                */
+  /*                                                                       */
+  typedef
+  void  (*TT_Forget_Glyph_Frame_Func)( TT_Loader*  loader );
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                         TrueType Face Type                            */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Face                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType face class.  These objects model the resolution and   */
+  /*    point-size independent data found in a TrueType font file.         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root                 :: The base FT_Face structure, managed by the */
+  /*                            base layer.                                */
+  /*                                                                       */
+  /*    ttc_header           :: The TrueType collection header, used when  */
+  /*                            the file is a `ttc' rather than a `ttf'.   */
+  /*                            For ordinary font files, the field         */
+  /*                            `ttc_header.count' is set to 0.            */
+  /*                                                                       */
+  /*    format_tag           :: The font format tag.                       */
+  /*                                                                       */
+  /*    num_tables           :: The number of TrueType tables in this font */
+  /*                            file.                                      */
+  /*                                                                       */
+  /*    dir_tables           :: The directory of TrueType tables for this  */
+  /*                            font file.                                 */
+  /*                                                                       */
+  /*    header               :: The font's font header (`head' table).     */
+  /*                            Read on font opening.                      */
+  /*                                                                       */
+  /*    horizontal           :: The font's horizontal header (`hhea'       */
+  /*                            table).  This field also contains the      */
+  /*                            associated horizontal metrics table        */
+  /*                            (`hmtx').                                  */
+  /*                                                                       */
+  /*    max_profile          :: The font's maximum profile table.  Read on */
+  /*                            font opening.  Note that some maximum      */
+  /*                            values cannot be taken directly from this  */
+  /*                            table.  We thus define additional fields   */
+  /*                            below to hold the computed maxima.         */
+  /*                                                                       */
+  /*    max_components       :: The maximum number of glyph components     */
+  /*                            required to load any composite glyph from  */
+  /*                            this font.  Used to size the load stack.   */
+  /*                                                                       */
+  /*    vertical_info        :: A boolean which is set when the font file  */
+  /*                            contains vertical metrics.  If not, the    */
+  /*                            value of the `vertical' field is           */
+  /*                            undefined.                                 */
+  /*                                                                       */
+  /*    vertical             :: The font's vertical header (`vhea' table). */
+  /*                            This field also contains the associated    */
+  /*                            vertical metrics table (`vmtx'), if found. */
+  /*                            IMPORTANT: The contents of this field is   */
+  /*                            undefined if the `verticalInfo' field is   */
+  /*                            unset.                                     */
+  /*                                                                       */
+  /*    num_names            :: The number of name records within this     */
+  /*                            TrueType font.                             */
+  /*                                                                       */
+  /*    name_table           :: The table of name records (`name').        */
+  /*                                                                       */
+  /*    os2                  :: The font's OS/2 table (`OS/2').            */
+  /*                                                                       */
+  /*    postscript           :: The font's PostScript table (`post'        */
+  /*                            table).  The PostScript glyph names are    */
+  /*                            not loaded by the driver on face opening.  */
+  /*                            See the `ttpost' module for more details.  */
+  /*                                                                       */
+  /*    num_charmaps         :: The number of character mappings in the    */
+  /*                            font.                                      */
+  /*                                                                       */
+  /*    charmaps             :: The array of charmap objects for this font */
+  /*                            file.  Note that this field is a typeless  */
+  /*                            pointer.  The Reason is that the format of */
+  /*                            charmaps varies with the underlying font   */
+  /*                            format and cannot be determined here.      */
+  /*                                                                       */
+  /*    goto_table           :: A function called by each TrueType table   */
+  /*                            loader to position a stream's cursor to    */
+  /*                            the start of a given table according to    */
+  /*                            its tag.  It defaults to TT_Goto_Face but  */
+  /*                            can be different for strange formats (e.g. */
+  /*                            Type 42).                                  */
+  /*                                                                       */
+  /*    access_glyph_frame   :: XXX                                        */
+  /*                                                                       */
+  /*    read_glyph_header    :: XXX                                        */
+  /*                                                                       */
+  /*    read_simple_glyph    :: XXX                                        */
+  /*                                                                       */
+  /*    read_composite_glyph :: XXX                                        */
+  /*                                                                       */
+  /*    forget_glyph_frame   :: XXX                                        */
+  /*                                                                       */
+  /*    sfnt                 :: A pointer to the SFNT `driver' interface.  */
+  /*                                                                       */
+  /*    psnames              :: A pointer to the `PSNames' module          */
+  /*                            interface.                                 */
+  /*                                                                       */
+  /*    hdmx                 :: The face's horizontal device metrics       */
+  /*                            (`hdmx' table).  This table is optional in */
+  /*                            TrueType/OpenType fonts.                   */
+  /*                                                                       */
+  /*    gasp                 :: The grid-fitting and scaling properties    */
+  /*                            table (`gasp').  This table is optional in */
+  /*                            TrueType/OpenType fonts.                   */
+  /*                                                                       */
+  /*    pclt                 :: XXX                                        */
+  /*                                                                       */
+  /*    num_sbit_strikes     :: The number of sbit strikes, i.e., bitmap   */
+  /*                            sizes, embedded in this font.              */
+  /*                                                                       */
+  /*    sbit_strikes         :: An array of sbit strikes embedded in this  */
+  /*                            font.  This table is optional in a         */
+  /*                            TrueType/OpenType font.                    */
+  /*                                                                       */
+  /*    num_sbit_scales      :: The number of sbit scales for this font.   */
+  /*                                                                       */
+  /*    sbit_scales          :: Array of sbit scales embedded in this      */
+  /*                            font.  This table is optional in a         */
+  /*                            TrueType/OpenType font.                    */
+  /*                                                                       */
+  /*    postscript_names     :: A table used to store the Postscript names */
+  /*                            of  the glyphs for this font.  See the     */
+  /*                            file  `ttconfig.h' for comments on the     */
+  /*                            TT_CONFIG_OPTION_POSTSCRIPT_NAMES option.  */
+  /*                                                                       */
+  /*    num_locations        :: The number of glyph locations in this      */
+  /*                            TrueType file.  This should be             */
+  /*                            identical to the number of glyphs.         */
+  /*                            Ignored for Type 2 fonts.                  */
+  /*                                                                       */
+  /*    glyph_locations      :: An array of longs.  These are offsets to   */
+  /*                            glyph data within the `glyf' table.        */
+  /*                            Ignored for Type 2 font faces.             */
+  /*                                                                       */
+  /*    font_program_size    :: Size in bytecodes of the face's font       */
+  /*                            program.  0 if none defined.  Ignored for  */
+  /*                            Type 2 fonts.                              */
+  /*                                                                       */
+  /*    font_program         :: The face's font program (bytecode stream)  */
+  /*                            executed at load time, also used during    */
+  /*                            glyph rendering.  Comes from the `fpgm'    */
+  /*                            table.  Ignored for Type 2 font fonts.     */
+  /*                                                                       */
+  /*    cvt_program_size     :: The size in bytecodes of the face's cvt    */
+  /*                            program.  Ignored for Type 2 fonts.        */
+  /*                                                                       */
+  /*    cvt_program          :: The face's cvt program (bytecode stream)   */
+  /*                            executed each time an instance/size is     */
+  /*                            changed/reset.  Comes from the `prep'      */
+  /*                            table.  Ignored for Type 2 fonts.          */
+  /*                                                                       */
+  /*    cvt_size             :: Size of the control value table (in        */
+  /*                            entries).   Ignored for Type 2 fonts.      */
+  /*                                                                       */
+  /*    cvt                  :: The face's original control value table.   */
+  /*                            Coordinates are expressed in unscaled font */
+  /*                            units.  Comes from the `cvt ' table.       */
+  /*                            Ignored for Type 2 fonts.                  */
+  /*                                                                       */
+  /*    num_kern_pairs       :: The number of kerning pairs present in the */
+  /*                            font file.  The engine only loads the      */
+  /*                            first horizontal format 0 kern table it    */
+  /*                            finds in the font file.  You should use    */
+  /*                            the `ttxkern' structures if you want to    */
+  /*                            access other kerning tables.  Ignored      */
+  /*                            for Type 2 fonts.                          */
+  /*                                                                       */
+  /*    kern_table_index     :: The index of the kerning table in the font */
+  /*                            kerning directory.  Only used by the       */
+  /*                            ttxkern extension to avoid data            */
+  /*                            duplication.  Ignored for Type 2 fonts.    */
+  /*                                                                       */
+  /*    interpreter          :: A pointer to the TrueType bytecode         */
+  /*                            interpreters field is also used to hook    */
+  /*                            the debugger in `ttdebug'.                 */
+  /*                                                                       */
+  /*    extra                :: XXX                                        */
+  /*                                                                       */
+  typedef struct  TT_FaceRec_
+  {
+    FT_FaceRec         root;
+
+    TTC_Header         ttc_header;
+
+    FT_ULong           format_tag;
+    FT_UShort          num_tables;
+    TT_Table*          dir_tables;
+
+    TT_Header          header;       /* TrueType header table          */
+    TT_HoriHeader      horizontal;   /* TrueType horizontal header     */
+
+    TT_MaxProfile      max_profile;
+    FT_ULong           max_components;
+
+    FT_Bool            vertical_info;
+    TT_VertHeader      vertical;     /* TT Vertical header, if present */
+
+    FT_Int             num_names;    /* number of name records  */
+    TT_NameTable       name_table;   /* name table              */
+
+    TT_OS2             os2;          /* TrueType OS/2 table            */
+    TT_Postscript      postscript;   /* TrueType Postscript table      */
+
+    FT_Int             num_charmaps;
+    TT_CharMap         charmaps;     /* array of TT_CharMapRec */
+
+    TT_Goto_Table_Func          goto_table;
+
+    TT_Access_Glyph_Frame_Func  access_glyph_frame;
+    TT_Load_Glyph_Element_Func  read_glyph_header;
+    TT_Load_Glyph_Element_Func  read_simple_glyph;
+    TT_Load_Glyph_Element_Func  read_composite_glyph;
+    TT_Forget_Glyph_Frame_Func  forget_glyph_frame;
+
+    /* a typeless pointer to the SFNT_Interface table used to load     */
+    /* the basic TrueType tables in the face object                    */
+    void*              sfnt;
+
+    /* a typeless pointer to the PSNames_Interface table used to       */
+    /* handle glyph names <-> unicode & Mac values                     */
+    void*              psnames;
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* Optional TrueType/OpenType tables                                   */
+    /*                                                                     */
+    /***********************************************************************/
+
+    /* horizontal device metrics */
+    TT_Hdmx            hdmx;
+
+    /* grid-fitting and scaling table */
+    TT_Gasp            gasp;                 /* the `gasp' table */
+
+    /* PCL 5 table */
+       TT_PCLT            pclt;
+
+    /* embedded bitmaps support */
+    FT_Int             num_sbit_strikes;
+    TT_SBit_Strike*    sbit_strikes;
+
+    FT_Int             num_sbit_scales;
+    TT_SBit_Scale*     sbit_scales;
+
+    /* postscript names table */
+    TT_Post_Names      postscript_names;
+
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* TrueType-specific fields (ignored by the OTF-Type2 driver)          */
+    /*                                                                     */
+    /***********************************************************************/
+
+    /* the glyph locations */
+    FT_UShort          num_locations;
+    FT_Long*           glyph_locations;
+
+    /* the font program, if any */
+    FT_ULong           font_program_size;
+    FT_Byte*           font_program;
+
+    /* the cvt program, if any */
+    FT_ULong           cvt_program_size;
+    FT_Byte*           cvt_program;
+
+    /* the original, unscaled, control value table */
+    FT_ULong           cvt_size;
+    FT_Short*          cvt;
+
+    /* the format 0 kerning table, if any */
+    FT_Int             num_kern_pairs;
+    FT_Int             kern_table_index;
+    TT_Kern_0_Pair*    kern_pairs;
+
+    /* A pointer to the bytecode interpreter to use.  This is also */
+    /* used to hook the debugger for the `ttdebug' utility.        */
+    TT_Interpreter     interpreter;
+
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* Other tables or fields. This is used by derivative formats like     */
+    /* OpenType.                                                           */
+    /*                                                                     */
+    /***********************************************************************/
+
+    FT_Generic      extra;
+
+  } TT_FaceRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  <Struct>                                                             */
+  /*     TT_GlyphZone                                                      */
+  /*                                                                       */
+  /*  <Description>                                                        */
+  /*     A glyph zone is used to load, scale and hint glyph outline        */
+  /*     coordinates.                                                      */
+  /*                                                                       */
+  /*  <Fields>                                                             */
+  /*     memory       :: A handle to the memory manager.                   */
+  /*                                                                       */
+  /*     max_points   :: The maximal size in points of the zone.           */
+  /*                                                                       */
+  /*     max_contours :: Max size in links contours of thez one.           */
+  /*                                                                       */
+  /*     n_points     :: The current number of points in the zone.         */
+  /*                                                                       */
+  /*     n_contours   :: The current number of contours in the zone.       */
+  /*                                                                       */
+  /*     org          :: The original glyph coordinates (font              */
+  /*                     units/scaled).                                    */
+  /*                                                                       */
+  /*     cur          :: The current glyph coordinates (scaled/hinted).    */
+  /*                                                                       */
+  /*     tags         :: The point control tags.                           */
+  /*                                                                       */
+  /*     contours     :: The contours end points.                          */
+  /*                                                                       */
+  typedef struct  TT_GlyphZone_
+  {
+    FT_Memory   memory;
+    FT_UShort   max_points;
+    FT_UShort   max_contours;
+    FT_UShort   n_points;   /* number of points in zone    */
+    FT_Short    n_contours; /* number of contours          */
+
+    FT_Vector*  org;        /* original point coordinates  */
+    FT_Vector*  cur;        /* current point coordinates   */
+
+    FT_Byte*    tags;       /* current touch flags         */
+    FT_UShort*  contours;   /* contour end points          */
+
+  } TT_GlyphZone;
+
+
+  /* handle to execution context */
+  typedef struct TT_ExecContextRec_*  TT_ExecContext;
+
+  /* glyph loader structure */
+  struct  TT_Loader_
+  {
+    FT_Face          face;
+    FT_Size          size;
+    FT_GlyphSlot     glyph;
+    FT_GlyphLoader*  gloader;
+
+    FT_ULong         load_flags;
+    FT_UInt          glyph_index;
+
+    FT_Stream        stream;
+    FT_Int           byte_len;
+
+    FT_Short         n_contours;
+    FT_BBox          bbox;
+    FT_Int           left_bearing;
+    FT_Int           advance;
+    FT_Bool          preserve_pps;
+    FT_Vector        pp1;
+    FT_Vector        pp2;
+
+    FT_ULong         glyf_offset;
+
+    /* the zone where we load our glyphs */
+    TT_GlyphZone     base;
+    TT_GlyphZone     zone;
+
+    TT_ExecContext   exec;
+    FT_Byte*         instructions;
+    FT_ULong         ins_pos;
+    
+    /* for possible extensibility in other formats */
+    void*            other;
+
+  };
+
+
+#endif /* TTTYPES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/t1tables.h b/src/freetype/freetype/t1tables.h
new file mode 100644 (file)
index 0000000..323e013
--- /dev/null
@@ -0,0 +1,235 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1tables.h                                                             */
+/*                                                                         */
+/*    Basic Type 1/Type 2 tables definitions and interface (specification  */
+/*    only).                                                               */
+/*                                                                         */
+/*  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 T1TABLES_H
+#define T1TABLES_H
+
+
+#include <freetype/freetype.h>
+
+
+  /* Note that we separate font data in T1_FontInfo and T1_Private */
+  /* structures in order to support Multiple Master fonts.         */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_FontInfo                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a Type1/Type2 FontInfo dictionary.  Note */
+  /*    that for Multiple Master fonts, each instance has its own          */
+  /*    FontInfo.                                                          */
+  /*                                                                       */
+  typedef struct  T1_FontInfo
+  {
+    FT_String*  version;
+    FT_String*  notice;
+    FT_String*  full_name;
+    FT_String*  family_name;
+    FT_String*  weight;
+    FT_Long     italic_angle;
+    FT_Bool     is_fixed_pitch;
+    FT_Short    underline_position;
+    FT_UShort   underline_thickness;
+
+  } T1_FontInfo;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Private                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a Type1/Type2 FontInfo dictionary.  Note */
+  /*    that for Multiple Master fonts, each instance has its own Private  */
+  /*    dict.                                                              */
+  /*                                                                       */
+  typedef struct  T1_Private
+  {
+    FT_Int     unique_id;
+    FT_Int     lenIV;
+
+    FT_Byte    num_blue_values;
+    FT_Byte    num_other_blues;
+    FT_Byte    num_family_blues;
+    FT_Byte    num_family_other_blues;
+
+    FT_Short   blue_values[14];
+    FT_Short   other_blues[10];
+
+    FT_Short   family_blues      [14];
+    FT_Short   family_other_blues[10];
+
+    FT_Fixed   blue_scale;
+    FT_Int     blue_shift;
+    FT_Int     blue_fuzz;
+
+    FT_UShort  standard_width[1];
+    FT_UShort  standard_height[1];
+
+    FT_Byte    num_snap_widths;
+    FT_Byte    num_snap_heights;
+    FT_Bool    force_bold;
+    FT_Bool    round_stem_up;
+
+    FT_Short   snap_widths [13];  /* reserve one place for the std */
+    FT_Short   snap_heights[13];  /* reserve one place for the std */
+
+    FT_Long    language_group;
+    FT_Long    password;
+
+    FT_Short   min_feature[2];
+
+  } T1_Private;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    T1_Blend_Flags                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A set of flags used to indicate which fields are present in a      */
+  /*    given blen dictionary (font info or private).  Used to support     */
+  /*    Multiple Masters fonts.                                            */
+  /*                                                                       */
+  typedef enum
+  {
+    /* required fields in a FontInfo blend dictionary */
+    t1_blend_underline_position = 0,
+    t1_blend_underline_thickness,
+    t1_blend_italic_angle,
+
+    /* required fields in a Private blend dictionary */
+    t1_blend_blue_values,
+    t1_blend_other_blues,
+    t1_blend_standard_width,
+    t1_blend_standard_height,
+    t1_blend_stem_snap_widths,
+    t1_blend_stem_snap_heights,
+    t1_blend_blue_scale,
+    t1_blend_blue_shift,
+    t1_blend_family_blues,
+    t1_blend_family_other_blues,
+    t1_blend_force_bold,
+
+    /* never remove */
+    t1_blend_max
+
+  } T1_Blend_Flags;
+
+
+  /* maximum number of Multiple Masters designs, as defined in the spec */
+#define T1_MAX_MM_DESIGNS     16
+
+  /* maximum number of Multiple Masters axes, as defined in the spec */
+#define T1_MAX_MM_AXIS         4
+
+  /* maximum number of elements in a design map */
+#define T1_MAX_MM_MAP_POINTS  20
+
+
+  /* this structure is used to store the BlendDesignMap entry for an axis */
+  typedef struct  T1_DesignMap_
+  {
+    FT_Byte    num_points;
+    FT_Fixed*  design_points;
+    FT_Fixed*  blend_points;
+
+  } T1_DesignMap;
+
+
+  typedef struct  T1_Blend_
+  {
+    FT_UInt       num_designs;
+    FT_UInt       num_axis;
+
+    FT_String*    axis_names[T1_MAX_MM_AXIS];
+    FT_Fixed*     design_pos[T1_MAX_MM_DESIGNS];
+    T1_DesignMap  design_map[T1_MAX_MM_AXIS];
+
+    FT_Fixed*     weight_vector;
+    FT_Fixed*     default_weight_vector;
+
+    T1_FontInfo*  font_infos[T1_MAX_MM_DESIGNS + 1];
+    T1_Private*   privates  [T1_MAX_MM_DESIGNS + 1];
+
+    FT_ULong      blend_bitflags;
+
+  } T1_Blend;
+
+
+  typedef struct  CID_FontDict_
+  {
+    T1_Private  private_dict;
+
+    FT_UInt     len_buildchar;
+    FT_Fixed    forcebold_threshold;
+    FT_Pos      stroke_width;
+    FT_Fixed    expansion_factor;
+
+    FT_Byte     paint_type;
+    FT_Byte     font_type;
+    FT_Matrix   font_matrix;
+
+    FT_UInt     num_subrs;
+    FT_ULong    subrmap_offset;
+    FT_Int      sd_bytes;
+
+  } CID_FontDict;
+
+
+  typedef struct  CID_Info_
+  {
+    FT_String*     cid_font_name;
+    FT_Fixed       cid_version;
+    FT_Int         cid_font_type;
+
+    FT_String*     registry;
+    FT_String*     ordering;
+    FT_Int         supplement;
+
+    T1_FontInfo    font_info;
+    FT_BBox        font_bbox;
+    FT_ULong       uid_base;
+
+    FT_Int         num_xuid;
+    FT_ULong       xuid[16];
+
+
+    FT_ULong       cidmap_offset;
+    FT_Int         fd_bytes;
+    FT_Int         gd_bytes;
+    FT_ULong       cid_count;
+
+    FT_Int         num_dicts;
+    CID_FontDict*  font_dicts;
+
+    FT_ULong       data_offset;
+
+  } CID_Info;
+
+
+#endif /* T1TABLES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/ttnameid.h b/src/freetype/freetype/ttnameid.h
new file mode 100644 (file)
index 0000000..4890242
--- /dev/null
@@ -0,0 +1,698 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttmakeid.h                                                             */
+/*                                                                         */
+/*    TrueType name ID definitions (specification only).                   */
+/*                                                                         */
+/*  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 TTNAMEID_H
+#define TTNAMEID_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values for the `platform' identifier code in the name        */
+  /* records of the TTF `name' table.                                      */
+  /*                                                                       */
+#define TT_PLATFORM_APPLE_UNICODE  0
+#define TT_PLATFORM_MACINTOSH      1
+#define TT_PLATFORM_ISO            2 /* deprecated */
+#define TT_PLATFORM_MICROSOFT      3
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_APPLE_UNICODE.                                    */
+  /*                                                                       */
+#define TT_APPLE_ID_DEFAULT      0
+#define TT_APPLE_ID_UNICODE_1_1  1 /* specify Hangul at U+34xx */
+#define TT_APPLE_ID_ISO_10646    2 /* deprecated */
+#define TT_APPLE_ID_UNICODE_2_0  3 /* or later */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_MACINTOSH.                                        */
+  /*                                                                       */
+#define TT_MAC_ID_ROMAN                 0
+#define TT_MAC_ID_JAPANESE              1
+#define TT_MAC_ID_TRADITIONAL_CHINESE   2
+#define TT_MAC_ID_KOREAN                3
+#define TT_MAC_ID_ARABIC                4
+#define TT_MAC_ID_HEBREW                5
+#define TT_MAC_ID_GREEK                 6
+#define TT_MAC_ID_RUSSIAN               7
+#define TT_MAC_ID_RSYMBOL               8
+#define TT_MAC_ID_DEVANAGARI            9
+#define TT_MAC_ID_GURMUKHI             10
+#define TT_MAC_ID_GUJARATI             11
+#define TT_MAC_ID_ORIYA                12
+#define TT_MAC_ID_BENGALI              13
+#define TT_MAC_ID_TAMIL                14
+#define TT_MAC_ID_TELUGU               15
+#define TT_MAC_ID_KANNADA              16
+#define TT_MAC_ID_MALAYALAM            17
+#define TT_MAC_ID_SINHALESE            18
+#define TT_MAC_ID_BURMESE              19
+#define TT_MAC_ID_KHMER                20
+#define TT_MAC_ID_THAI                 21
+#define TT_MAC_ID_LAOTIAN              22
+#define TT_MAC_ID_GEORGIAN             23
+#define TT_MAC_ID_ARMENIAN             24
+#define TT_MAC_ID_MALDIVIAN            25
+#define TT_MAC_ID_SIMPLIFIED_CHINESE   25
+#define TT_MAC_ID_TIBETAN              26
+#define TT_MAC_ID_MONGOLIAN            27
+#define TT_MAC_ID_GEEZ                 28
+#define TT_MAC_ID_SLAVIC               29
+#define TT_MAC_ID_VIETNAMESE           30
+#define TT_MAC_ID_SINDHI               31
+#define TT_MAC_ID_UNINTERP             32
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_ISO.                                              */
+  /*                                                                       */
+  /* This use is now deprecated.                                           */
+  /*                                                                       */
+#define TT_ISO_ID_7BIT_ASCII  0
+#define TT_ISO_ID_10646       1
+#define TT_ISO_ID_8859_1      2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_MICROSOFT.                                        */
+  /*                                                                       */
+#define TT_MS_ID_SYMBOL_CS   0
+#define TT_MS_ID_UNICODE_CS  1
+#define TT_MS_ID_SJIS        2
+#define TT_MS_ID_GB2312      3
+#define TT_MS_ID_BIG_5       4
+#define TT_MS_ID_WANSUNG     5
+#define TT_MS_ID_JOHAB       6
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the language identifier field in the name records  */
+  /* of the TTF `name' table if the `platform' identifier code is          */
+  /* TT_PLATFORM_MACINTOSH.                                                */
+  /*                                                                       */
+  /* The canonical source for the Apple assigned Language ID's is at       */
+  /*                                                                       */
+  /*   http://fonts.apple.com/TTRefMan/RM06/Chap6name.html                 */
+  /*                                                                       */
+#define TT_MAC_LANGID_ENGLISH                       0
+#define TT_MAC_LANGID_FRENCH                        1
+#define TT_MAC_LANGID_GERMAN                        2
+#define TT_MAC_LANGID_ITALIAN                       3
+#define TT_MAC_LANGID_DUTCH                         4
+#define TT_MAC_LANGID_SWEDISH                       5
+#define TT_MAC_LANGID_SPANISH                       6
+#define TT_MAC_LANGID_DANISH                        7
+#define TT_MAC_LANGID_PORTUGUESE                    8
+#define TT_MAC_LANGID_NORWEGIAN                     9
+#define TT_MAC_LANGID_HEBREW                       10
+#define TT_MAC_LANGID_JAPANESE                     11
+#define TT_MAC_LANGID_ARABIC                       12
+#define TT_MAC_LANGID_FINNISH                      13
+#define TT_MAC_LANGID_GREEK                        14
+#define TT_MAC_LANGID_ICELANDIC                    15
+#define TT_MAC_LANGID_MALTESE                      16
+#define TT_MAC_LANGID_TURKISH                      17
+#define TT_MAC_LANGID_CROATIAN                     18
+#define TT_MAC_LANGID_CHINESE_TRADITIONAL          19
+#define TT_MAC_LANGID_URDU                         20
+#define TT_MAC_LANGID_HINDI                        21
+#define TT_MAC_LANGID_THAI                         22
+#define TT_MAC_LANGID_KOREAN                       23
+#define TT_MAC_LANGID_LITHUANIAN                   24
+#define TT_MAC_LANGID_POLISH                       25
+#define TT_MAC_LANGID_HUNGARIAN                    26
+#define TT_MAC_LANGID_ESTONIAN                     27
+#define TT_MAC_LANGID_LETTISH                      28
+#define TT_MAC_LANGID_SAAMISK                      29
+#define TT_MAC_LANGID_FAEROESE                     30
+#define TT_MAC_LANGID_FARSI                        31
+#define TT_MAC_LANGID_RUSSIAN                      32
+#define TT_MAC_LANGID_CHINESE_SIMPLIFIED           33
+#define TT_MAC_LANGID_FLEMISH                      34
+#define TT_MAC_LANGID_IRISH                        35
+#define TT_MAC_LANGID_ALBANIAN                     36
+#define TT_MAC_LANGID_ROMANIAN                     37
+#define TT_MAC_LANGID_CZECH                        38
+#define TT_MAC_LANGID_SLOVAK                       39
+#define TT_MAC_LANGID_SLOVENIAN                    40
+#define TT_MAC_LANGID_YIDDISH                      41
+#define TT_MAC_LANGID_SERBIAN                      42
+#define TT_MAC_LANGID_MACEDONIAN                   43
+#define TT_MAC_LANGID_BULGARIAN                    44
+#define TT_MAC_LANGID_UKRAINIAN                    45
+#define TT_MAC_LANGID_BYELORUSSIAN                 46
+#define TT_MAC_LANGID_UZBEK                        47
+#define TT_MAC_LANGID_KAZAKH                       48
+#define TT_MAC_LANGID_AZERBAIJANI                  49
+#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT  49
+#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT    50
+#define TT_MAC_LANGID_ARMENIAN                     51
+#define TT_MAC_LANGID_GEORGIAN                     52
+#define TT_MAC_LANGID_MOLDAVIAN                    53
+#define TT_MAC_LANGID_KIRGHIZ                      54
+#define TT_MAC_LANGID_TAJIKI                       55
+#define TT_MAC_LANGID_TURKMEN                      56
+#define TT_MAC_LANGID_MONGOLIAN                    57
+#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT   57
+#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT    58
+#define TT_MAC_LANGID_PASHTO                       59
+#define TT_MAC_LANGID_KURDISH                      60
+#define TT_MAC_LANGID_KASHMIRI                     61
+#define TT_MAC_LANGID_SINDHI                       62
+#define TT_MAC_LANGID_TIBETAN                      63
+#define TT_MAC_LANGID_NEPALI                       64
+#define TT_MAC_LANGID_SANSKRIT                     65
+#define TT_MAC_LANGID_MARATHI                      66
+#define TT_MAC_LANGID_BENGALI                      67
+#define TT_MAC_LANGID_ASSAMESE                     68
+#define TT_MAC_LANGID_GUJARATI                     69
+#define TT_MAC_LANGID_PUNJABI                      70
+#define TT_MAC_LANGID_ORIYA                        71
+#define TT_MAC_LANGID_MALAYALAM                    72
+#define TT_MAC_LANGID_KANNADA                      73
+#define TT_MAC_LANGID_TAMIL                        74
+#define TT_MAC_LANGID_TELUGU                       75
+#define TT_MAC_LANGID_SINHALESE                    76
+#define TT_MAC_LANGID_BURMESE                      77
+#define TT_MAC_LANGID_KHMER                        78
+#define TT_MAC_LANGID_LAO                          79
+#define TT_MAC_LANGID_VIETNAMESE                   80
+#define TT_MAC_LANGID_INDONESIAN                   81
+#define TT_MAC_LANGID_TAGALOG                      82
+#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT           83
+#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT          84
+#define TT_MAC_LANGID_AMHARIC                      85
+#define TT_MAC_LANGID_TIGRINYA                     86
+#define TT_MAC_LANGID_GALLA                        87
+#define TT_MAC_LANGID_SOMALI                       88
+#define TT_MAC_LANGID_SWAHILI                      89
+#define TT_MAC_LANGID_RUANDA                       90
+#define TT_MAC_LANGID_RUNDI                        91
+#define TT_MAC_LANGID_CHEWA                        92
+#define TT_MAC_LANGID_MALAGASY                     93
+#define TT_MAC_LANGID_ESPERANTO                    94
+#define TT_MAC_LANGID_WELSH                       128
+#define TT_MAC_LANGID_BASQUE                      129
+#define TT_MAC_LANGID_CATALAN                     130
+#define TT_MAC_LANGID_LATIN                       131
+#define TT_MAC_LANGID_QUECHUA                     132
+#define TT_MAC_LANGID_GUARANI                     133
+#define TT_MAC_LANGID_AYMARA                      134
+#define TT_MAC_LANGID_TATAR                       135
+#define TT_MAC_LANGID_UIGHUR                      136
+#define TT_MAC_LANGID_DZONGKHA                    137
+#define TT_MAC_LANGID_JAVANESE                    138
+#define TT_MAC_LANGID_SUNDANESE                   139
+
+
+#if 0  /* these seem to be errors that have been dropped */
+
+#define TT_MAC_LANGID_SCOTTISH_GAELIC             140
+#define TT_MAC_LANGID_IRISH_GAELIC                141
+
+#endif
+
+
+  /* The following codes are new as of 2000-03-10 */
+#define TT_MAC_LANGID_GALICIAN                    140
+#define TT_MAC_LANGID_AFRIKAANS                   141
+#define TT_MAC_LANGID_BRETON                      142
+#define TT_MAC_LANGID_INUKTITUT                   143
+#define TT_MAC_LANGID_SCOTTISH_GAELIC             144
+#define TT_MAC_LANGID_MANX_GAELIC                 145
+#define TT_MAC_LANGID_IRISH_GAELIC                146
+#define TT_MAC_LANGID_TONGAN                      147
+#define TT_MAC_LANGID_GREEK_POLYTONIC             148
+#define TT_MAC_LANGID_GREELANDIC                  149
+#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT    150
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the language identifier field in the name records  */
+  /* of the TTF `name' table if the `platform' identifier code is          */
+  /* TT_PLATFORM_MICROSOFT.                                                */
+  /*                                                                       */
+  /* The canonical source for the MS assigned LCID's is at                 */
+  /*                                                                       */
+  /*   http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt              */
+  /*                                                                       */
+#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA               0x0401
+#define TT_MS_LANGID_ARABIC_IRAQ                       0x0801
+#define TT_MS_LANGID_ARABIC_EGYPT                      0x0c01
+#define TT_MS_LANGID_ARABIC_LIBYA                      0x1001
+#define TT_MS_LANGID_ARABIC_ALGERIA                    0x1401
+#define TT_MS_LANGID_ARABIC_MOROCCO                    0x1801
+#define TT_MS_LANGID_ARABIC_TUNISIA                    0x1c01
+#define TT_MS_LANGID_ARABIC_OMAN                       0x2001
+#define TT_MS_LANGID_ARABIC_YEMEN                      0x2401
+#define TT_MS_LANGID_ARABIC_SYRIA                      0x2801
+#define TT_MS_LANGID_ARABIC_JORDAN                     0x2c01
+#define TT_MS_LANGID_ARABIC_LEBANON                    0x3001
+#define TT_MS_LANGID_ARABIC_KUWAIT                     0x3401
+#define TT_MS_LANGID_ARABIC_UAE                        0x3801
+#define TT_MS_LANGID_ARABIC_BAHRAIN                    0x3c01
+#define TT_MS_LANGID_ARABIC_QATAR                      0x4001
+#define TT_MS_LANGID_BULGARIAN_BULGARIA                0x0402
+#define TT_MS_LANGID_CATALAN_SPAIN                     0x0403
+#define TT_MS_LANGID_CHINESE_TAIWAN                    0x0404
+#define TT_MS_LANGID_CHINESE_PRC                       0x0804
+#define TT_MS_LANGID_CHINESE_HONG_KONG                 0x0c04
+#define TT_MS_LANGID_CHINESE_SINGAPORE                 0x1004
+#define TT_MS_LANGID_CHINESE_MACAU                     0x1404
+#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC              0x0405
+#define TT_MS_LANGID_DANISH_DENMARK                    0x0406
+#define TT_MS_LANGID_GERMAN_GERMANY                    0x0407
+#define TT_MS_LANGID_GERMAN_SWITZERLAND                0x0807
+#define TT_MS_LANGID_GERMAN_AUSTRIA                    0x0c07
+#define TT_MS_LANGID_GERMAN_LUXEMBOURG                 0x1007
+#define TT_MS_LANGID_GERMAN_LIECHTENSTEI               0x1407
+#define TT_MS_LANGID_GREEK_GREECE                      0x0408
+#define TT_MS_LANGID_ENGLISH_UNITED_STATES             0x0409
+#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM            0x0809
+#define TT_MS_LANGID_ENGLISH_AUSTRALIA                 0x0c09
+#define TT_MS_LANGID_ENGLISH_CANADA                    0x1009
+#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND               0x1409
+#define TT_MS_LANGID_ENGLISH_IRELAND                   0x1809
+#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA              0x1c09
+#define TT_MS_LANGID_ENGLISH_JAMAICA                   0x2009
+#define TT_MS_LANGID_ENGLISH_CARIBBEAN                 0x2409
+#define TT_MS_LANGID_ENGLISH_BELIZE                    0x2809
+#define TT_MS_LANGID_ENGLISH_TRINIDAD                  0x2c09
+#define TT_MS_LANGID_ENGLISH_ZIMBABWE                  0x3009
+#define TT_MS_LANGID_ENGLISH_PHILIPPINES               0x3409
+#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT    0x040a
+#define TT_MS_LANGID_SPANISH_MEXICO                    0x080a
+#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT  0x0c0a
+#define TT_MS_LANGID_SPANISH_GUATEMALA                 0x100a
+#define TT_MS_LANGID_SPANISH_COSTA_RICA                0x140a
+#define TT_MS_LANGID_SPANISH_PANAMA                    0x180a
+#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC        0x1c0a
+#define TT_MS_LANGID_SPANISH_VENEZUELA                 0x200a
+#define TT_MS_LANGID_SPANISH_COLOMBIA                  0x240a
+#define TT_MS_LANGID_SPANISH_PERU                      0x280a
+#define TT_MS_LANGID_SPANISH_ARGENTINA                 0x2c0a
+#define TT_MS_LANGID_SPANISH_ECUADOR                   0x300a
+#define TT_MS_LANGID_SPANISH_CHILE                     0x340a
+#define TT_MS_LANGID_SPANISH_URUGUAY                   0x380a
+#define TT_MS_LANGID_SPANISH_PARAGUAY                  0x3c0a
+#define TT_MS_LANGID_SPANISH_BOLIVIA                   0x400a
+#define TT_MS_LANGID_SPANISH_EL_SALVADOR               0x440a
+#define TT_MS_LANGID_SPANISH_HONDURAS                  0x480a
+#define TT_MS_LANGID_SPANISH_NICARAGUA                 0x4c0a
+#define TT_MS_LANGID_SPANISH_PUERTO_RICO               0x500a
+#define TT_MS_LANGID_FINNISH_FINLAND                   0x040b
+#define TT_MS_LANGID_FRENCH_FRANCE                     0x040c
+#define TT_MS_LANGID_FRENCH_BELGIUM                    0x080c
+#define TT_MS_LANGID_FRENCH_CANADA                     0x0c0c
+#define TT_MS_LANGID_FRENCH_SWITZERLAND                0x100c
+#define TT_MS_LANGID_FRENCH_LUXEMBOURG                 0x140c
+#define TT_MS_LANGID_FRENCH_MONACO                     0x180c
+#define TT_MS_LANGID_HEBREW_ISRAEL                     0x040d
+#define TT_MS_LANGID_HUNGARIAN_HUNGARY                 0x040e
+#define TT_MS_LANGID_ICELANDIC_ICELAND                 0x040f
+#define TT_MS_LANGID_ITALIAN_ITALY                     0x0410
+#define TT_MS_LANGID_ITALIAN_SWITZERLAND               0x0810
+#define TT_MS_LANGID_JAPANESE_JAPAN                    0x0411
+#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA     0x0412
+#define TT_MS_LANGID_KOREAN_JOHAB_KOREA                0x0812
+#define TT_MS_LANGID_DUTCH_NETHERLANDS                 0x0413
+#define TT_MS_LANGID_DUTCH_BELGIUM                     0x0813
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL           0x0414
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK          0x0814
+#define TT_MS_LANGID_POLISH_POLAND                     0x0415
+#define TT_MS_LANGID_PORTUGUESE_BRAZIL                 0x0416
+#define TT_MS_LANGID_PORTUGUESE_PORTUGAL               0x0816
+#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND        0x0417
+#define TT_MS_LANGID_ROMANIAN_ROMANIA                  0x0418
+#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA                0x0818
+#define TT_MS_LANGID_RUSSIAN_RUSSIA                    0x0419
+#define TT_MS_LANGID_RUSSIAN_MOLDAVIA                  0x0819
+#define TT_MS_LANGID_CROATIAN_CROATIA                  0x041a
+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN              0x081a
+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC           0x0c1a
+#define TT_MS_LANGID_SLOVAK_SLOVAKIA                   0x041b
+#define TT_MS_LANGID_ALBANIAN_ALBANIA                  0x041c
+#define TT_MS_LANGID_SWEDISH_SWEDEN                    0x041d
+#define TT_MS_LANGID_SWEDISH_FINLAND                   0x081d
+#define TT_MS_LANGID_THAI_THAILAND                     0x041e
+#define TT_MS_LANGID_TURKISH_TURKEY                    0x041f
+#define TT_MS_LANGID_URDU_PAKISTAN                     0x0420
+#define TT_MS_LANGID_INDONESIAN_INDONESIA              0x0421
+#define TT_MS_LANGID_UKRAINIAN_UKRAINE                 0x0422
+#define TT_MS_LANGID_BELARUSIAN_BELARUS                0x0423
+#define TT_MS_LANGID_SLOVENE_SLOVENIA                  0x0424
+#define TT_MS_LANGID_ESTONIAN_ESTONIA                  0x0425
+#define TT_MS_LANGID_LATVIAN_LATVIA                    0x0426
+#define TT_MS_LANGID_LITHUANIAN_LITHUANIA              0x0427
+#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA      0x0827
+#define TT_MS_LANGID_MAORI_NEW_ZEALAND                 0x0428
+#define TT_MS_LANGID_FARSI_IRAN                        0x0429
+#define TT_MS_LANGID_VIETNAMESE_VIET_NAM               0x042a
+#define TT_MS_LANGID_ARMENIAN_ARMENIA                  0x042b
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN            0x042c
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC         0x082c
+#define TT_MS_LANGID_BASQUE_SPAIN                      0x042d
+#define TT_MS_LANGID_SORBIAN_GERMANY                   0x042e
+#define TT_MS_LANGID_MACEDONIAN_MACEDONIA              0x042f
+#define TT_MS_LANGID_SUTU_SOUTH_AFRICA                 0x0430
+#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA               0x0431
+#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA               0x0432
+#define TT_MS_LANGID_VENDA_SOUTH_AFRICA                0x0433
+#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA                0x0434
+#define TT_MS_LANGID_ZULU_SOUTH_AFRICA                 0x0435
+#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA            0x0436
+#define TT_MS_LANGID_GEORGIAN_GEORGIA                  0x0437
+#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS           0x0438
+#define TT_MS_LANGID_HINDI_INDIA                       0x0439
+#define TT_MS_LANGID_MALTESE_MALTA                     0x043a
+#define TT_MS_LANGID_SAAMI_LAPONIA                     0x043b
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND              0x043c
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    0x083c
+#define TT_MS_LANGID_MALAY_MALAYSIA                    0x043e
+#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM           0x083e
+#define TT_MS_LANGID_KAZAK_KAZAKSTAN                   0x043f
+#define TT_MS_LANGID_SWAHILI_KENYA                     0x0441
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN            0x0443
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC         0x0843
+#define TT_MS_LANGID_TATAR_TATARSTAN                   0x0444
+#define TT_MS_LANGID_BENGALI_INDIA                     0x0445
+#define TT_MS_LANGID_PUNJABI_INDIA                     0x0446
+#define TT_MS_LANGID_GUJARATI_INDIA                    0x0447
+#define TT_MS_LANGID_ORIYA_INDIA                       0x0448
+#define TT_MS_LANGID_TAMIL_INDIA                       0x0449
+#define TT_MS_LANGID_TELUGU_INDIA                      0x044a
+#define TT_MS_LANGID_KANNADA_INDIA                     0x044b
+#define TT_MS_LANGID_MALAYALAM_INDIA                   0x044c
+#define TT_MS_LANGID_ASSAMESE_INDIA                    0x044d
+#define TT_MS_LANGID_MARATHI_INDIA                     0x044e
+#define TT_MS_LANGID_SANSKRIT_INDIA                    0x044f
+#define TT_MS_LANGID_KONKANI_INDIA                     0x0457
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the `name' identifier field in the name records of */
+  /* the TTF `name' table.  These values are platform independent.         */
+  /*                                                                       */
+#define TT_NAME_ID_COPYRIGHT            0
+#define TT_NAME_ID_FONT_FAMILY          1
+#define TT_NAME_ID_FONT_SUBFAMILY       2
+#define TT_NAME_ID_UNIQUE_ID            3
+#define TT_NAME_ID_FULL_NAME            4
+#define TT_NAME_ID_VERSION_STRING       5
+#define TT_NAME_ID_PS_NAME              6
+#define TT_NAME_ID_TRADEMARK            7
+
+/* the following values are from the OpenType spec */
+#define TT_NAME_ID_MANUFACTURER         8
+#define TT_NAME_ID_DESIGNER             9
+#define TT_NAME_ID_DESCRIPTION          10
+#define TT_NAME_ID_VENDOR_URL           11
+#define TT_NAME_ID_DESIGNER_URL         12
+#define TT_NAME_ID_LICENSE              13
+#define TT_NAME_ID_LICENSE_URL          14
+/* number 15 is reserved */
+#define TT_NAME_ID_PREFERRED_FAMILY     16
+#define TT_NAME_ID_PREFERRED_SUBFAMILY  17
+#define TT_NAME_ID_MAC_FULL_NAME        18
+
+/* The following code is new as of 2000-01-21 */
+#define TT_NAME_ID_SAMPLE_TEXT          19
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table.     */
+  /*                                                                       */
+  /* Updated 02-Jul-2000.                                                  */
+  /*                                                                       */
+
+  /* General Scripts Area */
+
+  /* Bit  0   C0 Controls and Basic Latin */
+#define TT_UCR_BASIC_LATIN                     (1L <<  0) /* U+0020-U+007E */
+  /* Bit  1   C1 Controls and Latin-1 Supplement */
+#define TT_UCR_LATIN1_SUPPLEMENT               (1L <<  1) /* U+00A0-U+00FF */
+  /* Bit  2   Latin Extended-A */
+#define TT_UCR_LATIN_EXTENDED_A                (1L <<  2) /* U+0100-U+017F */
+  /* Bit  3   Latin Extended-B */
+#define TT_UCR_LATIN_EXTENDED_B                (1L <<  3) /* U+0180-U+024F */
+  /* Bit  4   IPA Extensions */
+#define TT_UCR_IPA_EXTENSIONS                  (1L <<  4) /* U+0250-U+02AF */
+  /* Bit  5   Spacing Modifier Letters */
+#define TT_UCR_SPACING_MODIFIER                (1L <<  5) /* U+02B0-U+02FF */
+  /* Bit  6   Combining Diacritical Marks */
+#define TT_UCR_COMBINING_DIACRITICS            (1L <<  6) /* U+0300-U+036F */
+  /* Bit  7   Greek */
+#define TT_UCR_GREEK                           (1L <<  7) /* U+0370-U+03FF */
+  /* Bit  8 is reserved (was: Greek Symbols and Coptic) */
+  /* Bit  9   Cyrillic */
+#define TT_UCR_CYRILLIC                        (1L <<  9) /* U+0400-U+04FF */
+  /* Bit 10   Armenian */
+#define TT_UCR_ARMENIAN                        (1L << 10) /* U+0530-U+058F */
+  /* Bit 11   Hebrew */
+#define TT_UCR_HEBREW                          (1L << 11) /* U+0590-U+05FF */
+  /* Bit 12 is reserved (was: Hebrew Extended) */
+  /* Bit 13   Arabic */
+#define TT_UCR_ARABIC                          (1L << 13) /* U+0600-U+06FF */
+  /* Bit 14 is reserved (was: Arabic Extended) */
+  /* Bit 15   Devanagari */
+#define TT_UCR_DEVANAGARI                      (1L << 15) /* U+0900-U+097F */
+  /* Bit 16   Bengali */
+#define TT_UCR_BENGALI                         (1L << 16) /* U+0980-U+09FF */
+  /* Bit 17   Gurmukhi */
+#define TT_UCR_GURMUKHI                        (1L << 17) /* U+0A00-U+0A7F */
+  /* Bit 18   Gujarati */
+#define TT_UCR_GUJARATI                        (1L << 18) /* U+0A80-U+0AFF */
+  /* Bit 19   Oriya */
+#define TT_UCR_ORIYA                           (1L << 19) /* U+0B00-U+0B7F */
+  /* Bit 20   Tamil */
+#define TT_UCR_TAMIL                           (1L << 20) /* U+0B80-U+0BFF */
+  /* Bit 21   Telugu */
+#define TT_UCR_TELUGU                          (1L << 21) /* U+0C00-U+0C7F */
+  /* Bit 22   Kannada */
+#define TT_UCR_KANNADA                         (1L << 22) /* U+0C80-U+0CFF */
+  /* Bit 23   Malayalam */
+#define TT_UCR_MALAYALAM                       (1L << 23) /* U+0D00-U+0D7F */
+  /* Bit 24   Thai */
+#define TT_UCR_THAI                            (1L << 24) /* U+0E00-U+0E7F */
+  /* Bit 25   Lao */
+#define TT_UCR_LAO                             (1L << 25) /* U+0E80-U+0EFF */
+  /* Bit 26   Georgian */
+#define TT_UCR_GEORGIAN                        (1L << 26) /* U+10A0-U+10FF */
+  /* Bit 27 is reserved (was Georgian Extended) */
+  /* Bit 28   Hangul Jamo */
+#define TT_UCR_HANGUL_JAMO                     (1L << 28) /* U+1100-U+11FF */
+  /* Bit 29   Latin Extended Additional */
+#define TT_UCR_LATIN_EXTENDED_ADDITIONAL       (1L << 29) /* U+1E00-U+1EFF */
+  /* Bit 30   Greek Extended */
+#define TT_UCR_GREEK_EXTENDED                  (1L << 30) /* U+1F00-U+1FFF */
+
+  /* Symbols Area */
+
+  /* Bit 31   General Punctuation */
+#define TT_UCR_GENERAL_PUNCTUATION             (1L << 31) /* U+2000-U+206F */
+  /* Bit 32   Superscripts And Subscripts */
+#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS         (1L <<  0) /* U+2070-U+209F */
+  /* Bit 33   Currency Symbols */
+#define TT_UCR_CURRENCY_SYMBOLS                (1L <<  1) /* U+20A0-U+20CF */
+  /* Bit 34   Combining Diacritical Marks For Symbols */
+#define TT_UCR_COMBINING_DIACRITICS_SYMB       (1L <<  2) /* U+20D0-U+20FF */
+  /* Bit 35   Letterlike Symbols */
+#define TT_UCR_LETTERLIKE_SYMBOLS              (1L <<  3) /* U+2100-U+214F */
+  /* Bit 36   Number Forms */
+#define TT_UCR_NUMBER_FORMS                    (1L <<  4) /* U+2150-U+218F */
+  /* Bit 37   Arrows */
+#define TT_UCR_ARROWS                          (1L <<  5) /* U+2190-U+21FF */
+  /* Bit 38   Mathematical Operators */
+#define TT_UCR_MATHEMATICAL_OPERATORS          (1L <<  6) /* U+2200-U+22FF */
+  /* Bit 39 Miscellaneous Technical */
+#define TT_UCR_MISCELLANEOUS_TECHNICAL         (1L <<  7) /* U+2300-U+23FF */
+  /* Bit 40   Control Pictures */
+#define TT_UCR_CONTROL_PICTURES                (1L <<  8) /* U+2400-U+243F */
+  /* Bit 41   Optical Character Recognition */
+#define TT_UCR_OCR                             (1L <<  9) /* U+2440-U+245F */
+  /* Bit 42   Enclosed Alphanumerics */
+#define TT_UCR_ENCLOSED_ALPHANUMERICS          (1L << 10) /* U+2460-U+24FF */
+  /* Bit 43   Box Drawing */
+#define TT_UCR_BOX_DRAWING                     (1L << 11) /* U+2500-U+257F */
+  /* Bit 44   Block Elements */
+#define TT_UCR_BLOCK_ELEMENTS                  (1L << 12) /* U+2580-U+259F */
+  /* Bit 45   Geometric Shapes */
+#define TT_UCR_GEOMETRIC_SHAPES                (1L << 13) /* U+25A0-U+25FF */
+  /* Bit 46   Miscellaneous Symbols */
+#define TT_UCR_MISCELLANEOUS_SYMBOLS           (1L << 14) /* U+2600-U+26FF */
+  /* Bit 47   Dingbats */
+#define TT_UCR_DINGBATS                        (1L << 15) /* U+2700-U+27BF */
+
+  /* CJK Phonetics and Symbols Area */
+
+  /* Bit 48   CJK Symbols And Punctuation */
+#define TT_UCR_CJK_SYMBOLS                     (1L << 16) /* U+3000-U+303F */
+  /* Bit 49   Hiragana */
+#define TT_UCR_HIRAGANA                        (1L << 17) /* U+3040-U+309F */
+  /* Bit 50   Katakana */
+#define TT_UCR_KATAKANA                        (1L << 18) /* U+30A0-U+30FF */
+  /* Bit 51   Bopomofo + Extended Bopomofo */
+#define TT_UCR_BOPOMOFO                        (1L << 19) /* U+3100-U+312F */
+                                                          /* U+31A0-U+31BF */
+  /* Bit 52   Hangul Compatibility Jamo */
+#define TT_UCR_HANGUL_COMPATIBILITY_JAMO       (1L << 20) /* U+3130-U+318F */
+  /* Bit 53   CJK Miscellaneous */
+#define TT_UCR_CJK_MISC                        (1L << 21) /* U+3190-U+319F */
+  /* Bit 54   Enclosed CJK Letters And Months */
+#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS     (1L << 22) /* U+3200-U+32FF */
+  /* Bit 55   CJK Compatibility */
+#define TT_UCR_CJK_COMPATIBILITY               (1L << 23) /* U+3300-U+33FF */
+
+  /* Hangul Syllables Area */
+
+  /* Bit 56   Hangul */
+#define TT_UCR_HANGUL                          (1L << 24) /* U+AC00-U+D7A3 */
+
+  /* Surrogates Area */
+
+  /* Bit 57   Surrogates */
+#define TT_UCR_SURROGATES                      (1L << 25) /* U+D800-U+DFFF */
+  /* Bit 58 is reserved for Unicode SubRanges */
+
+  /* CJK Ideographs Area */
+
+  /* Bit 59   CJK Unified Ideographs             + */
+  /*          CJK Radical Supplement             + */
+  /*          Kangxi Radicals                    + */
+  /*          Ideographic Description            + */
+  /*          CJK Unified Ideographs Extension A   */
+#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS          (1L << 27) /* U+4E00-U+9FFF */
+                                                          /* U+2E80-U+2EFF */
+                                                          /* U+2F00-U+2FDF */
+                                                          /* U+2FF0-U+2FFF */
+                                                          /* U+34E0-U+4DB5 */
+
+  /* Private Use Area */
+
+  /* Bit 60   Private Use */
+#define TT_UCR_PRIVATE_USE                     (1L << 28) /* U+E000-U+F8FF */
+
+  /* Compatibility Area and Specials */
+
+  /* Bit 61   CJK Compatibility Ideographs */
+#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS    (1L << 29) /* U+F900-U+FAFF */
+  /* Bit 62   Alphabetic Presentation Forms */
+#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS   (1L << 30) /* U+FB00-U+FB4F */
+  /* Bit 63   Arabic Presentation Forms-A */
+#define TT_UCR_ARABIC_PRESENTATIONS_A          (1L << 31) /* U+FB50-U+FDFF */
+  /* Bit 64   Combining Half Marks */
+#define TT_UCR_COMBINING_HALF_MARKS            (1L <<  0) /* U+FE20-U+FE2F */
+  /* Bit 65   CJK Compatibility Forms */
+#define TT_UCR_CJK_COMPATIBILITY_FORMS         (1L <<  1) /* U+FE30-U+FE4F */
+  /* Bit 66   Small Form Variants */
+#define TT_UCR_SMALL_FORM_VARIANTS             (1L <<  2) /* U+FE50-U+FE6F */
+  /* Bit 67   Arabic Presentation Forms-B */
+#define TT_UCR_ARABIC_PRESENTATIONS_B          (1L <<  3) /* U+FE70-U+FEFE */
+  /* Bit 68   Halfwidth And Fullwidth Forms */
+#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS       (1L <<  4) /* U+FF00-U+FFEF */
+  /* Bit 69   Specials */
+#define TT_UCR_SPECIALS                        (1L <<  5) /* U+FFF0-U+FFFD */
+  /* Bit 70   Tibetan */
+#define TT_UCR_TIBETAN                         (1L <<  6) /* U+0F00-U+0FCF */
+  /* Bit 71   Syriac */
+#define TT_UCR_SYRIAC                          (1L <<  7) /* U+0700-U+074F */
+  /* Bit 72   Thaana */
+#define TT_UCR_THAANA                          (1L <<  8) /* U+0780-U+07BF */
+  /* Bit 73   Sinhala */
+#define TT_UCR_SINHALA                         (1L <<  9) /* U+0D80-U+0DFF */
+  /* Bit 74   Myanmar */
+#define TT_UCR_MYANMAR                         (1L << 10) /* U+1000-U+109F */
+  /* Bit 75   Ethiopic */
+#define TT_UCR_ETHIOPIC                        (1L << 11) /* U+1200-U+12BF */
+  /* Bit 76   Cherokee */
+#define TT_UCR_CHEROKEE                        (1L << 12) /* U+13A0-U+13FF */
+  /* Bit 77   Canadian Aboriginal Syllabics */
+#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS   (1L << 13) /* U+1400-U+14DF */
+  /* Bit 78   Ogham */
+#define TT_UCR_OGHAM                           (1L << 14) /* U+1680-U+169F */
+  /* Bit 79   Runic */
+#define TT_UCR_RUNIC                           (1L << 15) /* U+16A0-U+16FF */
+  /* Bit 80   Khmer */
+#define TT_UCR_KHMER                           (1L << 16) /* U+1780-U+17FF */
+  /* Bit 81   Mongolian */
+#define TT_UCR_MONGOLIAN                       (1L << 17) /* U+1800-U+18AF */
+  /* Bit 82   Braille */
+#define TT_UCR_BRAILLE                         (1L << 18) /* U+2800-U+28FF */
+  /* Bit 83   Yi + Yi Radicals */
+#define TT_UCR_YI                              (1L << 19) /* U+A000-U+A48C */
+                                                          /* U+A490-U+A4CF */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Some compilers have a very limited length of identifiers.             */
+  /*                                                                       */
+#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ )
+#define HAVE_LIMIT_ON_IDENTS
+#endif
+
+
+#ifndef HAVE_LIMIT_ON_IDENTS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Here some alias #defines in order to be clearer.                      */
+  /*                                                                       */
+  /* These are not always #defined to stay within the 31 character limit   */
+  /* which some compilers have.                                            */
+  /*                                                                       */
+  /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern  */
+  /* Borland compilers (read: from BC++ 3.1 on) can increase this limit.   */
+  /* If you get a warning with such a compiler, use the -i40 switch.       */
+  /*                                                                       */
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_A      \
+         TT_UCR_ARABIC_PRESENTATIONS_A
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_B      \
+         TT_UCR_ARABIC_PRESENTATIONS_B
+
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS      \
+         TT_UCR_COMBINING_DIACRITICS
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \
+         TT_UCR_COMBINING_DIACRITICS_SYMB
+
+
+#endif /* !HAVE_LIMIT_ON_IDENTS */
+
+
+#endif /* TTNAMEID_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/tttables.h b/src/freetype/freetype/tttables.h
new file mode 100644 (file)
index 0000000..27c46f3
--- /dev/null
@@ -0,0 +1,583 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tttables.h                                                             */
+/*                                                                         */
+/*    Basic SFNT/TrueType tables definitions and interface                 */
+/*    (specification only).                                                */
+/*                                                                         */
+/*  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 TTTABLES_H
+#define TTTABLES_H
+
+
+#include <freetype/freetype.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Header                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType font header table.  All       */
+  /*    fields follow the TrueType specification.                          */
+  /*                                                                       */
+  typedef struct  TT_Header_
+  {
+    FT_Fixed   Table_Version;
+    FT_Fixed   Font_Revision;
+
+    FT_Long    CheckSum_Adjust;
+    FT_Long    Magic_Number;
+
+    FT_UShort  Flags;
+    FT_UShort  Units_Per_EM;
+
+    FT_Long    Created [2];
+    FT_Long    Modified[2];
+
+    FT_Short   xMin;
+    FT_Short   yMin;
+    FT_Short   xMax;
+    FT_Short   yMax;
+
+    FT_UShort  Mac_Style;
+    FT_UShort  Lowest_Rec_PPEM;
+
+    FT_Short   Font_Direction;
+    FT_Short   Index_To_Loc_Format;
+    FT_Short   Glyph_Data_Format;
+
+  } TT_Header;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_HoriHeader                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType horizontal header, the `hhea' */
+  /*    table, as well as the corresponding horizontal metrics table,      */
+  /*    i.e., the `hmtx' table.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Version                :: The table version.                       */
+  /*                                                                       */
+  /*    Ascender               :: The font's ascender, i.e., the distance  */
+  /*                              from the baseline to the top-most of all */
+  /*                              glyph points found in the font.          */
+  /*                                                                       */
+  /*                              This value is invalid in many fonts, as  */
+  /*                              it is usually set by the font designer,  */
+  /*                              and often reflects only a portion of the */
+  /*                              glyphs found in the font (maybe ASCII).  */
+  /*                                                                       */
+  /*                              You should use the `sTypoAscender' field */
+  /*                              of the OS/2 table instead if you want    */
+  /*                              the correct one.                         */
+  /*                                                                       */
+  /*    Descender              :: The font's descender, i.e., the distance */
+  /*                              from the baseline to the bottom-most of  */
+  /*                              all glyph points found in the font.  It  */
+  /*                              is negative.                             */
+  /*                                                                       */
+  /*                              This value is invalid in many fonts, as  */
+  /*                              it is usually set by the font designer,  */
+  /*                              and often reflects only a portion of the */
+  /*                              glyphs found in the font (maybe ASCII).  */
+  /*                                                                       */
+  /*                              You should use the `sTypoDescender'      */
+  /*                              field of the OS/2 table instead if you   */
+  /*                              want the correct one.                    */
+  /*                                                                       */
+  /*    Line_Gap               :: The font's line gap, i.e., the distance  */
+  /*                              to add to the ascender and descender to  */
+  /*                              get the BTB, i.e., the                   */
+  /*                              baseline-to-baseline distance for the    */
+  /*                              font.                                    */
+  /*                                                                       */
+  /*    advance_Width_Max      :: This field is the maximum of all advance */
+  /*                              widths found in the font.  It can be     */
+  /*                              used to compute the maximum width of an  */
+  /*                              arbitrary string of text.                */
+  /*                                                                       */
+  /*    min_Left_Side_Bearing  :: The minimum left side bearing of all     */
+  /*                              glyphs within the font.                  */
+  /*                                                                       */
+  /*    min_Right_Side_Bearing :: The minimum right side bearing of all    */
+  /*                              glyphs within the font.                  */
+  /*                                                                       */
+  /*    xMax_Extent            :: The maximum horizontal extent (i.e., the */
+  /*                              `width' of a glyph's bounding box) for   */
+  /*                              all glyphs in the font.                  */
+  /*                                                                       */
+  /*    caret_Slope_Rise       :: The rise coefficient of the cursor's     */
+  /*                              slope of the cursor (slope=rise/run).    */
+  /*                                                                       */
+  /*    caret_Slope_Run        :: The run coefficient of the cursor's      */
+  /*                              slope.                                   */
+  /*                                                                       */
+  /*    Reserved               :: 10 reserved bytes.                       */
+  /*                                                                       */
+  /*    metric_Data_Format     :: Always 0.                                */
+  /*                                                                       */
+  /*    number_Of_HMetrics     :: Number of HMetrics entries in the `hmtx' */
+  /*                              table -- this value can be smaller than  */
+  /*                              the total number of glyphs in the font.  */
+  /*                                                                       */
+  /*    long_metrics           :: A pointer into the `hmtx' table.         */
+  /*                                                                       */
+  /*    short_metrics          :: A pointer into the `hmtx' table.         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
+  /*               be identical except for the names of their fields which */
+  /*               are different.                                          */
+  /*                                                                       */
+  /*               This ensures that a single function in the `ttload'     */
+  /*               module is able to read both the horizontal and vertical */
+  /*               headers.                                                */
+  /*                                                                       */
+  typedef struct  TT_HoriHeader_
+  {
+    FT_Fixed   Version;
+    FT_Short   Ascender;
+    FT_Short   Descender;
+    FT_Short   Line_Gap;
+
+    FT_UShort  advance_Width_Max;      /* advance width maximum */
+
+    FT_Short   min_Left_Side_Bearing;  /* minimum left-sb       */
+    FT_Short   min_Right_Side_Bearing; /* minimum right-sb      */
+    FT_Short   xMax_Extent;            /* xmax extents          */
+    FT_Short   caret_Slope_Rise;
+    FT_Short   caret_Slope_Run;
+    FT_Short   caret_Offset;
+
+    FT_Short   Reserved[4];
+
+    FT_Short   metric_Data_Format;
+    FT_UShort  number_Of_HMetrics;
+
+    /* The following fields are not defined by the TrueType specification */
+    /* but they're used to connect the metrics header to the relevant     */
+    /* `HMTX' table.                                                      */
+
+    void*      long_metrics;
+    void*      short_metrics;
+
+  } TT_HoriHeader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_VertHeader                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType vertical header, the `vhea'   */
+  /*    table, as well as the corresponding vertical metrics table, i.e.,  */
+  /*    the `vmtx' table.                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Version                 :: The table version.                      */
+  /*                                                                       */
+  /*    Ascender                :: The font's ascender, i.e., the distance */
+  /*                               from the baseline to the top-most of    */
+  /*                               all glyph points found in the font.     */
+  /*                                                                       */
+  /*                               This value is invalid in many fonts, as */
+  /*                               it is usually set by the font designer, */
+  /*                               and often reflects only a portion of    */
+  /*                               the glyphs found in the font (maybe     */
+  /*                               ASCII).                                 */
+  /*                                                                       */
+  /*                               You should use the `sTypoAscender'      */
+  /*                               field of the OS/2 table instead if you  */
+  /*                               want the correct one.                   */
+  /*                                                                       */
+  /*    Descender               :: The font's descender, i.e., the         */
+  /*                               distance from the baseline to the       */
+  /*                               bottom-most of all glyph points found   */
+  /*                               in the font.  It is negative.           */
+  /*                                                                       */
+  /*                               This value is invalid in many fonts, as */
+  /*                               it is usually set by the font designer, */
+  /*                               and often reflects only a portion of    */
+  /*                               the glyphs found in the font (maybe     */
+  /*                               ASCII).                                 */
+  /*                                                                       */
+  /*                               You should use the `sTypoDescender'     */
+  /*                               field of the OS/2 table instead if you  */
+  /*                               want the correct one.                   */
+  /*                                                                       */
+  /*    Line_Gap                :: The font's line gap, i.e., the distance */
+  /*                               to add to the ascender and descender to */
+  /*                               get the BTB, i.e., the                  */
+  /*                               baseline-to-baseline distance for the   */
+  /*                               font.                                   */
+  /*                                                                       */
+  /*    advance_Height_Max      :: This field is the maximum of all        */
+  /*                               advance heights found in the font.  It  */
+  /*                               can be used to compute the maximum      */
+  /*                               height of an arbitrary string of text.  */
+  /*                                                                       */
+  /*    min_Top_Side_Bearing    :: The minimum top side bearing of all     */
+  /*                               glyphs within the font.                 */
+  /*                                                                       */
+  /*    min_Bottom_Side_Bearing :: The minimum bottom side bearing of all  */
+  /*                               glyphs within the font.                 */
+  /*                                                                       */
+  /*    yMax_Extent             :: The maximum vertical extent (i.e., the  */
+  /*                               `height' of a glyph's bounding box) for */
+  /*                               all glyphs in the font.                 */
+  /*                                                                       */
+  /*    caret_Slope_Rise        :: The rise coefficient of the cursor's    */
+  /*                               slope of the cursor (slope=rise/run).   */
+  /*                                                                       */
+  /*    caret_Slope_Run         :: The run coefficient of the cursor's     */
+  /*                               slope.                                  */
+  /*                                                                       */
+  /*    Reserved                :: 10 reserved bytes.                      */
+  /*                                                                       */
+  /*    metric_Data_Format      :: Always 0.                               */
+  /*                                                                       */
+  /*    number_Of_HMetrics      :: Number of VMetrics entries in the       */
+  /*                               `vmtx' table -- this value can be       */
+  /*                               smaller than the total number of glyphs */
+  /*                               in the font.                            */
+  /*                                                                       */
+  /*    long_metrics           :: A pointer into the `vmtx' table.         */
+  /*                                                                       */
+  /*    short_metrics          :: A pointer into the `vmtx' table.         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
+  /*               be identical except for the names of their fields which */
+  /*               are different.                                          */
+  /*                                                                       */
+  /*               This ensures that a single function in the `ttload'     */
+  /*               module is able to read both the horizontal and vertical */
+  /*               headers.                                                */
+  /*                                                                       */
+  typedef struct TT_VertHeader_
+  {
+    FT_Fixed   Version;
+    FT_Short   Ascender;
+    FT_Short   Descender;
+    FT_Short   Line_Gap;
+
+    FT_UShort  advance_Height_Max;      /* advance height maximum */
+
+    FT_Short   min_Top_Side_Bearing;    /* minimum left-sb or top-sb       */
+    FT_Short   min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb   */
+    FT_Short   yMax_Extent;             /* xmax or ymax extents            */
+    FT_Short   caret_Slope_Rise;
+    FT_Short   caret_Slope_Run;
+    FT_Short   caret_Offset;
+
+    FT_Short   Reserved[4];
+
+    FT_Short   metric_Data_Format;
+    FT_UShort  number_Of_VMetrics;
+
+    /* The following fields are not defined by the TrueType specification */
+    /* but they're used to connect the metrics header to the relevant     */
+    /* `HMTX' or `VMTX' table.                                            */
+
+    void*      long_metrics;
+    void*      short_metrics;
+
+  } TT_VertHeader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_OS2                                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType OS/2 table. This is the long  */
+  /*    table version.  All fields comply to the TrueType specification.   */
+  /*                                                                       */
+  /*    Note that we now support old Mac fonts which do not include an     */
+  /*    OS/2 table.  In this case, the `version' field is always set to    */
+  /*    0xFFFF.                                                            */
+  /*                                                                       */
+  typedef struct  TT_OS2_
+  {
+    FT_UShort  version;                /* 0x0001 - more or 0xFFFF */
+    FT_Short   xAvgCharWidth;
+    FT_UShort  usWeightClass;
+    FT_UShort  usWidthClass;
+    FT_Short   fsType;
+    FT_Short   ySubscriptXSize;
+    FT_Short   ySubscriptYSize;
+    FT_Short   ySubscriptXOffset;
+    FT_Short   ySubscriptYOffset;
+    FT_Short   ySuperscriptXSize;
+    FT_Short   ySuperscriptYSize;
+    FT_Short   ySuperscriptXOffset;
+    FT_Short   ySuperscriptYOffset;
+    FT_Short   yStrikeoutSize;
+    FT_Short   yStrikeoutPosition;
+    FT_Short   sFamilyClass;
+
+    FT_Byte    panose[10];
+
+    FT_ULong   ulUnicodeRange1;        /* Bits 0-31   */
+    FT_ULong   ulUnicodeRange2;        /* Bits 32-63  */
+    FT_ULong   ulUnicodeRange3;        /* Bits 64-95  */
+    FT_ULong   ulUnicodeRange4;        /* Bits 96-127 */
+
+    FT_Char    achVendID[4];
+
+    FT_UShort  fsSelection;
+    FT_UShort  usFirstCharIndex;
+    FT_UShort  usLastCharIndex;
+    FT_Short   sTypoAscender;
+    FT_Short   sTypoDescender;
+    FT_Short   sTypoLineGap;
+    FT_UShort  usWinAscent;
+    FT_UShort  usWinDescent;
+
+    /* only version 1 tables: */
+
+    FT_ULong   ulCodePageRange1;       /* Bits 0-31   */
+    FT_ULong   ulCodePageRange2;       /* Bits 32-63  */
+
+    /* only version 2 tables: */
+
+    FT_Short   sxHeight;
+    FT_Short   sCapHeight;
+    FT_UShort  usDefaultChar;
+    FT_UShort  usBreakChar;
+    FT_UShort  usMaxContext;
+
+  } TT_OS2;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Postscript                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType Postscript table.  All fields */
+  /*    comply to the TrueType table.  This structure does not reference   */
+  /*    the Postscript glyph names, which can be nevertheless accessed     */
+  /*    with the `ttpost' module.                                          */
+  /*                                                                       */
+  typedef struct  TT_Postscript_
+  {
+    FT_Fixed  FormatType;
+    FT_Fixed  italicAngle;
+    FT_Short  underlinePosition;
+    FT_Short  underlineThickness;
+    FT_ULong  isFixedPitch;
+    FT_ULong  minMemType42;
+    FT_ULong  maxMemType42;
+    FT_ULong  minMemType1;
+    FT_ULong  maxMemType1;
+
+    /* Glyph names follow in the file, but we don't   */
+    /* load them by default.  See the ttpost.c file.  */
+
+  } TT_Postscript;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_PCLT                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType PCLT table.  All fields       */
+  /*    comply to the TrueType table.                                      */
+  /*                                                                       */
+  typedef struct TT_PCLT_
+  {
+    FT_Fixed   Version;
+    FT_ULong   FontNumber;
+    FT_UShort  Pitch;
+    FT_UShort  xHeight;
+    FT_UShort  Style;
+    FT_UShort  TypeFamily;
+    FT_UShort  CapHeight;
+    FT_UShort  SymbolSet;
+    FT_Char    TypeFace[16];
+    FT_Char    CharacterComplement[8];
+    FT_Char    FileName[6];
+    FT_Char    StrokeWeight;
+    FT_Char    WidthType;
+    FT_Byte    SerifStyle;
+    FT_Byte    Reserved;
+
+  } TT_PCLT;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_MaxProfile                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The maximum profile is a table containing many max values which    */
+  /*    can be used to pre-allocate arrays.  This ensures that no memory   */
+  /*    allocation occurs during a glyph load.                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version               :: The version number.                       */
+  /*                                                                       */
+  /*    numGlyphs             :: The number of glyphs in this TrueType     */
+  /*                             font.                                     */
+  /*                                                                       */
+  /*    maxPoints             :: The maximum number of points in a         */
+  /*                             non-composite TrueType glyph.  See also   */
+  /*                             the structure element                     */
+  /*                             `maxCompositePoints'.                     */
+  /*                                                                       */
+  /*    maxContours           :: The maximum number of contours in a       */
+  /*                             non-composite TrueType glyph.  See also   */
+  /*                             the structure element                     */
+  /*                             `maxCompositeContours'.                   */
+  /*                                                                       */
+  /*    maxCompositePoints    :: The maximum number of points in a         */
+  /*                             composite TrueType glyph.  See also the   */
+  /*                             structure element `maxPoints'.            */
+  /*                                                                       */
+  /*    maxCompositeContours  :: The maximum number of contours in a       */
+  /*                             composite TrueType glyph.  See also the   */
+  /*                             structure element `maxContours'.          */
+  /*                                                                       */
+  /*    maxZones              :: The maximum number of zones used for      */
+  /*                             glyph hinting.                            */
+  /*                                                                       */
+  /*    maxTwilightPoints     :: The maximum number of points in the       */
+  /*                             twilight zone used for glyph hinting.     */
+  /*                                                                       */
+  /*    maxStorage            :: The maximum number of elements in the     */
+  /*                             storage area used for glyph hinting.      */
+  /*                                                                       */
+  /*    maxFunctionDefs       :: The maximum number of function            */
+  /*                             definitions in the TrueType bytecode for  */
+  /*                             this font.                                */
+  /*                                                                       */
+  /*    maxInstructionDefs    :: The maximum number of instruction         */
+  /*                             definitions in the TrueType bytecode for  */
+  /*                             this font.                                */
+  /*                                                                       */
+  /*    maxStackElements      :: The maximum number of stack elements used */
+  /*                             during bytecode interpretation.           */
+  /*                                                                       */
+  /*    maxSizeOfInstructions :: The maximum number of TrueType opcodes    */
+  /*                             used for glyph hinting.                   */
+  /*                                                                       */
+  /*    maxComponentElements  :: An obscure value related to composite     */
+  /*                             glyphs definitions.                       */
+  /*                                                                       */
+  /*    maxComponentDepth     :: An obscure value related to composite     */
+  /*                             glyphs definitions.  Probably the maximum */
+  /*                             number of simple glyphs in a composite.   */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font loading.                   */
+  /*                                                                       */
+  typedef struct  TT_MaxProfile_
+  {
+    FT_Fixed   version;
+    FT_UShort  numGlyphs;
+    FT_UShort  maxPoints;
+    FT_UShort  maxContours;
+    FT_UShort  maxCompositePoints;
+    FT_UShort  maxCompositeContours;
+    FT_UShort  maxZones;
+    FT_UShort  maxTwilightPoints;
+    FT_UShort  maxStorage;
+    FT_UShort  maxFunctionDefs;
+    FT_UShort  maxInstructionDefs;
+    FT_UShort  maxStackElements;
+    FT_UShort  maxSizeOfInstructions;
+    FT_UShort  maxComponentElements;
+    FT_UShort  maxComponentDepth;
+
+  } TT_MaxProfile;
+
+
+  typedef enum
+  {
+    ft_sfnt_head = 0,
+    ft_sfnt_maxp = 1,
+    ft_sfnt_os2  = 2,
+    ft_sfnt_hhea = 3,
+    ft_sfnt_vhea = 4,
+    ft_sfnt_post = 5,
+    ft_sfnt_pclt = 6,
+
+    sfnt_max   /* don't remove */
+
+  } FT_Sfnt_Tag;
+
+
+  /* internal use only */
+  typedef void*  (*FT_Get_Sfnt_Table_Func)( FT_Face      face,
+                                            FT_Sfnt_Tag  tag );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Sfnt_Table                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a pointer to a given SFNT table within a face.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source.                                    */
+  /*                                                                       */
+  /*    tag  :: The index of the SFNT table.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A type-less pointer to the table.  This will be 0 in case of       */
+  /*    error, or if the corresponding table was not found *OR* loaded     */
+  /*    from the file.                                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The table is owned by the face object and disappears with it.      */
+  /*                                                                       */
+  /*    This function is only useful to access SFNT tables that are loaded */
+  /*    by the sfnt/truetype/opentype drivers.  See FT_Sfnt_tag for a      */
+  /*    list.                                                              */
+  /*                                                                       */
+  /*    You can load any table using the (internal) SFNT_Interface         */
+  /*    structure -- this is available via FT_Get_Module_Interface().      */
+  /*                                                                       */
+  FT_EXPORT_DEF( void* )  FT_Get_Sfnt_Table( FT_Face      face,
+                                             FT_Sfnt_Tag  tag );
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* TTTABLES_H */
+
+
+/* END */
diff --git a/src/freetype/freetype/tttags.h b/src/freetype/freetype/tttags.h
new file mode 100644 (file)
index 0000000..9de9810
--- /dev/null
@@ -0,0 +1,66 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tttags.h                                                               */
+/*                                                                         */
+/*    Tags for TrueType tables (specification only).                       */
+/*                                                                         */
+/*  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 TTAGS_H
+#define TTAGS_H
+
+
+#include <freetype/freetype.h>   /* for MAKE_TT_TAG() */
+
+
+#define TTAG_cmap  FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
+#define TTAG_cvt   FT_MAKE_TAG( 'c', 'v', 't', ' ' )
+#define TTAG_CFF   FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
+#define TTAG_DSIG  FT_MAKE_TAG( 'D', 'S', 'I', 'G' )
+#define TTAG_bdat  FT_MAKE_TAG( 'b', 'd', 'a', 't' )
+#define TTAG_bloc  FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
+#define TTAG_EBDT  FT_MAKE_TAG( 'E', 'B', 'D', 'T' )
+#define TTAG_EBLC  FT_MAKE_TAG( 'E', 'B', 'L', 'C' )
+#define TTAG_EBSC  FT_MAKE_TAG( 'E', 'B', 'S', 'C' )
+#define TTAG_fpgm  FT_MAKE_TAG( 'f', 'p', 'g', 'm' )
+#define TTAG_fvar  FT_MAKE_TAG( 'f', 'v', 'a', 'r' )
+#define TTAG_gasp  FT_MAKE_TAG( 'g', 'a', 's', 'p' )
+#define TTAG_glyf  FT_MAKE_TAG( 'g', 'l', 'y', 'f' )
+#define TTAG_GSUB  FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#define TTAG_hdmx  FT_MAKE_TAG( 'h', 'd', 'm', 'x' )
+#define TTAG_head  FT_MAKE_TAG( 'h', 'e', 'a', 'd' )
+#define TTAG_hhea  FT_MAKE_TAG( 'h', 'h', 'e', 'a' )
+#define TTAG_hmtx  FT_MAKE_TAG( 'h', 'm', 't', 'x' )
+#define TTAG_kern  FT_MAKE_TAG( 'k', 'e', 'r', 'n' )
+#define TTAG_loca  FT_MAKE_TAG( 'l', 'o', 'c', 'a' )
+#define TTAG_LTSH  FT_MAKE_TAG( 'L', 'T', 'S', 'H' )
+#define TTAG_maxp  FT_MAKE_TAG( 'm', 'a', 'x', 'p' )
+#define TTAG_MMSD  FT_MAKE_TAG( 'M', 'M', 'S', 'D' )
+#define TTAG_MMFX  FT_MAKE_TAG( 'M', 'M', 'F', 'X' )
+#define TTAG_name  FT_MAKE_TAG( 'n', 'a', 'm', 'e' )
+#define TTAG_OS2   FT_MAKE_TAG( 'O', 'S', '/', '2' )
+#define TTAG_OTTO  FT_MAKE_TAG( 'O', 'T', 'T', 'O' )
+#define TTAG_PCLT  FT_MAKE_TAG( 'P', 'C', 'L', 'T' )
+#define TTAG_post  FT_MAKE_TAG( 'p', 'o', 's', 't' )
+#define TTAG_prep  FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
+#define TTAG_true  FT_MAKE_TAG( 't', 'r', 'u', 'e' )
+#define TTAG_ttc   FT_MAKE_TAG( 't', 't', 'c', ' ' )
+#define TTAG_ttcf  FT_MAKE_TAG( 't', 't', 'c', 'f' )
+#define TTAG_VDMX  FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
+#define TTAG_vhea  FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
+#define TTAG_vmtx  FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+
+#endif /* TTAGS_H */
+
+
+/* END */
diff --git a/src/freetype/ftconfig.h b/src/freetype/ftconfig.h
new file mode 100644 (file)
index 0000000..f21a164
--- /dev/null
@@ -0,0 +1,168 @@
+/* ftconfig.h.  Generated automatically by configure.  */
+/***************************************************************************/
+/*                                                                         */
+/*  ftconfig.in                                                            */
+/*                                                                         */
+/*    UNIX-specific configuration file (specification only).               */
+/*                                                                         */
+/*  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 header file contains a number of macro definitions that are used */
+  /* by the rest of the engine.  Most of the macros here are automatically */
+  /* determined at compile time, and you should not need to change it to   */
+  /* port FreeType, except to compile the library with a non-ANSI          */
+  /* compiler.                                                             */
+  /*                                                                       */
+  /* Note however that if some specific modifications are needed, we       */
+  /* advise you to place a modified copy in your build directory.          */
+  /*                                                                       */
+  /* The build directory is usually `freetype/builds/<system>', and        */
+  /* contains system-specific files that are always included first when    */
+  /* building the library.                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef FTCONFIG_H
+#define FTCONFIG_H
+
+
+  /* Include the header file containing all developer build options */
+#include <freetype/config/ftoption.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*               PLATFORM-SPECIFIC CONFIGURATION MACROS                  */
+  /*                                                                       */
+  /* These macros can be toggled to suit a specific system.  The current   */
+  /* ones are defaults used to compile FreeType in an ANSI C environment   */
+  /* (16bit compilers are also supported).  Copy this file to your own     */
+  /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include "wx/setup.h"
+
+#define FT_SIZEOF_INT   SIZEOF_INT
+#define FT_SIZEOF_LONG  SIZEOF_LONG
+
+
+  /* Preferred alignment of data */
+#define FT_ALIGNMENT  8
+
+
+  /* UNUSED is a macro used to indicate that a given parameter is not used */
+  /* -- this is only used to get rid of unpleasant compiler warnings       */
+#ifndef FT_UNUSED
+#define FT_UNUSED( arg )  ( (arg) = (arg) )
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     AUTOMATIC CONFIGURATION MACROS                    */
+  /*                                                                       */
+  /* These macros are computed from the ones defined above.  Don't touch   */
+  /* their definition, unless you know precisely what you are doing.  No   */
+  /* porter should need to mess with them.                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IntN types                                                            */
+  /*                                                                       */
+  /*   Used to guarantee the size of some specific integers.               */
+  /*                                                                       */
+  typedef signed short    FT_Int16;
+  typedef unsigned short  FT_UInt16;
+
+#if FT_SIZEOF_INT == 4
+
+  typedef signed int      FT_Int32;
+  typedef unsigned int    FT_UInt32;
+
+#elif FT_SIZEOF_LONG == 4
+
+  typedef signed long     FT_Int32;
+  typedef unsigned long   FT_UInt32;
+
+#else
+#error "no 32bit type found -- please check your configuration files"
+#endif
+
+#if FT_SIZEOF_LONG == 8
+
+  /* FT_LONG64 must be defined if a 64-bit type is available */
+#define FT_LONG64
+#define FT_INT64   long
+
+#else
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Many compilers provide the non-ANSI `long long' 64-bit type.  You can */
+  /* activate it by defining the FTCALC_USE_LONG_LONG macro in             */
+  /* `ftoption.h'.                                                         */
+  /*                                                                       */
+  /* Note that this will produce many -ansi warnings during library        */
+  /* compilation, and that in many cases,  the generated code will be      */
+  /* neither smaller nor faster!                                           */
+  /*                                                                       */
+#ifdef FTCALC_USE_LONG_LONG
+
+#define FT_LONG64
+#define FT_INT64   long long
+
+#endif /* FTCALC_USE_LONG_LONG */
+#endif /* FT_SIZEOF_LONG == 8 */
+
+
+#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+#define  LOCAL_DEF   static
+#define  LOCAL_FUNC  static
+#else
+#define  LOCAL_DEF   extern
+#define  LOCAL_FUNC  /* nothing */
+#endif
+
+#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT
+#define  BASE_DEF( x )   static  x
+#define  BASE_FUNC( x )  static  x
+#else
+#define  BASE_DEF( x )   extern  x
+#define  BASE_FUNC( x )  extern  x
+#endif
+
+#ifndef  FT_EXPORT_DEF
+#define  FT_EXPORT_DEF( x )   extern  x
+#endif
+
+#ifndef  FT_EXPORT_FUNC
+#define  FT_EXPORT_FUNC( x )  extern  x
+#endif
+
+#ifndef  FT_EXPORT_VAR
+#define  FT_EXPORT_VAR( x )   extern  x
+#endif
+
+#endif /* FTCONFIG_H */
+
+
+/* END */
diff --git a/src/freetype/macfond/fonddrvr.c b/src/freetype/macfond/fonddrvr.c
new file mode 100644 (file)
index 0000000..45a9141
--- /dev/null
@@ -0,0 +1,616 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fonddrvr.c                                                             */
+/*                                                                         */
+/*    Mac FOND font driver. Written by just@letterror.com.                 */
+/*                                                                         */
+/*  Copyright 1996-2000 by                                                 */
+/*  Just van Rossum, 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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+/*
+    Notes
+
+    Mac suitcase files can (and often do!) contain multiple fonts. To
+    support this I use the face_index argument of FT_(Open|New)_Face()
+    functions, and pretend the suitcase file is a collection.
+    Warning: although the FOND driver sets face->num_faces field to the
+    number of available fonts, but the Type 1 driver sets it to 1 anyway.
+    So this field is currently not reliable, and I don't see a clean way
+    to  resolve that. The face_index argument translates to
+      Get1IndResource( 'FOND', face_index + 1 );
+    so clients should figure out the resource index of the FOND.
+    (I'll try to provide some example code for this at some point.)
+
+    The Mac FOND driver works roughly like this:
+
+    - Check whether the offered stream points to a Mac suitcase file.
+      This is done by checking the file type: it has to be 'FFIL' or 'tfil'.
+      The stream that gets passed to our init_face() routine is a stdio
+      stream, which isn't usable for us, since the FOND resources live
+      in the resource fork. So we just grab the stream->pathname field.
+
+    - Read the FOND resource into memory, then check whether there is
+      a TrueType font and/or (!) a Type 1 font available.
+
+    - If there is a Type 1 font available (as a separate 'LWFN' file),
+      read its data into memory, massage it slightly so it becomes
+      PFB data, wrap it into a memory stream, load the Type 1 driver
+      and delegate the rest of the work to it, by calling the init_face()
+      method of the Type 1 driver.
+      (XXX TODO: after this has been done, the kerning data from the FOND
+      resource should be appended to the face: on the Mac there are usually
+      no AFM files available. However, this is tricky since we need to map
+      Mac char codes to ps glyph names to glyph ID's...)
+
+    - If there is a TrueType font (an 'sfnt' resource), read it into
+      memory, wrap it into a memory stream, load the TrueType driver
+      and delegate the rest of the work to it, by calling the init_face()
+      method if the TrueType driver.
+
+    - In both cases, the original stream gets closed and *reinitialized*
+      to become a memory stream. Additionally, the face->driver field --
+      which is set to the FOND driver upon entering our init_face() --
+      gets *reset* to either the TT or the T1 driver. I had to make a minor
+      change to ftobjs.c to make this work.
+
+    - We might consider creating an FT_New_Face_Mac() API call, as this
+      would avoid some of the mess described above.
+*/
+
+#include <truetype/ttobjs.h>
+#include <type1z/z1objs.h>
+
+#include <Resources.h>
+#include <Fonts.h>
+#include <Errors.h>
+
+#include <ctype.h>  /* for isupper() and isalnum() */
+#include <stdlib.h> /* for malloc() and free() */
+
+
+/* set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
+   TrueType in case *both* are available */
+#ifndef PREFER_LWFN
+#define PREFER_LWFN 1
+#endif
+
+
+  static
+  FT_Error init_driver( FT_Driver  driver )
+  {
+    /* we don't keep no stinkin' state ;-) */
+    return FT_Err_Ok;
+  }
+
+  static
+  FT_Error done_driver( FT_Driver  driver )
+  {
+    return FT_Err_Ok;
+  }
+
+
+  /* MacRoman glyph names, needed for FOND kerning support. */
+  /* XXX which is not implemented yet! */
+  static const char*  mac_roman_glyph_names[256] = {
+    ".null",
+  };
+
+
+  /* The FOND face object is just a union of TT and T1: both is possible,
+     and we don't need anything else. We still need to be able to hold
+     either, as the face object is not allocated by us. Again, creating
+     an FT_New_Face_Mac() would avoid this kludge. */
+  typedef union FOND_FaceRec_
+  {
+    TT_FaceRec     tt;
+    T1_FaceRec     t1;
+  } FOND_FaceRec, *FOND_Face;
+
+
+  /* given a pathname, fill in a File Spec */
+  static
+  int make_file_spec( char* pathname, FSSpec *spec )
+  {
+    Str255  p_path;
+    int     path_len;
+
+    /* convert path to a pascal string */
+    path_len = strlen( pathname );
+    if ( path_len > 255 )
+      return -1;
+    p_path[0] = path_len;
+    strncpy( (char*)p_path+1, pathname, path_len );
+
+    if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr )
+      return -1;
+    else
+      return 0;
+  }
+
+
+  /* is_suitcase() returns true if the file specified by 'pathname'
+     is a Mac suitcase file, and false if it ain't. */
+  static
+  int is_suitcase( FSSpec  *spec )
+  {
+    FInfo   finfo;
+
+    if ( FSpGetFInfo( spec, &finfo ) != noErr )
+      return 0;
+    if ( finfo.fdType == 'FFIL' || finfo.fdType == 'tfil' )
+      return 1;
+    else
+      return 0;
+  }
+
+
+  /* Quick 'n' Dirty Pascal string to C string converter.
+     Warning: this call is not thread safe! Use with caution. */
+  static
+  char * p2c_str( unsigned char *pstr )
+  {
+    static char cstr[256];
+
+    strncpy( cstr, (char*)pstr+1, pstr[0] );
+    cstr[pstr[0]] = '\0';
+    return cstr;
+  }
+
+
+  /* Given a PostScript font name, create the Macintosh LWFN file name */
+  static
+  void create_lwfn_name( char* ps_name, Str255 lwfn_file_name )
+  {
+    int  max = 5, count = 0;
+    unsigned char* p = lwfn_file_name;
+    char* q = ps_name;
+
+    lwfn_file_name[0] = 0;
+
+    while ( *q )
+    {
+      if ( isupper(*q) )
+      {
+        if ( count )
+          max = 3;
+        count = 0;
+      }
+      if ( count < max && (isalnum(*q) || *q == '_' ) )
+      {
+        *++p = *q;
+        lwfn_file_name[0]++;
+        count++;
+      }
+      q++;
+    }
+  }
+
+
+  /* Suck the relevant info out of the FOND data */
+  static
+  FT_Error parse_fond( char*   fond_data,
+                       short   *have_sfnt,
+                       short   *sfnt_id,
+                       Str255  lwfn_file_name )
+  {
+    AsscEntry*  assoc;
+    FamRec*     fond;
+
+    *sfnt_id = *have_sfnt = 0;
+    lwfn_file_name[0] = 0;
+
+    fond = (FamRec*)fond_data;
+    assoc = (AsscEntry*)(fond_data + sizeof(FamRec) + 2);
+
+    if ( assoc->fontSize == 0 )
+    {
+      *have_sfnt = 1;
+      *sfnt_id = assoc->fontID;
+    }
+
+    if ( fond->ffStylOff )
+    {
+      unsigned char*  p = (unsigned char*)fond_data;
+      StyleTable*     style;
+      unsigned short  string_count;
+      unsigned char*  name_table = 0;
+      char            ps_name[256];
+      unsigned char*  names[64];
+      int             i;
+
+      p += fond->ffStylOff;
+      style = (StyleTable*)p;
+      p += sizeof(StyleTable);
+      string_count = *(unsigned short*)(p);
+      p += sizeof(short);
+
+      for ( i=0 ; i<string_count && i<64; i++ )
+      {
+        names[i] = p;
+        p += names[i][0];
+        p++;
+      }
+      strcpy(ps_name, p2c_str(names[0])); /* Family name */
+
+      if ( style->indexes[0] > 1 )
+      {
+        unsigned char* suffixes = names[style->indexes[0]-1];
+        for ( i=1; i<=suffixes[0]; i++ )
+          strcat( ps_name, p2c_str(names[suffixes[i]-1]) );
+      }
+      create_lwfn_name( ps_name, lwfn_file_name );
+    }
+    return FT_Err_Ok;
+  }
+
+
+  /* Read Type 1 data from the POST resources inside the LWFN file, return a
+     PFB buffer -- apparently FT doesn't like a pure binary T1 stream. */
+  static
+  unsigned char* read_type1_data( FT_Memory memory, FSSpec* lwfn_spec, unsigned long *size )
+  {
+    short          res_ref, res_id;
+    unsigned char  *buffer, *p, *size_p;
+    unsigned long  total_size = 0;
+    unsigned long  post_size, pfb_chunk_size;
+    Handle         post_data;
+    char           code, last_code;
+
+    res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm );
+    if ( ResError() )
+      return NULL;
+    UseResFile( res_ref );
+
+    /* first pass: load all POST resources, and determine the size of
+       the output buffer */
+    res_id = 501;
+    last_code = -1;
+    for (;;)
+    {
+      post_data = Get1Resource( 'POST', res_id++ );
+      if ( post_data == NULL )
+        break;
+      code = (*post_data)[0];
+      if ( code != last_code )
+      {
+        if ( code == 5 )
+          total_size += 2; /* just the end code */
+        else
+          total_size += 6; /* code + 4 bytes chunk length */
+      }
+      total_size += GetHandleSize( post_data ) - 2;
+      last_code = code;
+    }
+
+    buffer = memory->alloc( memory, total_size );
+    if ( !buffer )
+      goto error;
+
+    /* second pass: append all POST data to the buffer, add PFB fields */
+    p = buffer;
+    res_id = 501;
+    last_code = -1;
+    pfb_chunk_size = 0;
+    for (;;)
+    {
+      post_data = Get1Resource( 'POST', res_id++ );
+      if ( post_data == NULL )
+        break;
+      post_size = GetHandleSize( post_data ) - 2;
+      code = (*post_data)[0];
+      if ( code != last_code )
+      {
+        if ( last_code != -1 )
+        {
+          /* we're done adding a chunk, fill in the size field */
+          *size_p++ = pfb_chunk_size & 0xFF;
+          *size_p++ = (pfb_chunk_size >> 8) & 0xFF;
+          *size_p++ = (pfb_chunk_size >> 16) & 0xFF;
+          *size_p++ = (pfb_chunk_size >> 24) & 0xFF;
+          pfb_chunk_size = 0;
+        }
+        *p++ = 0x80;
+        if ( code == 5 )
+          *p++ = 0x03;  /* the end */
+        else if ( code == 2 )
+          *p++ = 0x02;  /* binary segment */
+        else
+          *p++ = 0x01;  /* ASCII segment */
+        if ( code != 5 )
+        {
+          size_p = p;   /* save for later */
+          p += 4;       /* make space for size field */
+        }
+      }
+      memcpy( p, *post_data + 2, post_size );
+      pfb_chunk_size += post_size;
+      p += post_size;
+      last_code = code;
+    }
+
+    CloseResFile( res_ref );
+
+    *size = total_size;
+/*    printf( "XXX %d %d\n", p - buffer, total_size ); */
+    return buffer;
+
+error:
+    CloseResFile( res_ref );
+    return NULL;
+  }
+
+
+  /* Finalizer for the sfnt stream */
+  static
+  void sfnt_stream_close( FT_Stream  stream )
+  {
+    Handle sfnt_data = stream->descriptor.pointer;
+    HUnlock( sfnt_data );
+    DisposeHandle( sfnt_data );
+
+    stream->descriptor.pointer = NULL;
+    stream->size               = 0;
+    stream->base               = 0;
+    stream->close              = 0;
+  }
+
+
+  /* Finalizer for the LWFN stream */
+  static
+  void lwfn_stream_close( FT_Stream  stream )
+  {
+    stream->memory->free( stream->memory, stream->base );
+    stream->descriptor.pointer = NULL;
+    stream->size               = 0;
+    stream->base               = 0;
+    stream->close              = 0;
+  }
+
+
+  /* Main entry point. Determine whether we're dealing with a Mac
+     suitcase or not; then determine if we're dealing with Type 1
+     or TrueType; delegate the work to the proper driver. */
+  static
+  FT_Error init_face( FT_Stream      stream,
+                      FT_Face        face,
+                      FT_Int         face_index,
+                      FT_Int         num_params,
+                      FT_Parameter*  parameters )
+  {
+    FT_Error      err;
+    FSSpec        suit_spec, lwfn_spec;
+    short         res_ref;
+    Handle        fond_data, sfnt_data;
+    short         res_index, sfnt_id, have_sfnt;
+    Str255        lwfn_file_name;
+
+    if ( !stream->pathname.pointer )
+      return FT_Err_Unknown_File_Format;
+
+    if ( make_file_spec( stream->pathname.pointer, &suit_spec ) )
+      return FT_Err_Invalid_Argument;
+
+    if ( !is_suitcase( &suit_spec ) )
+      return FT_Err_Unknown_File_Format;
+
+    res_ref = FSpOpenResFile( &suit_spec, fsRdPerm );
+    if ( ResError() )
+      return FT_Err_Invalid_File_Format;
+    UseResFile( res_ref );
+
+    /* face_index may be -1, in which case we
+       just need to do a sanity check */
+    if ( face_index < 0)
+      res_index = 1;
+    else
+    {
+      res_index = face_index + 1;
+      face_index = 0;
+    }
+    fond_data = Get1IndResource( 'FOND', res_index );
+    if ( ResError() )
+    {
+      CloseResFile( res_ref );
+      return FT_Err_Invalid_File_Format;
+    }
+    /* Set the number of faces. Not that it helps much: the t1 driver
+       just sets it to 1 anyway :-( */
+    face->num_faces = Count1Resources('FOND');
+
+    HLock( fond_data );
+    err = parse_fond( *fond_data, &have_sfnt, &sfnt_id, lwfn_file_name );
+    HUnlock( fond_data );
+    if ( err )
+    {
+      CloseResFile( res_ref );
+      return FT_Err_Invalid_Handle;
+    }
+
+    if ( lwfn_file_name[0] )
+    {
+      /* We look for the LWFN file in the same directory as the suitcase
+         file. ATM would look in other places, too, but this is the usual
+         situation. */
+      err = FSMakeFSSpec( suit_spec.vRefNum, suit_spec.parID, lwfn_file_name, &lwfn_spec );
+      if ( err != noErr )
+        lwfn_file_name[0] = 0;  /* no LWFN file found */
+    }
+
+    if ( lwfn_file_name[0] && ( !have_sfnt || PREFER_LWFN ) )
+    {
+      FT_Driver       t1_driver;
+      unsigned char*  type1_data;
+      unsigned long   size;
+
+      CloseResFile( res_ref ); /* XXX still need to read kerning! */
+
+      type1_data = read_type1_data( stream->memory, &lwfn_spec, &size );
+      if ( !type1_data )
+      {
+        return FT_Err_Out_Of_Memory;
+      }
+
+#if 0
+      {
+        FILE* f;
+        char * path;
+
+        path = p2c_str( lwfn_file_name );
+        strcat( path, ".PFB" );
+        f = fopen(path, "wb");
+        if ( f )
+        {
+          fwrite( type1_data, 1, size, f );
+          fclose( f );
+        }
+      }
+#endif
+
+      /* reinitialize the stream */
+      if ( stream->close )
+        stream->close( stream );
+      stream->close = lwfn_stream_close;
+      stream->read = 0; /* it's now memory based */
+      stream->base = type1_data;
+      stream->size = size;
+      stream->pos = 0; /* just in case */
+
+      /* delegate the work to the Type 1 module */
+      t1_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "type1z" );
+      if ( t1_driver )
+      {
+        face->driver = t1_driver;
+        return t1_driver->clazz->init_face( stream, face, face_index, 0, NULL );
+      }
+      else
+        return FT_Err_Invalid_Driver_Handle;
+    }
+    else if ( have_sfnt )
+    {
+      FT_Driver     tt_driver;
+
+      sfnt_data = Get1Resource( 'sfnt', sfnt_id );
+      if ( ResError() )
+      {
+        CloseResFile( res_ref );
+        return FT_Err_Invalid_Handle;
+      }
+      DetachResource( sfnt_data );
+      CloseResFile( res_ref );
+      HLockHi( sfnt_data );
+
+      /* reinitialize the stream */
+      if ( stream->close )
+        stream->close( stream );
+      stream->close = sfnt_stream_close;
+      stream->descriptor.pointer = sfnt_data;
+      stream->read = 0; /* it's now memory based */
+      stream->base = (unsigned char *)*sfnt_data;
+      stream->size = GetHandleSize( sfnt_data );
+      stream->pos = 0; /* just in case */
+
+      /* delegate the work to the TrueType driver */
+      tt_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "truetype" );
+      if ( tt_driver )
+      {
+        face->driver = tt_driver;
+        return tt_driver->clazz->init_face( stream, face, face_index, 0, NULL );
+      }
+      else
+        return FT_Err_Invalid_Driver_Handle;
+    }
+    else
+    {
+      CloseResFile( res_ref );
+    }
+    return FT_Err_Invalid_File_Format;
+  }
+
+
+  static
+  void  done_face( FT_Face  face )
+  {
+    /* nothing to do */
+  }
+
+  /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+  const FT_Driver_Class  fond_driver_class =
+  {
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof ( FT_DriverRec ),
+
+      "fond",          /* driver name                           */
+      0x10000L,        /* driver version == 1.0                 */
+      0x20000L,        /* driver requires FreeType 2.0 or above */
+
+      (void*)0,
+
+      (FT_Module_Constructor)     init_driver,
+      (FT_Module_Destructor)      done_driver,
+      (FT_Module_Requester)       0
+    },
+
+    sizeof ( FOND_FaceRec ),
+    0,
+    0,
+
+    (FTDriver_initFace)          init_face,
+    (FTDriver_doneFace)          done_face,
+    (FTDriver_initSize)          0,
+    (FTDriver_doneSize)          0,
+    (FTDriver_initGlyphSlot)     0,
+    (FTDriver_doneGlyphSlot)     0,
+
+    (FTDriver_setCharSizes)      0,
+    (FTDriver_setPixelSizes)     0,
+    (FTDriver_loadGlyph)         0,
+    (FTDriver_getCharIndex)      0,
+
+    (FTDriver_getKerning)        0,
+    (FTDriver_attachFile)        0,
+    (FTDriver_getAdvances)       0
+  };
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverInterface                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the FOND driver as a          */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+  FT_EXPORT_FUNC(const FT_Driver_Class*)  getDriverClass( void )
+  {
+    return &fond_driver_class;
+  }
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/src/freetype/otlayout/oltypes.c b/src/freetype/otlayout/oltypes.c
new file mode 100644 (file)
index 0000000..bd2fa22
--- /dev/null
@@ -0,0 +1,614 @@
+#include <oltypes.h>
+
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Init( OTL_Table*  table,
+                            FT_Memory   memory )
+  {
+    MEM_Set( table, 0, sizeof(*table) );
+    table->memory = memory;
+  }
+
+ /* read a script list table */
+ /* use with any table       */
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Set_Scripts( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len,
+                                   OTL_Type    otl_type )
+  {
+    TT_Byte*  p;
+    TT_Byte*  start = bytes;
+    TT_UInt   count, max_langs;
+    TT_Error  error;
+
+    /* skip version of the JSTF table */
+    if (otl_type == otl_jstf)
+      start += 4;
+
+    p = start;
+
+    /* we must allocate the script_tags and language_tags arrays     */
+    /* this requires that we compute the maximum number of languages */
+    /* per script..                                                  */
+
+    count     = table->num_scripts = OTL_UShort(p);
+    max_langs = 0;
+    for ( ; count > 0; count++ )
+    {
+      TT_Byte*  script;
+      TT_UInt   num_langs;
+
+      p += 4; /* skip tag */
+      script = bytes + OTL_UShort(p);
+
+      /* skip the baseValues or extenders field of the BASE and JSTF table */
+      if (otl_type == otl_type_base || otl_type == otl_type_jstf)
+        script += 2;
+
+      /* test if there is a default language system */
+      if ( OTL_UShort(script) )
+        num_langs++;
+
+      /* test other language systems */
+      num_langs += OTL_UShort(script); /* add other lang sys */
+
+      if (num_langs > max_langs)
+        max_langs = num_langs;
+    }
+
+    /* good, now allocate the tag arrays */
+    if ( !ALLOC_ARRAY( table->script_tags,
+                      table->num_scripts + max_langs,
+                      TT_ULong ) )
+    {
+      table->language_tags = table->script_tags + table->num_scripts;
+      table->max_languages = max_langs;
+      table->num_languages = 0;
+      table->otl_type      = otl_type;
+
+      table->scripts_table = bytes;
+      table->scripts_len   = len;
+
+      /* fill the script_tags array */
+      {
+        TT_UInt  n;
+        TT_Byte* p = start + 2; /* skip count */
+
+        for ( n = 0; n < table->num_scripts; n++ )
+        {
+          table->script_tags[n] = OTL_ULong(p);
+          p += 2; /* skip offset */
+        }
+      }
+    }
+    return error;
+  }
+
+
+
+ /* add a features list to the table   */
+ /* use only with a GSUB or GPOS table */
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Set_Features( OTL_Table*  table,
+                                    TT_Byte*    bytes,
+                                    TT_Long     len )
+  {
+    TT_Error  error;
+    TT_Byte*  p = bytes;
+    TT_UInt   count;
+
+    table->max_features = count = OTL_UShort(p);
+    if ( !ALLOC_ARRAY( table->feature_tags, count, TT_ULong ) &&
+         !ALLOC_ARRAY( table->features,     count, TT_Bool  ) )
+    {
+      table->features_table = bytes;
+      table->features_len   = len;
+    }
+    return error;
+  }
+
+
+ /* add a lookup list to the table     */
+ /* use only with a GSUB or GPOS table */
+  LOCAL_FUNC
+  TT_Error  OTL_Table_Set_Lookups( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len )
+  {
+    TT_Error  error;
+    TT_Byte*  p = bytes;
+    TT_UInt   count;
+
+    table->max_lookups = count = OTL_UShort(p);
+    if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) )
+    {
+      table->lookups_table = bytes;
+      table->lookups_len   = len;
+    }
+    return error;
+  }
+
+ /* discard table arrays */
+  LOCAL_FUNC
+  void      OTL_Table_Done( OTL_Table*  table )
+  {
+    FREE( table->scrip_tags );
+    FREE( table->language_tags );
+    FREE( table->feature_tags );
+    FREE( table->lookups );
+  }
+
+
+ /* return the list of available languages for a given script */
+ /* use with any table..                                      */
+  LOCAL_FUNC
+  void  OTL_Get_Languages_List( OTL_Table*  table,
+                                TT_ULong    script_tag )
+  {
+    TT_UInt  n;
+    TT_Byte* p;
+    TT_Byte* script = 0;
+    TT_Byte* start = table->scripts_table;
+
+    if ( table->otl_type == otl_type_jstf )  /* skip version for JSTF */
+      start += 4;
+
+    p = start + 6; /* skip count+first tag */
+
+    for ( n = 0; n < table->num_scripts; n++, p += 6 )
+    {
+      if ( table->script_tags[n] == script_tag )
+      {
+        script = table->scripts_table + OTL_UShort(p);
+        break;
+      }
+    }
+
+    table->cur_script = script;
+    if (!script)
+      table->num_languages = 0;
+    else
+    {
+      /* now fill the language_tags array with the appropriate values    */
+      /* not that we put a '0' tag in front of the list to indicate that */
+      /* there is a default language for this script..                   */
+      TT_ULong* tags = table->language_tags;
+
+      switch (table->otl_type)
+      {
+        case otl_type_base:
+        case otl_type_jstf:
+          script += 2;    /* skip basevalue or extenders */
+          /* fall-through */
+
+        default:
+          if ( OTL_UShort(script) )
+            *tags++ = 0;
+      }
+
+      count = OTL_UShort(script);
+      for ( ; count > 0; count-- )
+      {
+        *tags++ = OTL_ULong(script);
+        script += 2; /* skip offset */
+      }
+
+      table->num_langs = tags - table->language_tags;
+    }
+  }
+
+
+ /* return the list of available features for the current script/language */
+ /* use with a GPOS or GSUB script table                                  */
+  LOCAL_FUNC
+  void OTL_Get_Features_List( OTL_Table*  table,
+                              TT_ULong    language_tag )
+  {
+    TT_UInt   n;
+    TT_Byte*  script   = table->cur_script;
+    TT_Byte*  language = 0;
+    TT_UShort offset;
+
+    /* clear feature selection table */
+    for ( n = 0; n < table->max_features; n++ )
+      table->features[n] = 0;
+
+    /* now, look for the current language */
+    if ( language_tag == 0 )
+    {
+      offset = OTL_UShort(script);
+      if (!offset) return; /* if there is no default language, exit */
+
+      language = script - 2 + offset;
+    }
+    else
+    {
+      TT_Byte*  p = script + 8; /* skip default+count+1st tag */
+      TT_UShort index;
+
+      for ( n = 0; n < table->num_languages; n++, p+=6 )
+      {
+        if ( table->language_tags[n] == language_tag )
+        {
+          language = script + OTL_UShort(p);
+          break;
+        }
+      }
+
+      table->cur_language = language;
+      if (!language) return;
+
+      p     = language + 2;   /* skip lookup order */
+      index = OTL_UShort(p);  /* required feature index */
+      if (index != 0xFFFF)
+      {
+        if (index < table->max_features)
+          table->features[index] = 1;
+      }
+
+      count = OTL_UShort(p);
+      for ( ; count > 0; count-- )
+      {
+        index = OTL_UShort(p);
+        if (index < table->max_features)
+          table->features[index] = 1;
+      }
+    }
+  }
+
+
+ /* return the list of lookups for the current features list */
+ /* use only with a GSUB or GPOS table                       */
+  LOCAL_FUNC
+  void  OTL_Get_Lookups_List( OTL_Table*  table )
+  {
+    TT_UInt  n;
+    TT_Byte* features = table->features_table;
+    TT_Byte* p        = features + 6; /* skip count+1st tag */
+
+    /* clear lookup list */
+    for ( n = 0; n < table->max_lookups; n++ )
+      table->lookups[n] = 0;
+
+    /* now, parse the features list */
+    for ( n = 0; n < table->features; n++ )
+    {
+      if (table->features[n])
+      {
+        TT_UInt   count;
+        TT_UShort index;
+        TT_Byte*  feature;
+
+        feature = features + OTL_UShort(p);
+        p      += 4;  /* skip tag */
+
+        /* now, select all lookups from this feature */
+        count = OTL_UShort(feature);
+        for ( ; count > 0; count-- )
+        {
+          index = OTL_UShort(feature);
+          if (index < table->max_lookups)
+            table->lookups[index] = 1;
+        }
+      }
+    }
+  }
+
+
+ /* find the basevalues and minmax for the current script/language */
+ /* only use it with a BASE table..                                */
+  LOCAL_FUNC
+  void OTL_Get_Baseline_Values( OTL_Table*  table,
+                                TT_ULong    language_tag )
+  {
+    TT_Byte*  script   = table->cur_script;
+    TT_Byte*  p        = script;
+    TT_UShort offset, count;
+
+    table->cur_basevalues = 0;
+    table->cur_minmax     = 0;
+
+    /* read basevalues */
+    offset = OTL_UShort(p);
+    if (offset)
+      table->cur_basevalues = script + offset;
+
+    offset = OTL_UShort(p);
+    if (offset)
+      table->cur_minmax = script + offset;
+
+    count = OTL_UShort(p);
+    for ( ; count > 0; count-- )
+    {
+      TT_ULong  tag;
+
+      tag = OTL_ULong(p);
+      if ( language_tag == tag )
+      {
+        table->cur_minmax = script + OTL_UShort(p);
+        break;
+      }
+      p += 2; /* skip offset */
+    }
+  }
+
+
+ /* compute the coverage value of a given glyph id */
+  LOCAL_FUNC
+  TT_Long  OTL_Get_Coverage_Index( TT_Byte*  coverage,
+                                   TT_UInt   glyph_id )
+  {
+    TT_Long    result = -1;
+    TT_UInt    count, index, start, end;
+    TT_Byte*   p = coverage;
+
+    switch ( OTL_UShort(p) )
+    {
+      case 1:  /* coverage format 1 - array of glyph indices */
+        {
+          count = OTL_UShort(p);
+          for ( index = 0; index < count; index++ )
+          {
+            if ( OTL_UShort(p) == glyph_id )
+            {
+              result = index;
+              break;
+            }
+          }
+        }
+        break;
+
+      case 2:
+        {
+          count = OTL_UShort(p);
+          for ( ; count > 0; count-- )
+          {
+            start = OTL_UShort(p);
+            end   = OTL_UShort(p);
+            index = OTL_UShort(p);
+            if (start <= glyph_id && glyph_id <= end)
+            {
+              result = glyph_id - start + index;
+              break;
+            }
+          }
+        }
+        break;
+    }
+    return result;
+  }
+
+
+ /* compute the class value of a given glyph_id */
+  LOCAL_FUNC
+  TT_UInt  OTL_Get_Glyph_Class( TT_Byte*  class_def,
+                                TT_UInt   glyph_id )
+  {
+    TT_Byte*  p = class_def;
+    TT_UInt   result = 0;
+    TT_UInt   start, end, count, index;
+
+    switch ( OTL_UShort(p) )
+    {
+      case 1:
+        {
+          start = OTL_UShort(p);
+          count = OTL_UShort(p);
+
+          glyph_id -= start;
+          if (glyph_id < count)
+          {
+            p += 2*glyph_id;
+            result = OTL_UShort(p);
+          }
+        }
+        break;
+
+      case 2:
+        {
+          count = OTL_UShort(p);
+          for ( ; count > 0; count-- )
+          {
+            start = OTL_UShort(p);
+            end   = OTL_UShort(p);
+            index = OTL_UShort(p);
+            if ( start <= glyph_id && glyph_id <= end )
+            {
+              result = index;
+              break;
+            }
+          }
+        }
+        break;
+    }
+    return result;
+  }
+
+
+ /* compute the adjustement necessary for a given device size */
+  LOCAL_FUNC
+  TT_Int  OTL_Get_Device_Adjustment( TT_Byte* device,
+                                     TT_UInt  size )
+  {
+    TT_Byte*  p = device;
+    TT_Int    result = 0;
+    TT_UInt   start, end;
+    TT_Short  value;
+
+    start = OTL_UShort(p);
+    end   = OTL_UShort(p);
+    if (size >= start && size <= end)
+    {
+      /* I know we could do all of this without a switch, with */
+      /* clever shifts and everything, but it makes the code   */
+      /* really difficult to understand..                      */
+
+      size -= start;
+      switch ( OTL_UShort(p) )
+      {
+        case 1: /* 2-bits per value */
+          {
+            p     += 2*(size >> 3);
+            size   = (size & 7) << 1;
+            value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+            result = value >> 14;
+          }
+          break;
+
+        case 2: /* 4-bits per value */
+          {
+            p     += 2*(size >> 2);
+            size   = (size & 3) << 2;
+            value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+            result = value >> 12;
+          }
+          break;
+
+        case 3: /* 8-bits per value */
+          {
+            p     += 2*(size >> 1);
+            size   = (size & 1) << 3;
+            value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
+            result = value >> 8;
+          }
+          break;
+      }
+    }
+    return result;
+  }
+
+ /* extract a BaseCoord value */
+  LOCAL_FUNC
+  void    OTL_Get_Base_Coordinate( TT_Byte*          base_coord,
+                                   OTL_ValueRecord*  coord )
+  {
+    TT_Byte*  p = base_coord;
+    TT_Int    result = 0;
+
+    coord->format     = OTL_UShort(p);
+    coord->coordinate = OTL_Short(p);
+    coord->device     = 0;
+
+    switch (coord->format)
+    {
+      case 2: /* format 2 */
+        coord->ref_glyph = OTL_UShort(p);
+        coord->ref_point = OTL_UShort(p);
+        break;
+
+      case 3: /* format 3 */
+        coord->device = p - 4 + OTL_UShort(p);
+        break;
+
+      default:
+        ;
+    }
+  }
+
+
+ /* compute size of ValueRecord */
+ LOCAL_FUNC
+ TT_Int  OTL_ValueRecord_Size( TT_UShort  format )
+ {
+   TT_Int  count;
+
+   /* each bit in the value format corresponds to a single ushort */
+   /* we thus count the bits, and multiply the result by 2        */
+
+   count = (TT_Int)(format & 0xFF);
+   count = ((count & 0xAA) >> 1) + (count & 0x55);
+   count = ((count & 0xCC) >> 2) + (count & 0x33);
+   count = ((count & 0xF0) >> 4) + (count & 0x0F);
+
+   return count*2;
+ }
+
+
+
+ /* extract ValueRecord */
+ LOCAL_FUNC
+ void  OTL_Get_ValueRecord( TT_Byte*          value_record,
+                            TT_UShort         value_format,
+                           TT_Byte*          pos_table,
+                           OTL_ValueRecord*  record )
+ {
+   TT_Byte*  p = value_record;
+
+   /* clear vectors */
+   record->placement.x = 0;
+   record->placement.y = 0;
+   record->advance.x   = 0;
+   record->advance.y   = 0;
+
+   record->device_pla_x = 0;
+   record->device_pla_y = 0;
+   record->device_adv_x = 0;
+   record->device_adv_y = 0;
+
+   if (value_format & 1) record->placement.x = NEXT_Short(p);
+   if (value_format & 2) record->placement.y = NEXT_Short(p);
+   if (value_format & 4) record->advance.x   = NEXT_Short(p);
+   if (value_format & 8) record->advance.y   = NEXT_Short(p);
+
+   if (value_format & 16)  record->device_pla_x = pos_table + NEXT_UShort(p);
+   if (value_format & 32)  record->device_pla_y = pos_table + NEXT_UShort(p);
+   if (value_format & 64)  record->device_adv_x = pos_table + NEXT_UShort(p);
+   if (value_format & 128) record->device_adv_y = pos_table + NEXT_UShort(p);
+ }
+
+
+
+ /* extract Anchor */
+ LOCAL_FUNC
+ void  OTL_Get_Anchor( TT_Byte*     anchor_table,
+                       OTL_Anchor*  anchor )
+ {
+   TT_Byte*  p = anchor_table;
+
+   anchor->format   = NEXT_UShort(p);
+   anchor->coord.x  = NEXT_Short(p);
+   anchor->coord.y  = NEXT_Short(p);
+   anchor->point    = 0;
+   anchor->device_x = 0;
+   anchor->device_y = 0;
+
+   switch (anchor->format)
+   {
+     case 2:
+       anchor->point = NEXT_UShort(p);
+       break;
+
+     case 3:
+       anchor->device_x = anchor_table + NEXT_UShort(p);
+       anchor->device_y = anchor_table + NEXT_UShort(p);
+       break;
+
+     default:
+       ;
+   }
+ }
+
+
+
+ /* extract Mark from MarkArray */
+ LOCAL_FUNC
+ void  OTL_Get_Mark( TT_Byte*     mark_array,
+                     TT_UInt      index,
+                    TT_UShort*   clazz,
+                    OTL_Anchor*  anchor )
+ {
+   TT_Byte* p = mark_array;
+   TT_UInt  count;
+
+   *clazz = 0;
+   MEM_Set( anchor, 0, sizeof(*anchor) );
+
+   count = NEXT_UShort(p);
+   if (index < count)
+   {
+     p += 4*index;
+     *clazz = NEXT_UShort(p);
+     OTL_Get_Anchor( mark_array + NEXT_UShort(p), anchor );
+   }
+ }
+
diff --git a/src/freetype/otlayout/oltypes.h b/src/freetype/otlayout/oltypes.h
new file mode 100644 (file)
index 0000000..b4a4d80
--- /dev/null
@@ -0,0 +1,310 @@
+#ifndef OLTYPES_H
+#define OLTYPES_H
+
+#include <ftobjs.h>
+#include <tttypes.h>
+
+ /*************************************************************
+  *
+  * <Struct> OTL_Table
+  *
+  * <Description>
+  *    The base table of most OpenType Layout sub-tables.
+  *    Provides a simple way to scan a table for script,
+  *    languages, features and lookups..
+  *
+  * <Fields>
+  *    num_scripts  :: number of scripts in table's script list
+  *    script_tags  :: array of tags for each table script
+  *
+  *    max_languages :: max number of languages for any script in
+  *                     the table.
+  *    num_languages :: number of languages available for current script
+  *    language_tags :: tags of all languages available for current script.
+  *
+  *    max_features  :: total number of features in table
+  *    feature_tags  :: tags of all features for current script/language
+  *    features      :: selection flags for all features in current script/lang
+  *
+  *    max_lookups   :: total number of lookups in table
+  *    lookups       :: selection flags for all lookups for current
+  *                     feature list.
+  *
+  ****************************************************************/
+
+  typedef enum OTL_Type_
+  {
+    otl_type_none = 0,
+    otl_type_base,
+    otl_type_gdef,
+    otl_type_gpos,
+    otl_type_gsub,
+    otl_type_jstf
+
+  } OTL_Type;
+
+
+  typedef struct OTL_Table_
+  {
+    FT_Memory memory;
+
+    TT_Int    num_scripts;
+    TT_Tag*   script_tags;
+
+    TT_Int    max_languages;
+    TT_Int    num_languages;
+    TT_Tag*   language_tags;
+
+    TT_Int    max_features;
+    TT_Tag*   feature_tags;
+    TT_Bool*  features;
+
+    TT_Int    max_lookups;
+    TT_Bool*  lookups;
+
+    TT_Byte*  scripts_table;
+    TT_Long   scripts_len;
+
+    TT_Byte*  features_table;
+    TT_Long*  features_len;
+
+    TT_Byte*  lookups_table;
+    TT_Byte*  lookups_len;
+
+    TT_Byte*  cur_script;   /* current script   */
+    TT_Byte*  cur_language; /* current language */
+
+    TT_Byte*  cur_base_values;
+    TT_Byte*  cur_min_max;
+
+    OTL_Type  otl_type;
+
+  } OTL_Table;
+
+
+  typedef struct OTL_BaseCoord_
+  {
+    TT_UShort  format;
+    TT_Short   coordinate;
+    TT_UShort  ref_glyph;
+    TT_UShort  ref_point;
+    TT_Byte*   device;
+
+  } OTL_BaseCoord;
+
+
+  typedef struct OTL_ValueRecord_
+  {
+    TT_Vector  placement;
+    TT_Vector  advance;
+
+    TT_Byte*   device_pla_x;
+    TT_Byte*   device_pla_y;
+    TT_Byte*   device_adv_x;
+    TT_Byte*   device_adv_y;
+
+  } OTL_ValueRecord;
+
+
+  typedef struct OTL_Anchor_
+  {
+    TT_UInt    format;
+    TT_Vector  coord;
+    TT_UInt    anchor_point;
+    TT_Byte*   device_x;
+    TT_Byte*   device_y;
+
+  } OTL_Anchor;
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Init( OTL_Table*  table,
+                            FT_Memory   memory );
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Set_Scripts( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len,
+                                   OTL_Type    otl_type );
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Set_Features( OTL_Table*  table,
+                                    TT_Byte*    bytes,
+                                    TT_Long     len );
+
+  LOCAL_DEF
+  TT_Error  OTL_Table_Set_Lookups( OTL_Table*  table,
+                                   TT_Byte*    bytes,
+                                   TT_Long     len );
+
+  LOCAL_DEF
+  void      OTL_Table_Done( OTL_Table*  table );
+
+
+
+/*****************************************************
+ *
+ *  Typical uses:
+ *
+ *  - after OTL_Table_Set_Scripts have been called :
+ *
+ *      table->script_tags contains the list of tags of all
+ *      scripts defined for this table.
+ *
+ *      table->num_scripts is the number of scripts
+ *
+ */
+
+/********************************************************
+ *
+ *  - after calling OTL_Table_Set_Features:
+ *
+ *      table->max_features is the number of all features
+ *      in the table
+ *
+ *      table->feature_tags is the list of tags of all
+ *      features in the table
+ *
+ *      table->features[] is an array of boolean used to
+ *      indicate which feature is active for a given script/language
+ *      it is empty (zero-filled) by default.
+ *
+ */
+
+/*******************************************************************
+ *
+ *  - after calling OTL_Get_Languages_List(script_tag):
+ *
+ *      table->num_languages is the number of language systems
+ *      available for the script, including the default
+ *      langsys if there is one
+ *
+ *      table->language_tags contains the list of tags of all
+ *      languages for the script. Note that the default langsys
+ *      has tag "0" and is always placed first in "language_tags".
+ *
+ *
+ *
+ */
+  LOCAL_DEF
+  void  OTL_Get_Languages_List( OTL_Table*  table,
+                                TT_ULong    script_tag );
+
+
+/*******************************************************************
+ *
+ *  - after calling OTL_Get_Features_List(language_tag):
+ *
+ *      table->features[] is an array of booleans used to indicate
+ *      which features are active for the current script/language
+ *
+ *      note that this function must be called after OTL_Get_Languages
+ *      which remembers the last "script_tag" used..
+ *
+ *      A client application can change the table->features[] array
+ *      to add or remove features from the list.
+ *
+ *
+ *
+ */
+  LOCAL_DEF
+  void OTL_Get_Features_List( OTL_Table*  table,
+                              TT_ULong    language_tag );
+
+  LOCAL_DEF
+  void OTL_Get_Baseline_Values( OTL_Table*  table,
+                                TT_ULong    language_tag );
+
+  LOCAL_DEF
+  void OTL_Get_Justification( OTL_Table*  table,
+                              TT_ULong    language_tag );
+
+/*******************************************************************
+ *
+ *  - after calling OTL_Get_Lookups_List():
+ *
+ *      The function uses the table->features[] array of boolean
+ *      to determine which lookups must be processed.
+ *
+ *      It fills the table->lookups[] array accordingly. It is also
+ *      an array of booleans (one for each lookup).
+ *
+ *
+ */
+
+  LOCAL_DEF
+  void  OTL_Get_Lookups_List( OTL_Table*  table );
+
+
+/***************************************************************
+ *
+ *  So the whole thing looks like:
+ *
+ *
+ *  1.  A client specifies a given script and requests available
+ *      language through OTL_Get_Languages_List()
+ *
+ *  2.  It selects the language tag it needs, then calls
+ *      OTL_Get_Features_List()
+ *
+ *  3.  It updates the list of active features if it needs to
+ *
+ *  4.  It calls OTL_Get_Lookups_List()
+ *      It now has a list of active lookups in "table->lookups[]"
+ *
+ *  5.  The lookups are processed according to the table's type..
+ *
+ */
+
+
+
+
+  LOCAL_DEF
+  TT_Long  OTL_Get_Coverage_Index( TT_Byte*  coverage,
+                                   TT_UInt   glyph_id );
+
+  LOCAL_DEF
+  TT_UInt  OTL_Get_Glyph_Class( TT_Byte*  class_def,
+                                TT_UInt   glyph_id );
+
+  LOCAL_DEF
+  TT_Int  OTL_Get_Device_Adjustment( TT_Byte* device,
+                                     TT_UInt  size );
+
+  LOCAL_DEF
+  void    OTL_Get_Base_Coordinate( TT_Byte*        base_coord,
+                                   OTL_BaseCoord*  coord );
+
+
+  LOCAL_DEF
+  TT_Int  OTL_ValueRecord_Size( TT_UShort  value_format );
+
+
+  LOCAL_DEF
+  void  OTL_Get_ValueRecord( TT_Byte*          value_record,
+                             TT_UShort         value_format,
+                            TT_Byte*          pos_table,
+                            OTL_ValueRecord*  record );
+
+
+  LOCAL_DEF
+  void  OTL_Get_Anchor( TT_Byte*     anchor_table,
+                        OTL_Anchor*  anchor );
+
+
+  LOCAL_DEF
+  void  OTL_Get_Mark( TT_Byte*     mark_array,
+                      TT_UInt      index,
+                     TT_UShort*   clazz,
+                     OTL_Anchor*  anchor );
+
+
+
+#define OTL_Byte(p)   (p++, p[-1])
+
+#define OTL_UShort(p) (p+=2, ((TT_UShort)p[-2] << 8) | p[-1])
+
+#define OTL_ULong(p)  (p+=4, ((TT_ULong)p[-4] << 24) |        \
+                             ((TT_ULong)p[-3] << 16) |        \
+                             ((TT_ULong)p[-2] << 8 ) | p[-1] )
+
+#endif /* OLTYPES_H */
diff --git a/src/freetype/psnames/module.mk b/src/freetype/psnames/module.mk
new file mode 100644 (file)
index 0000000..3d33c12
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_psnames_module
+
+add_psnames_module:
+       $(OPEN_DRIVER)psnames_module_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)psnames   $(ECHO_DRIVER_DESC)Postscript & Unicode Glyph name handling$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/psnames/psmodule.c b/src/freetype/psnames/psmodule.c
new file mode 100644 (file)
index 0000000..55ab5df
--- /dev/null
@@ -0,0 +1,320 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psmodule.c                                                             */
+/*                                                                         */
+/*    PSNames module implementation (body).                                */
+/*                                                                         */
+/*  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 <freetype/internal/psnames.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "psmodule.h"
+#include "pstables.h"
+
+#else
+
+#include <psnames/psmodule.h>
+#include <psnames/pstables.h>
+
+#endif
+
+
+#include <stdlib.h>     /* for qsort()             */
+#include <string.h>     /* for strcmp(), strncpy() */
+
+
+#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+
+
+
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+  /* return the Unicode value corresponding to a given glyph.  Note that */
+  /* we do deal with glyph variants by detecting a non-initial dot in    */
+  /* the name, as in `A.swash' or `e.final', etc.                        */
+  /*                                                                     */
+  static
+  FT_ULong  PS_Unicode_Value( const char*  glyph_name )
+  {
+    FT_Int  n;
+    char    first = glyph_name[0];
+    char    temp[64];
+
+
+    /* if the name begins with `uni', then the glyph name may be a */
+    /* hard-coded unicode character code.                          */
+    if ( glyph_name[0] == 'u' &&
+         glyph_name[1] == 'n' &&
+         glyph_name[2] == 'i' )
+    {
+      /* determine whether the next four characters following are */
+      /* hexadecimal.                                             */
+
+      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
+      /*      `uniXXXXYYYYZZZZ'...                                   */
+
+      FT_Int       count;
+      FT_ULong     value = 0;
+      const char*  p     = glyph_name + 4;
+
+
+      for ( count = 4; count > 0; count--, p++ )
+      {
+        char           c = *p;
+        unsigned char  d;
+
+
+        d = (unsigned char)c - '0';
+        if ( d >= 10 )
+        {
+          d = (unsigned char)c - 'A';
+          if ( d >= 6 )
+            d = 16;
+          else
+            d += 10;
+        }
+
+        /* exit if a non-uppercase hexadecimal character was found */
+        if ( d >= 16 )
+          break;
+
+        value = ( value << 4 ) + d;
+
+        if ( count == 0 )
+          return value;
+      }
+    }
+
+    /* look for a non-initial dot in the glyph name in order to */
+    /* sort-out variants like `A.swash', `e.final', etc.        */
+    {
+      const char*  p;
+      int          len;
+
+
+      p = glyph_name;
+
+      while ( *p && *p != '.' )
+        p++;
+
+      len = p - glyph_name;
+
+      if ( *p && len < 64 )
+      {
+        strncpy( temp, glyph_name, len );
+        temp[len]  = 0;
+        glyph_name = temp;
+      }
+    }
+
+    /* now, look up the glyph in the Adobe Glyph List */
+    for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
+    {
+      const char*  name = t1_standard_glyphs[n];
+
+
+      if ( first == name[0] && strcmp( glyph_name, name ) == 0 )
+        return names_to_unicode[n];
+    }
+
+    /* not found, there is probably no Unicode value for this glyph name */
+    return 0;
+  }
+
+
+  /* qsort callback to sort the unicode map */
+  static
+  int  compare_uni_maps( const void*  a,
+                         const void*  b )
+  {
+    PS_UniMap*  map1 = (PS_UniMap*)a;
+    PS_UniMap*  map2 = (PS_UniMap*)b;
+
+
+    return ( map1->unicode - map2->unicode );
+  }
+
+
+  /* Builds a table that maps Unicode values to glyph indices */
+  static
+  FT_Error  PS_Build_Unicode_Table( FT_Memory     memory,
+                                    FT_UInt       num_glyphs,
+                                    const char**  glyph_names,
+                                    PS_Unicodes*  table )
+  {
+    FT_Error  error;
+
+
+    /* we first allocate the table */
+    table->num_maps = 0;
+    table->maps     = 0;
+
+    if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) )
+    {
+      FT_UInt     n;
+      FT_UInt     count;
+      PS_UniMap*  map;
+      FT_ULong    uni_char;
+
+
+      map = table->maps;
+
+      for ( n = 0; n < num_glyphs; n++ )
+      {
+        const char*  gname = glyph_names[n];
+
+
+        if ( gname )
+        {
+          uni_char = PS_Unicode_Value( gname );
+
+          if ( uni_char && uni_char != 0xFFFF )
+          {
+            map->unicode     = uni_char;
+            map->glyph_index = n;
+            map++;
+          }
+        }
+      }
+
+      /* now, compress the table a bit */
+      count = map - table->maps;
+
+      if ( count > 0 && REALLOC( table->maps,
+                                 num_glyphs * sizeof ( PS_UniMap ),
+                                 count * sizeof ( PS_UniMap ) ) )
+        count = 0;
+
+      if ( count == 0 )
+      {
+        FREE( table->maps );
+        if ( !error )
+          error = FT_Err_Invalid_Argument;  /* no unicode chars here! */
+      }
+      else
+        /* sort the table in increasing order of unicode values */
+        qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
+
+      table->num_maps = count;
+    }
+
+    return error;
+  }
+
+
+  static
+  FT_UInt  PS_Lookup_Unicode( PS_Unicodes*  table,
+                              FT_ULong      unicode )
+  {
+    PS_UniMap  *min, *max, *mid;
+
+
+    /* perform a binary search on the table */
+
+    min = table->maps;
+    max = min + table->num_maps - 1;
+
+    while ( min <= max )
+    {
+      mid = min + ( max - min ) / 2;
+      if ( mid->unicode == unicode )
+        return mid->glyph_index;
+
+      if ( min == max )
+        break;
+
+      if ( mid->unicode < unicode )
+        min = mid + 1;
+      else
+        max = mid - 1;
+    }
+
+    return 0xFFFF;
+  }
+
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+
+  static
+  const char*  PS_Macintosh_Name( FT_UInt  name_index )
+  {
+    if ( name_index >= 258 )
+      name_index = 0;
+
+    return standard_glyph_names[mac_standard_names[name_index]];
+  }
+
+
+  static
+  const char*  PS_Standard_Strings( FT_UInt  sid )
+  {
+    return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[sid] : 0 );
+  }
+
+
+  static const PSNames_Interface  psnames_interface =
+  {
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+    (PS_Unicode_Value_Func)    PS_Unicode_Value,
+    (PS_Build_Unicodes_Func)   PS_Build_Unicode_Table,
+    (PS_Lookup_Unicode_Func)   PS_Lookup_Unicode,
+
+#else
+
+    0,
+    0,
+    0,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+    (PS_Macintosh_Name_Func)   PS_Macintosh_Name,
+    (PS_Adobe_Std_Strings_Func)PS_Standard_Strings,
+
+    t1_standard_encoding,
+    t1_expert_encoding
+  };
+
+
+#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
+
+
+  const FT_Module_Class  psnames_module_class =
+  {
+    0,  /* this is not a font driver, nor a renderer */
+    sizeof( FT_ModuleRec ),
+
+    "psnames",  /* driver name                         */
+    0x10000L,   /* driver version                      */
+    0x20000L,   /* driver requires FreeType 2 or above */
+
+#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+    0,
+#else
+    (void*)&psnames_interface,   /* module specific interface */
+#endif
+
+    (FT_Module_Constructor)0,
+    (FT_Module_Destructor) 0,
+    (FT_Module_Requester)  0
+  };
+
+
+/* END */
diff --git a/src/freetype/psnames/psmodule.h b/src/freetype/psnames/psmodule.h
new file mode 100644 (file)
index 0000000..ff7ef06
--- /dev/null
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psmodule.h                                                             */
+/*                                                                         */
+/*    High-level PSNames module interface (specification).                 */
+/*                                                                         */
+/*  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 PSDRIVER_H
+#define PSDRIVER_H
+
+#include <freetype/ftmodule.h>
+
+  FT_EXPORT_VAR( const FT_Module_Class )  psnames_module_class;
+
+#endif /* PSDRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/psnames/psnames.c b/src/freetype/psnames/psnames.c
new file mode 100644 (file)
index 0000000..0491b48
--- /dev/null
@@ -0,0 +1,24 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psnames.c                                                              */
+/*                                                                         */
+/*    FreeType PSNames module component (body only).                       */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <psmodule.c>
+
+
+/* END */
diff --git a/src/freetype/psnames/pstables.h b/src/freetype/psnames/pstables.h
new file mode 100644 (file)
index 0000000..094bc27
--- /dev/null
@@ -0,0 +1,2942 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pstables.h                                                             */
+/*                                                                         */
+/*    PostScript glyph names (specification only).                         */
+/*                                                                         */
+/*  Copyright 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 has been generated automatically -- do not edit! */
+
+
+  static const char*  standard_glyph_names[] =
+  {
+    ".null",
+    "CR",
+    "notequal",
+    "infinity",
+    "lessequal",
+    "greaterequal",
+    "partialdiff",
+    "summation",
+    "product",
+    "pi",
+    "integral",
+    "Omega",
+    "radical",
+    "approxequal",
+    "Delta",
+    "nbspace",
+    "lozenge",
+    "periodcentered",
+    "apple",
+    "lslash",
+    "franc",
+    "Gbreve",
+    "gbreve",
+    "Idot",
+    "Scedilla",
+    "scedilla",
+    "Cacute",
+    "cacute",
+    "Ccaron",
+    "ccaron",
+    "dmacron",
+    ".notdef",
+    "space",
+    "exclam",
+    "quotedbl",
+    "numbersign",
+    "dollar",
+    "percent",
+    "ampersand",
+    "quoteright",
+    "parenleft",
+    "parenright",
+    "asterisk",
+    "plus",
+    "comma",
+    "hyphen",
+    "period",
+    "slash",
+    "zero",
+    "one",
+    "two",
+    "three",
+    "four",
+    "five",
+    "six",
+    "seven",
+    "eight",
+    "nine",
+    "colon",
+    "semicolon",
+    "less",
+    "equal",
+    "greater",
+    "question",
+    "at",
+    "A",
+    "B",
+    "C",
+    "D",
+    "E",
+    "F",
+    "G",
+    "H",
+    "I",
+    "J",
+    "K",
+    "L",
+    "M",
+    "N",
+    "O",
+    "P",
+    "Q",
+    "R",
+    "S",
+    "T",
+    "U",
+    "V",
+    "W",
+    "X",
+    "Y",
+    "Z",
+    "bracketleft",
+    "backslash",
+    "bracketright",
+    "asciicircum",
+    "underscore",
+    "quoteleft",
+    "a",
+    "b",
+    "c",
+    "d",
+    "e",
+    "f",
+    "g",
+    "h",
+    "i",
+    "j",
+    "k",
+    "l",
+    "m",
+    "n",
+    "o",
+    "p",
+    "q",
+    "r",
+    "s",
+    "t",
+    "u",
+    "v",
+    "w",
+    "x",
+    "y",
+    "z",
+    "braceleft",
+    "bar",
+    "braceright",
+    "asciitilde",
+    "exclamdown",
+    "cent",
+    "sterling",
+    "fraction",
+    "yen",
+    "florin",
+    "section",
+    "currency",
+    "quotesingle",
+    "quotedblleft",
+    "guillemotleft",
+    "guilsinglleft",
+    "guilsinglright",
+    "fi",
+    "fl",
+    "endash",
+    "dagger",
+    "daggerdbl",
+    "periodcenter",
+    "paragraph",
+    "bullet",
+    "quotesinglbase",
+    "quotedblbase",
+    "quotedblright",
+    "guillemotright",
+    "ellipsis",
+    "perthousand",
+    "questiondown",
+    "grave",
+    "acute",
+    "circumflex",
+    "tilde",
+    "macron",
+    "breve",
+    "dotaccent",
+    "dieresis",
+    "ring",
+    "cedilla",
+    "hungarumlaut",
+    "ogonek",
+    "caron",
+    "emdash",
+    "AE",
+    "ordfeminine",
+    "Lslash",
+    "Oslash",
+    "OE",
+    "ordmasculine",
+    "ae",
+    "dotlessi",
+    "Islash",
+    "oslash",
+    "oe",
+    "germandbls",
+    "onesuperior",
+    "logicalnot",
+    "mu",
+    "trademark",
+    "Eth",
+    "onehalf",
+    "plusminus",
+    "Thorn",
+    "onequarter",
+    "divide",
+    "brokenbar",
+    "degree",
+    "thorn",
+    "threequarters",
+    "twosuperior",
+    "registered",
+    "minus",
+    "eth",
+    "multiply",
+    "threesuperior",
+    "copyright",
+    "Aacute",
+    "Acircumflex",
+    "Adieresis",
+    "Agrave",
+    "Aring",
+    "Atilde",
+    "Ccedilla",
+    "Eacute",
+    "Ecircumflex",
+    "Edieresis",
+    "Egrave",
+    "Iacute",
+    "Icircumflex",
+    "Idieresis",
+    "Igrave",
+    "Ntilde",
+    "Oacute",
+    "Ocircumflex",
+    "Odieresis",
+    "Ograve",
+    "Otilde",
+    "Scaron",
+    "Uacute",
+    "Ucircumflex",
+    "Udieresis",
+    "Ugrave",
+    "Yacute",
+    "Ydieresis",
+    "Zcaron",
+    "aacute",
+    "acircumflex",
+    "adieresis",
+    "agrave",
+    "aring",
+    "atilde",
+    "ccedilla",
+    "eacute",
+    "ecircumflex",
+    "edieresis",
+    "egrave",
+    "iacute",
+    "icircumflex",
+    "idieresis",
+    "igrave",
+    "ntilde",
+    "oacute",
+    "ocircumflex",
+    "odieresis",
+    "ograve",
+    "otilde",
+    "scaron",
+    "uacute",
+    "ucircumflex",
+    "udieresis",
+    "ugrave",
+    "yacute",
+    "ydieresis",
+    "zcaron",
+    "exclamsmall",
+    "Hungarumlautsmall",
+    "dollaroldstyle",
+    "dollarsuperior",
+    "ampersandsmall",
+    "Acutesmall",
+    "parenleftsuperior",
+    "parenrightsuperior",
+    "twodotenleader",
+    "onedotenleader",
+    "zerooldstyle",
+    "oneoldstyle",
+    "twooldstyle",
+    "threeoldstyle",
+    "fouroldstyle",
+    "fiveoldstyle",
+    "sixoldstyle",
+    "sevenoldstyle",
+    "eightoldstyle",
+    "nineoldstyle",
+    "commasuperior",
+    "threequartersemdash",
+    "periodsuperior",
+    "questionsmall",
+    "asuperior",
+    "bsuperior",
+    "centsuperior",
+    "dsuperior",
+    "esuperior",
+    "isuperior",
+    "lsuperior",
+    "msuperior",
+    "nsuperior",
+    "osuperior",
+    "rsuperior",
+    "ssuperior",
+    "tsuperior",
+    "ff",
+    "ffi",
+    "ffl",
+    "parenleftinferior",
+    "parenrightinferior",
+    "Circumflexsmall",
+    "hyphensuperior",
+    "Gravesmall",
+    "Asmall",
+    "Bsmall",
+    "Csmall",
+    "Dsmall",
+    "Esmall",
+    "Fsmall",
+    "Gsmall",
+    "Hsmall",
+    "Ismall",
+    "Jsmall",
+    "Ksmall",
+    "Lsmall",
+    "Msmall",
+    "Nsmall",
+    "Osmall",
+    "Psmall",
+    "Qsmall",
+    "Rsmall",
+    "Ssmall",
+    "Tsmall",
+    "Usmall",
+    "Vsmall",
+    "Wsmall",
+    "Xsmall",
+    "Ysmall",
+    "Zsmall",
+    "colonmonetary",
+    "onefitted",
+    "rupiah",
+    "Tildesmall",
+    "exclamdownsmall",
+    "centoldstyle",
+    "Lslashsmall",
+    "Scaronsmall",
+    "Zcaronsmall",
+    "Dieresissmall",
+    "Brevesmall",
+    "Caronsmall",
+    "Dotaccentsmall",
+    "Macronsmall",
+    "figuredash",
+    "hypheninferior",
+    "Ogoneksmall",
+    "Ringsmall",
+    "Cedillasmall",
+    "questiondownsmall",
+    "oneeighth",
+    "threeeighths",
+    "fiveeighths",
+    "seveneighths",
+    "onethird",
+    "twothirds",
+    "zerosuperior",
+    "foursuperior",
+    "fivesuperior",
+    "sixsuperior",
+    "sevensuperior",
+    "eightsuperior",
+    "ninesuperior",
+    "zeroinferior",
+    "oneinferior",
+    "twoinferior",
+    "threeinferior",
+    "fourinferior",
+    "fiveinferior",
+    "sixinferior",
+    "seveninferior",
+    "eightinferior",
+    "nineinferior",
+    "centinferior",
+    "dollarinferior",
+    "periodinferior",
+    "commainferior",
+    "Agravesmall",
+    "Aacutesmall",
+    "Acircumflexsmall",
+    "Atildesmall",
+    "Adieresissmall",
+    "Aringsmall",
+    "AEsmall",
+    "Ccedillasmall",
+    "Egravesmall",
+    "Eacutesmall",
+    "Ecircumflexsmall",
+    "Edieresissmall",
+    "Igravesmall",
+    "Iacutesmall",
+    "Icircumflexsmall",
+    "Idieresissmall",
+    "Ethsmall",
+    "Ntildesmall",
+    "Ogravesmall",
+    "Oacutesmall",
+    "Ocircumflexsmall",
+    "Otildesmall",
+    "Odieresissmall",
+    "OEsmall",
+    "Oslashsmall",
+    "Ugravesmall",
+    "Uacautesmall",
+    "Ucircumflexsmall",
+    "Udieresissmall",
+    "Yacutesmall",
+    "Thornsmall",
+    "Ydieresissmall",
+    "001.000",
+    "001.001",
+    "001.002",
+    "001.003",
+    "Black",
+    "Bold",
+    "Book",
+    "Light",
+    "Medium",
+    "Regular",
+    "Roman",
+    "Semibold",
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+    "AEacute",
+    "Abreve",
+    "Acute",
+    "Alpha",
+    "Alphatonos",
+    "Amacron",
+    "Aogonek",
+    "Aringacute",
+    "Beta",
+    "Caron",
+    "Ccircumflex",
+    "Cdotaccent",
+    "Chi",
+    "Dcaron",
+    "Dcroat",
+    "Dieresis",
+    "DieresisAcute",
+    "DieresisGrave",
+    "Ebreve",
+    "Ecaron",
+    "Edotaccent",
+    "Emacron",
+    "Eng",
+    "Eogonek",
+    "Epsilon",
+    "Epsilontonos",
+    "Eta",
+    "Etatonos",
+    "Euro",
+    "Gamma",
+    "Gcaron",
+    "Gcircumflex",
+    "Gcommaaccent",
+    "Gdotaccent",
+    "Grave",
+    "H18533",
+    "H18543",
+    "H18551",
+    "H22073",
+    "Hbar",
+    "Hcircumflex",
+    "Hungarumlaut",
+    "IJ",
+    "Ibreve",
+    "Idotaccent",
+    "Ifraktur",
+    "Imacron",
+    "Iogonek",
+    "Iota",
+    "Iotadieresis",
+    "Iotatonos",
+    "Itilde",
+    "Jcircumflex",
+    "Kappa",
+    "Kcommaaccent",
+    "LL",
+    "Lacute",
+    "Lambda",
+    "Lcaron",
+    "Lcommaaccent",
+    "Ldot",
+    "Macron",
+    "Mu",
+    "Nacute",
+    "Ncaron",
+    "Ncommaaccent",
+    "Nu",
+    "Obreve",
+    "Ohorn",
+    "Ohungarumlaut",
+    "Omacron",
+    "Omegatonos",
+    "Omicron",
+    "Omicrontonos",
+    "Oslashacute",
+    "Phi",
+    "Pi",
+    "Psi",
+    "Racute",
+    "Rcaron",
+    "Rcommaaccent",
+    "Rfraktur",
+    "Rho",
+    "SF010000",
+    "SF020000",
+    "SF030000",
+    "SF040000",
+    "SF050000",
+    "SF060000",
+    "SF070000",
+    "SF080000",
+    "SF090000",
+    "SF100000",
+    "SF110000",
+    "SF190000",
+    "SF200000",
+    "SF210000",
+    "SF220000",
+    "SF230000",
+    "SF240000",
+    "SF250000",
+    "SF260000",
+    "SF270000",
+    "SF280000",
+    "SF360000",
+    "SF370000",
+    "SF380000",
+    "SF390000",
+    "SF400000",
+    "SF410000",
+    "SF420000",
+    "SF430000",
+    "SF440000",
+    "SF450000",
+    "SF460000",
+    "SF470000",
+    "SF480000",
+    "SF490000",
+    "SF500000",
+    "SF510000",
+    "SF520000",
+    "SF530000",
+    "SF540000",
+    "Sacute",
+    "Scircumflex",
+    "Scommaaccent",
+    "Sigma",
+    "Tau",
+    "Tbar",
+    "Tcaron",
+    "Tcommaaccent",
+    "Tcommaaccent",
+    "Theta",
+    "Uacutesmall",
+    "Ubreve",
+    "Uhorn",
+    "Uhungarumlaut",
+    "Umacron",
+    "Uogonek",
+    "Upsilon",
+    "Upsilon1",
+    "Upsilondieresis",
+    "Upsilontonos",
+    "Uring",
+    "Utilde",
+    "Wacute",
+    "Wcircumflex",
+    "Wdieresis",
+    "Wgrave",
+    "Xi",
+    "Ycircumflex",
+    "Ygrave",
+    "Zacute",
+    "Zdotaccent",
+    "Zeta",
+    "abreve",
+    "acutecomb",
+    "aeacute",
+    "afii00208",
+    "afii10017",
+    "afii10018",
+    "afii10019",
+    "afii10020",
+    "afii10021",
+    "afii10022",
+    "afii10023",
+    "afii10024",
+    "afii10025",
+    "afii10026",
+    "afii10027",
+    "afii10028",
+    "afii10029",
+    "afii10030",
+    "afii10031",
+    "afii10032",
+    "afii10033",
+    "afii10034",
+    "afii10035",
+    "afii10036",
+    "afii10037",
+    "afii10038",
+    "afii10039",
+    "afii10040",
+    "afii10041",
+    "afii10042",
+    "afii10043",
+    "afii10044",
+    "afii10045",
+    "afii10046",
+    "afii10047",
+    "afii10048",
+    "afii10049",
+    "afii10050",
+    "afii10051",
+    "afii10052",
+    "afii10053",
+    "afii10054",
+    "afii10055",
+    "afii10056",
+    "afii10057",
+    "afii10058",
+    "afii10059",
+    "afii10060",
+    "afii10061",
+    "afii10062",
+    "afii10063",
+    "afii10064",
+    "afii10065",
+    "afii10066",
+    "afii10067",
+    "afii10068",
+    "afii10069",
+    "afii10070",
+    "afii10071",
+    "afii10072",
+    "afii10073",
+    "afii10074",
+    "afii10075",
+    "afii10076",
+    "afii10077",
+    "afii10078",
+    "afii10079",
+    "afii10080",
+    "afii10081",
+    "afii10082",
+    "afii10083",
+    "afii10084",
+    "afii10085",
+    "afii10086",
+    "afii10087",
+    "afii10088",
+    "afii10089",
+    "afii10090",
+    "afii10091",
+    "afii10092",
+    "afii10093",
+    "afii10094",
+    "afii10095",
+    "afii10096",
+    "afii10097",
+    "afii10098",
+    "afii10099",
+    "afii10100",
+    "afii10101",
+    "afii10102",
+    "afii10103",
+    "afii10104",
+    "afii10105",
+    "afii10106",
+    "afii10107",
+    "afii10108",
+    "afii10109",
+    "afii10110",
+    "afii10145",
+    "afii10146",
+    "afii10147",
+    "afii10148",
+    "afii10192",
+    "afii10193",
+    "afii10194",
+    "afii10195",
+    "afii10196",
+    "afii10831",
+    "afii10832",
+    "afii10846",
+    "afii299",
+    "afii300",
+    "afii301",
+    "afii57381",
+    "afii57388",
+    "afii57392",
+    "afii57393",
+    "afii57394",
+    "afii57395",
+    "afii57396",
+    "afii57397",
+    "afii57398",
+    "afii57399",
+    "afii57400",
+    "afii57401",
+    "afii57403",
+    "afii57407",
+    "afii57409",
+    "afii57410",
+    "afii57411",
+    "afii57412",
+    "afii57413",
+    "afii57414",
+    "afii57415",
+    "afii57416",
+    "afii57417",
+    "afii57418",
+    "afii57419",
+    "afii57420",
+    "afii57421",
+    "afii57422",
+    "afii57423",
+    "afii57424",
+    "afii57425",
+    "afii57426",
+    "afii57427",
+    "afii57428",
+    "afii57429",
+    "afii57430",
+    "afii57431",
+    "afii57432",
+    "afii57433",
+    "afii57434",
+    "afii57440",
+    "afii57441",
+    "afii57442",
+    "afii57443",
+    "afii57444",
+    "afii57445",
+    "afii57446",
+    "afii57448",
+    "afii57449",
+    "afii57450",
+    "afii57451",
+    "afii57452",
+    "afii57453",
+    "afii57454",
+    "afii57455",
+    "afii57456",
+    "afii57457",
+    "afii57458",
+    "afii57470",
+    "afii57505",
+    "afii57506",
+    "afii57507",
+    "afii57508",
+    "afii57509",
+    "afii57511",
+    "afii57512",
+    "afii57513",
+    "afii57514",
+    "afii57519",
+    "afii57534",
+    "afii57636",
+    "afii57645",
+    "afii57658",
+    "afii57664",
+    "afii57665",
+    "afii57666",
+    "afii57667",
+    "afii57668",
+    "afii57669",
+    "afii57670",
+    "afii57671",
+    "afii57672",
+    "afii57673",
+    "afii57674",
+    "afii57675",
+    "afii57676",
+    "afii57677",
+    "afii57678",
+    "afii57679",
+    "afii57680",
+    "afii57681",
+    "afii57682",
+    "afii57683",
+    "afii57684",
+    "afii57685",
+    "afii57686",
+    "afii57687",
+    "afii57688",
+    "afii57689",
+    "afii57690",
+    "afii57694",
+    "afii57695",
+    "afii57700",
+    "afii57705",
+    "afii57716",
+    "afii57717",
+    "afii57718",
+    "afii57723",
+    "afii57793",
+    "afii57794",
+    "afii57795",
+    "afii57796",
+    "afii57797",
+    "afii57798",
+    "afii57799",
+    "afii57800",
+    "afii57801",
+    "afii57802",
+    "afii57803",
+    "afii57804",
+    "afii57806",
+    "afii57807",
+    "afii57839",
+    "afii57841",
+    "afii57842",
+    "afii57929",
+    "afii61248",
+    "afii61289",
+    "afii61352",
+    "afii61573",
+    "afii61574",
+    "afii61575",
+    "afii61664",
+    "afii63167",
+    "afii64937",
+    "aleph",
+    "alpha",
+    "alphatonos",
+    "amacron",
+    "angle",
+    "angleleft",
+    "angleright",
+    "anoteleia",
+    "aogonek",
+    "aringacute",
+    "arrowboth",
+    "arrowdblboth",
+    "arrowdbldown",
+    "arrowdblleft",
+    "arrowdblright",
+    "arrowdblup",
+    "arrowdown",
+    "arrowhorizex",
+    "arrowleft",
+    "arrowright",
+    "arrowup",
+    "arrowupdn",
+    "arrowupdnbse",
+    "arrowvertex",
+    "asteriskmath",
+    "beta",
+    "block",
+    "braceex",
+    "braceleftbt",
+    "braceleftmid",
+    "bracelefttp",
+    "bracerightbt",
+    "bracerightmid",
+    "bracerighttp",
+    "bracketleftbt",
+    "bracketleftex",
+    "bracketlefttp",
+    "bracketrightbt",
+    "bracketrightex",
+    "bracketrighttp",
+    "carriagereturn",
+    "ccircumflex",
+    "cdotaccent",
+    "chi",
+    "circle",
+    "circlemultiply",
+    "circleplus",
+    "club",
+    "commaaccent",
+    "congruent",
+    "copyrightsans",
+    "copyrightserif",
+    "cyrBreve",
+    "cyrFlex",
+    "cyrbreve",
+    "cyrflex",
+    "dblGrave",
+    "dblgrave",
+    "dcaron",
+    "dcroat",
+    "delta",
+    "diamond",
+    "dieresisacute",
+    "dieresisgrave",
+    "dieresistonos",
+    "dkshade",
+    "dnblock",
+    "dong",
+    "dotbelowcomb",
+    "dotlessj",
+    "dotmath",
+    "ebreve",
+    "ecaron",
+    "edotaccent",
+    "element",
+    "emacron",
+    "emptyset",
+    "eng",
+    "eogonek",
+    "epsilon",
+    "epsilontonos",
+    "equivalence",
+    "estimated",
+    "eta",
+    "etatonos",
+    "exclamdbl",
+    "existential",
+    "female",
+    "filledbox",
+    "filledrect",
+    "gamma",
+    "gcaron",
+    "gcircumflex",
+    "gcommaaccent",
+    "gdotaccent",
+    "gradient",
+    "gravecomb",
+    "hbar",
+    "hcircumflex",
+    "heart",
+    "hookabovecomb",
+    "house",
+    "ibreve",
+    "ij",
+    "imacron",
+    "integralbt",
+    "integralex",
+    "integraltp",
+    "intersection",
+    "invbullet",
+    "invcircle",
+    "invsmileface",
+    "iogonek",
+    "iota",
+    "iotadieresis",
+    "iotadieresistonos",
+    "iotatonos",
+    "itilde",
+    "jcircumflex",
+    "kappa",
+    "kcommaaccent",
+    "kgreenlandic",
+    "lacute",
+    "lambda",
+    "lcaron",
+    "lcommaaccent",
+    "ldot",
+    "lfblock",
+    "lira",
+    "ll",
+    "logicaland",
+    "logicalor",
+    "longs",
+    "ltshade",
+    "male",
+    "minute",
+    "musicalnote",
+    "musicalnotedbl",
+    "nacute",
+    "napostrophe",
+    "ncaron",
+    "ncommaaccent",
+    "notelement",
+    "notsubset",
+    "nu",
+    "obreve",
+    "ohorn",
+    "ohungarumlaut",
+    "omacron",
+    "omega",
+    "omega1",
+    "omegatonos",
+    "omicron",
+    "omicrontonos",
+    "openbullet",
+    "orthogonal",
+    "oslashacute",
+    "parenleftbt",
+    "parenleftex",
+    "parenlefttp",
+    "parenrightbt",
+    "parenrightex",
+    "parenrighttp",
+    "perpendicular",
+    "peseta",
+    "phi",
+    "phi1",
+    "prescription",
+    "propersubset",
+    "propersuperset",
+    "proportional",
+    "psi",
+    "quotereversed",
+    "racute",
+    "radicalex",
+    "rcaron",
+    "rcommaaccent",
+    "reflexsubset",
+    "reflexsuperset",
+    "registersans",
+    "registerserif",
+    "revlogicalnot",
+    "rho",
+    "rtblock",
+    "sacute",
+    "scircumflex",
+    "scommaaccent",
+    "second",
+    "shade",
+    "sigma",
+    "sigma1",
+    "similar",
+    "smileface",
+    "spade",
+    "suchthat",
+    "sun",
+    "tau",
+    "tbar",
+    "tcaron",
+    "tcommaaccent",
+    "tcommaaccent",
+    "therefore",
+    "theta",
+    "theta1",
+    "tildecomb",
+    "tonos",
+    "trademarksans",
+    "trademarkserif",
+    "triagdn",
+    "triaglf",
+    "triagrt",
+    "triagup",
+    "ubreve",
+    "uhorn",
+    "uhungarumlaut",
+    "umacron",
+    "underscoredbl",
+    "union",
+    "universal",
+    "uogonek",
+    "upblock",
+    "upsilon",
+    "upsilondieresis",
+    "upsilondieresistonos",
+    "upsilontonos",
+    "uring",
+    "utilde",
+    "wacute",
+    "wcircumflex",
+    "wdieresis",
+    "weierstrass",
+    "wgrave",
+    "xi",
+    "ycircumflex",
+    "ygrave",
+    "zacute",
+    "zdotaccent",
+    "zeta",
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+    0
+  };
+
+
+  static const char**  t1_standard_glyphs = standard_glyph_names + 31;
+
+
+#define NUM_STD_GLYPHS 391
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+#define NUM_ADOBE_GLYPHS 1032
+#else
+#define NUM_ADOBE_GLYPHS 391
+#endif
+
+
+  static const unsigned short  mac_standard_names[259] =
+  {
+    0,
+    0,
+    1,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    104,
+    9,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    124,
+    66,
+    67,
+    68,
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    173,
+    175,
+    177,
+    178,
+    186,
+    189,
+    195,
+    200,
+    203,
+    201,
+    202,
+    205,
+    204,
+    206,
+    207,
+    210,
+    208,
+    209,
+    211,
+    214,
+    212,
+    213,
+    215,
+    216,
+    219,
+    217,
+    218,
+    220,
+    222,
+    225,
+    223,
+    224,
+    112,
+    161,
+    97,
+    98,
+    102,
+    116,
+    115,
+    149,
+    165,
+    170,
+    153,
+    125,
+    131,
+    2,
+    138,
+    141,
+    3,
+    156,
+    4,
+    5,
+    100,
+    152,
+    6,
+    7,
+    8,
+    9,
+    10,
+    139,
+    143,
+    11,
+    144,
+    147,
+    123,
+    96,
+    151,
+    12,
+    101,
+    13,
+    14,
+    106,
+    120,
+    121,
+    15,
+    174,
+    176,
+    191,
+    142,
+    148,
+    111,
+    137,
+    105,
+    119,
+    65,
+    8,
+    159,
+    16,
+    227,
+    198,
+    99,
+    103,
+    107,
+    108,
+    109,
+    110,
+    113,
+    17,
+    117,
+    118,
+    122,
+    172,
+    179,
+    171,
+    180,
+    181,
+    182,
+    183,
+    184,
+    185,
+    187,
+    188,
+    18,
+    190,
+    193,
+    194,
+    196,
+    145,
+    126,
+    127,
+    128,
+    129,
+    130,
+    132,
+    133,
+    134,
+    135,
+    136,
+    140,
+    19,
+    192,
+    221,
+    199,
+    228,
+    160,
+    154,
+    167,
+    197,
+    226,
+    157,
+    162,
+    166,
+    168,
+    150,
+    164,
+    169,
+    155,
+    158,
+    163,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    0
+  };
+
+
+
+  static const unsigned short  names_to_unicode[1033] =
+  {
+    0,
+    0x0020,
+    0x0021,
+    0x0022,
+    0x0023,
+    0x0024,
+    0x0025,
+    0x0026,
+    0x2019,
+    0x0028,
+    0x0029,
+    0x002A,
+    0x002B,
+    0x002C,
+    0x002D,
+    0x002E,
+    0x002F,
+    0x0030,
+    0x0031,
+    0x0032,
+    0x0033,
+    0x0034,
+    0x0035,
+    0x0036,
+    0x0037,
+    0x0038,
+    0x0039,
+    0x003A,
+    0x003B,
+    0x003C,
+    0x003D,
+    0x003E,
+    0x003F,
+    0x0040,
+    0x0041,
+    0x0042,
+    0x0043,
+    0x0044,
+    0x0045,
+    0x0046,
+    0x0047,
+    0x0048,
+    0x0049,
+    0x004A,
+    0x004B,
+    0x004C,
+    0x004D,
+    0x004E,
+    0x004F,
+    0x0050,
+    0x0051,
+    0x0052,
+    0x0053,
+    0x0054,
+    0x0055,
+    0x0056,
+    0x0057,
+    0x0058,
+    0x0059,
+    0x005A,
+    0x005B,
+    0x005C,
+    0x005D,
+    0x005E,
+    0x005F,
+    0x2018,
+    0x0061,
+    0x0062,
+    0x0063,
+    0x0064,
+    0x0065,
+    0x0066,
+    0x0067,
+    0x0068,
+    0x0069,
+    0x006A,
+    0x006B,
+    0x006C,
+    0x006D,
+    0x006E,
+    0x006F,
+    0x0070,
+    0x0071,
+    0x0072,
+    0x0073,
+    0x0074,
+    0x0075,
+    0x0076,
+    0x0077,
+    0x0078,
+    0x0079,
+    0x007A,
+    0x007B,
+    0x007C,
+    0x007D,
+    0x007E,
+    0x00A1,
+    0x00A2,
+    0x00A3,
+    0x2044,
+    0x00A5,
+    0x0192,
+    0x00A7,
+    0x00A4,
+    0x0027,
+    0x201C,
+    0x00AB,
+    0x2039,
+    0x203A,
+    0xFB01,
+    0xFB02,
+    0x2013,
+    0x2020,
+    0x2021,
+    0,
+    0x00B6,
+    0x2022,
+    0x201A,
+    0x201E,
+    0x201D,
+    0x00BB,
+    0x2026,
+    0x2030,
+    0x00BF,
+    0x0060,
+    0x00B4,
+    0x02C6,
+    0x02DC,
+    0x00AF,
+    0x02D8,
+    0x02D9,
+    0x00A8,
+    0x02DA,
+    0x00B8,
+    0x02DD,
+    0x02DB,
+    0x02C7,
+    0x2014,
+    0x00C6,
+    0x00AA,
+    0x0141,
+    0x00D8,
+    0x0152,
+    0x00BA,
+    0x00E6,
+    0x0131,
+    0,
+    0x00F8,
+    0x0153,
+    0x00DF,
+    0x00B9,
+    0x00AC,
+    0x00B5,
+    0x2122,
+    0x00D0,
+    0x00BD,
+    0x00B1,
+    0x00DE,
+    0x00BC,
+    0x00F7,
+    0x00A6,
+    0x00B0,
+    0x00FE,
+    0x00BE,
+    0x00B2,
+    0x00AE,
+    0x2212,
+    0x00F0,
+    0x00D7,
+    0x00B3,
+    0x00A9,
+    0x00C1,
+    0x00C2,
+    0x00C4,
+    0x00C0,
+    0x00C5,
+    0x00C3,
+    0x00C7,
+    0x00C9,
+    0x00CA,
+    0x00CB,
+    0x00C8,
+    0x00CD,
+    0x00CE,
+    0x00CF,
+    0x00CC,
+    0x00D1,
+    0x00D3,
+    0x00D4,
+    0x00D6,
+    0x00D2,
+    0x00D5,
+    0x0160,
+    0x00DA,
+    0x00DB,
+    0x00DC,
+    0x00D9,
+    0x00DD,
+    0x0178,
+    0x017D,
+    0x00E1,
+    0x00E2,
+    0x00E4,
+    0x00E0,
+    0x00E5,
+    0x00E3,
+    0x00E7,
+    0x00E9,
+    0x00EA,
+    0x00EB,
+    0x00E8,
+    0x00ED,
+    0x00EE,
+    0x00EF,
+    0x00EC,
+    0x00F1,
+    0x00F3,
+    0x00F4,
+    0x00F6,
+    0x00F2,
+    0x00F5,
+    0x0161,
+    0x00FA,
+    0x00FB,
+    0x00FC,
+    0x00F9,
+    0x00FD,
+    0x00FF,
+    0x017E,
+    0xF721,
+    0xF6F8,
+    0xF724,
+    0xF6E4,
+    0xF726,
+    0xF7B4,
+    0x207D,
+    0x207E,
+    0x2025,
+    0x2024,
+    0xF730,
+    0xF731,
+    0xF732,
+    0xF733,
+    0xF734,
+    0xF735,
+    0xF736,
+    0xF737,
+    0xF738,
+    0xF739,
+    0xF6E2,
+    0xF6DE,
+    0xF6E8,
+    0xF73F,
+    0xF6E9,
+    0xF6EA,
+    0xF6E0,
+    0xF6EB,
+    0xF6EC,
+    0xF6ED,
+    0xF6EE,
+    0xF6EF,
+    0x207F,
+    0xF6F0,
+    0xF6F1,
+    0xF6F2,
+    0xF6F3,
+    0xFB00,
+    0xFB03,
+    0xFB04,
+    0x208D,
+    0x208E,
+    0xF6F6,
+    0xF6E6,
+    0xF760,
+    0xF761,
+    0xF762,
+    0xF763,
+    0xF764,
+    0xF765,
+    0xF766,
+    0xF767,
+    0xF768,
+    0xF769,
+    0xF76A,
+    0xF76B,
+    0xF76C,
+    0xF76D,
+    0xF76E,
+    0xF76F,
+    0xF770,
+    0xF771,
+    0xF772,
+    0xF773,
+    0xF774,
+    0xF775,
+    0xF776,
+    0xF777,
+    0xF778,
+    0xF779,
+    0xF77A,
+    0x20A1,
+    0xF6DC,
+    0xF6DD,
+    0xF6FE,
+    0xF7A1,
+    0xF7A2,
+    0xF6F9,
+    0xF6FD,
+    0xF6FF,
+    0xF7A8,
+    0xF6F4,
+    0xF6F5,
+    0xF6F7,
+    0xF7AF,
+    0x2012,
+    0xF6E5,
+    0xF6FB,
+    0xF6FC,
+    0xF7B8,
+    0xF7BF,
+    0x215B,
+    0x215C,
+    0x215D,
+    0x215E,
+    0x2153,
+    0x2154,
+    0x2070,
+    0x2074,
+    0x2075,
+    0x2076,
+    0x2077,
+    0x2078,
+    0x2079,
+    0x2080,
+    0x2081,
+    0x2082,
+    0x2083,
+    0x2084,
+    0x2085,
+    0x2086,
+    0x2087,
+    0x2088,
+    0x2089,
+    0xF6DF,
+    0xF6E3,
+    0xF6E7,
+    0xF6E1,
+    0xF7E0,
+    0xF7E1,
+    0xF7E2,
+    0xF7E3,
+    0xF7E4,
+    0xF7E5,
+    0xF7E6,
+    0xF7E7,
+    0xF7E8,
+    0xF7E9,
+    0xF7EA,
+    0xF7EB,
+    0xF7EC,
+    0xF7ED,
+    0xF7EE,
+    0xF7EF,
+    0xF7F0,
+    0xF7F1,
+    0xF7F2,
+    0xF7F3,
+    0xF7F4,
+    0xF7F5,
+    0xF7F6,
+    0xF6FA,
+    0xF7F8,
+    0xF7F9,
+    0,
+    0xF7FB,
+    0xF7FC,
+    0xF7FD,
+    0xF7FE,
+    0xF7FF,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+    0x01FC,
+    0x0102,
+    0xF6C9,
+    0x0391,
+    0x0386,
+    0x0100,
+    0x0104,
+    0x01FA,
+    0x0392,
+    0xF6CA,
+    0x0108,
+    0x010A,
+    0x03A7,
+    0x010E,
+    0x0110,
+    0xF6CB,
+    0xF6CC,
+    0xF6CD,
+    0x0114,
+    0x011A,
+    0x0116,
+    0x0112,
+    0x014A,
+    0x0118,
+    0x0395,
+    0x0388,
+    0x0397,
+    0x0389,
+    0x20AC,
+    0x0393,
+    0x01E6,
+    0x011C,
+    0x0122,
+    0x0120,
+    0xF6CE,
+    0x25CF,
+    0x25AA,
+    0x25AB,
+    0x25A1,
+    0x0126,
+    0x0124,
+    0xF6CF,
+    0x0132,
+    0x012C,
+    0x0130,
+    0x2111,
+    0x012A,
+    0x012E,
+    0x0399,
+    0x03AA,
+    0x038A,
+    0x0128,
+    0x0134,
+    0x039A,
+    0x0136,
+    0xF6BF,
+    0x0139,
+    0x039B,
+    0x013D,
+    0x013B,
+    0x013F,
+    0xF6D0,
+    0x039C,
+    0x0143,
+    0x0147,
+    0x0145,
+    0x039D,
+    0x014E,
+    0x01A0,
+    0x0150,
+    0x014C,
+    0x038F,
+    0x039F,
+    0x038C,
+    0x01FE,
+    0x03A6,
+    0x03A0,
+    0x03A8,
+    0x0154,
+    0x0158,
+    0x0156,
+    0x211C,
+    0x03A1,
+    0x250C,
+    0x2514,
+    0x2510,
+    0x2518,
+    0x253C,
+    0x252C,
+    0x2534,
+    0x251C,
+    0x2524,
+    0x2500,
+    0x2502,
+    0x2561,
+    0x2562,
+    0x2556,
+    0x2555,
+    0x2563,
+    0x2551,
+    0x2557,
+    0x255D,
+    0x255C,
+    0x255B,
+    0x255E,
+    0x255F,
+    0x255A,
+    0x2554,
+    0x2569,
+    0x2566,
+    0x2560,
+    0x2550,
+    0x256C,
+    0x2567,
+    0x2568,
+    0x2564,
+    0x2565,
+    0x2559,
+    0x2558,
+    0x2552,
+    0x2553,
+    0x256B,
+    0x256A,
+    0x015A,
+    0x015C,
+    0x0218,
+    0x03A3,
+    0x03A4,
+    0x0166,
+    0x0164,
+    0x0162,
+    0x0162,
+    0x0398,
+    0xF7FA,
+    0x016C,
+    0x01AF,
+    0x0170,
+    0x016A,
+    0x0172,
+    0x03A5,
+    0x03D2,
+    0x03AB,
+    0x038E,
+    0x016E,
+    0x0168,
+    0x1E82,
+    0x0174,
+    0x1E84,
+    0x1E80,
+    0x039E,
+    0x0176,
+    0x1EF2,
+    0x0179,
+    0x017B,
+    0x0396,
+    0x0103,
+    0x0301,
+    0x01FD,
+    0x2015,
+    0x0410,
+    0x0411,
+    0x0412,
+    0x0413,
+    0x0414,
+    0x0415,
+    0x0401,
+    0x0416,
+    0x0417,
+    0x0418,
+    0x0419,
+    0x041A,
+    0x041B,
+    0x041C,
+    0x041D,
+    0x041E,
+    0x041F,
+    0x0420,
+    0x0421,
+    0x0422,
+    0x0423,
+    0x0424,
+    0x0425,
+    0x0426,
+    0x0427,
+    0x0428,
+    0x0429,
+    0x042A,
+    0x042B,
+    0x042C,
+    0x042D,
+    0x042E,
+    0x042F,
+    0x0490,
+    0x0402,
+    0x0403,
+    0x0404,
+    0x0405,
+    0x0406,
+    0x0407,
+    0x0408,
+    0x0409,
+    0x040A,
+    0x040B,
+    0x040C,
+    0x040E,
+    0xF6C4,
+    0xF6C5,
+    0x0430,
+    0x0431,
+    0x0432,
+    0x0433,
+    0x0434,
+    0x0435,
+    0x0451,
+    0x0436,
+    0x0437,
+    0x0438,
+    0x0439,
+    0x043A,
+    0x043B,
+    0x043C,
+    0x043D,
+    0x043E,
+    0x043F,
+    0x0440,
+    0x0441,
+    0x0442,
+    0x0443,
+    0x0444,
+    0x0445,
+    0x0446,
+    0x0447,
+    0x0448,
+    0x0449,
+    0x044A,
+    0x044B,
+    0x044C,
+    0x044D,
+    0x044E,
+    0x044F,
+    0x0491,
+    0x0452,
+    0x0453,
+    0x0454,
+    0x0455,
+    0x0456,
+    0x0457,
+    0x0458,
+    0x0459,
+    0x045A,
+    0x045B,
+    0x045C,
+    0x045E,
+    0x040F,
+    0x0462,
+    0x0472,
+    0x0474,
+    0xF6C6,
+    0x045F,
+    0x0463,
+    0x0473,
+    0x0475,
+    0xF6C7,
+    0xF6C8,
+    0x04D9,
+    0x200E,
+    0x200F,
+    0x200D,
+    0x066A,
+    0x060C,
+    0x0660,
+    0x0661,
+    0x0662,
+    0x0663,
+    0x0664,
+    0x0665,
+    0x0666,
+    0x0667,
+    0x0668,
+    0x0669,
+    0x061B,
+    0x061F,
+    0x0621,
+    0x0622,
+    0x0623,
+    0x0624,
+    0x0625,
+    0x0626,
+    0x0627,
+    0x0628,
+    0x0629,
+    0x062A,
+    0x062B,
+    0x062C,
+    0x062D,
+    0x062E,
+    0x062F,
+    0x0630,
+    0x0631,
+    0x0632,
+    0x0633,
+    0x0634,
+    0x0635,
+    0x0636,
+    0x0637,
+    0x0638,
+    0x0639,
+    0x063A,
+    0x0640,
+    0x0641,
+    0x0642,
+    0x0643,
+    0x0644,
+    0x0645,
+    0x0646,
+    0x0648,
+    0x0649,
+    0x064A,
+    0x064B,
+    0x064C,
+    0x064D,
+    0x064E,
+    0x064F,
+    0x0650,
+    0x0651,
+    0x0652,
+    0x0647,
+    0x06A4,
+    0x067E,
+    0x0686,
+    0x0698,
+    0x06AF,
+    0x0679,
+    0x0688,
+    0x0691,
+    0x06BA,
+    0x06D2,
+    0x06D5,
+    0x20AA,
+    0x05BE,
+    0x05C3,
+    0x05D0,
+    0x05D1,
+    0x05D2,
+    0x05D3,
+    0x05D4,
+    0x05D5,
+    0x05D6,
+    0x05D7,
+    0x05D8,
+    0x05D9,
+    0x05DA,
+    0x05DB,
+    0x05DC,
+    0x05DD,
+    0x05DE,
+    0x05DF,
+    0x05E0,
+    0x05E1,
+    0x05E2,
+    0x05E3,
+    0x05E4,
+    0x05E5,
+    0x05E6,
+    0x05E7,
+    0x05E8,
+    0x05E9,
+    0x05EA,
+    0xFB2A,
+    0xFB2B,
+    0xFB4B,
+    0xFB1F,
+    0x05F0,
+    0x05F1,
+    0x05F2,
+    0xFB35,
+    0x05B4,
+    0x05B5,
+    0x05B6,
+    0x05BB,
+    0x05B8,
+    0x05B7,
+    0x05B0,
+    0x05B2,
+    0x05B1,
+    0x05B3,
+    0x05C2,
+    0x05C1,
+    0x05B9,
+    0x05BC,
+    0x05BD,
+    0x05BF,
+    0x05C0,
+    0x02BC,
+    0x2105,
+    0x2113,
+    0x2116,
+    0x202C,
+    0x202D,
+    0x202E,
+    0x200C,
+    0x066D,
+    0x02BD,
+    0x2135,
+    0x03B1,
+    0x03AC,
+    0x0101,
+    0x2220,
+    0x2329,
+    0x232A,
+    0x0387,
+    0x0105,
+    0x01FB,
+    0x2194,
+    0x21D4,
+    0x21D3,
+    0x21D0,
+    0x21D2,
+    0x21D1,
+    0x2193,
+    0xF8E7,
+    0x2190,
+    0x2192,
+    0x2191,
+    0x2195,
+    0x21A8,
+    0xF8E6,
+    0x2217,
+    0x03B2,
+    0x2588,
+    0xF8F4,
+    0xF8F3,
+    0xF8F2,
+    0xF8F1,
+    0xF8FE,
+    0xF8FD,
+    0xF8FC,
+    0xF8F0,
+    0xF8EF,
+    0xF8EE,
+    0xF8FB,
+    0xF8FA,
+    0xF8F9,
+    0x21B5,
+    0x0109,
+    0x010B,
+    0x03C7,
+    0x25CB,
+    0x2297,
+    0x2295,
+    0x2663,
+    0xF6C3,
+    0x2245,
+    0xF8E9,
+    0xF6D9,
+    0xF6D1,
+    0xF6D2,
+    0xF6D4,
+    0xF6D5,
+    0xF6D3,
+    0xF6D6,
+    0x010F,
+    0x0111,
+    0x03B4,
+    0x2666,
+    0xF6D7,
+    0xF6D8,
+    0x0385,
+    0x2593,
+    0x2584,
+    0x20AB,
+    0x0323,
+    0xF6BE,
+    0x22C5,
+    0x0115,
+    0x011B,
+    0x0117,
+    0x2208,
+    0x0113,
+    0x2205,
+    0x014B,
+    0x0119,
+    0x03B5,
+    0x03AD,
+    0x2261,
+    0x212E,
+    0x03B7,
+    0x03AE,
+    0x203C,
+    0x2203,
+    0x2640,
+    0x25A0,
+    0x25AC,
+    0x03B3,
+    0x01E7,
+    0x011D,
+    0x0123,
+    0x0121,
+    0x2207,
+    0x0300,
+    0x0127,
+    0x0125,
+    0x2665,
+    0x0309,
+    0x2302,
+    0x012D,
+    0x0133,
+    0x012B,
+    0x2321,
+    0xF8F5,
+    0x2320,
+    0x2229,
+    0x25D8,
+    0x25D9,
+    0x263B,
+    0x012F,
+    0x03B9,
+    0x03CA,
+    0x0390,
+    0x03AF,
+    0x0129,
+    0x0135,
+    0x03BA,
+    0x0137,
+    0x0138,
+    0x013A,
+    0x03BB,
+    0x013E,
+    0x013C,
+    0x0140,
+    0x258C,
+    0x20A4,
+    0xF6C0,
+    0x2227,
+    0x2228,
+    0x017F,
+    0x2591,
+    0x2642,
+    0x2032,
+    0x266A,
+    0x266B,
+    0x0144,
+    0x0149,
+    0x0148,
+    0x0146,
+    0x2209,
+    0x2284,
+    0x03BD,
+    0x014F,
+    0x01A1,
+    0x0151,
+    0x014D,
+    0x03C9,
+    0x03D6,
+    0x03CE,
+    0x03BF,
+    0x03CC,
+    0x25E6,
+    0x221F,
+    0x01FF,
+    0xF8ED,
+    0xF8EC,
+    0xF8EB,
+    0xF8F8,
+    0xF8F7,
+    0xF8F6,
+    0x22A5,
+    0x20A7,
+    0x03C6,
+    0x03D5,
+    0x211E,
+    0x2282,
+    0x2283,
+    0x221D,
+    0x03C8,
+    0x201B,
+    0x0155,
+    0xF8E5,
+    0x0159,
+    0x0157,
+    0x2286,
+    0x2287,
+    0xF8E8,
+    0xF6DA,
+    0x2310,
+    0x03C1,
+    0x2590,
+    0x015B,
+    0x015D,
+    0x0219,
+    0x2033,
+    0x2592,
+    0x03C3,
+    0x03C2,
+    0x223C,
+    0x263A,
+    0x2660,
+    0x220B,
+    0x263C,
+    0x03C4,
+    0x0167,
+    0x0165,
+    0x0163,
+    0x0163,
+    0x2234,
+    0x03B8,
+    0x03D1,
+    0x0303,
+    0x0384,
+    0xF8EA,
+    0xF6DB,
+    0x25BC,
+    0x25C4,
+    0x25BA,
+    0x25B2,
+    0x016D,
+    0x01B0,
+    0x0171,
+    0x016B,
+    0x2017,
+    0x222A,
+    0x2200,
+    0x0173,
+    0x2580,
+    0x03C5,
+    0x03CB,
+    0x03B0,
+    0x03CD,
+    0x016F,
+    0x0169,
+    0x1E83,
+    0x0175,
+    0x1E85,
+    0x2118,
+    0x1E81,
+    0x03BE,
+    0x0177,
+    0x1EF3,
+    0x017A,
+    0x017C,
+    0x03B6,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+    0
+  };
+
+
+
+  static const unsigned short  t1_standard_encoding[257] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    65,
+    66,
+    67,
+    68,
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    96,
+    97,
+    98,
+    99,
+    100,
+    101,
+    102,
+    103,
+    104,
+    105,
+    106,
+    107,
+    108,
+    109,
+    110,
+    0,
+    111,
+    112,
+    113,
+    114,
+    0,
+    115,
+    116,
+    117,
+    118,
+    119,
+    120,
+    121,
+    122,
+    0,
+    123,
+    0,
+    124,
+    125,
+    126,
+    127,
+    128,
+    129,
+    130,
+    131,
+    0,
+    132,
+    133,
+    0,
+    134,
+    135,
+    136,
+    137,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    138,
+    0,
+    139,
+    0,
+    0,
+    0,
+    0,
+    140,
+    141,
+    142,
+    143,
+    0,
+    0,
+    0,
+    0,
+    0,
+    144,
+    0,
+    0,
+    0,
+    145,
+    0,
+    0,
+    146,
+    147,
+    148,
+    149,
+    0,
+    0,
+    0,
+    0,
+    0
+  };
+
+
+  static const unsigned short  t1_expert_encoding[257] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    229,
+    230,
+    0,
+    231,
+    232,
+    233,
+    234,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    252,
+    0,
+    253,
+    254,
+    255,
+    256,
+    257,
+    0,
+    0,
+    0,
+    258,
+    0,
+    0,
+    259,
+    260,
+    261,
+    262,
+    0,
+    0,
+    263,
+    264,
+    265,
+    0,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    0,
+    270,
+    271,
+    272,
+    273,
+    274,
+    275,
+    276,
+    277,
+    278,
+    279,
+    280,
+    281,
+    282,
+    283,
+    284,
+    285,
+    286,
+    287,
+    288,
+    289,
+    290,
+    291,
+    292,
+    293,
+    294,
+    295,
+    296,
+    297,
+    298,
+    299,
+    300,
+    301,
+    302,
+    303,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    304,
+    305,
+    306,
+    0,
+    0,
+    307,
+    308,
+    309,
+    310,
+    311,
+    0,
+    312,
+    0,
+    0,
+    312,
+    0,
+    0,
+    314,
+    315,
+    0,
+    0,
+    316,
+    317,
+    318,
+    0,
+    0,
+    0,
+    158,
+    155,
+    163,
+    319,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    0,
+    0,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346,
+    347,
+    348,
+    349,
+    350,
+    351,
+    352,
+    353,
+    354,
+    355,
+    356,
+    357,
+    358,
+    359,
+    360,
+    361,
+    362,
+    363,
+    364,
+    365,
+    366,
+    367,
+    368,
+    369,
+    370,
+    371,
+    372,
+    373,
+    374,
+    375,
+    376,
+    377,
+    378,
+    0
+  };
+
+
+/* END */
diff --git a/src/freetype/psnames/rules.mk b/src/freetype/psnames/rules.mk
new file mode 100644 (file)
index 0000000..25552b2
--- /dev/null
@@ -0,0 +1,70 @@
+#
+# FreeType 2 PSNames driver configuration rules
+#
+
+
+# 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.
+
+
+# PSNames driver directory
+#
+PSNAMES_DIR  := $(SRC_)psnames
+PSNAMES_DIR_ := $(PSNAMES_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+PSNAMES_COMPILE := $(FT_COMPILE)
+
+
+# PSNames driver sources (i.e., C files)
+#
+PSNAMES_DRV_SRC := $(PSNAMES_DIR_)psmodule.c
+
+
+# PSNames driver headers
+#
+PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \
+                 $(PSNAMES_DIR_)pstables.h
+
+
+# PSNames driver object(s)
+#
+#   PSNAMES_DRV_OBJ_M is used during `multi' builds
+#   PSNAMES_DRV_OBJ_S is used during `single' builds
+#
+PSNAMES_DRV_OBJ_M := $(PSNAMES_DRV_SRC:$(PSNAMES_DIR_)%.c=$(OBJ_)%.$O)
+PSNAMES_DRV_OBJ_S := $(OBJ_)psnames.$O
+
+# PSNames driver source file for single build
+#
+PSNAMES_DRV_SRC_S := $(PSNAMES_DIR_)psmodule.c
+
+
+# PSNames driver - single object
+#
+$(PSNAMES_DRV_OBJ_S): $(PSNAMES_DRV_SRC_S) $(PSNAMES_DRV_SRC) \
+                      $(FREETYPE_H) $(PSNAMES_DRV_H)
+       $(PSNAMES_COMPILE) $T$@ $(PSNAMES_DRV_SRC_S)
+
+
+# PSNames driver - multiple objects
+#
+$(OBJ_)%.$O: $(PSNAMES_DIR_)%.c $(FREETYPE_H) $(PSNAMES_DRV_H)
+       $(PSNAMES_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(PSNAMES_DRV_OBJ_S)
+DRV_OBJS_M += $(PSNAMES_DRV_OBJ_M)
+
+
+# EOF
diff --git a/src/freetype/raster1/ftraster.c b/src/freetype/raster1/ftraster.c
new file mode 100644 (file)
index 0000000..65d0405
--- /dev/null
@@ -0,0 +1,3300 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftraster.c                                                             */
+/*                                                                         */
+/*    The FreeType glyph rasterizer (body).                                */
+/*                                                                         */
+/*  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 is a rewrite of the FreeType 1.x scan-line converter             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include "ftraster.h"
+#include <freetype/internal/ftcalc.h>      /* for FT_MulDiv() only */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A simple technical note on how the raster works                       */
+  /* -----------------------------------------------                       */
+  /*                                                                       */
+  /*   Converting an outline into a bitmap is achieved in several steps:   */
+  /*                                                                       */
+  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
+  /*       profile is simply an array of scanline intersections on a given */
+  /*       dimension.  A profile's main attributes are                     */
+  /*                                                                       */
+  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */
+  /*                                                                       */
+  /*       o an array of intersection coordinates for each scanline        */
+  /*         between `Ymin' and `Ymax'.                                    */
+  /*                                                                       */
+  /*       o a direction, indicating whether it was built going `up' or    */
+  /*         `down', as this is very important for filling rules.          */
+  /*                                                                       */
+  /*   2 - Sweeping the target map's scanlines in order to compute segment */
+  /*       `spans' which are then filled.  Additionally, this pass         */
+  /*       performs drop-out control.                                      */
+  /*                                                                       */
+  /*   The outline data is parsed during step 1 only.  The profiles are    */
+  /*   built from the bottom of the render pool, used as a stack.  The     */
+  /*   following graphics shows the profile list under construction:       */
+  /*                                                                       */
+  /*     ____________________________________________________________ _ _  */
+  /*    |         |                   |         |                 |        */
+  /*    | profile | coordinates for   | profile | coordinates for |-->     */
+  /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */
+  /*    |_________|___________________|_________|_________________|__ _ _  */
+  /*                                                                       */
+  /*    ^                                                         ^        */
+  /*    |                                                         |        */
+  /*  start of render pool                                       top       */
+  /*                                                                       */
+  /*   The top of the profile stack is kept in the `top' variable.         */
+  /*                                                                       */
+  /*   As you can see, a profile record is pushed on top of the render     */
+  /*   pool, which is then followed by its coordinates/intersections.  If  */
+  /*   a change of direction is detected in the outline, a new profile is  */
+  /*   generated until the end of the outline.                             */
+  /*                                                                       */
+  /*   Note that when all profiles have been generated, the function       */
+  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
+  /*   bottom-most scanline as well as the scanline above its upmost       */
+  /*   boundary.  These positions are called `y-turns' because they (sort  */
+  /*   of) correspond to local extrema.  They are stored in a sorted list  */
+  /*   built from the top of the render pool as a downwards stack:         */
+  /*                                                                       */
+  /*      _ _ _______________________________________                      */
+  /*                            |                    |                     */
+  /*                         <--| sorted list of     |                     */
+  /*                         <--|  extrema scanlines |                     */
+  /*      _ _ __________________|____________________|                     */
+  /*                                                                       */
+  /*                            ^                    ^                     */
+  /*                            |                    |                     */
+  /*                         maxBuff           sizeBuff = end of pool      */
+  /*                                                                       */
+  /*   This list is later used during the sweep phase in order to          */
+  /*   optimize performance (see technical note on the sweep below).       */
+  /*                                                                       */
+  /*   Of course, the raster detects whether the two stacks collide and    */
+  /*   handles the situation propertly.                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  CONFIGURATION MACROS                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* define DEBUG_RASTER if you want to compile a debugging version */
+#define xxxDEBUG_RASTER
+
+  /* The default render pool size in bytes */
+#define RASTER_RENDER_POOL  8192
+
+  /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
+  /* 5-levels anti-aliasing                                                */
+#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
+#define FT_RASTER_OPTION_ANTI_ALIASING
+#endif
+
+  /* The size of the two-lines intermediate bitmap used */
+  /* for anti-aliasing, in bytes.                       */
+#define RASTER_GRAY_LINES  2048
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  OTHER MACROS (do not change)                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_raster
+
+
+#ifdef _STANDALONE_
+
+
+  /* This macro is used to indicate that a function parameter is unused. */
+  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
+  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+  /* ANSI compilers (e.g. LCC).                                          */
+#define FT_UNUSED( x )  (x) = (x)
+
+  /* Disable the tracing mechanism for simplicity -- developers can      */
+  /* activate it easily by redefining these two macros.                  */
+#ifndef FT_ERROR
+#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#define Raster_Err_None          0
+#define Raster_Err_Not_Ini      -1
+#define Raster_Err_Overflow     -2
+#define Raster_Err_Neg_Height   -3
+#define Raster_Err_Invalid      -4
+#define Raster_Err_Unsupported  -5
+
+
+#else /* _STANDALONE_ */
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
+
+#define Raster_Err_None         FT_Err_Ok
+#define Raster_Err_Not_Ini      FT_Err_Raster_Uninitialized
+#define Raster_Err_Overflow     FT_Err_Raster_Overflow
+#define Raster_Err_Neg_Height   FT_Err_Raster_Negative_Height
+#define Raster_Err_Invalid      FT_Err_Invalid_Outline
+#define Raster_Err_Unsupported  FT_Err_Unimplemented_Feature
+
+
+#endif /* _STANDALONE_ */
+
+
+  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
+  /* typically a small value and the result of a*b is known to fit into */
+  /* 32 bits.                                                           */
+#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
+
+  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
+  /* defined in `ftcalc.h'.                                                */
+#define SMulDiv  FT_MulDiv
+
+  /* The rasterizer is a very general purpose component; please leave */
+  /* the following redefinitions there (you never know your target    */
+  /* environment).                                                    */
+
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef NULL
+#define NULL  (void*)0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS  0
+#endif
+
+#ifndef FAILURE
+#define FAILURE  1
+#endif
+
+
+#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
+                        /* Setting this constant to more than 32 is a   */
+                        /* pure waste of space.                         */
+
+#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SIMPLE TYPE DECLARATIONS                                           **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef int             Int;
+  typedef unsigned int    UInt;
+  typedef short           Short;
+  typedef unsigned short  UShort, *PUShort;
+  typedef long            Long, *PLong;
+  typedef unsigned long   ULong;
+
+  typedef unsigned char   Byte, *PByte;
+  typedef char            Bool;
+
+  typedef struct  TPoint_
+  {
+    Long  x;
+    Long  y;
+
+  } TPoint;
+
+
+  typedef enum  TFlow_
+  {
+    Flow_None = 0,
+    Flow_Up   = 1,
+    Flow_Down = -1
+
+  } TFlow;
+
+
+  /* States of each line, arc, and profile */
+  typedef enum  TStates_
+  {
+    Unknown,
+    Ascending,
+    Descending,
+    Flat
+
+  } TStates;
+
+
+  typedef struct TProfile_  TProfile;
+  typedef TProfile*         PProfile;
+
+  struct  TProfile_
+  {
+    FT_F26Dot6  X;           /* current coordinate during sweep        */
+    PProfile    link;        /* link to next profile - various purpose */
+    PLong       offset;      /* start of profile's data in render pool */
+    Int         flow;        /* Profile orientation: Asc/Descending    */
+    Long        height;      /* profile's height in scanlines          */
+    Long        start;       /* profile's starting scanline            */
+
+    UShort      countL;      /* number of lines to step before this    */
+                             /* profile becomes drawable               */
+
+    PProfile    next;        /* next profile in same contour, used     */
+                             /* during drop-out control                */
+  };
+
+  typedef PProfile   TProfileList;
+  typedef PProfile*  PProfileList;
+
+
+  /* Simple record used to implement a stack of bands, required */
+  /* by the sub-banding mechanism                               */
+  typedef struct  TBand_
+  {
+    Short  y_min;   /* band's minimum */
+    Short  y_max;   /* band's maximum */
+
+  } TBand;
+
+
+#define AlignProfileSize \
+          ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) )
+
+
+#ifdef TT_STATIC_RASTER
+
+
+#define RAS_ARGS       /* void */
+#define RAS_ARG        /* void */
+
+#define RAS_VARS       /* void */
+#define RAS_VAR        /* void */
+
+#define FT_UNUSED_RASTER  do ; while ( 0 )
+
+
+#else /* TT_STATIC_RASTER */
+
+
+#define RAS_ARGS       TRaster_Instance*  raster,
+#define RAS_ARG        TRaster_Instance*  raster
+
+#define RAS_VARS       raster,
+#define RAS_VAR        raster
+
+#define FT_UNUSED_RASTER  FT_UNUSED( raster )
+
+
+#endif /* TT_STATIC_RASTER */
+
+
+  typedef struct TRaster_Instance_  TRaster_Instance;
+
+
+  /* prototypes used for sweep function dispatch */
+  typedef void  Function_Sweep_Init( RAS_ARGS Short*  min,
+                                              Short*  max );
+
+  typedef void  Function_Sweep_Span( RAS_ARGS Short       y,
+                                              FT_F26Dot6  x1,
+                                              FT_F26Dot6  x2,
+                                              PProfile    left,
+                                              PProfile    right );
+
+  typedef void  Function_Sweep_Step( RAS_ARG );
+
+
+  /* NOTE: These operations are only valid on 2's complement processors */
+
+#define FLOOR( x )    ( (x) & -ras.precision )
+#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
+#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
+#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
+#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
+
+  /* Note that I have moved the location of some fields in the */
+  /* structure to ensure that the most used variables are used */
+  /* at the top.  Thus, their offset can be coded with less    */
+  /* opcodes, and it results in a smaller executable.          */
+
+  struct  TRaster_Instance_
+  {
+    Int       precision_bits;       /* precision related variables         */
+    Int       precision;
+    Int       precision_half;
+    Long      precision_mask;
+    Int       precision_shift;
+    Int       precision_step;
+    Int       precision_jitter;
+
+    Int       scale_shift;          /* == precision_shift   for bitmaps    */
+                                    /* == precision_shift+1 for pixmaps    */
+
+    PLong     buff;                 /* The profiles buffer                 */
+    PLong     sizeBuff;             /* Render pool size                    */
+    PLong     maxBuff;              /* Profiles buffer size                */
+    PLong     top;                  /* Current cursor in buffer            */
+
+    FT_Error  error;
+
+    Int       numTurns;             /* number of Y-turns in outline        */
+
+    TPoint*   arc;                  /* current Bezier arc pointer          */
+
+    UShort    bWidth;               /* target bitmap width                 */
+    PByte     bTarget;              /* target bitmap buffer                */
+    PByte     gTarget;              /* target pixmap buffer                */
+
+    Long      lastX, lastY, minY, maxY;
+
+    UShort    num_Profs;            /* current number of profiles          */
+
+    Bool      fresh;                /* signals a fresh new profile which   */
+                                    /* 'start' field must be completed     */
+    Bool      joint;                /* signals that the last arc ended     */
+                                    /* exactly on a scanline.  Allows      */
+                                    /* removal of doublets                 */
+    PProfile  cProfile;             /* current profile                     */
+    PProfile  fProfile;             /* head of linked list of profiles     */
+    PProfile  gProfile;             /* contour's first profile in case     */
+                                    /* of impact                           */
+
+    TStates   state;                /* rendering state                     */
+
+    FT_Bitmap   target;             /* description of target bit/pixmap    */
+    FT_Outline  outline;
+
+    Long      traceOfs;             /* current offset in target bitmap     */
+    Long      traceG;               /* current offset in target pixmap     */
+
+    Short     traceIncr;            /* sweep's increment in target bitmap  */
+
+    Short     gray_min_x;           /* current min x during gray rendering */
+    Short     gray_max_x;           /* current max x during gray rendering */
+
+    /* dispatch variables */
+
+    Function_Sweep_Init*  Proc_Sweep_Init;
+    Function_Sweep_Span*  Proc_Sweep_Span;
+    Function_Sweep_Span*  Proc_Sweep_Drop;
+    Function_Sweep_Step*  Proc_Sweep_Step;
+
+    Byte      dropOutControl;       /* current drop_out control method     */
+
+    Bool      second_pass;          /* indicates wether a horizontal pass  */
+                                    /* should be performed to control      */
+                                    /* drop-out accurately when calling    */
+                                    /* Render_Glyph.  Note that there is   */
+                                    /* no horizontal pass during gray      */
+                                    /* rendering.                          */
+
+    TPoint    arcs[2 * MaxBezier + 1]; /* The Bezier stack                 */
+
+    TBand     band_stack[16];       /* band stack used for sub-banding     */
+    Int       band_top;             /* band stack top                      */
+
+    Int       count_table[256];     /* Look-up table used to quickly count */
+                                    /* set bits in a gray 2x2 cell         */
+
+    void*     memory;
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    Byte      grays[5];             /* Palette of gray levels used for     */
+                                    /* render.                             */
+
+    Byte      gray_lines[RASTER_GRAY_LINES];
+                                /* Intermediate table used to render the   */
+                                /* graylevels pixmaps.                     */
+                                /* gray_lines is a buffer holding two      */
+                                /* monochrome scanlines                    */
+
+    Short     gray_width;       /* width in bytes of one monochrome        */
+                                /* intermediate scanline of gray_lines.    */
+                                /* Each gray pixel takes 2 bits long there */
+
+                       /* The gray_lines must hold 2 lines, thus with size */
+                       /* in bytes of at least `gray_width*2'.             */
+
+#endif /* FT_RASTER_ANTI_ALIASING */
+
+#if 0
+    PByte       flags;              /* current flags table                 */
+    PUShort     outs;               /* current outlines table              */
+    FT_Vector*  coords;
+
+    UShort      nPoints;            /* number of points in current glyph   */
+    Short       nContours;          /* number of contours in current glyph */
+#endif
+
+  };
+
+
+#ifdef FT_CONFIG_OPTION_STATIC_RASTER
+
+  static TRaster_Instance  cur_ras;
+#define ras  cur_ras
+
+#else
+
+#define ras  (*raster)
+
+#endif /* FT_CONFIG_OPTION_STATIC_RASTER */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  PROFILES COMPUTATION                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_High_Precision                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets precision variables according to param flag.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    High :: Set to True for high precision (typically for ppem < 18),  */
+  /*            false otherwise.                                           */
+  /*                                                                       */
+  static
+  void  Set_High_Precision( RAS_ARGS Int  High )
+  {
+    if ( High )
+    {
+      ras.precision_bits   = 10;
+      ras.precision_step   = 128;
+      ras.precision_jitter = 24;
+    }
+    else
+    {
+      ras.precision_bits   = 6;
+      ras.precision_step   = 32;
+      ras.precision_jitter = 2;
+    }
+
+    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+
+    ras.precision       = 1L << ras.precision_bits;
+    ras.precision_half  = ras.precision / 2;
+    ras.precision_shift = ras.precision_bits - Pixel_Bits;
+    ras.precision_mask  = -ras.precision;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    New_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new profile in the render pool.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    aState :: The state/orientation of the new profile.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  New_Profile( RAS_ARGS TStates  aState )
+  {
+    if ( !ras.fProfile )
+    {
+      ras.cProfile  = (PProfile)ras.top;
+      ras.fProfile  = ras.cProfile;
+      ras.top      += AlignProfileSize;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    switch ( aState )
+    {
+    case Ascending:
+      ras.cProfile->flow = Flow_Up;
+      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    case Descending:
+      ras.cProfile->flow = Flow_Down;
+      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    default:
+      FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    ras.cProfile->start  = 0;
+    ras.cProfile->height = 0;
+    ras.cProfile->offset = ras.top;
+    ras.cProfile->link   = (PProfile)0;
+    ras.cProfile->next   = (PProfile)0;
+
+    if ( !ras.gProfile )
+      ras.gProfile = ras.cProfile;
+
+    ras.state = aState;
+    ras.fresh = TRUE;
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    End_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes the current profile.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
+  /*                                                                       */
+  static
+  Bool  End_Profile( RAS_ARG )
+  {
+    Long      h;
+    PProfile  oldProfile;
+
+
+    h = ras.top - ras.cProfile->offset;
+
+    if ( h < 0 )
+    {
+      FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+      ras.error = Raster_Err_Neg_Height;
+      return FAILURE;
+    }
+
+    if ( h > 0 )
+    {
+      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
+                  (long)ras.cProfile, ras.cProfile->start, h ));
+
+      oldProfile           = ras.cProfile;
+      ras.cProfile->height = h;
+      ras.cProfile         = (PProfile)ras.top;
+
+      ras.top             += AlignProfileSize;
+
+      ras.cProfile->height = 0;
+      ras.cProfile->offset = ras.top;
+      oldProfile->next     = ras.cProfile;
+      ras.num_Profs++;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      FT_TRACE1(( "overflow in End_Profile\n" ));
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Insert_Y_Turn                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inserts a salient into the sorted list placed on top of the render */
+  /*    pool.                                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    New y scanline position.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static
+  Bool  Insert_Y_Turn( RAS_ARGS Int  y )
+  {
+    PLong     y_turns;
+    Int       y2, n;
+
+
+    n       = ras.numTurns - 1;
+    y_turns = ras.sizeBuff - ras.numTurns;
+
+    /* look for first y value that is <= */
+    while ( n >= 0 && y < y_turns[n] )
+      n--;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n >= 0 && y > y_turns[n] )
+      while ( n >= 0 )
+      {
+        y2 = y_turns[n];
+        y_turns[n] = y;
+        y = y2;
+        n--;
+      }
+
+    if ( n < 0 )
+    {
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = Raster_Err_Overflow;
+        return FAILURE;
+      }
+      ras.maxBuff--;
+      ras.numTurns++;
+      ras.sizeBuff[-ras.numTurns] = y;
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Finalize_Profile_Table                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adjusts all links in the profiles list.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static
+  Bool  Finalize_Profile_Table( RAS_ARG )
+  {
+    Int       bottom, top;
+    UShort    n;
+    PProfile  p;
+
+
+    n = ras.num_Profs;
+
+    if ( n > 1 )
+    {
+      p = ras.fProfile;
+      while ( n > 0 )
+      {
+        if ( n > 1 )
+          p->link = (PProfile)( p->offset + p->height );
+        else
+          p->link = NULL;
+
+        switch ( p->flow )
+        {
+        case Flow_Down:
+          bottom     = p->start - p->height+1;
+          top        = p->start;
+          p->start   = bottom;
+          p->offset += p->height - 1;
+          break;
+
+        case Flow_Up:
+        default:
+          bottom = p->start;
+          top    = p->start + p->height - 1;
+        }
+
+        if ( Insert_Y_Turn( RAS_VARS bottom )   ||
+             Insert_Y_Turn( RAS_VARS top + 1 )  )
+          return FAILURE;
+
+        p = p->link;
+        n--;
+      }
+    }
+    else
+      ras.fProfile = NULL;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Conic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides one conic Bezier into two joint sub-arcs in the Bezier  */
+  /*    stack.                                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    None (subdivided Bezier is taken from the top of the stack).       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
+  /*    loop that should be optimized to hell to get the best performance. */
+  /*                                                                       */
+  static
+  void  Split_Conic( TPoint*  base )
+  {
+    Long  a, b;
+
+
+    base[4].x = base[2].x;
+    b = base[1].x;
+    a = base[3].x = ( base[2].x + b ) / 2;
+    b = base[1].x = ( base[0].x + b ) / 2;
+    base[2].x = ( a + b ) / 2;
+
+    base[4].y = base[2].y;
+    b = base[1].y;
+    a = base[3].y = ( base[2].y + b ) / 2;
+    b = base[1].y = ( base[0].y + b ) / 2;
+    base[2].y = ( a + b ) / 2;
+
+    /* hand optimized.  gcc doesn't seem to be too good at common      */
+    /* expression substitution and instruction scheduling ;-)          */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Cubic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+  /*    Bezier stack.                                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of the component.  It is one of _the_   */
+  /*    inner loops that should be optimized like hell to get the best     */
+  /*    performance.                                                       */
+  /*                                                                       */
+  static
+  void  Split_Cubic( TPoint*  base )
+  {
+    Long  a, b, c, d;
+
+
+    base[6].x = base[3].x;
+    c = base[1].x;
+    d = base[2].x;
+    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
+    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].x = a = ( a + c + 1 ) >> 1;
+    base[4].x = b = ( b + c + 1 ) >> 1;
+    base[3].x = ( a + b + 1 ) >> 1;
+
+    base[6].y = base[3].y;
+    c = base[1].y;
+    d = base[2].y;
+    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
+    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].y = a = ( a + c + 1 ) >> 1;
+    base[4].y = b = ( b + c + 1 ) >> 1;
+    base[3].y = ( a + b + 1 ) >> 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Up                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending line segment and stores */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Line_Up( RAS_ARGS Long  x1,
+                          Long  y1,
+                          Long  x2,
+                          Long  y2,
+                          Long  miny,
+                          Long  maxy )
+  {
+    Long   Dx, Dy;
+    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
+    Long   Ix, Rx, Ax;
+
+    PLong  top;
+
+
+    Dx = x2 - x1;
+    Dy = y2 - y1;
+
+    if ( Dy <= 0 || y2 < miny || y1 > maxy )
+      return SUCCESS;
+
+    if ( y1 < miny )
+    {
+      /* Take care: miny-y1 can be a very large value; we use     */
+      /*            a slow MulDiv function to avoid clipping bugs */
+      x1 += SMulDiv( Dx, miny - y1, Dy );
+      e1  = TRUNC( miny );
+      f1  = 0;
+    }
+    else
+    {
+      e1 = TRUNC( y1 );
+      f1 = FRAC( y1 );
+    }
+
+    if ( y2 > maxy )
+    {
+      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
+      e2  = TRUNC( maxy );
+      f2  = 0;
+    }
+    else
+    {
+      e2 = TRUNC( y2 );
+      f2 = FRAC( y2 );
+    }
+
+    if ( f1 > 0 )
+    {
+      if ( e1 == e2 )
+        return SUCCESS;
+      else
+      {
+        x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+        e1 += 1;
+      }
+    }
+    else
+      if ( ras.joint )
+      {
+        ras.top--;
+        ras.joint = FALSE;
+      }
+
+    ras.joint = ( f2 == 0 );
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = e1;
+      ras.fresh           = FALSE;
+    }
+
+    size = e2 - e1 + 1;
+    if ( ras.top + size >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    if ( Dx > 0 )
+    {
+      Ix = ( ras.precision * Dx ) / Dy;
+      Rx = ( ras.precision * Dx ) % Dy;
+      Dx = 1;
+    }
+    else
+    {
+      Ix = -( ( ras.precision * -Dx ) / Dy );
+      Rx =    ( ras.precision * -Dx ) % Dy;
+      Dx = -1;
+    }
+
+    Ax  = -Dy;
+    top = ras.top;
+
+    while ( size > 0 )
+    {
+      *top++ = x1;
+
+      x1 += Ix;
+      Ax += Rx;
+      if ( Ax >= 0 )
+      {
+        Ax -= Dy;
+        x1 += Dx;
+      }
+      size--;
+    }
+
+    ras.top = top;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Down                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending line segment and       */
+  /*    stores them in the render pool.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Line_Down( RAS_ARGS Long  x1,
+                            Long  y1,
+                            Long  x2,
+                            Long  y2,
+                            Long  miny,
+                            Long  maxy )
+  {
+    Bool  result, fresh;
+
+
+    fresh  = ras.fresh;
+
+    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    return result;
+  }
+
+
+  /* A function type describing the functions used to split Bezier arcs */
+  typedef void  (*TSplitter)( TPoint*  base );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Up                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending Bezier arc and stores   */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Bezier_Up( RAS_ARGS Int        degree,
+                            TSplitter  splitter,
+                            Long       miny,
+                            Long       maxy )
+  {
+    Long   y1, y2, e, e2, e0;
+    Short  f1;
+
+    TPoint*  arc;
+    TPoint*  start_arc;
+
+    PLong top;
+
+
+    arc = ras.arc;
+    y1  = arc[degree].y;
+    y2  = arc[0].y;
+    top = ras.top;
+
+    if ( y2 < miny || y1 > maxy )
+      goto Fin;
+
+    e2 = FLOOR( y2 );
+
+    if ( e2 > maxy )
+      e2 = maxy;
+
+    e0 = miny;
+
+    if ( y1 < miny )
+      e = miny;
+    else
+    {
+      e  = CEILING( y1 );
+      f1 = FRAC( y1 );
+      e0 = e;
+
+      if ( f1 == 0 )
+      {
+        if ( ras.joint )
+        {
+          top--;
+          ras.joint = FALSE;
+        }
+
+        *top++ = arc[degree].x;
+
+        e += ras.precision;
+      }
+    }
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = TRUNC( e0 );
+      ras.fresh = FALSE;
+    }
+
+    if ( e2 < e )
+      goto Fin;
+
+    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+    {
+      ras.top   = top;
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    start_arc = arc;
+
+    while ( arc >= start_arc && e <= e2 )
+    {
+      ras.joint = FALSE;
+
+      y2 = arc[0].y;
+
+      if ( y2 > e )
+      {
+        y1 = arc[degree].y;
+        if ( y2 - y1 >= ras.precision_step )
+        {
+          splitter( arc );
+          arc += degree;
+        }
+        else
+        {
+          *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+                                            e - y1, y2 - y1 );
+          arc -= degree;
+          e   += ras.precision;
+        }
+      }
+      else
+      {
+        if ( y2 == e )
+        {
+          ras.joint  = TRUE;
+          *top++     = arc[0].x;
+
+          e += ras.precision;
+        }
+        arc -= degree;
+      }
+    }
+
+  Fin:
+    ras.top  = top;
+    ras.arc -= degree;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Down                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending Bezier arc and stores  */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static
+  Bool  Bezier_Down( RAS_ARGS Int        degree,
+                              TSplitter  splitter,
+                              Long       miny,
+                              Long       maxy )
+  {
+    TPoint*  arc = ras.arc;
+    Bool     result, fresh;
+
+
+    arc[0].y = -arc[0].y;
+    arc[1].y = -arc[1].y;
+    arc[2].y = -arc[2].y;
+    if ( degree > 2 )
+      arc[3].y = -arc[3].y;
+
+    fresh = ras.fresh;
+
+    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    arc[0].y = -arc[0].y;
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_To                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new line segment and adjusts Profiles list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   x :: The x-coordinate of the segment's end point (its start point   */
+  /*        is stored in `LastX').                                         */
+  /*                                                                       */
+  /*   y :: The y-coordinate of the segment's end point (its start point   */
+  /*        is stored in `LastY').                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  Line_To( RAS_ARGS Long  x,
+                          Long  y )
+  {
+    /* First, detect a change of direction */
+
+    switch ( ras.state )
+    {
+    case Unknown:
+      if ( y > ras.lastY )
+      {
+        if ( New_Profile( RAS_VARS Ascending ) )
+          return FAILURE;
+      }
+      else
+      {
+        if ( y < ras.lastY )
+          if ( New_Profile( RAS_VARS Descending ) )
+            return FAILURE;
+      }
+      break;
+
+    case Ascending:
+      if ( y < ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )             ||
+             New_Profile( RAS_VARS Descending ) )
+          return FAILURE;
+      }
+      break;
+
+    case Descending:
+      if ( y > ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )            ||
+             New_Profile( RAS_VARS Ascending ) )
+          return FAILURE;
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    /* Then compute the lines */
+
+    switch ( ras.state )
+    {
+    case Ascending:
+      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
+                    x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    case Descending:
+      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+                      x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    default:
+      ;
+    }
+
+    ras.lastX = x;
+    ras.lastY = y;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Conic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new conic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx :: The x-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   cy :: The y-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
+  /*         stored in `LastX').                                           */
+  /*                                                                       */
+  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
+  /*         stored in `LastY').                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  Conic_To( RAS_ARGS Long  cx,
+                           Long  cy,
+                           Long  x,
+                           Long  y )
+  {
+    Long     y1, y2, y3, x3, ymin, ymax;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[2].x = ras.lastX;
+    ras.arc[2].y = ras.lastY;
+    ras.arc[1].x = cx; ras.arc[1].y = cy;
+    ras.arc[0].x = x;  ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[2].y;
+      y2 = ras.arc[1].y;
+      y3 = ras.arc[0].y;
+      x3 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y3 )
+      {
+        ymin = y1;
+        ymax = y3;
+      }
+      else
+      {
+        ymin = y3;
+        ymax = y1;
+      }
+
+      if ( y2 < ymin || y2 > ymax )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Conic( ras.arc );
+        ras.arc += 2;
+      }
+      else if ( y1 == y3 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 2;
+      }
+      else
+      {
+        /* the arc is y-monotonous, either ascending or descending */
+        /* detect a change of direction                            */
+        state_bez = y1 < y3 ? Ascending : Descending;
+        if ( ras.state != state_bez )
+        {
+          /* finalize current profile if any */
+          if ( ras.state != Unknown   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          /* create a new profile */
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* now call the appropriate routine */
+        if ( state_bez == Ascending )
+        {
+          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x3;
+    ras.lastY = y3;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Cubic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new cubic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
+  /*          stored in `LastX').                                          */
+  /*                                                                       */
+  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
+  /*          stored in `LastY').                                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static
+  Bool  Cubic_To( RAS_ARGS Long  cx1,
+                           Long  cy1,
+                           Long  cx2,
+                           Long  cy2,
+                           Long  x,
+                           Long  y )
+  {
+    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[3].x = ras.lastX;
+    ras.arc[3].y = ras.lastY;
+    ras.arc[2].x = cx1; ras.arc[2].y = cy1;
+    ras.arc[1].x = cx2; ras.arc[1].y = cy2;
+    ras.arc[0].x = x;   ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[3].y;
+      y2 = ras.arc[2].y;
+      y3 = ras.arc[1].y;
+      y4 = ras.arc[0].y;
+      x4 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y4 )
+      {
+        ymin1 = y1;
+        ymax1 = y4;
+      }
+      else
+      {
+        ymin1 = y4;
+        ymax1 = y1;
+      }
+
+      if ( y2 <= y3 )
+      {
+        ymin2 = y2;
+        ymax2 = y3;
+      }
+      else
+      {
+        ymin2 = y3;
+        ymax2 = y2;
+      }
+
+      if ( ymin2 < ymin1 || ymax2 > ymax1 )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Cubic( ras.arc );
+        ras.arc += 3;
+      }
+      else if ( y1 == y4 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 3;
+      }
+      else
+      {
+        state_bez = ( y1 <= y4 ) ? Ascending : Descending;
+
+        /* detect a change of direction */
+        if ( ras.state != state_bez )
+        {
+          if ( ras.state != Unknown   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* compute intersections */
+        if ( state_bez == Ascending )
+        {
+          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x4;
+    ras.lastY = y4;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+#undef  SWAP_
+#define SWAP_( x, y )  do                \
+                       {                 \
+                         Long  swap = x; \
+                                         \
+                                         \
+                         x = y;          \
+                         y = swap;       \
+                       } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Decompose_Curve                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Scans the outline arays in order to emit individual segments and   */
+  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
+  /*    weird cases, like when the first point is off the curve, or when   */
+  /*    there are simply no `on' points in the contour!                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    first   :: The index of the first point in the contour.            */
+  /*                                                                       */
+  /*    last    :: The index of the last point in the contour.             */
+  /*                                                                       */
+  /*    flipped :: If set, flip the direction of the curve.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on error.                              */
+  /*                                                                       */
+  static
+  Bool  Decompose_Curve( RAS_ARGS UShort  first,
+                                  UShort  last,
+                                  int     flipped )
+  {
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  points;
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    char        tag;       /* current point's state           */
+
+
+    points = ras.outline.points;
+    limit  = points + last;
+
+    v_start.x = SCALED( points[first].x );
+    v_start.y = SCALED( points[first].y );
+    v_last.x  = SCALED( points[last].x );
+    v_last.y  = SCALED( points[last].y );
+
+    if ( flipped )
+    {
+      SWAP_( v_start.x, v_start.y );
+      SWAP_( v_last.x, v_last.y );
+    }
+
+    v_control = v_start;
+
+    point = points + first;
+    tags  = ras.outline.tags  + first;
+    tag   = FT_CURVE_TAG( tags[0] );
+
+    /* A contour cannot start with a cubic control point! */
+    if ( tag == FT_Curve_Tag_Cubic )
+      goto Invalid_Outline;
+
+    /* check first point to determine origin */
+    if ( tag == FT_Curve_Tag_Conic )
+    {
+      /* first point is conic control.  Yes, this happens. */
+      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_Curve_Tag_On )
+      {
+        /* start at last point if it is on the curve */
+        v_start = v_last;
+        limit--;
+      }
+      else
+      {
+        /* if both first and last points are conic,         */
+        /* start at their middle and record its position    */
+        /* for closure                                      */
+        v_start.x = ( v_start.x + v_last.x ) / 2;
+        v_start.y = ( v_start.y + v_last.y ) / 2;
+
+        v_last = v_start;
+      }
+      point--;
+      tags--;
+    }
+
+    ras.lastX = v_start.x;
+    ras.lastY = v_start.y;
+
+    while ( point < limit )
+    {
+      point++;
+      tags++;
+
+      tag = FT_CURVE_TAG( tags[0] );
+
+      switch ( tag )
+      {
+      case FT_Curve_Tag_On:  /* emit a single line_to */
+        {
+          Long  x, y;
+
+
+          x = SCALED( point->x );
+          y = SCALED( point->y );
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( Line_To( RAS_VARS x, y ) )
+            goto Fail;
+          continue;
+        }
+
+      case FT_Curve_Tag_Conic:  /* consume conic arcs */
+        v_control.x = SCALED( point[0].x );
+        v_control.y = SCALED( point[0].y );
+
+        if ( flipped )
+          SWAP_( v_control.x, v_control.y );
+
+      Do_Conic:
+        if ( point < limit )
+        {
+          FT_Vector  v_middle;
+          Long       x, y;
+
+
+          point++;
+          tags++;
+          tag = FT_CURVE_TAG( tags[0] );
+
+          x = SCALED( point[0].x );
+          y = SCALED( point[0].y );
+
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( tag == FT_Curve_Tag_On )
+          {
+            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( tag != FT_Curve_Tag_Conic )
+            goto Invalid_Outline;
+
+          v_middle.x = ( v_control.x + x ) / 2;
+          v_middle.y = ( v_control.y + y ) / 2;
+
+          if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                  v_middle.x,  v_middle.y ) )
+            goto Fail;
+
+          v_control.x = x;
+          v_control.y = y;
+
+          goto Do_Conic;
+        }
+
+        if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                v_start.x,   v_start.y ) )
+          goto Fail;
+
+        goto Close;
+
+      default:  /* FT_Curve_Tag_Cubic */
+        {
+          Long  x1, y1, x2, y2, x3, y3;
+
+
+          if ( point + 1 > limit                             ||
+               FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+            goto Invalid_Outline;
+
+          point += 2;
+          tags  += 2;
+
+          x1 = SCALED( point[-2].x );
+          y1 = SCALED( point[-2].y );
+          x2 = SCALED( point[-1].x );
+          y2 = SCALED( point[-1].y );
+          x3 = SCALED( point[ 0].x );
+          y3 = SCALED( point[ 0].y );
+
+          if ( flipped )
+          {
+            SWAP_( x1, y1 );
+            SWAP_( x2, y2 );
+            SWAP_( x3, y3 );
+          }
+
+          if ( point <= limit )
+          {
+            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
+            goto Fail;
+          goto Close;
+        }
+      }
+    }
+
+    /* close the contour with a line segment */
+    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
+      goto Fail;
+
+  Close:
+    return SUCCESS;
+
+  Invalid_Outline:
+    ras.error = Raster_Err_Invalid;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Convert_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a glyph into a series of segments and arcs and makes a    */
+  /*    profiles list with them.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of curve.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE if any error was encountered during    */
+  /*    rendering.                                                         */
+  /*                                                                       */
+  static
+  Bool  Convert_Glyph( RAS_ARGS int  flipped )
+  {
+    Short     i;
+    UShort    start;
+
+    PProfile  lastProfile;
+
+
+    ras.fProfile = NULL;
+    ras.joint    = FALSE;
+    ras.fresh    = FALSE;
+
+    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
+
+    ras.numTurns = 0;
+
+    ras.cProfile         = (PProfile)ras.top;
+    ras.cProfile->offset = ras.top;
+    ras.num_Profs        = 0;
+
+    start = 0;
+
+    for ( i = 0; i < ras.outline.n_contours; i++ )
+    {
+      ras.state    = Unknown;
+      ras.gProfile = NULL;
+
+      if ( Decompose_Curve( RAS_VARS start, ras.outline.contours[i], flipped ) )
+        return FAILURE;
+
+      start = ras.outline.contours[i] + 1;
+
+      /* We must now see whether the extreme arcs join or not */
+      if ( FRAC( ras.lastY ) == 0 &&
+           ras.lastY >= ras.minY  &&
+           ras.lastY <= ras.maxY  )
+        if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+          ras.top--;
+        /* Note that ras.gProfile can be nil if the contour was too small */
+        /* to be drawn.                                                   */
+
+      lastProfile = ras.cProfile;
+      if ( End_Profile( RAS_VAR ) )
+        return FAILURE;
+
+      /* close the `next profile in contour' linked list */
+      if ( ras.gProfile )
+        lastProfile->next = ras.gProfile;
+    }
+
+    if ( Finalize_Profile_Table( RAS_VAR ) )
+      return FAILURE;
+
+    return ( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Init_Linked                                                          */
+  /*                                                                       */
+  /*    Initializes an empty linked list.                                  */
+  /*                                                                       */
+  static
+  void  Init_Linked( TProfileList*  l )
+  {
+    *l = NULL;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  InsNew                                                               */
+  /*                                                                       */
+  /*    Inserts a new profile in a linked list.                            */
+  /*                                                                       */
+  static
+  void  InsNew( PProfileList  list,
+                PProfile      profile )
+  {
+    PProfile  *old, current;
+    Long       x;
+
+
+    old     = list;
+    current = *old;
+    x       = profile->X;
+
+    while ( current )
+    {
+      if ( x < current->X )
+        break;
+      old     = &current->link;
+      current = *old;
+    }
+
+    profile->link = current;
+    *old          = profile;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  DelOld                                                               */
+  /*                                                                       */
+  /*    Removes an old profile from a linked list.                         */
+  /*                                                                       */
+  static
+  void  DelOld( PProfileList  list,
+                PProfile      profile )
+  {
+    PProfile  *old, current;
+
+
+    old     = list;
+    current = *old;
+
+    while ( current )
+    {
+      if ( current == profile )
+      {
+        *old = current->link;
+        return;
+      }
+
+      old     = &current->link;
+      current = *old;
+    }
+
+    /* we should never get there, unless the profile was not part of */
+    /* the list.                                                     */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Update                                                               */
+  /*                                                                       */
+  /*    Update all X offsets of a drawing list.                            */
+  /*                                                                       */
+  static
+  void  Update( PProfile  first )
+  {
+    PProfile  current = first;
+
+
+    while ( current )
+    {
+      current->X       = *current->offset;
+      current->offset += current->flow;
+      current->height--;
+      current = current->link;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Sort                                                                 */
+  /*                                                                       */
+  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
+  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
+  /*    and simple.                                                        */
+  /*                                                                       */
+  static
+  void  Sort( PProfileList  list )
+  {
+    PProfile  *old, current, next;
+
+
+    /* First, set the new X coordinate of each profile */
+    Update( *list );
+
+    /* Then sort them */
+    old     = list;
+    current = *old;
+
+    if ( !current )
+      return;
+
+    next = current->link;
+
+    while ( next )
+    {
+      if ( current->X <= next->X )
+      {
+        old     = &current->link;
+        current = *old;
+
+        if ( !current )
+          return;
+      }
+      else
+      {
+        *old          = next;
+        current->link = next->link;
+        next->link    = current;
+
+        old     = list;
+        current = *old;
+      }
+
+      next = current->link;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Sweep Procedure Set                                         */
+  /*                                                                       */
+  /*  These four routines are used during the vertical black/white sweep   */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  void  Vertical_Sweep_Init( RAS_ARGS Short*  min,
+                                      Short*  max )
+  {
+    Long  pitch = ras.target.pitch;
+
+    FT_UNUSED( max );
+
+
+    ras.traceIncr = (Short)-pitch;
+    ras.traceOfs  = -*min * pitch;
+    if ( pitch > 0 )
+      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
+
+    ras.gray_min_x = 0;
+    ras.gray_max_x = 0;
+  }
+
+
+  static
+  void  Vertical_Sweep_Span( RAS_ARGS Short       y,
+                                      FT_F26Dot6  x1,
+                                      FT_F26Dot6  x2,
+                                      PProfile    left,
+                                      PProfile    right )
+  {
+    Long   e1, e2;
+    Short  c1, c2;
+    Byte   f1, f2;
+    Byte*  target;
+
+    FT_UNUSED( y );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    /* Drop-out control */
+
+    e1 = TRUNC( CEILING( x1 ) );
+
+    if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+      e2 = e1;
+    else
+      e2 = TRUNC( FLOOR( x2 ) );
+
+    if ( e2 >= 0 && e1 < ras.bWidth )
+    {
+      if ( e1 < 0 )
+        e1 = 0;
+      if ( e2 >= ras.bWidth )
+        e2 = ras.bWidth - 1;
+
+      c1 = (Short)( e1 >> 3 );
+      c2 = (Short)( e2 >> 3 );
+
+      f1 =    (unsigned char)0xFF >> ( e1 & 7 );
+      f2 = ~( (unsigned char)0x7F >> ( e2 & 7 ) );
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+      if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2;
+
+      target = ras.bTarget + ras.traceOfs + c1;
+      c2 -= c1;
+
+      if ( c2 > 0 )
+      {
+        target[0] |= f1;
+
+        /* memset() is slower than the following code on many platforms. */
+        /* This is due to the fact that, in the vast majority of cases,  */
+        /* the span length in bytes is relatively small.                 */
+        c2--;
+        while ( c2 > 0 )
+        {
+          *(++target) = 0xFF;
+          c2--;
+        }
+        target[1] |= f2;
+      }
+      else
+        *target |= ( f1 & f2 );
+    }
+  }
+
+
+  static
+  void Vertical_Sweep_Drop( RAS_ARGS Short       y,
+                                     FT_F26Dot6  x1,
+                                     FT_F26Dot6  x2,
+                                     PProfile    left,
+                                     PProfile    right )
+  {
+    Long   e1, e2;
+    Short  c1, f1;
+
+
+    /* Drop-out control */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( (x1 + x2 + 1) / 2 );
+          break;
+
+        case 2:
+        case 5:
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+          /* Here, we only get rid of stubs recognized if:          */
+          /*                                                        */
+          /*  upper stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Right is the successor of P_Left in that contour */
+          /*   - y is the top of P_Left and P_Right                 */
+          /*                                                        */
+          /*  lower stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Left is the successor of P_Right in that contour */
+          /*   - y is the bottom of P_Left                          */
+          /*                                                        */
+
+          /* FIXXXME: uncommenting this line solves the disappearing */
+          /*          bit problem in the `7' of verdana 10pts, but   */
+          /*          makes a new one in the `C' of arial 14pts      */
+
+#if 0
+          if ( x2 - x1 < ras.precision_half )
+#endif
+          {
+            /* upper stub test */
+            if ( left->next == right && left->height <= 0 )
+              return;
+
+            /* lower stub test */
+            if ( right->next == left && left->start == y )
+              return;
+          }
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          c1 = (Short)( e1 >> 3 );
+          f1 = e1 &  7;
+
+          if ( e1 >= 0 && e1 < ras.bWidth                      &&
+               ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.bWidth )
+    {
+      c1 = (Short)( e1 >> 3 );
+      f1 = e1 & 7;
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+      if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+
+      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+    }
+  }
+
+
+  static
+  void Vertical_Sweep_Step( RAS_ARG )
+  {
+    ras.traceOfs += ras.traceIncr;
+  }
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /*  Horizontal Sweep Procedure Set                                     */
+  /*                                                                     */
+  /*  These four routines are used during the horizontal black/white     */
+  /*  sweep phase by the generic Draw_Sweep() function.                  */
+  /*                                                                     */
+  /***********************************************************************/
+
+  static
+  void  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
+                                        Short*  max )
+  {
+    /* nothing, really */
+    FT_UNUSED( raster );
+    FT_UNUSED( min );
+    FT_UNUSED( max );
+  }
+
+
+  static
+  void  Horizontal_Sweep_Span( RAS_ARGS Short       y,
+                                        FT_F26Dot6  x1,
+                                        FT_F26Dot6  x2,
+                                        PProfile    left,
+                                        PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    if ( x2 - x1 < ras.precision )
+    {
+      e1 = CEILING( x1 );
+      e2 = FLOOR  ( x2 );
+
+      if ( e1 == e2 )
+      {
+        bits = ras.bTarget + ( y >> 3 );
+        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+        e1 = TRUNC( e1 );
+
+        if ( e1 >= 0 && e1 < ras.target.rows )
+        {
+          PByte  p;
+
+
+          p = bits - e1*ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            p += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          p[0] |= f1;
+        }
+      }
+    }
+  }
+
+
+  static
+  void  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
+                                        FT_F26Dot6  x1,
+                                        FT_F26Dot6  x2,
+                                        PProfile    left,
+                                        PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          bits = ras.bTarget + ( y >> 3 );
+          f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+          bits -= e1 * ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          if ( e1 >= 0              &&
+               e1 < ras.target.rows &&
+               *bits & f1 )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    bits = ras.bTarget + ( y >> 3 );
+    f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.target.rows )
+    {
+      bits -= e1 * ras.target.pitch;
+      if ( ras.target.pitch > 0 )
+        bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+      bits[0] |= f1;
+    }
+  }
+
+
+  static
+  void Horizontal_Sweep_Step( RAS_ARG )
+  {
+    /* Nothing, really */
+    FT_UNUSED( raster );
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Gray Sweep Procedure Set                                    */
+  /*                                                                       */
+  /*  These two routines are used during the vertical gray-levels sweep    */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*  NOTES                                                                */
+  /*                                                                       */
+  /*  - The target pixmap's width *must* be a multiple of 4.               */
+  /*                                                                       */
+  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
+  /*    span call.                                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  void  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
+                                           Short*  max )
+  {
+    Long  pitch, byte_len;
+
+
+    *min = *min & -2;
+    *max = ( *max + 3 ) & -2;
+
+    ras.traceOfs  = 0;
+    pitch         = ras.target.pitch;
+    byte_len      = -pitch;
+    ras.traceIncr = (Short)byte_len;
+    ras.traceG    = ( *min / 2 ) * byte_len;
+
+    if ( pitch > 0 )
+    {
+      ras.traceG += ( ras.target.rows - 1 ) * pitch;
+      byte_len    = -byte_len;
+    }
+
+    ras.gray_min_x =  (Short)byte_len;
+    ras.gray_max_x = -(Short)byte_len;
+  }
+
+
+  static
+  void  Vertical_Gray_Sweep_Step( RAS_ARG )
+  {
+    Int    c1, c2;
+    PByte  pix, bit, bit2;
+    Int*   count = ras.count_table;
+    Byte*  grays;
+
+
+    ras.traceOfs += ras.gray_width;
+
+    if ( ras.traceOfs > ras.gray_width )
+    {
+      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
+      grays = ras.grays;
+
+      if ( ras.gray_max_x >= 0 )
+      {
+        Long   last_pixel = ras.target.width - 1;
+        Int    last_cell  = last_pixel >> 2;
+        Int    last_bit   = last_pixel & 3;
+        Bool   over       = 0;
+
+
+        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
+        {
+          ras.gray_max_x = last_cell - 1;
+          over = 1;
+        }
+
+        if ( ras.gray_min_x < 0 )
+          ras.gray_min_x = 0;
+
+        bit   = ras.bTarget + ras.gray_min_x;
+        bit2  = bit + ras.gray_width;
+
+        c1 = ras.gray_max_x - ras.gray_min_x;
+
+        while ( c1 >= 0 )
+        {
+          c2 = count[*bit] + count[*bit2];
+
+          if ( c2 )
+          {
+            pix[0] = grays[(c2 >> 12) & 0x000F];
+            pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            pix[3] = grays[ c2        & 0x000F];
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+
+          bit++;
+          bit2++;
+          pix += 4;
+          c1--;
+        }
+
+        if ( over )
+        {
+          c2 = count[*bit] + count[*bit2];
+          if ( c2 )
+          {
+            switch ( last_bit )
+            {
+            case 2:
+              pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            case 1:
+              pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            default:
+              pix[0] = grays[(c2 >> 12) & 0x000F];
+            }
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+        }
+      }
+
+      ras.traceOfs = 0;
+      ras.traceG  += ras.traceIncr;
+
+      ras.gray_min_x =  32000;
+      ras.gray_max_x = -32000;
+    }
+  }
+
+
+  static
+  void  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
+                                             FT_F26Dot6  x1,
+                                             FT_F26Dot6  x2,
+                                             PProfile    left,
+                                             PProfile    right )
+  {
+    /* nothing, really */
+    FT_UNUSED( raster );
+    FT_UNUSED( y );
+    FT_UNUSED( x1 );
+    FT_UNUSED( x2 );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+  }
+
+
+  static
+  void  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
+                                             FT_F26Dot6  x1,
+                                             FT_F26Dot6  x2,
+                                             PProfile    left,
+                                             PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  pixel;
+    Byte   color;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    if ( e1 >= 0 )
+    {
+      if ( x2 - x1 >= ras.precision_half )
+        color = ras.grays[2];
+      else
+        color = ras.grays[1];
+
+      e1 = TRUNC( e1 ) / 2;
+      if ( e1 < ras.target.rows )
+      {
+        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
+        if ( ras.target.pitch > 0 )
+          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+        if ( pixel[0] == ras.grays[0] )
+          pixel[0] = color;
+      }
+    }
+  }
+
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Generic Sweep Drawing routine                                        */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  Bool  Draw_Sweep( RAS_ARG )
+  {
+    Short         y, y_change, y_height;
+
+    PProfile      P, Q, P_Left, P_Right;
+
+    Short         min_Y, max_Y, top, bottom, dropouts;
+
+    Long          x1, x2, xs, e1, e2;
+
+    TProfileList  wait;
+    TProfileList  draw_left, draw_right;
+
+
+    /* Init empty linked lists */
+
+    Init_Linked( &wait );
+
+    Init_Linked( &draw_left  );
+    Init_Linked( &draw_right );
+
+    /* first, compute min and max Y */
+
+    P     = ras.fProfile;
+    max_Y = (Short)TRUNC( ras.minY );
+    min_Y = (Short)TRUNC( ras.maxY );
+
+    while ( P )
+    {
+      Q = P->link;
+
+      bottom = (Short)P->start;
+      top    = (Short)P->start + P->height - 1;
+
+      if ( min_Y > bottom ) min_Y = bottom;
+      if ( max_Y < top    ) max_Y = top;
+
+      P->X = 0;
+      InsNew( &wait, P );
+
+      P = Q;
+    }
+
+    /* Check the Y-turns */
+    if ( ras.numTurns == 0 )
+    {
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    /* Now inits the sweep */
+
+    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+
+    /* Then compute the distance of each profile from min_Y */
+
+    P = wait;
+
+    while ( P )
+    {
+      P->countL = P->start - min_Y;
+      P = P->link;
+    }
+
+    /* Let's go */
+
+    y        = min_Y;
+    y_height = 0;
+
+    if ( ras.numTurns > 0 &&
+         ras.sizeBuff[-ras.numTurns] == min_Y )
+      ras.numTurns--;
+
+    while ( ras.numTurns > 0 )
+    {
+      /* look in the wait list for new activations */
+
+      P = wait;
+
+      while ( P )
+      {
+        Q = P->link;
+        P->countL -= y_height;
+        if ( P->countL == 0 )
+        {
+          DelOld( &wait, P );
+
+          switch ( P->flow )
+          {
+          case Flow_Up:
+            InsNew( &draw_left,  P );
+            break;
+
+          case Flow_Down:
+            InsNew( &draw_right, P );
+            break;
+          }
+        }
+
+        P = Q;
+      }
+
+      /* Sort the drawing lists */
+
+      Sort( &draw_left );
+      Sort( &draw_right );
+
+      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+      y_height = y_change - y;
+
+      while ( y < y_change )
+      {
+        /* Let's trace */
+
+        dropouts = 0;
+
+        P_Left  = draw_left;
+        P_Right = draw_right;
+
+        while ( P_Left )
+        {
+          x1 = P_Left ->X;
+          x2 = P_Right->X;
+
+          if ( x1 > x2 )
+          {
+            xs = x1;
+            x1 = x2;
+            x2 = xs;
+          }
+
+          if ( x2 - x1 <= ras.precision )
+          {
+            e1 = FLOOR( x1 );
+            e2 = CEILING( x2 );
+
+            if ( ras.dropOutControl != 0                 &&
+                 ( e1 > e2 || e2 == e1 + ras.precision ) )
+            {
+              /* a drop out was detected */
+
+              P_Left ->X = x1;
+              P_Right->X = x2;
+
+              /* mark profile for drop-out processing */
+              P_Left->countL = 1;
+              dropouts++;
+
+              goto Skip_To_Next;
+            }
+          }
+
+          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+
+        Skip_To_Next:
+
+          P_Left  = P_Left->link;
+          P_Right = P_Right->link;
+        }
+
+        /* now perform the dropouts _after_ the span drawing -- */
+        /* drop-outs processing has been moved out of the loop  */
+        /* for performance tuning                               */
+        if ( dropouts > 0 )
+          goto Scan_DropOuts;
+
+      Next_Line:
+
+        ras.Proc_Sweep_Step( RAS_VAR );
+
+        y++;
+
+        if ( y < y_change )
+        {
+          Sort( &draw_left  );
+          Sort( &draw_right );
+        }
+      }
+
+      /* Now finalize the profiles that needs it */
+
+      {
+        PProfile  Q, P;
+
+
+        P = draw_left;
+        while ( P )
+        {
+          Q = P->link;
+          if ( P->height == 0 )
+            DelOld( &draw_left, P );
+          P = Q;
+        }
+      }
+
+      {
+        PProfile  Q, P = draw_right;
+
+
+        while ( P )
+        {
+          Q = P->link;
+          if ( P->height == 0 )
+            DelOld( &draw_right, P );
+          P = Q;
+        }
+      }
+    }
+
+    /* for gray-scaling, flushes the bitmap scanline cache */
+    while ( y <= max_Y )
+    {
+      ras.Proc_Sweep_Step( RAS_VAR );
+      y++;
+    }
+
+    return SUCCESS;
+
+  Scan_DropOuts:
+
+    P_Left  = draw_left;
+    P_Right = draw_right;
+
+    while ( P_Left )
+    {
+      if ( P_Left->countL )
+      {
+        P_Left->countL = 0;
+#if 0
+        dropouts--;  /* -- this is useful when debugging only */
+#endif
+        ras.Proc_Sweep_Drop( RAS_VARS y,
+                                      P_Left->X,
+                                      P_Right->X,
+                                      P_Left,
+                                      P_Right );
+      }
+
+      P_Left  = P_Left->link;
+      P_Right = P_Right->link;
+    }
+
+    goto Next_Line;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Single_Pass                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs one sweep with sub-banding.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of the outline.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Renderer error code.                                               */
+  /*                                                                       */
+  static
+  int  Render_Single_Pass( RAS_ARGS Bool  flipped )
+  {
+    Short  i, j, k;
+
+
+    while ( ras.band_top >= 0 )
+    {
+      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
+      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+
+      ras.top = ras.buff;
+
+      ras.error = Raster_Err_None;
+
+      if ( Convert_Glyph( RAS_VARS flipped ) )
+      {
+        if ( ras.error != Raster_Err_Overflow )
+          return FAILURE;
+
+        ras.error = Raster_Err_None;
+
+        /* sub-banding */
+
+#ifdef DEBUG_RASTER
+        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
+#endif
+
+        i = ras.band_stack[ras.band_top].y_min;
+        j = ras.band_stack[ras.band_top].y_max;
+
+        k = ( i + j ) / 2;
+
+        if ( ras.band_top >= 7 || k < i )
+        {
+          ras.band_top = 0;
+          ras.error    = Raster_Err_Invalid;
+
+          return ras.error;
+        }
+
+        ras.band_stack[ras.band_top + 1].y_min = k;
+        ras.band_stack[ras.band_top + 1].y_max = j;
+
+        ras.band_stack[ras.band_top].y_max = k - 1;
+
+        ras.band_top++;
+      }
+      else
+      {
+        if ( ras.fProfile )
+          if ( Draw_Sweep( RAS_VAR ) )
+             return ras.error;
+        ras.band_top--;
+      }
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Glyph                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph in a bitmap.  Sub-banding if needed.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* XXX Fixme: ftraster's error codes don't harmonize with FT2's ones!    */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Render_Glyph( RAS_ARG )
+  {
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        ft_outline_high_precision );
+    ras.scale_shift    = ras.precision_shift;
+    ras.dropOutControl = 2;
+    ras.second_pass    = !( ras.outline.flags & ft_outline_single_pass );
+
+    /* Vertical Sweep */
+    ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = ras.target.rows - 1;
+
+    ras.bWidth  = ras.target.width;
+    ras.bTarget = (Byte*)ras.target.buffer;
+
+    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = ras.target.width - 1;
+
+      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+        return error;
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Gray_Glyph                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph with grayscaling.  Sub-banding if needed.          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Render_Gray_Glyph( RAS_ARG )
+  {
+    Long      pixel_width;
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        ft_outline_high_precision );
+    ras.scale_shift    = ras.precision_shift + 1;
+    ras.dropOutControl = 2;
+    ras.second_pass    = !( ras.outline.flags & ft_outline_single_pass );
+
+    /* Vertical Sweep */
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
+
+    ras.bWidth  = ras.gray_width;
+    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
+
+    if ( ras.bWidth > pixel_width )
+      ras.bWidth = pixel_width;
+
+    ras.bWidth  = ras.bWidth * 8;
+    ras.bTarget = (Byte*)ras.gray_lines;
+    ras.gTarget = (Byte*)ras.target.buffer;
+
+    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
+
+    error = Render_Single_Pass( RAS_VARS 0 );
+    if ( error )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
+
+      error = Render_Single_Pass( RAS_VARS 1 );
+      if ( error )
+        return error;
+    }
+
+    return FT_Err_Ok;
+  }
+
+#else /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+  LOCAL_FUNC
+  FT_Error  Render_Gray_Glyph( RAS_ARG )
+  {
+    FT_UNUSED_RASTER;
+
+    return FT_Err_Cannot_Render_Glyph;
+  }
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  static
+  void  ft_black_init( TRaster_Instance*  raster )
+  {
+    FT_UInt  n;
+    FT_ULong c;
+
+
+    /* setup count table */
+    for ( n = 0; n < 256; n++ )
+    {
+      c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 );
+
+      c = ( ( c << 6 ) & 0x3000 ) |
+          ( ( c << 4 ) & 0x0300 ) |
+          ( ( c << 2 ) & 0x0030 ) |
+                   (c  & 0x0003 );
+
+      raster->count_table[n] = c;
+    }
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    /* set default 5-levels gray palette */
+    for ( n = 0; n < 5; n++ )
+      raster->grays[n] = n * 255 / 4;
+
+    raster->gray_width = RASTER_GRAY_LINES / 2;
+
+#endif
+  }
+
+
+  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+  /****                         a static object.                  *****/
+
+
+#ifdef _STANDALONE_
+
+
+  static
+  int  ft_black_new( void*      memory,
+                     FT_Raster  *araster )
+  {
+     static FT_RasterRec_  the_raster;
+
+
+     *araster = &the_raster;
+     memset( &the_raster, sizeof ( the_raster ), 0 );
+     ft_black_init( &the_raster );
+
+     return 0;
+  }
+
+
+  static
+  void  ft_black_done( FT_Raster  raster )
+  {
+    /* nothing */
+    raster->init = 0;
+  }
+
+
+#else /* _STANDALONE_ */
+
+
+  static
+  int  ft_black_new( FT_Memory           memory,
+                     TRaster_Instance**  araster )
+  {
+    FT_Error           error;
+    TRaster_Instance*  raster;
+
+
+    *araster = 0;
+    if ( !ALLOC( raster, sizeof ( *raster ) ) )
+    {
+      raster->memory = memory;
+      ft_black_init( raster );
+
+      *araster = raster;
+    }
+
+    return error;
+  }
+
+
+  static
+  void ft_black_done( TRaster_Instance*  raster )
+  {
+    FT_Memory  memory = (FT_Memory)raster->memory;
+    FREE( raster );
+  }
+
+
+#endif /* _STANDALONE_ */
+
+
+  static
+  void ft_black_reset( TRaster_Instance*  raster,
+                       const char*        pool_base,
+                       long               pool_size )
+  {
+    if ( raster && pool_base && pool_size >= 4096 )
+    {
+      /* save the pool */
+      raster->buff     = (PLong)pool_base;
+      raster->sizeBuff = raster->buff + pool_size / sizeof ( Long );
+    }
+  }
+
+
+  static
+  void ft_black_set_mode( TRaster_Instance* raster,
+                          unsigned long     mode,
+                          const char*       palette )
+  {
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
+    {
+      /* set 5-levels gray palette */
+      raster->grays[0] = palette[0];
+      raster->grays[1] = palette[1];
+      raster->grays[2] = palette[2];
+      raster->grays[3] = palette[3];
+      raster->grays[4] = palette[4];
+    }
+
+#else
+
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( palette );
+
+#endif
+  }
+
+
+  static
+  int  ft_black_render( TRaster_Instance*  raster,
+                        FT_Raster_Params*  params )
+  {
+    FT_Outline*  outline    = (FT_Outline*)params->source;
+    FT_Bitmap*   target_map = params->target;
+
+
+    if ( !raster || !raster->buff || !raster->sizeBuff )
+      return Raster_Err_Not_Ini;
+
+    if ( !outline || !outline->contours || !outline->points )
+      return Raster_Err_Invalid;
+
+    /* return immediately if the outline is empty */
+    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+      return Raster_Err_None;
+
+    if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+      return Raster_Err_Invalid;
+
+    if ( !target_map || !target_map->buffer )
+      return Raster_Err_Invalid;
+
+    /* this version of the raster does not support direct rendering, sorry */
+    if ( params->flags & ft_raster_flag_direct )
+      return Raster_Err_Unsupported;
+
+    ras.outline  = *outline;
+    ras.target   = *target_map;
+
+    return ( ( params->flags & ft_raster_flag_aa )
+               ? Render_Gray_Glyph( raster )
+               : Render_Glyph( raster ) );
+  }
+
+
+  FT_Raster_Funcs  ft_standard_raster =
+  {
+    ft_glyph_format_outline,
+    (FT_Raster_New_Func)     ft_black_new,
+    (FT_Raster_Reset_Func)   ft_black_reset,
+    (FT_Raster_Set_Mode_Func)ft_black_set_mode,
+    (FT_Raster_Render_Func)  ft_black_render,
+    (FT_Raster_Done_Func)    ft_black_done
+  };
+
+
+/* END */
diff --git a/src/freetype/raster1/ftraster.h b/src/freetype/raster1/ftraster.h
new file mode 100644 (file)
index 0000000..5c7faae
--- /dev/null
@@ -0,0 +1,50 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftraster.h                                                             */
+/*                                                                         */
+/*    The FreeType glyph rasterizer (specification).                       */
+/*                                                                         */
+/*  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 FTRASTER_H
+#define FTRASTER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+#include <freetype/ftimage.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Uncomment the following line if you are using ftraster.c as a         */
+  /* standalone module, fully independent of FreeType.                     */
+  /*                                                                       */
+/* #define _STANDALONE_ */
+
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x )  extern x
+#endif
+
+  FT_EXPORT_VAR( FT_Raster_Funcs )  ft_standard_raster;
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* FTRASTER_H */
+
+
+/* END */
diff --git a/src/freetype/raster1/ftrend1.c b/src/freetype/raster1/ftrend1.c
new file mode 100644 (file)
index 0000000..d774cf1
--- /dev/null
@@ -0,0 +1,275 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrend1.c                                                              */
+/*                                                                         */
+/*    The FreeType glyph rasterizer interface (body).                      */
+/*                                                                         */
+/*  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 <freetype/internal/ftobjs.h>
+#include <freetype/ftoutln.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftrend1.h"
+#include "ftraster.h"
+
+#else
+
+#include <raster1/ftrend1.h>
+#include <raster1/ftraster.h>
+
+#endif
+
+
+  /* initialize renderer -- init its raster */
+  static
+  FT_Error  ft_raster1_init( FT_Renderer  render )
+  {
+    FT_Library  library = FT_MODULE_LIBRARY( render );
+
+
+    render->clazz->raster_class->raster_reset( render->raster,
+                                               library->raster_pool,
+                                               library->raster_pool_size );
+
+    return FT_Err_Ok;
+  }
+
+
+  /* set render-specific mode */
+  static
+  FT_Error  ft_raster1_set_mode( FT_Renderer  render,
+                                 FT_ULong     mode_tag,
+                                 FT_Pointer   data )
+  {
+    /* we simply pass it to the raster */
+    return render->clazz->raster_class->raster_set_mode( render->raster,
+                                                         mode_tag,
+                                                         data );
+  }
+
+
+  /* transform a given glyph image */
+  static
+  FT_Error  ft_raster1_transform( FT_Renderer   render,
+                                  FT_GlyphSlot  slot,
+                                  FT_Matrix*    matrix,
+                                  FT_Vector*    delta )
+  {
+    FT_Error error = FT_Err_Ok;
+
+
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    if ( matrix )
+      FT_Outline_Transform( &slot->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+  Exit:
+    return error;
+  }
+
+
+  /* return the glyph's control box */
+  static
+  void  ft_raster1_get_cbox( FT_Renderer   render,
+                             FT_GlyphSlot  slot,
+                             FT_BBox*      cbox )
+  {
+    MEM_Set( cbox, 0, sizeof ( *cbox ) );
+
+    if ( slot->format == render->glyph_format )
+      FT_Outline_Get_CBox( &slot->outline, cbox );
+  }
+
+
+  /* convert a slot's glyph image into a bitmap */
+  static
+  FT_Error  ft_raster1_render( FT_Renderer   render,
+                               FT_GlyphSlot  slot,
+                               FT_UInt       mode,
+                               FT_Vector*    origin )
+  {
+    FT_Error     error;
+    FT_Outline*  outline;
+    FT_BBox      cbox;
+    FT_UInt      width, height, pitch;
+    FT_Bitmap*   bitmap;
+    FT_Memory    memory;
+
+    FT_Raster_Params  params;
+
+
+    /* check glyph image format */
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* check rendering mode */
+    if ( mode != ft_render_mode_mono )
+    {
+      /* raster1 is only capable of producing monochrome bitmaps */
+      if ( render->clazz == &ft_raster1_renderer_class )
+        return FT_Err_Cannot_Render_Glyph;
+    }
+    else
+    {
+      /* raster5 is only capable of producing 5-gray-levels bitmaps */
+      if ( render->clazz == &ft_raster5_renderer_class )
+        return FT_Err_Cannot_Render_Glyph;
+    }
+
+    outline = &slot->outline;
+
+    /* translate the outline to the new origin if needed */
+    if ( origin )
+      FT_Outline_Translate( outline, origin->x, origin->y );
+
+    /* compute the control box, and grid fit it */
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    cbox.xMin &= -64;
+    cbox.yMin &= -64;
+    cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+    cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+
+    width  = ( cbox.xMax - cbox.xMin ) >> 6;
+    height = ( cbox.yMax - cbox.yMin ) >> 6;
+    bitmap = &slot->bitmap;
+    memory = render->root.memory;
+
+    /* release old bitmap buffer */
+    if ( slot->flags & ft_glyph_own_bitmap )
+    {
+      FREE( bitmap->buffer );
+      slot->flags &= ~ft_glyph_own_bitmap;
+    }
+
+    /* allocate new one, depends on pixel format */
+    if ( !( mode & ft_render_mode_mono ) )
+    {
+      /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
+      pitch = ( width + 3 ) & -4;
+      bitmap->pixel_mode = ft_pixel_mode_grays;
+      bitmap->num_grays  = 256;
+    }
+    else
+    {
+      pitch = ( width + 7 ) >> 3;
+      bitmap->pixel_mode = ft_pixel_mode_mono;
+    }
+
+    bitmap->width = width;
+    bitmap->rows  = height;
+    bitmap->pitch = pitch;
+
+    if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+      goto Exit;
+
+    slot->flags |= ft_glyph_own_bitmap;
+
+    /* translate outline to render it into the bitmap */
+    FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+    /* set up parameters */
+    params.target = bitmap;
+    params.source = outline;
+    params.flags  = 0;
+
+    if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+      params.flags |= ft_raster_flag_aa;
+
+    /* render outline into the bitmap */
+    error = render->raster_render( render->raster, &params );
+    if ( error )
+      goto Exit;
+
+    slot->format      = ft_glyph_format_bitmap;
+    slot->bitmap_left = cbox.xMin >> 6;
+    slot->bitmap_top  = cbox.yMax >> 6;
+
+  Exit:
+    return error;
+  }
+
+
+  const FT_Renderer_Class  ft_raster1_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "raster1",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_raster1_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_raster1_render,
+    (FTRenderer_transform)ft_raster1_transform,
+    (FTRenderer_getCBox)  ft_raster1_get_cbox,
+    (FTRenderer_setMode)  ft_raster1_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_standard_raster
+  };
+
+
+  /* this renderer is _NOT_ part of the default modules, you'll need */
+  /* to register it by hand in your application.  It should only be  */
+  /* used for backwards-compatibility with FT 1.x anyway.            */
+  const FT_Renderer_Class  ft_raster5_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "raster5",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_raster1_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_raster1_render,
+    (FTRenderer_transform)ft_raster1_transform,
+    (FTRenderer_getCBox)  ft_raster1_get_cbox,
+    (FTRenderer_setMode)  ft_raster1_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_standard_raster
+  };
+
+
+/* END */
diff --git a/src/freetype/raster1/ftrend1.h b/src/freetype/raster1/ftrend1.h
new file mode 100644 (file)
index 0000000..b8fff83
--- /dev/null
@@ -0,0 +1,37 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrend1.h                                                              */
+/*                                                                         */
+/*    The FreeType glyph rasterizer interface (specification).             */
+/*                                                                         */
+/*  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 FTREND1_H
+#define FTREND1_H
+
+#include <freetype/ftrender.h>
+
+
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_raster1_renderer_class;
+
+  /* this renderer is _NOT_ part of the default modules, you'll need */
+  /* to register it by hand in your application.  It should only be  */
+  /* used for backwards-compatibility with FT 1.x anyway.            */
+  /*                                                                 */
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_raster5_renderer_class;
+
+
+#endif /* FTREND1_H */
+
+
+/* END */
diff --git a/src/freetype/raster1/module.mk b/src/freetype/raster1/module.mk
new file mode 100644 (file)
index 0000000..c1ceb21
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_raster1_module
+
+add_raster1_module:
+       $(OPEN_DRIVER)ft_raster1_renderer_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)raster1   $(ECHO_DRIVER_DESC)monochrome bitmap renderer$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/raster1/raster1.c b/src/freetype/raster1/raster1.c
new file mode 100644 (file)
index 0000000..cf2835a
--- /dev/null
@@ -0,0 +1,35 @@
+/***************************************************************************/
+/*                                                                         */
+/*  raster1.c                                                              */
+/*                                                                         */
+/*    FreeType monochrome rasterer module component (body only).           */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftraster.c"
+#include "ftrend1.c"
+
+#else
+
+#include <raster1/ftraster.c>
+#include <raster1/ftrend1.c>
+
+#endif
+
+
+/* END */
diff --git a/src/freetype/raster1/rules.mk b/src/freetype/raster1/rules.mk
new file mode 100644 (file)
index 0000000..3810845
--- /dev/null
@@ -0,0 +1,69 @@
+#
+# FreeType 2 renderer module build rules
+#
+
+
+# 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.
+
+
+# raster1 driver directory
+#
+RAS1_DIR  := $(SRC_)raster1
+RAS1_DIR_ := $(RAS1_DIR)$(SEP)
+
+# compilation flags for the driver
+#
+RAS1_COMPILE := $(FT_COMPILE)
+
+
+# raster1 driver sources (i.e., C files)
+#
+RAS1_DRV_SRC := $(RAS1_DIR_)ftraster.c \
+                $(RAS1_DIR_)ftrend1.c
+
+
+# raster1 driver headers
+#
+RAS1_DRV_H := $(RAS1_DRV_SRC:%.c=%.h)
+
+
+# raster1 driver object(s)
+#
+#   RAS1_DRV_OBJ_M is used during `multi' builds.
+#   RAS1_DRV_OBJ_S is used during `single' builds.
+#
+RAS1_DRV_OBJ_M := $(RAS1_DRV_SRC:$(RAS1_DIR_)%.c=$(OBJ_)%.$O)
+RAS1_DRV_OBJ_S := $(OBJ_)raster1.$O
+
+# raster1 driver source file for single build
+#
+RAS1_DRV_SRC_S := $(RAS1_DIR_)raster1.c
+
+
+# raster1 driver - single object
+#
+$(RAS1_DRV_OBJ_S): $(RAS1_DRV_SRC_S) $(RAS1_DRV_SRC) \
+                   $(FREETYPE_H) $(RAS1_DRV_H)
+       $(RAS1_COMPILE) $T$@ $(RAS1_DRV_SRC_S)
+
+
+# raster1 driver - multiple objects
+#
+$(OBJ_)%.$O: $(RAS1_DIR_)%.c $(FREETYPE_H) $(RAS1_DRV_H)
+       $(RAS1_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(RAS1_DRV_OBJ_S)
+DRV_OBJS_M += $(RAS1_DRV_OBJ_M)
+
+
+# EOF
diff --git a/src/freetype/sfnt/module.mk b/src/freetype/sfnt/module.mk
new file mode 100644 (file)
index 0000000..48b494f
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_sfnt_module
+
+add_sfnt_module:
+       $(OPEN_DRIVER)sfnt_module_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)sfnt      $(ECHO_DRIVER_DESC)helper module for TrueType & OpenType formats$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/sfnt/rules.mk b/src/freetype/sfnt/rules.mk
new file mode 100644 (file)
index 0000000..2255e6a
--- /dev/null
@@ -0,0 +1,73 @@
+#
+# FreeType 2 SFNT driver configuration rules
+#
+
+
+# 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.
+
+
+# SFNT driver directory
+#
+SFNT_DIR  := $(SRC_)sfnt
+SFNT_DIR_ := $(SFNT_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+SFNT_COMPILE := $(FT_COMPILE)
+
+
+# SFNT driver sources (i.e., C files)
+#
+SFNT_DRV_SRC := $(SFNT_DIR_)ttload.c   \
+                $(SFNT_DIR_)ttcmap.c   \
+                $(SFNT_DIR_)ttsbit.c   \
+                $(SFNT_DIR_)ttpost.c   \
+                $(SFNT_DIR_)sfobjs.c   \
+                $(SFNT_DIR_)sfdriver.c
+
+# SFNT driver headers
+#
+SFNT_DRV_H := $(SFNT_DRV_SRC:%c=%h)
+
+
+# SFNT driver object(s)
+#
+#   SFNT_DRV_OBJ_M is used during `multi' builds.
+#   SFNT_DRV_OBJ_S is used during `single' builds.
+#
+SFNT_DRV_OBJ_M := $(SFNT_DRV_SRC:$(SFNT_DIR_)%.c=$(OBJ_)%.$O)
+SFNT_DRV_OBJ_S := $(OBJ_)sfnt.$O
+
+# SFNT driver source file for single build
+#
+SFNT_DRV_SRC_S := $(SFNT_DIR_)sfnt.c
+
+
+# SFNT driver - single object
+#
+$(SFNT_DRV_OBJ_S): $(SFNT_DRV_SRC_S) $(SFNT_DRV_SRC) \
+                   $(FREETYPE_H) $(SFNT_DRV_H)
+       $(SFNT_COMPILE) $T$@ $(SFNT_DRV_SRC_S)
+
+
+# SFNT driver - multiple objects
+#
+$(OBJ_)%.$O: $(SFNT_DIR_)%.c $(FREETYPE_H) $(SFNT_DRV_H)
+       $(SFNT_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(SFNT_DRV_OBJ_S)
+DRV_OBJS_M += $(SFNT_DRV_OBJ_M)
+
+
+# EOF
diff --git a/src/freetype/sfnt/sfdriver.c b/src/freetype/sfnt/sfdriver.c
new file mode 100644 (file)
index 0000000..96a738b
--- /dev/null
@@ -0,0 +1,225 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfdriver.c                                                             */
+/*                                                                         */
+/*    High-level SFNT driver interface (body).                             */
+/*                                                                         */
+/*  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 <freetype/internal/sfnt.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "sfdriver.h"
+#include "ttload.h"
+#include "ttsbit.h"
+#include "ttpost.h"
+#include "ttcmap.h"
+#include "sfobjs.h"
+
+#else
+
+#include <sfnt/sfdriver.h>
+#include <sfnt/ttload.h>
+#include <sfnt/ttsbit.h>
+#include <sfnt/ttpost.h>
+#include <sfnt/ttcmap.h>
+#include <sfnt/sfobjs.h>
+
+#endif
+
+
+#include <string.h>     /* for strcmp() */
+
+
+  static
+  void*  get_sfnt_table( TT_Face      face,
+                         FT_Sfnt_Tag  tag )
+  {
+    void*  table;
+
+
+    switch ( tag )
+    {
+    case ft_sfnt_head:
+      table = &face->header;
+      break;
+
+    case ft_sfnt_hhea:
+      table = &face->horizontal;
+      break;
+
+    case ft_sfnt_vhea:
+      table = face->vertical_info ? &face->vertical : 0;
+      break;
+
+    case ft_sfnt_os2:
+      table = face->os2.version == 0xFFFF ? 0 : &face->os2;
+      break;
+
+    case ft_sfnt_post:
+      table = &face->postscript;
+      break;
+
+    case ft_sfnt_maxp:
+      table = &face->max_profile;
+      break;
+
+    case ft_sfnt_pclt:
+      table = face->pclt.Version ? &face->pclt : 0;
+      break;
+
+    default:
+      table = 0;
+    }
+
+    return table;
+  }
+
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+  static
+  FT_Error  get_sfnt_glyph_name( TT_Face     face,
+                                 FT_UInt     glyph_index,
+                                 FT_Pointer  buffer,
+                                 FT_UInt     buffer_max )
+  {
+    FT_String*  gname;
+    FT_Error    error;
+    
+
+    error = TT_Get_PS_Name( face, glyph_index, &gname );
+    if ( !error && buffer_max > 0 )
+    {
+      FT_UInt  len = strlen( gname );
+      
+
+      if ( len >= buffer_max )
+        len = buffer_max - 1;
+        
+      MEM_Copy( buffer, gname, len );
+      ((FT_Byte*)buffer)[len] = 0;
+    }
+    
+    return error;
+  }                                  
+
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+  static
+  FT_Module_Interface  SFNT_Get_Interface( FT_Module    module,
+                                           const char*  interface )
+  {
+    FT_UNUSED( module );
+
+    if ( strcmp( interface, "get_sfnt" ) == 0 )
+      return (FT_Module_Interface)get_sfnt_table;
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+    if ( strcmp( interface, "glyph_name" ) == 0 )
+      return (FT_Module_Interface)get_sfnt_glyph_name;
+#endif
+    return 0;
+  }
+
+
+  static
+  const SFNT_Interface  sfnt_interface =
+  {
+    TT_Goto_Table,
+
+    SFNT_Init_Face,
+    SFNT_Load_Face,
+    SFNT_Done_Face,
+    SFNT_Get_Interface,
+
+    TT_Load_Any,
+    TT_Load_SFNT_Header,
+    TT_Load_Directory,
+
+    TT_Load_Header,
+    TT_Load_Metrics_Header,
+    TT_Load_CMap,
+    TT_Load_MaxProfile,
+    TT_Load_OS2,
+    TT_Load_PostScript,
+
+    TT_Load_Names,
+    TT_Free_Names,
+
+    TT_Load_Hdmx,
+    TT_Free_Hdmx,
+
+    TT_Load_Kern,
+    TT_Load_Gasp,
+    TT_Load_PCLT,
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    /* see `ttsbit.h' */
+    TT_Load_SBit_Strikes,
+    TT_Load_SBit_Image,
+    TT_Free_SBit_Strikes,
+
+#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    0,
+    0,
+    0,
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+    /* see `ttpost.h' */
+    TT_Get_PS_Name,
+    TT_Free_Post_Names,
+
+#else /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+    0,
+    0,
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+    /* see `ttcmap.h' */
+    TT_CharMap_Load,
+    TT_CharMap_Free,
+  };
+
+
+  const
+  FT_Module_Class  sfnt_module_class =
+  {
+    0,  /* not a font driver or renderer */
+    sizeof( FT_ModuleRec ),
+
+    "sfnt",     /* driver name                            */
+    0x10000L,   /* driver version 1.0                     */
+    0x20000L,   /* driver requires FreeType 2.0 or higher */
+
+    (const void*)&sfnt_interface,  /* module specific interface */
+
+    (FT_Module_Constructor)0,
+    (FT_Module_Destructor) 0,
+    (FT_Module_Requester)  SFNT_Get_Interface
+  };
+
+
+/* END */
diff --git a/src/freetype/sfnt/sfdriver.h b/src/freetype/sfnt/sfdriver.h
new file mode 100644 (file)
index 0000000..92c9c81
--- /dev/null
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfdriver.h                                                             */
+/*                                                                         */
+/*    High-level SFNT driver interface (specification).                    */
+/*                                                                         */
+/*  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 SFDRIVER_H
+#define SFDRIVER_H
+
+#include <freetype/ftmodule.h>
+
+  FT_EXPORT_VAR( const FT_Module_Class )  sfnt_module_class;
+
+#endif /* SFDRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/sfnt/sfnt.c b/src/freetype/sfnt/sfnt.c
new file mode 100644 (file)
index 0000000..cca7342
--- /dev/null
@@ -0,0 +1,57 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfnt.c                                                                 */
+/*                                                                         */
+/*    Single object library component.                                     */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.c"
+#include "ttcmap.c"
+#include "sfobjs.c"
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include "ttsbit.c"
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include "ttpost.c"
+#endif
+
+#include "sfdriver.c"
+
+#else /* FT_FLAT_COMPILE */
+
+#include <sfnt/ttload.c>
+#include <sfnt/ttcmap.c>
+#include <sfnt/sfobjs.c>
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include <sfnt/ttsbit.c>
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include <sfnt/ttpost.c>
+#endif
+
+#include <sfnt/sfdriver.c>
+
+#endif   /* FT_FLAT_COMPILE */
+
+
+/* END */
diff --git a/src/freetype/sfnt/sfobjs.c b/src/freetype/sfnt/sfobjs.c
new file mode 100644 (file)
index 0000000..4ae8502
--- /dev/null
@@ -0,0 +1,561 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfobjs.c                                                               */
+/*                                                                         */
+/*    SFNT object management (base).                                       */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "sfobjs.h"
+
+#else
+
+#include <sfnt/sfobjs.h>
+
+#endif
+
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+#include <freetype/ttnameid.h>
+#include <freetype/internal/tterrors.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_sfobjs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Name                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a given ENGLISH name record in ASCII.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the source face object.                      */
+  /*                                                                       */
+  /*    nameid :: The name id of the name record to return.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Character string.  NULL if no name is present.                     */
+  /*                                                                       */
+  static
+  FT_String*  Get_Name( TT_Face    face,
+                        FT_UShort  nameid )
+  {
+    FT_Memory    memory = face->root.memory;
+    FT_UShort    n;
+    TT_NameRec*  rec;
+    FT_Bool      wide_chars = 1;
+
+
+    rec = face->name_table.names;
+    for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ )
+    {
+      if ( rec->nameID == nameid )
+      {
+        /* found the name -- now create an ASCII string from it */
+        FT_Bool  found = 0;
+
+
+        /* test for Microsoft English language */
+        if ( rec->platformID == TT_PLATFORM_MICROSOFT &&
+             rec->encodingID <= TT_MS_ID_UNICODE_CS   &&
+             ( rec->languageID & 0x3FF ) == 0x009     )
+          found = 1;
+
+        /* test for Apple Unicode encoding */
+        else if ( rec->platformID == TT_PLATFORM_APPLE_UNICODE )
+          found = 1;
+
+        /* test for Apple Roman */
+        else if ( rec->platformID == TT_PLATFORM_MACINTOSH &&
+                  rec->languageID == TT_MAC_ID_ROMAN       )
+        {
+          found      = 1;
+          wide_chars = 0;
+        }
+
+        /* found a Unicode name */
+        if ( found )
+        {
+          FT_String*  string;
+          FT_UInt     len;
+
+
+          if ( wide_chars )
+          {
+            FT_UInt   m;
+
+
+            len = (FT_UInt)rec->stringLength / 2;
+            if ( MEM_Alloc( string, len + 1 ) )
+              return NULL;
+
+            for ( m = 0; m < len; m ++ )
+              string[m] = rec->string[2 * m + 1];
+          }
+          else
+          {
+            len = rec->stringLength;
+            if ( MEM_Alloc( string, len + 1 ) )
+              return NULL;
+
+            MEM_Copy( string, rec->string, len );
+          }
+
+          string[len] = '\0';
+          return string;
+        }
+      }
+    }
+
+    return NULL;
+  }
+
+
+  static
+  FT_Encoding  find_encoding( int  platform_id,
+                              int  encoding_id )
+  {
+    typedef struct  TEncoding
+    {
+      int          platform_id;
+      int          encoding_id;
+      FT_Encoding  encoding;
+
+    } TEncoding;
+
+    static
+    const TEncoding  tt_encodings[] =
+    {
+      { TT_PLATFORM_ISO,           -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_APPLE_UNICODE, -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     ft_encoding_apple_roman },
+
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       ft_encoding_sjis },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     ft_encoding_gb2312 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      ft_encoding_big5 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    ft_encoding_wansung },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      ft_encoding_johab }
+    };
+
+    const TEncoding  *cur, *limit;
+
+
+    cur   = tt_encodings;
+    limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur->platform_id == platform_id )
+      {
+        if ( cur->encoding_id == encoding_id ||
+             cur->encoding_id == -1          )
+          return cur->encoding;
+      }
+    }
+
+    return ft_encoding_none;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  SFNT_Init_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            FT_Int         face_index,
+                            FT_Int         num_params,
+                            FT_Parameter*  params )
+  {
+    FT_Error            error;
+    FT_Library          library = face->root.driver->root.library;
+    SFNT_Interface*     sfnt;
+    SFNT_Header         sfnt_header;
+
+    /* for now, parameters are unused */
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+
+    sfnt = (SFNT_Interface*)face->sfnt;
+    if ( !sfnt )
+    {
+      sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
+      if ( !sfnt )
+      {
+        error = FT_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      face->sfnt       = sfnt;
+      face->goto_table = sfnt->goto_table;
+    }
+
+    if ( !face->psnames )
+    {
+      face->psnames = (PSNames_Interface*)
+                       FT_Get_Module_Interface( library, "psnames" );
+    }
+
+    /* check that we have a valid TrueType file */
+    error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header );
+    if ( error )
+      goto Exit;
+
+    face->format_tag = sfnt_header.format_tag;
+    face->num_tables = sfnt_header.num_tables;
+
+    /* Load font directory */
+    error = sfnt->load_directory( face, stream, &sfnt_header );
+    if ( error )
+      goto Exit;
+
+    face->root.num_faces = face->ttc_header.count;
+    if ( face->root.num_faces < 1 )
+      face->root.num_faces = 1;
+
+  Exit:
+    return error;
+  }
+
+
+#undef  LOAD_
+#define LOAD_( x )  ( ( error = sfnt->load_##x( face, stream ) ) \
+                      != TT_Err_Ok )
+
+
+  LOCAL_FUNC
+  FT_Error  SFNT_Load_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            FT_Int         face_index,
+                            FT_Int         num_params,
+                            FT_Parameter*  params )
+  {
+    FT_Error         error;
+    SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+    FT_UNUSED( face_index );
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+
+
+    /* Load tables */
+    if ( LOAD_( header )        ||
+         LOAD_( max_profile )   ||
+
+         /* load the `hhea' & `hmtx' tables at once */
+         ( error = sfnt->load_metrics( face, stream, 0 ) ) != TT_Err_Ok  ||
+
+         /* try to load the `vhea' & `vmtx' at once if present */
+         ( error = sfnt->load_metrics( face, stream, 1 ) ) != TT_Err_Ok  ||
+
+         LOAD_( charmaps )      ||
+         LOAD_( names )         ||
+         LOAD_( os2 )           ||
+         LOAD_( psnames )       )
+     goto Exit;
+
+    /* the optional tables */
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    /* embedded bitmap support. */
+    if ( sfnt->load_sbits && LOAD_( sbits ) )
+      goto Exit;
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    if ( LOAD_( hdmx )          ||
+         LOAD_( gasp )          ||
+         LOAD_( kerning )       ||
+         LOAD_( pclt )          )
+      goto Exit;
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+    if ( ( error = TT_Extension_Create( face ) ) != TT_Err_Ok )
+      goto Exit;
+#endif
+
+    face->root.family_name = Get_Name( face, TT_NAME_ID_FONT_FAMILY );
+    face->root.style_name  = Get_Name( face, TT_NAME_ID_FONT_SUBFAMILY );
+
+    /* now set up root fields */
+    {
+      FT_Face     root = &face->root;
+      FT_Int      flags;
+      TT_CharMap  charmap;
+      FT_Int      n;
+      FT_Memory   memory;
+
+
+      memory = root->memory;
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Compute face flags.                                               */
+      /*                                                                   */
+      flags = FT_FACE_FLAG_SCALABLE  |    /* scalable outlines */
+              FT_FACE_FLAG_SFNT      |    /* SFNT file format  */
+              FT_FACE_FLAG_HORIZONTAL;    /* horizontal data   */
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+      /* might need more polish to detect the presence of a Postscript */
+      /* name table in the font                                        */
+      flags |= FT_FACE_FLAG_GLYPH_NAMES;
+#endif
+
+      /* fixed width font? */
+      if ( face->postscript.isFixedPitch )
+        flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      /* vertical information? */
+      if ( face->vertical_info )
+        flags |= FT_FACE_FLAG_VERTICAL;
+
+      /* kerning available ? */
+      if ( face->kern_pairs )
+        flags |= FT_FACE_FLAG_KERNING;
+
+      root->face_flags = flags;
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Compute style flags.                                              */
+      /*                                                                   */
+      flags = 0;
+
+      if ( face->os2.version != 0xFFFF )
+      {
+        /* we have an OS/2 table; use the `fsSelection' field */
+        if ( face->os2.fsSelection & 1 )
+          flags |= FT_STYLE_FLAG_ITALIC;
+
+        if ( face->os2.fsSelection & 32 )
+          flags |= FT_STYLE_FLAG_BOLD;
+      }
+      else
+      {
+        /* this is an old Mac font, use the header field */
+        if ( face->header.Mac_Style & 1 )
+          flags |= FT_STYLE_FLAG_BOLD;
+
+        if ( face->header.Mac_Style & 2 )
+          flags |= FT_STYLE_FLAG_ITALIC;
+      }
+
+      root->style_flags = flags;
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Polish the charmaps.                                              */
+      /*                                                                   */
+      /*   Try to set the charmap encoding according to the platform &     */
+      /*   encoding ID of each charmap.                                    */
+      /*                                                                   */
+      charmap            = face->charmaps;
+      root->num_charmaps = face->num_charmaps;
+
+      /* allocate table of pointers */
+      if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
+        goto Exit;
+
+      for ( n = 0; n < root->num_charmaps; n++, charmap++ )
+      {
+        FT_Int  platform = charmap->cmap.platformID;
+        FT_Int  encoding = charmap->cmap.platformEncodingID;
+
+
+        charmap->root.face        = (FT_Face)face;
+        charmap->root.platform_id = platform;
+        charmap->root.encoding_id = encoding;
+        charmap->root.encoding    = find_encoding( platform, encoding );
+
+        /* now, set root->charmap with a unicode charmap */
+        /* wherever available                            */
+        if ( !root->charmap                                &&
+             charmap->root.encoding == ft_encoding_unicode )
+          root->charmap = (FT_CharMap)charmap;
+
+        root->charmaps[n] = (FT_CharMap)charmap;
+      }
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+      if ( face->num_sbit_strikes )
+      {
+       root->num_fixed_sizes = face->num_sbit_strikes;
+       if ( ALLOC_ARRAY( root->available_sizes,
+                         face->num_sbit_strikes,
+                         FT_Bitmap_Size ) )
+         return error;
+
+        for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
+        {
+          root->available_sizes[n].width =
+            face->sbit_strikes[n].x_ppem;
+          root->available_sizes[n].height =
+            face->sbit_strikes[n].y_ppem;
+        }
+      }
+      else
+
+#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+      {
+       root->num_fixed_sizes = 0;
+       root->available_sizes = 0;
+      }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+      /*********************************************************************/
+      /*                                                                   */
+      /*  Set up metrics.                                                  */
+      /*                                                                   */
+      root->bbox.xMin    = face->header.xMin;
+      root->bbox.yMin    = face->header.yMin;
+      root->bbox.xMax    = face->header.xMax;
+      root->bbox.yMax    = face->header.yMax;
+      root->units_per_EM = face->header.Units_Per_EM;
+
+      /* The ascender/descender/height are computed from the OS/2 table    */
+      /* when found.  Otherwise, they're taken from the horizontal header. */
+      if ( face->os2.version != 0xFFFF )
+      {
+        root->ascender  =  face->os2.sTypoAscender;
+        root->descender = -face->os2.sTypoDescender;
+        root->height    =  root->ascender + root->descender +
+                           face->os2.sTypoLineGap;
+      }
+      else
+      {
+        root->ascender  = face->horizontal.Ascender;
+        root->descender = face->horizontal.Descender;
+        root->height    = root->ascender + root->descender +
+                          face->horizontal.Line_Gap;
+      }
+
+      root->max_advance_width   = face->horizontal.advance_Width_Max;
+
+      root->max_advance_height  = face->vertical_info
+                                    ? face->vertical.advance_Height_Max
+                                    : root->height;
+
+      root->underline_position  = face->postscript.underlinePosition;
+      root->underline_thickness = face->postscript.underlineThickness;
+
+      /* root->max_points     -- already set up */
+      /* root->max_contours   -- already set up */
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#undef LOAD_
+
+
+  LOCAL_FUNC
+  void  SFNT_Done_Face( TT_Face  face )
+  {
+    FT_Memory        memory = face->root.memory;
+    SFNT_Interface*  sfnt   = (SFNT_Interface*)face->sfnt;
+
+
+    if ( sfnt )
+    {
+      /* destroy the postscript names table if it is loaded */
+      if ( sfnt->free_psnames )
+        sfnt->free_psnames( face );
+
+      /* destroy the embedded bitmaps table if it is loaded */
+      if ( sfnt->free_sbits )
+        sfnt->free_sbits( face );
+    }
+
+    /* freeing the kerning table */
+    FREE( face->kern_pairs );
+    face->num_kern_pairs = 0;
+
+    /* freeing the collection table */
+    FREE( face->ttc_header.offsets );
+    face->ttc_header.count = 0;
+
+    /* freeing table directory */
+    FREE( face->dir_tables );
+    face->num_tables = 0;
+
+    /* freeing the character mapping tables */
+    if ( sfnt && sfnt->load_charmaps )
+    {
+      FT_UShort  n;
+
+
+      for ( n = 0; n < face->num_charmaps; n++ )
+        sfnt->free_charmap( face, &face->charmaps[n].cmap );
+    }
+
+    FREE( face->charmaps );
+    face->num_charmaps = 0;
+
+    FREE( face->root.charmaps );
+    face->root.num_charmaps = 0;
+    face->root.charmap      = 0;
+
+    /* freeing the horizontal metrics */
+    FREE( face->horizontal.long_metrics );
+    FREE( face->horizontal.short_metrics );
+
+    /* freeing the vertical ones, if any */
+    if ( face->vertical_info )
+    {
+      FREE( face->vertical.long_metrics  );
+      FREE( face->vertical.short_metrics );
+      face->vertical_info = 0;
+    }
+
+    /* freeing the gasp table */
+    FREE( face->gasp.gaspRanges );
+    face->gasp.numRanges = 0;
+
+    /* freeing the name table */
+    sfnt->free_names( face );
+
+    /* freeing the hdmx table */
+    sfnt->free_hdmx( face );
+
+    /* freeing family and style name */
+    FREE( face->root.family_name );
+    FREE( face->root.style_name );
+
+    /* freeing sbit size table */
+    face->root.num_fixed_sizes = 0;
+    if ( face->root.available_sizes )
+      FREE( face->root.available_sizes );
+
+    face->sfnt = 0;
+  }
+
+
+/* END */
diff --git a/src/freetype/sfnt/sfobjs.h b/src/freetype/sfnt/sfobjs.h
new file mode 100644 (file)
index 0000000..35d92f9
--- /dev/null
@@ -0,0 +1,57 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfobjs.h                                                               */
+/*                                                                         */
+/*    SFNT object management (specification).                              */
+/*                                                                         */
+/*  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 SFOBJS_H
+#define SFOBJS_H
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  LOCAL_DEF
+  FT_Error  SFNT_Init_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            FT_Int         face_index,
+                            FT_Int         num_params,
+                            FT_Parameter*  params );
+
+  LOCAL_DEF
+  FT_Error  SFNT_Load_Face( FT_Stream      stream,
+                            TT_Face        face,
+                            FT_Int         face_index,
+                            FT_Int         num_params,
+                            FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  SFNT_Done_Face( TT_Face  face );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* SFDRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttcmap.c b/src/freetype/sfnt/ttcmap.c
new file mode 100644 (file)
index 0000000..87ad04f
--- /dev/null
@@ -0,0 +1,550 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttcmap.c                                                               */
+/*                                                                         */
+/*    TrueType character mapping table (cmap) support (body).              */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/tterrors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.h"
+#include "ttcmap.h"
+
+#else
+
+#include <sfnt/ttload.h>
+#include <sfnt/ttcmap.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttcmap
+
+
+  static FT_UInt  code_to_index0( TT_CMapTable*  charmap,
+                                  FT_ULong       char_code );
+  static FT_UInt  code_to_index2( TT_CMapTable*  charmap,
+                                  FT_ULong       char_code );
+  static FT_UInt  code_to_index4( TT_CMapTable*  charmap,
+                                  FT_ULong       char_code );
+  static FT_UInt  code_to_index6( TT_CMapTable*  charmap,
+                                  FT_ULong       char_code );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_CharMap_Load                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given TrueType character map into memory.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the parent face object.                      */
+  /*    stream :: A handle to the current stream object.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: A pointer to a cmap object.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function assumes that the stream is already in use (i.e.,      */
+  /*    opened).  In case of error, all partially allocated tables are     */
+  /*    released.                                                          */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_CharMap_Load( TT_Face        face,
+                             TT_CMapTable*  cmap,
+                             FT_Stream      stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+    FT_UShort  num_SH, num_Seg, i;
+
+    FT_UShort  u, l;
+
+    TT_CMap0*  cmap0;
+    TT_CMap2*  cmap2;
+    TT_CMap4*  cmap4;
+    TT_CMap6*  cmap6;
+
+    TT_CMap2SubHeader*  cmap2sub;
+    TT_CMap4Segment*    segments;
+
+
+    if ( cmap->loaded )
+      return TT_Err_Ok;
+
+    memory = stream->memory;
+
+    if ( FILE_Seek( cmap->offset ) )
+      return error;
+
+    switch ( cmap->format )
+    {
+    case 0:
+      cmap0 = &cmap->c.cmap0;
+
+      if ( ALLOC( cmap0->glyphIdArray, 256L )            ||
+           FILE_Read( cmap0->glyphIdArray, 256L ) )
+         goto Fail;
+
+      cmap->get_index = code_to_index0;
+      break;
+
+    case 2:
+      num_SH = 0;
+      cmap2  = &cmap->c.cmap2;
+
+      /* allocate subheader keys */
+
+      if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_UShort ) ||
+           ACCESS_Frame( 512L )                                )
+        goto Fail;
+
+      for ( i = 0; i < 256; i++ )
+      {
+        u = GET_UShort() / 8;
+        cmap2->subHeaderKeys[i] = u;
+
+        if ( num_SH < u )
+          num_SH = u;
+      }
+
+      FORGET_Frame();
+
+      /* load subheaders */
+
+      cmap2->numGlyphId = l =
+        ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFF ) / 2;
+
+      if ( ALLOC_ARRAY( cmap2->subHeaders,
+                        num_SH + 1,
+                        TT_CMap2SubHeader )    ||
+           ACCESS_Frame( ( num_SH + 1 ) * 8L ) )
+        goto Fail;
+
+      cmap2sub = cmap2->subHeaders;
+
+      for ( i = 0; i <= num_SH; i++ )
+      {
+        cmap2sub->firstCode     = GET_UShort();
+        cmap2sub->entryCount    = GET_UShort();
+        cmap2sub->idDelta       = GET_Short();
+        /* we apply the location offset immediately */
+        cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2;
+
+        cmap2sub++;
+      }
+
+      FORGET_Frame();
+
+      /* load glyph IDs */
+
+      if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, FT_UShort ) ||
+           ACCESS_Frame( l * 2L )                           )
+        goto Fail;
+
+      for ( i = 0; i < l; i++ )
+        cmap2->glyphIdArray[i] = GET_UShort();
+
+      FORGET_Frame();
+
+      cmap->get_index = code_to_index2;
+      break;
+
+    case 4:
+      cmap4 = &cmap->c.cmap4;
+
+      /* load header */
+
+      if ( ACCESS_Frame( 8L ) )
+        goto Fail;
+
+      cmap4->segCountX2    = GET_UShort();
+      cmap4->searchRange   = GET_UShort();
+      cmap4->entrySelector = GET_UShort();
+      cmap4->rangeShift    = GET_UShort();
+
+      num_Seg = cmap4->segCountX2 / 2;
+
+      FORGET_Frame();
+
+      /* load segments */
+
+      if ( ALLOC_ARRAY( cmap4->segments,
+                        num_Seg,
+                        TT_CMap4Segment )           ||
+           ACCESS_Frame( ( num_Seg * 4 + 1 ) * 2L ) )
+        goto Fail;
+
+      segments = cmap4->segments;
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].endCount      = GET_UShort();
+
+      (void)GET_UShort();
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].startCount    = GET_UShort();
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].idDelta       = GET_Short();
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].idRangeOffset = GET_UShort();
+
+      FORGET_Frame();
+
+      cmap4->numGlyphId = l =
+        ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2;
+
+      /* load IDs */
+
+      if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) ||
+           ACCESS_Frame( l * 2L )                           )
+        goto Fail;
+
+      for ( i = 0; i < l; i++ )
+        cmap4->glyphIdArray[i] = GET_UShort();
+
+      FORGET_Frame();
+
+      cmap->get_index = code_to_index4;
+
+      cmap4->last_segment = cmap4->segments;
+      break;
+
+    case 6:
+      cmap6 = &cmap->c.cmap6;
+
+      if ( ACCESS_Frame( 4L ) )
+        goto Fail;
+
+      cmap6->firstCode  = GET_UShort();
+      cmap6->entryCount = GET_UShort();
+
+      FORGET_Frame();
+
+      l = cmap6->entryCount;
+
+      if ( ALLOC_ARRAY( cmap6->glyphIdArray,
+                        cmap6->entryCount,
+                        FT_Short )           ||
+           ACCESS_Frame( l * 2L )            )
+        goto Fail;
+
+      for ( i = 0; i < l; i++ )
+        cmap6->glyphIdArray[i] = GET_UShort();
+
+      FORGET_Frame();
+      cmap->get_index = code_to_index6;
+      break;
+
+    default:   /* corrupt character mapping table */
+      return TT_Err_Invalid_CharMap_Format;
+
+    }
+
+    return TT_Err_Ok;
+
+  Fail:
+    TT_CharMap_Free( face, cmap );
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_CharMap_Free                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a character mapping table.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the parent face object.                        */
+  /*    cmap :: A handle to a cmap object.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_CharMap_Free( TT_Face        face,
+                             TT_CMapTable*  cmap )
+  {
+    FT_Memory  memory;
+
+
+    if ( !cmap )
+      return TT_Err_Ok;
+
+    memory = face->root.driver->root.memory;
+
+    switch ( cmap->format )
+    {
+    case 0:
+      FREE( cmap->c.cmap0.glyphIdArray );
+      break;
+
+    case 2:
+      FREE( cmap->c.cmap2.subHeaderKeys );
+      FREE( cmap->c.cmap2.subHeaders );
+      FREE( cmap->c.cmap2.glyphIdArray );
+      break;
+
+    case 4:
+      FREE( cmap->c.cmap4.segments );
+      FREE( cmap->c.cmap4.glyphIdArray );
+      cmap->c.cmap4.segCountX2 = 0;
+      break;
+
+    case 6:
+      FREE( cmap->c.cmap6.glyphIdArray );
+      cmap->c.cmap6.entryCount = 0;
+      break;
+
+    default:
+      /* invalid table format, do nothing */
+      ;
+    }
+
+    cmap->loaded = FALSE;
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index0                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 0.    */
+  /*    `charCode' must be in the range 0x00-0xFF (otherwise 0 is          */
+  /*    returned).                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap0    :: A pointer to a cmap table in format 0.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  static
+  FT_UInt  code_to_index0( TT_CMapTable*  cmap,
+                           FT_ULong       charCode )
+  {
+    TT_CMap0*  cmap0 = &cmap->c.cmap0;
+
+
+    return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index2                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 2.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap2    :: A pointer to a cmap table in format 2.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  static
+  FT_UInt  code_to_index2( TT_CMapTable*  cmap,
+                           FT_ULong       charCode )
+  {
+    FT_UInt             result, index1, offset;
+    FT_UInt             char_lo;
+    FT_ULong            char_hi;
+    TT_CMap2SubHeader*  sh2;
+    TT_CMap2*           cmap2;
+
+
+    cmap2   = &cmap->c.cmap2;
+    result  = 0;
+    char_lo = (FT_UInt)( charCode & 0xFF );
+    char_hi = charCode >> 8;
+
+    if ( char_hi == 0 )
+    {
+      /* an 8-bit character code -- we use the subHeader 0 in this case */
+      /* to test whether the character code is in the charmap           */
+      if ( cmap2->subHeaderKeys[char_lo] == 0 )
+        result = cmap2->glyphIdArray[char_lo];
+    }
+    else
+    {
+      /* a 16-bit character code */
+      index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
+      if ( index1 )
+      {
+        sh2      = cmap2->subHeaders + index1;
+        char_lo -= sh2->firstCode;
+
+        if ( char_lo < sh2->entryCount )
+        {
+          offset = sh2->idRangeOffset / 2 + char_lo;
+          if ( offset < cmap2->numGlyphId )
+          {
+            result = cmap2->glyphIdArray[offset];
+            if ( result )
+              result = ( result + sh2->idDelta ) & 0xFFFF;
+          }
+        }
+      }
+    }
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index4                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 4.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap4    :: A pointer to a cmap table in format 4.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  static
+  FT_UInt  code_to_index4( TT_CMapTable*  cmap,
+                           FT_ULong       charCode )
+  {
+    FT_UInt          result, index1, segCount;
+    TT_CMap4*        cmap4;
+    TT_CMap4Segment  *seg4, *limit;
+
+
+    cmap4    = &cmap->c.cmap4;
+    result   = 0;
+    segCount = cmap4->segCountX2 / 2;
+    seg4     = cmap4->segments;
+    limit    = seg4 + segCount;
+
+    /* check against the last segment */
+    seg4 = cmap4->last_segment;
+
+    /* the following is equivalent to performing two tests, as in         */
+    /*                                                                    */
+    /*  if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */
+    /*                                                                    */
+    /* Yes, that's a bit strange, but it's faster, and the idea behind    */
+    /* the cache is to significantly speed up charcode to glyph index     */
+    /* conversion.                                                        */
+
+    if ( (FT_ULong)(charCode       - seg4->startCount) <
+         (FT_ULong)(seg4->endCount - seg4->startCount) )
+      goto Found;
+
+    for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
+    {
+      /* the ranges are sorted in increasing order.  If we are out of */
+      /* the range here, the char code isn't in the charmap, so exit. */
+
+      if ( charCode > seg4->endCount )
+        continue;
+
+      if ( charCode >= seg4->startCount )
+        goto Found;
+    }
+    return 0;
+
+ Found:
+    cmap4->last_segment = seg4;
+
+    /* if the idRangeOffset is 0, we can compute the glyph index */
+    /* directly                                                  */
+
+    if ( seg4->idRangeOffset == 0 )
+      result = ( charCode + seg4->idDelta ) & 0xFFFF;
+    else
+    {
+      /* otherwise, we must use the glyphIdArray to do it */
+      index1 = seg4->idRangeOffset / 2
+               + ( charCode - seg4->startCount )
+               + ( seg4 - cmap4->segments )
+               - segCount;
+
+      if ( index1 < cmap4->numGlyphId       &&
+           cmap4->glyphIdArray[index1] != 0 )
+        result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFF;
+    }
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index6                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 6.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap6    :: A pointer to a cmap table in format 6.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  static
+  FT_UInt  code_to_index6( TT_CMapTable*  cmap,
+                           FT_ULong       charCode )
+  {
+    TT_CMap6*  cmap6;
+    FT_UInt    result = 0;
+
+
+    cmap6     = &cmap->c.cmap6;
+    result    = 0;
+    charCode -= cmap6->firstCode;
+
+    if ( charCode < cmap6->entryCount )
+      result =  cmap6->glyphIdArray[charCode];
+
+    return result;
+  }
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttcmap.h b/src/freetype/sfnt/ttcmap.h
new file mode 100644 (file)
index 0000000..609972a
--- /dev/null
@@ -0,0 +1,45 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttcmap.h                                                               */
+/*                                                                         */
+/*    TrueType character mapping table (cmap) support (specification).     */
+/*                                                                         */
+/*  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 TTCMAP_H
+#define TTCMAP_H
+
+#include <freetype/internal/tttypes.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  LOCAL_DEF
+  FT_Error  TT_CharMap_Load( TT_Face        face,
+                             TT_CMapTable*  cmap,
+                             FT_Stream      input );
+
+  LOCAL_DEF
+  FT_Error  TT_CharMap_Free( TT_Face        face,
+                             TT_CMapTable*  cmap );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* TTCMAP_H */
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttload.c b/src/freetype/sfnt/ttload.c
new file mode 100644 (file)
index 0000000..e787187
--- /dev/null
@@ -0,0 +1,1676 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttload.c                                                               */
+/*                                                                         */
+/*    Load the basic TrueType tables, i.e., tables that can be either in   */
+/*    TTF or OTF fonts (body).                                             */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/tterrors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.h"
+#include "ttcmap.h"
+
+#else
+
+#include <sfnt/ttload.h>
+#include <sfnt/ttcmap.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttload
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_LookUp_Table                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks for a TrueType table by name.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A face object handle.                                      */
+  /*    tag  :: The searched tag.                                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A pointer to the table directory entry.  0 if not found.           */
+  /*                                                                       */
+  LOCAL_FUNC
+  TT_Table*  TT_LookUp_Table( TT_Face   face,
+                              FT_ULong  tag  )
+  {
+    TT_Table*  entry;
+    TT_Table*  limit;
+
+
+    FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c'\n",
+                  face,
+                  (FT_Char)( tag >> 24 ),
+                  (FT_Char)( tag >> 16 ),
+                  (FT_Char)( tag >> 8  ),
+                  (FT_Char)( tag       ) ));
+
+    entry = face->dir_tables;
+    limit = entry + face->num_tables;
+
+    for ( ; entry < limit; entry++ )
+    {
+      if ( entry->Tag == tag )
+        return entry;
+    }
+
+    FT_TRACE3(( "    Could not find table!\n" ));
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Goto_Table                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks for a TrueType table by name, then seek a stream to it.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A face object handle.                                    */
+  /*    tag    :: The searched tag.                                        */
+  /*    stream :: The stream to seek when the table is found.              */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    length :: The length of the table if found, undefined otherwise.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Goto_Table( TT_Face    face,
+                           FT_ULong   tag,
+                           FT_Stream  stream,
+                           FT_ULong*  length )
+  {
+    TT_Table*  table;
+    FT_Error   error;
+
+
+    table = TT_LookUp_Table( face, tag );
+    if ( table )
+    {
+      if ( length )
+        *length = table->Length;
+
+      (void)FILE_Seek( table->Offset );
+    }
+    else
+      error = TT_Err_Table_Missing;
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SFNT_Header                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the header of a SFNT font file.  Supports collections.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the target face object.                  */
+  /*    stream     :: The input stream.                                    */
+  /*    face_index :: If the font is a collection, the number of the font  */
+  /*                  in the collection, ignored otherwise.                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    sfnt       :: The SFNT header.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  /*    This function recognizes fonts embedded in a `TrueType collection' */
+  /*                                                                       */
+  /*    The header will be checked whether it is valid by looking at the   */
+  /*    values of `search_range', `entry_selector', and `range_shift'.     */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_SFNT_Header( TT_Face       face,
+                                 FT_Stream     stream,
+                                 FT_Long       face_index,
+                                 SFNT_Header*  sfnt )
+  {
+    FT_Error   error;
+    FT_ULong   format_tag;
+    FT_Memory  memory = stream->memory;
+
+    const FT_Frame_Field  sfnt_header_fields[] =
+    {
+      FT_FRAME_START( 8 ),
+        FT_FRAME_USHORT( SFNT_Header, num_tables ),
+        FT_FRAME_USHORT( SFNT_Header, search_range ),
+        FT_FRAME_USHORT( SFNT_Header, entry_selector ),
+        FT_FRAME_USHORT( SFNT_Header, range_shift ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  ttc_header_fields[] =
+    {
+      FT_FRAME_START( 8 ),
+        FT_FRAME_LONG( TTC_Header, version ),
+        FT_FRAME_LONG( TTC_Header, count   ),
+      FT_FRAME_END };
+
+
+    FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
+                face, face_index ));
+
+    face->ttc_header.tag      = 0;
+    face->ttc_header.version  = 0;
+    face->ttc_header.count    = 0;
+
+    face->num_tables = 0;
+
+    /* first of all, read the first 4 bytes.  If it is `ttcf', then the */
+    /* file is a TrueType collection, otherwise it can be any other     */
+    /* kind of font.                                                    */
+    if ( READ_ULong( format_tag ) )
+      goto Exit;
+
+    if ( format_tag == TTAG_ttcf )
+    {
+      FT_Int  n;
+
+
+      FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" ));
+
+      /* it's a TrueType collection, i.e. a file containing several */
+      /* font files.  Read the font directory now                   */
+      if ( READ_Fields( ttc_header_fields, &face->ttc_header ) )
+        goto Exit;
+
+      /* now read the offsets of each font in the file */
+      if ( ALLOC_ARRAY( face->ttc_header.offsets,
+                        face->ttc_header.count,
+                        FT_ULong )                     ||
+           ACCESS_Frame( face->ttc_header.count * 4L ) )
+        goto Exit;
+
+      for ( n = 0; n < face->ttc_header.count; n++ )
+        face->ttc_header.offsets[n] = GET_ULong();
+
+      FORGET_Frame();
+
+      /* check face index */
+      if ( face_index >= face->ttc_header.count )
+      {
+        error = TT_Err_Bad_Argument;
+        goto Exit;
+      }
+
+      /* seek to the appropriate TrueType file, then read tag */
+      if ( FILE_Seek( face->ttc_header.offsets[face_index] ) ||
+           READ_Long( format_tag )                           )
+        goto Exit;
+    }
+
+    /* the format tag was read, now check the rest of the header */
+    sfnt->format_tag = format_tag;
+    if ( READ_Fields( sfnt_header_fields, sfnt ) )
+      goto Exit;
+
+    /* now, check the values of `num_tables', `seach_range', etc. */
+    {
+      FT_UInt   num_tables     = sfnt->num_tables;
+      FT_ULong  entry_selector = 1L << sfnt->entry_selector;
+
+
+      /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
+      /*            we only check the `entry_selector' correctness here.  */
+      /*                                                                  */
+      if ( num_tables == 0                  ||
+           entry_selector > num_tables      ||
+           entry_selector * 2 <= num_tables )
+      {
+        FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
+        error = FT_Err_Unknown_File_Format;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Directory                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the table directory into a face object.                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: The input stream.                                        */
+  /*    sfnt   :: The SFNT directory header.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Directory( TT_Face       face,
+                               FT_Stream     stream,
+                               SFNT_Header*  sfnt )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    TT_Table *entry, *limit;
+
+
+    FT_TRACE2(( "TT_Load_Directory: %08p\n", face ));
+
+    FT_TRACE2(( "-- Tables count:   %12u\n",  sfnt->num_tables ));
+    FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
+
+    face->num_tables = sfnt->num_tables;
+
+    if ( ALLOC_ARRAY( face->dir_tables,
+                      face->num_tables,
+                      TT_Table ) )
+      goto Exit;
+
+    if ( ACCESS_Frame( face->num_tables * 16L ) )
+      goto Exit;
+
+    entry = face->dir_tables;
+    limit = entry + face->num_tables;
+
+    for ( ; entry < limit; entry++ )
+    {                    /* loop through the tables and get all entries */
+      entry->Tag      = GET_Tag4();
+      entry->CheckSum = GET_ULong();
+      entry->Offset   = GET_Long();
+      entry->Length   = GET_Long();
+
+      FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
+                  (FT_Char)( entry->Tag >> 24 ),
+                  (FT_Char)( entry->Tag >> 16 ),
+                  (FT_Char)( entry->Tag >> 8  ),
+                  (FT_Char)( entry->Tag       ),
+                  entry->Offset,
+                  entry->Length ));
+    }
+
+    FORGET_Frame();
+
+    FT_TRACE2(( "Directory loaded\n\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Any                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads any font table into client memory.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: The face object to look for.                             */
+  /*                                                                       */
+  /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
+  /*              to access the whole font file, else set this parameter   */
+  /*              to a valid TrueType table tag that you can forge with    */
+  /*              the MAKE_TT_TAG macro.                                   */
+  /*                                                                       */
+  /*    offset :: The starting offset in the table (or the file if         */
+  /*              tag == 0).                                               */
+  /*                                                                       */
+  /*    length :: The address of the decision variable:                    */
+  /*                                                                       */
+  /*                If length == NULL:                                     */
+  /*                  Loads the whole table.  Returns an error if          */
+  /*                  `offset' == 0!                                       */
+  /*                                                                       */
+  /*                If *length == 0:                                       */
+  /*                  Exits immediately; returning the length of the given */
+  /*                  table or of the font file, depending on the value of */
+  /*                  `tag'.                                               */
+  /*                                                                       */
+  /*                If *length != 0:                                       */
+  /*                  Loads the next `length' bytes of table or font,      */
+  /*                  starting at offset `offset' (in table or font too).  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    buffer :: The address of target buffer.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Any( TT_Face    face,
+                         FT_ULong   tag,
+                         FT_Long    offset,
+                         FT_Byte*   buffer,
+                         FT_ULong*  length )
+  {
+    FT_Error   error;
+    FT_Stream  stream;
+    TT_Table*  table;
+    FT_ULong   size;
+
+
+    if ( tag != 0 )
+    {
+      /* look for tag in font directory */
+      table = TT_LookUp_Table( face, tag );
+      if ( !table )
+      {
+        error = TT_Err_Table_Missing;
+        goto Exit;
+      }
+
+      offset += table->Offset;
+      size    = table->Length;
+    }
+    else
+      /* tag == 0 -- the user wants to access the font file directly */
+      size = face->root.stream->size;
+
+    if ( length && *length == 0 )
+    {
+      *length = size;
+
+      return TT_Err_Ok;
+    }
+
+    if ( length )
+      size = *length;
+
+    stream = face->root.stream;
+    (void)FILE_Read_At( offset, buffer, size );
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Header                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the TrueType font header.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Header( TT_Face    face,
+                            FT_Stream  stream )
+  {
+    FT_Error    error;
+    TT_Header*  header;
+
+    static const FT_Frame_Field  header_fields[] =
+    {
+      FT_FRAME_START( 54 ),
+        FT_FRAME_ULONG(  TT_Header, Table_Version ),
+        FT_FRAME_ULONG(  TT_Header, Font_Revision ),
+        FT_FRAME_LONG(   TT_Header, CheckSum_Adjust ),
+        FT_FRAME_LONG(   TT_Header, Magic_Number ),
+        FT_FRAME_USHORT( TT_Header, Flags ),
+        FT_FRAME_USHORT( TT_Header, Units_Per_EM ),
+        FT_FRAME_LONG(   TT_Header, Created[0] ),
+        FT_FRAME_LONG(   TT_Header, Created[1] ),
+        FT_FRAME_LONG(   TT_Header, Modified[0] ),
+        FT_FRAME_LONG(   TT_Header, Modified[1] ),
+        FT_FRAME_SHORT(  TT_Header, xMin ),
+        FT_FRAME_SHORT(  TT_Header, yMin ),
+        FT_FRAME_SHORT(  TT_Header, xMax ),
+        FT_FRAME_SHORT(  TT_Header, yMax ),
+        FT_FRAME_USHORT( TT_Header, Mac_Style ),
+        FT_FRAME_USHORT( TT_Header, Lowest_Rec_PPEM ),
+        FT_FRAME_SHORT(  TT_Header, Font_Direction ),
+        FT_FRAME_SHORT(  TT_Header, Index_To_Loc_Format ),
+        FT_FRAME_SHORT(  TT_Header, Glyph_Data_Format ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "Load_TT_Header: %08p\n", face ));
+
+    error = face->goto_table( face, TTAG_head, stream, 0 );
+    if ( error )
+    {
+      FT_TRACE0(( "Font Header is missing!\n" ));
+      goto Exit;
+    }
+
+    header = &face->header;
+
+    if ( READ_Fields( header_fields, header ) )
+      goto Exit;
+
+    FT_TRACE2(( "    Units per EM: %8u\n", header->Units_Per_EM ));
+    FT_TRACE2(( "    IndexToLoc:   %8d\n", header->Index_To_Loc_Format ));
+    FT_TRACE2(( "Font Header Loaded.\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_MaxProfile                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the maximum profile into a face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_MaxProfile( TT_Face    face,
+                                FT_Stream  stream )
+  {
+    FT_Error        error;
+    TT_MaxProfile*  maxProfile = &face->max_profile;
+
+    const FT_Frame_Field  maxp_fields[] =
+    {
+      FT_FRAME_START( 32 ),
+        FT_FRAME_ULONG(  TT_MaxProfile, version ),
+        FT_FRAME_USHORT( TT_MaxProfile, numGlyphs ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxPoints ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxContours ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxCompositePoints ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxCompositeContours ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxZones ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxTwilightPoints ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxStorage ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxFunctionDefs ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxInstructionDefs ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxStackElements ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxSizeOfInstructions ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxComponentElements ),
+        FT_FRAME_USHORT( TT_MaxProfile, maxComponentDepth ),
+      FT_FRAME_END };
+
+
+    FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
+
+    error = face->goto_table( face, TTAG_maxp, stream, 0 );
+    if ( error )
+      goto Exit;
+
+    if ( READ_Fields( maxp_fields, maxProfile ) )
+      goto Exit;
+
+    /* XXX: an adjustment that is necessary to load certain */
+    /*      broken fonts like `Keystrokes MT' :-(           */
+    /*                                                      */
+    /*   We allocate 64 function entries by default when    */
+    /*   the maxFunctionDefs field is null.                 */
+
+    if ( maxProfile->maxFunctionDefs == 0 )
+      maxProfile->maxFunctionDefs = 64;
+
+    face->root.num_glyphs = maxProfile->numGlyphs;
+
+    face->root.max_points = MAX( maxProfile->maxCompositePoints,
+                                 maxProfile->maxPoints );
+
+    face->root.max_contours = MAX( maxProfile->maxCompositeContours,
+                                   maxProfile->maxContours );
+
+    face->max_components = (FT_ULong)maxProfile->maxComponentElements +
+                           maxProfile->maxComponentDepth;
+
+    /* XXX: some fonts have maxComponents set to 0; we will */
+    /*      then use 16 of them by default.                 */
+    if ( face->max_components == 0 )
+      face->max_components = 16;
+
+    /* We also increase maxPoints and maxContours in order to support */
+    /* some broken fonts.                                             */
+    face->root.max_points   += 8;
+    face->root.max_contours += 4;
+
+    FT_TRACE2(( "MAXP loaded.\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Metrics                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal or vertical metrics table into a face object. */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the target face object.                    */
+  /*    stream   :: The input stream.                                      */
+  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  TT_Load_Metrics( TT_Face    face,
+                             FT_Stream  stream,
+                             FT_Bool    vertical )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_ULong   table_len;
+    FT_Long    num_shorts, num_longs, num_shorts_checked;
+
+    TT_LongMetrics**   longs;
+    TT_ShortMetrics**  shorts;
+
+
+    FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
+                                                       : "Horizontal",
+                                              face ));
+
+    if ( vertical )
+    {
+      /* The table is optional, quit silently if it wasn't found       */
+      /* XXX: Some fonts have a valid vertical header with a non-null  */
+      /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
+      /*      table to get the metrics from (e.g. mingliu).            */
+      /*                                                               */
+      /*      For safety, we set the field to 0!                       */
+      /*                                                               */
+      error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
+      if ( error )
+      {
+        /* Set number_Of_VMetrics to 0! */
+        FT_TRACE2(( "  no vertical header in file.\n" ));
+        face->vertical.number_Of_VMetrics = 0;
+        error = TT_Err_Ok;
+        goto Exit;
+      }
+
+      num_longs = face->vertical.number_Of_VMetrics;
+      longs     = (TT_LongMetrics**)&face->vertical.long_metrics;
+      shorts    = (TT_ShortMetrics**)&face->vertical.short_metrics;
+    }
+    else
+    {
+      error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
+      if ( error )
+      {
+        FT_ERROR(( " no horizontal metrics in file!\n" ));
+        error = TT_Err_Hmtx_Table_Missing;
+        goto Exit;
+      }
+
+      num_longs = face->horizontal.number_Of_HMetrics;
+      longs     = (TT_LongMetrics**)&face->horizontal.long_metrics;
+      shorts    = (TT_ShortMetrics**)&face->horizontal.short_metrics;
+    }
+
+    /* never trust derived values */
+
+    num_shorts         = face->max_profile.numGlyphs - num_longs;
+    num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
+
+    if ( num_shorts < 0 )
+    {
+      FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
+                 vertical ? "Vertical"
+                          : "Horizontal" ));
+
+      error = vertical ? TT_Err_Invalid_Vert_Metrics
+                       : TT_Err_Invalid_Horiz_Metrics;
+      goto Exit;
+    }
+
+    if ( ALLOC_ARRAY( *longs,  num_longs,  TT_LongMetrics )  ||
+         ALLOC_ARRAY( *shorts, num_shorts, TT_ShortMetrics ) )
+      goto Exit;
+
+    if ( ACCESS_Frame( table_len ) )
+      goto Exit;
+
+    {
+      TT_LongMetrics*  cur   = *longs;
+      TT_LongMetrics*  limit = cur + num_longs;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        cur->advance = GET_UShort();
+        cur->bearing = GET_Short();
+      }
+    }
+
+    /* do we have an inconsistent number of metric values? */
+    {
+      TT_ShortMetrics*  cur   = *shorts;
+      TT_ShortMetrics*  limit = cur + MIN( num_shorts, num_shorts_checked );
+
+
+      for ( ; cur < limit; cur++ )
+        *cur = GET_Short();
+
+      /* we fill up the missing left side bearings with the     */
+      /* last valid value.  Since this will occur for buggy CJK */
+      /* fonts usually only, nothing serious will happen        */
+      if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
+      {
+        FT_Short  val = *(shorts)[num_shorts_checked - 1];
+
+
+        limit = *shorts + num_shorts;
+        for ( ; cur < limit; cur++ )
+          *cur = val;
+      }
+    }
+
+    FORGET_Frame();
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Metrics_Header                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal or vertical header in a face object.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the target face object.                    */
+  /*    stream   :: The input stream.                                      */
+  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Metrics_Header( TT_Face    face,
+                                    FT_Stream  stream,
+                                    FT_Bool    vertical )
+  {
+    FT_Error        error;
+    TT_HoriHeader*  header;
+
+    const FT_Frame_Field  metrics_header_fields[] =
+    {
+      FT_FRAME_START( 36 ),
+        FT_FRAME_ULONG(  TT_HoriHeader, Version ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Ascender ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Descender ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Line_Gap ),
+        FT_FRAME_USHORT( TT_HoriHeader, advance_Width_Max ),
+        FT_FRAME_SHORT(  TT_HoriHeader, min_Left_Side_Bearing ),
+        FT_FRAME_SHORT(  TT_HoriHeader, min_Right_Side_Bearing ),
+        FT_FRAME_SHORT(  TT_HoriHeader, xMax_Extent ),
+        FT_FRAME_SHORT(  TT_HoriHeader, caret_Slope_Rise ),
+        FT_FRAME_SHORT(  TT_HoriHeader, caret_Slope_Run ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Reserved[0] ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Reserved[1] ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Reserved[2] ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Reserved[3] ),
+        FT_FRAME_SHORT(  TT_HoriHeader, Reserved[4] ),
+        FT_FRAME_SHORT(  TT_HoriHeader, metric_Data_Format ),
+        FT_FRAME_USHORT( TT_HoriHeader, number_Of_HMetrics ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
+
+    if ( vertical )
+    {
+      face->vertical_info = 0;
+
+      /* The vertical header table is optional, so return quietly if */
+      /* we don't find it.                                           */
+      error = face->goto_table( face, TTAG_vhea, stream, 0 );
+      if ( error )
+      {
+        error = TT_Err_Ok;
+        goto Exit;
+      }
+
+      face->vertical_info = 1;
+      header = (TT_HoriHeader*)&face->vertical;
+    }
+    else
+    {
+      /* The horizontal header is mandatory; return an error if we */
+      /* don't find it.                                            */
+      error = face->goto_table( face, TTAG_hhea, stream, 0 );
+      if ( error )
+      {
+        error = TT_Err_Horiz_Header_Missing;
+        goto Exit;
+      }
+
+      header = &face->horizontal;
+    }
+
+    if ( READ_Fields( metrics_header_fields, header ) )
+      goto Exit;
+
+    header->long_metrics  = NULL;
+    header->short_metrics = NULL;
+
+    FT_TRACE2(( "loaded\n" ));
+
+    /* Now try to load the corresponding metrics */
+
+    error = TT_Load_Metrics( face, stream, vertical );
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Names                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the name records.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Names( TT_Face    face,
+                           FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_ULong   table_pos, table_len;
+    FT_ULong   storageSize;
+
+    TT_NameTable*  names;
+
+    const FT_Frame_Field  name_table_fields[] =
+    {
+      FT_FRAME_START( 6 ),
+        FT_FRAME_USHORT( TT_NameTable, format ),
+        FT_FRAME_USHORT( TT_NameTable, numNameRecords ),
+        FT_FRAME_USHORT( TT_NameTable, storageOffset ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  name_record_fields[] =
+    {
+      /* no FT_FRAME_START */
+        FT_FRAME_USHORT( TT_NameRec, platformID ),
+        FT_FRAME_USHORT( TT_NameRec, encodingID ),
+        FT_FRAME_USHORT( TT_NameRec, languageID ),
+        FT_FRAME_USHORT( TT_NameRec, nameID ),
+        FT_FRAME_USHORT( TT_NameRec, stringLength ),
+        FT_FRAME_USHORT( TT_NameRec, stringOffset ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "Names " ));
+
+    error = face->goto_table( face, TTAG_name, stream, &table_len );
+    if ( error )
+    {
+      /* The name table is required so indicate failure. */
+      FT_TRACE2(( "is missing!\n" ));
+      error = TT_Err_Name_Table_Missing;
+      goto Exit;
+    }
+
+    table_pos = FILE_Pos();
+
+    names = &face->name_table;
+
+    if ( READ_Fields( name_table_fields, names ) )
+      goto Exit;
+
+    /* Allocate the array of name records. */
+    if ( ALLOC_ARRAY( names->names,
+                      names->numNameRecords,
+                      TT_NameRec )                   ||
+         ACCESS_Frame( names->numNameRecords * 12L ) )
+      goto Exit;
+
+    /* Load the name records and determine how much storage is needed */
+    /* to hold the strings themselves.                                */
+    {
+      TT_NameRec*  cur   = names->names;
+      TT_NameRec*  limit = cur + names->numNameRecords;
+
+
+      storageSize = 0;
+
+      for ( ; cur < limit; cur ++ )
+      {
+        FT_ULong  upper;
+
+
+        (void)READ_Fields( name_record_fields, cur );
+
+        upper = (FT_ULong)( cur->stringOffset + cur->stringLength );
+        if ( upper > storageSize )
+          storageSize = upper;
+      }
+    }
+
+    FORGET_Frame();
+
+    if ( storageSize > 0 )
+    {
+      /* allocate the name storage area in memory, then read it */
+      if ( ALLOC( names->storage, storageSize )               ||
+           FILE_Read_At( table_pos + names->storageOffset,
+                         names->storage, storageSize ) )
+        goto Exit;
+
+      /* Go through and assign the string pointers to the name records. */
+      {
+        TT_NameRec*  cur   = names->names;
+        TT_NameRec*  limit = cur + names->numNameRecords;
+
+
+        for ( ; cur < limit; cur++ )
+          cur->string = names->storage + cur->stringOffset;
+      }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+      /* Print Name Record Table in case of debugging */
+      {
+        TT_NameRec*  cur   = names->names;
+        TT_NameRec*  limit = cur + names->numNameRecords;
+
+
+        for ( ; cur < limit; cur++ )
+        {
+          FT_UInt  j;
+
+
+          FT_TRACE3(( "%d %d %x %d\n  ",
+                       cur->platformID,
+                       cur->encodingID,
+                       cur->languageID,
+                       cur->nameID ));
+
+          /* I know that M$ encoded strings are Unicode,            */
+          /* but this works reasonable well for debugging purposes. */
+          if ( cur->string )
+            for ( j = 0; j < cur->stringLength; j++ )
+            {
+              FT_Char  c = *( cur->string + j );
+
+
+              if ( (FT_Byte)c < 128 )
+                FT_TRACE3(( "%c", c ));
+            }
+        }
+      }
+      FT_TRACE3(( "\n" ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+    }
+    FT_TRACE2(( "loaded\n" ));
+
+    /* everything went well, update face->num_names */
+    face->num_names = names->numNameRecords;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Free_Names                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Frees the name records.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  TT_Free_Names( TT_Face  face )
+  {
+    FT_Memory      memory = face->root.driver->root.memory;
+    TT_NameTable*  names  = &face->name_table;
+
+
+    /* free strings table */
+    FREE( names->names );
+
+    /* free strings storage */
+    FREE( names->storage );
+
+    names->numNameRecords = 0;
+    names->format         = 0;
+    names->storageOffset  = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_CMap                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the cmap directory in a face object.  The cmaps itselves are */
+  /*    loaded on demand in the `ttcmap.c' module.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_CMap( TT_Face    face,
+                          FT_Stream  stream )
+  {
+    FT_Error    error;
+    FT_Memory   memory = stream->memory;
+    FT_Long     table_start;
+    TT_CMapDir  cmap_dir;
+
+    const FT_Frame_Field  cmap_fields[] =
+    {
+      FT_FRAME_START( 4 ),
+        FT_FRAME_USHORT( TT_CMapDir, tableVersionNumber ),
+        FT_FRAME_USHORT( TT_CMapDir, numCMaps ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  cmap_rec_fields[] =
+    {
+      FT_FRAME_START( 6 ),
+        FT_FRAME_USHORT( TT_CMapTable, format ),
+        FT_FRAME_USHORT( TT_CMapTable, length ),
+        FT_FRAME_USHORT( TT_CMapTable, version ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "CMaps " ));
+
+    error = face->goto_table( face, TTAG_cmap, stream, 0 );
+    if ( error )
+    {
+      error = TT_Err_CMap_Table_Missing;
+      goto Exit;
+    }
+
+    table_start = FILE_Pos();
+
+    if ( READ_Fields( cmap_fields, &cmap_dir ) )
+      goto Exit;
+
+    /* reserve space in face table for cmap tables */
+    if ( ALLOC_ARRAY( face->charmaps,
+                      cmap_dir.numCMaps,
+                      TT_CharMapRec ) )
+      goto Exit;
+
+    face->num_charmaps = cmap_dir.numCMaps;
+    {
+      TT_CharMap  charmap = face->charmaps;
+      TT_CharMap  limit   = charmap + face->num_charmaps;
+
+
+      /* read the header of each charmap first */
+      if ( ACCESS_Frame( face->num_charmaps * 8L ) )
+        goto Exit;
+
+      for ( ; charmap < limit; charmap++ )
+      {
+        TT_CMapTable*  cmap;
+
+
+        charmap->root.face = (FT_Face)face;
+        cmap               = &charmap->cmap;
+
+        cmap->loaded             = FALSE;
+        cmap->platformID         = GET_UShort();
+        cmap->platformEncodingID = GET_UShort();
+        cmap->offset             = (FT_ULong)GET_Long();
+      }
+
+      FORGET_Frame();
+
+      /* now read the rest of each table */
+      for ( charmap = face->charmaps; charmap < limit; charmap++ )
+      {
+        TT_CMapTable* cmap = &charmap->cmap;
+
+
+        if ( FILE_Seek( table_start + (FT_Long)cmap->offset ) ||
+             READ_Fields( cmap_rec_fields, cmap )             )
+          goto Exit;
+
+        cmap->offset = FILE_Pos();
+      }
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_OS2                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the OS2 table.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_OS2( TT_Face    face,
+                         FT_Stream  stream )
+  {
+    FT_Error  error;
+    TT_OS2*   os2;
+
+    const FT_Frame_Field  os2_fields[] =
+    {
+      FT_FRAME_START( 78 ),
+        FT_FRAME_USHORT( TT_OS2, version ),
+        FT_FRAME_SHORT(  TT_OS2, xAvgCharWidth ),
+        FT_FRAME_USHORT( TT_OS2, usWeightClass ),
+        FT_FRAME_USHORT( TT_OS2, usWidthClass ),
+        FT_FRAME_SHORT(  TT_OS2, fsType ),
+        FT_FRAME_SHORT(  TT_OS2, ySubscriptXSize ),
+        FT_FRAME_SHORT(  TT_OS2, ySubscriptYSize ),
+        FT_FRAME_SHORT(  TT_OS2, ySubscriptXOffset ),
+        FT_FRAME_SHORT(  TT_OS2, ySubscriptYOffset ),
+        FT_FRAME_SHORT(  TT_OS2, ySuperscriptXSize ),
+        FT_FRAME_SHORT(  TT_OS2, ySuperscriptYSize ),
+        FT_FRAME_SHORT(  TT_OS2, ySuperscriptXOffset ),
+        FT_FRAME_SHORT(  TT_OS2, ySuperscriptYOffset ),
+        FT_FRAME_SHORT(  TT_OS2, yStrikeoutSize ),
+        FT_FRAME_SHORT(  TT_OS2, yStrikeoutPosition ),
+        FT_FRAME_SHORT(  TT_OS2, sFamilyClass ),
+        FT_FRAME_BYTE(   TT_OS2, panose[0] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[1] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[2] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[3] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[4] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[5] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[6] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[7] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[8] ),
+        FT_FRAME_BYTE(   TT_OS2, panose[9] ),
+        FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange1 ),
+        FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange2 ),
+        FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange3 ),
+        FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange4 ),
+        FT_FRAME_BYTE(   TT_OS2, achVendID[0] ),
+        FT_FRAME_BYTE(   TT_OS2, achVendID[1] ),
+        FT_FRAME_BYTE(   TT_OS2, achVendID[2] ),
+        FT_FRAME_BYTE(   TT_OS2, achVendID[3] ),
+
+        FT_FRAME_USHORT( TT_OS2, fsSelection ),
+        FT_FRAME_USHORT( TT_OS2, usFirstCharIndex ),
+        FT_FRAME_USHORT( TT_OS2, usLastCharIndex ),
+        FT_FRAME_SHORT(  TT_OS2, sTypoAscender ),
+        FT_FRAME_SHORT(  TT_OS2, sTypoDescender ),
+        FT_FRAME_SHORT(  TT_OS2, sTypoLineGap ),
+        FT_FRAME_USHORT( TT_OS2, usWinAscent ),
+        FT_FRAME_USHORT( TT_OS2, usWinDescent ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  os2_fields_extra[] =
+    {
+      FT_FRAME_START( 8 ),
+        FT_FRAME_ULONG( TT_OS2, ulCodePageRange1 ),
+        FT_FRAME_ULONG( TT_OS2, ulCodePageRange2 ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  os2_fields_extra2[] =
+    {
+      FT_FRAME_START( 10 ),
+        FT_FRAME_SHORT( TT_OS2,  sxHeight ),
+        FT_FRAME_SHORT( TT_OS2,  sCapHeight ),
+        FT_FRAME_USHORT( TT_OS2, usDefaultChar ),
+        FT_FRAME_USHORT( TT_OS2, usBreakChar ),
+        FT_FRAME_USHORT( TT_OS2, usMaxContext ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "OS/2 Table " ));
+
+    /* We now support old Mac fonts where the OS/2 table doesn't  */
+    /* exist.  Simply put, we set the `version' field to 0xFFFF   */
+    /* and test this value each time we need to access the table. */
+    error = face->goto_table( face, TTAG_OS2, stream, 0 );
+    if ( error )
+    {
+      FT_TRACE2(( "is missing!\n" ));
+      face->os2.version = 0xFFFF;
+      error = TT_Err_Ok;
+      goto Exit;
+    }
+
+    os2 = &face->os2;
+
+    if ( READ_Fields( os2_fields, os2 ) )
+      goto Exit;
+
+    os2->ulCodePageRange1 = 0;
+    os2->ulCodePageRange2 = 0;
+
+    if ( os2->version >= 0x0001 )
+    {
+      /* only version 1 tables */
+      if ( READ_Fields( os2_fields_extra, os2 ) )
+        goto Exit;
+
+      if ( os2->version >= 0x0002 )
+      {
+        /* only version 2 tables */
+        if ( READ_Fields( os2_fields_extra2, os2 ) )
+          goto Exit;
+      }
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Postscript                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the Postscript table.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_PostScript( TT_Face    face,
+                                FT_Stream  stream )
+  {
+    FT_Error        error;
+    TT_Postscript*  post = &face->postscript;
+
+    static const FT_Frame_Field  post_fields[] =
+    {
+      FT_FRAME_START( 32 ),
+        FT_FRAME_ULONG( TT_Postscript, FormatType ),
+        FT_FRAME_ULONG( TT_Postscript, italicAngle ),
+        FT_FRAME_SHORT( TT_Postscript, underlinePosition ),
+        FT_FRAME_SHORT( TT_Postscript, underlineThickness ),
+        FT_FRAME_ULONG( TT_Postscript, isFixedPitch ),
+        FT_FRAME_ULONG( TT_Postscript, minMemType42 ),
+        FT_FRAME_ULONG( TT_Postscript, maxMemType42 ),
+        FT_FRAME_ULONG( TT_Postscript, minMemType1 ),
+        FT_FRAME_ULONG( TT_Postscript, maxMemType1 ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "PostScript " ));
+
+    error = face->goto_table( face, TTAG_post, stream, 0 );
+    if ( error )
+      return TT_Err_Post_Table_Missing;
+
+    if ( READ_Fields( post_fields, post ) )
+      return error;
+
+    /* we don't load the glyph names, we do that in another */
+    /* module (ttpost).                                     */
+    FT_TRACE2(( "loaded\n" ));
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_PCLT                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the PCL 5 Table.                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_PCLT( TT_Face    face,
+                          FT_Stream  stream )
+  {
+    static const FT_Frame_Field  pclt_fields[] =
+    {
+      FT_FRAME_START( 54 ),
+        FT_FRAME_ULONG ( TT_PCLT, Version ),
+        FT_FRAME_ULONG ( TT_PCLT, FontNumber ),
+        FT_FRAME_USHORT( TT_PCLT, Pitch ),
+        FT_FRAME_USHORT( TT_PCLT, xHeight ),
+        FT_FRAME_USHORT( TT_PCLT, Style ),
+        FT_FRAME_USHORT( TT_PCLT, TypeFamily ),
+        FT_FRAME_USHORT( TT_PCLT, CapHeight ),
+        FT_FRAME_BYTES ( TT_PCLT, TypeFace, 16 ),
+        FT_FRAME_BYTES ( TT_PCLT, CharacterComplement, 8 ),
+        FT_FRAME_BYTES ( TT_PCLT, FileName, 6 ),
+        FT_FRAME_CHAR  ( TT_PCLT, StrokeWeight ),
+        FT_FRAME_CHAR  ( TT_PCLT, WidthType ),
+        FT_FRAME_BYTE  ( TT_PCLT, SerifStyle ),
+        FT_FRAME_BYTE  ( TT_PCLT, Reserved ),
+      FT_FRAME_END
+    };
+
+    FT_Error  error;
+    TT_PCLT*  pclt = &face->pclt;
+
+
+    FT_TRACE2(( "PCLT " ));
+
+    /* optional table */
+    error = face->goto_table( face, TTAG_PCLT, stream, 0 );
+    if ( error )
+    {
+      FT_TRACE2(( "missing (optional)\n" ));
+      pclt->Version = 0;
+      return TT_Err_Ok;
+    }
+
+    if ( READ_Fields( pclt_fields, pclt ) )
+      goto Exit;
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Gasp                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the `gasp' table into a face object.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Gasp( TT_Face    face,
+                          FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_UInt        j,num_ranges;
+    TT_GaspRange*  gaspranges;
+
+
+    FT_TRACE2(( "TT_Load_Gasp: %08p\n", face ));
+
+    /* the gasp table is optional */
+    error = face->goto_table( face, TTAG_gasp, stream, 0 );
+    if ( error )
+      return TT_Err_Ok;
+
+    if ( ACCESS_Frame( 4L ) )
+      goto Exit;
+
+    face->gasp.version   = GET_UShort();
+    face->gasp.numRanges = GET_UShort();
+
+    FORGET_Frame();
+
+    num_ranges = face->gasp.numRanges;
+    FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
+
+    if ( ALLOC_ARRAY( gaspranges, num_ranges, TT_GaspRange ) ||
+         ACCESS_Frame( num_ranges * 4L )                     )
+      goto Exit;
+
+    face->gasp.gaspRanges = gaspranges;
+
+    for ( j = 0; j < num_ranges; j++ )
+    {
+      gaspranges[j].maxPPEM  = GET_UShort();
+      gaspranges[j].gaspFlag = GET_UShort();
+
+      FT_TRACE3(( " [max:%d flag:%d]",
+                    gaspranges[j].maxPPEM,
+                    gaspranges[j].gaspFlag ));
+    }
+    FT_TRACE3(( "\n" ));
+
+    FORGET_Frame();
+    FT_TRACE2(( "GASP loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Kern                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the first kerning table with format 0 in the font.  Only     */
+  /*    accepts the first horizontal kerning table.  Developers should use */
+  /*    the `ftxkern' extension to access other kerning tables in the font */
+  /*    file, if they really want to.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Kern( TT_Face    face,
+                          FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_UInt    n, num_tables, version;
+
+
+    /* the kern table is optional; exit silently if it is missing */
+    error = face->goto_table( face, TTAG_kern, stream, 0 );
+    if ( error )
+      return TT_Err_Ok;
+
+    if ( ACCESS_Frame( 4L ) )
+      goto Exit;
+
+    version    = GET_UShort();
+    num_tables = GET_UShort();
+
+    FORGET_Frame();
+
+    for ( n = 0; n < num_tables; n++ )
+    {
+      FT_UInt  coverage;
+      FT_UInt  length;
+
+
+      if ( ACCESS_Frame( 6L ) )
+        goto Exit;
+
+      version  = GET_UShort();      /* version                 */
+      length   = GET_UShort() - 6;  /* substract header length */
+      coverage = GET_UShort();
+
+      FORGET_Frame();
+
+      if ( coverage == 0x0001 )
+      {
+        FT_UInt          num_pairs;
+        TT_Kern_0_Pair*  pair;
+        TT_Kern_0_Pair*  limit;
+
+
+        /* found a horizontal format 0 kerning table! */
+        if ( ACCESS_Frame( 8L ) )
+          goto Exit;
+
+        num_pairs = GET_UShort();
+
+        /* skip the rest */
+
+        FORGET_Frame();
+
+        /* allocate array of kerning pairs */
+        if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) ||
+             ACCESS_Frame( 6L * num_pairs )                             )
+          goto Exit;
+
+        pair  = face->kern_pairs;
+        limit = pair + num_pairs;
+        for ( ; pair < limit; pair++ )
+        {
+          pair->left  = GET_UShort();
+          pair->right = GET_UShort();
+          pair->value = GET_UShort();
+        }
+
+        FORGET_Frame();
+
+        face->num_kern_pairs   = num_pairs;
+        face->kern_table_index = n;
+        goto Exit;
+      }
+
+      if ( FILE_Skip( length ) )
+        goto Exit;
+    }
+
+    /* no kern table found -- doesn't matter */
+    face->kern_table_index = -1;
+    face->num_kern_pairs   = 0;
+    face->kern_pairs       = NULL;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Hdmx                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal device metrics table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Hdmx( TT_Face    face,
+                          FT_Stream  stream )
+  {
+    FT_Error  error;
+    FT_Memory memory = stream->memory;
+
+    TT_Hdmx*  hdmx = &face->hdmx;
+    FT_Long   num_glyphs;
+    FT_Long   record_size;
+
+
+    hdmx->version     = 0;
+    hdmx->num_records = 0;
+    hdmx->records     = 0;
+
+    /* this table is optional */
+    error = face->goto_table( face, TTAG_hdmx, stream, 0 );
+    if ( error )
+      return TT_Err_Ok;
+
+    if ( ACCESS_Frame( 8L ) )
+      goto Exit;
+
+    hdmx->version     = GET_UShort();
+    hdmx->num_records = GET_Short();
+    record_size       = GET_Long();
+
+    FORGET_Frame();
+
+    /* Only recognize format 0 */
+    if ( hdmx->version != 0 )
+      goto Exit;
+
+    if ( ALLOC_ARRAY( hdmx->records, hdmx->num_records, TT_HdmxRec ) )
+      goto Exit;
+
+    num_glyphs   = face->root.num_glyphs;
+    record_size -= num_glyphs + 2;
+
+    {
+      TT_HdmxRec*  cur   = hdmx->records;
+      TT_HdmxRec*  limit = cur + hdmx->num_records;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        /* read record */
+        if ( READ_Byte( cur->ppem      ) ||
+             READ_Byte( cur->max_width ) )
+          goto Exit;
+
+        if ( ALLOC( cur->widths, num_glyphs )     ||
+             FILE_Read( cur->widths, num_glyphs ) )
+          goto Exit;
+
+        /* skip padding bytes */
+        if ( record_size > 0 && FILE_Skip( record_size ) )
+            goto Exit;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Free_Hdmx                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Frees the horizontal device metrics table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  TT_Free_Hdmx( TT_Face  face )
+  {
+    if ( face )
+    {
+      FT_Int     n;
+      FT_Memory  memory = face->root.driver->root.memory;
+
+
+      for ( n = 0; n < face->hdmx.num_records; n++ )
+        FREE( face->hdmx.records[n].widths );
+
+      FREE( face->hdmx.records );
+      face->hdmx.num_records = 0;
+    }
+  }
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttload.h b/src/freetype/sfnt/ttload.h
new file mode 100644 (file)
index 0000000..dd0de6a
--- /dev/null
@@ -0,0 +1,132 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttload.h                                                               */
+/*                                                                         */
+/*    Load the basic TrueType tables, i.e., tables that can be either in   */
+/*    TTF or OTF fonts (specification).                                    */
+/*                                                                         */
+/*  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 TTLOAD_H
+#define TTLOAD_H
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/tttypes.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  LOCAL_DEF
+  TT_Table*  TT_LookUp_Table( TT_Face   face,
+                              FT_ULong  tag );
+
+  LOCAL_DEF
+  FT_Error  TT_Goto_Table( TT_Face    face,
+                           FT_ULong   tag,
+                           FT_Stream  stream,
+                           FT_ULong*  length );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_SFNT_Header( TT_Face       face,
+                                 FT_Stream     stream,
+                                 FT_Long       face_index,
+                                 SFNT_Header*  sfnt );
+  LOCAL_DEF
+  FT_Error  TT_Load_Directory( TT_Face       face,
+                               FT_Stream     stream,
+                               SFNT_Header*  sfnt );
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Any( TT_Face    face,
+                         FT_ULong   tag,
+                         FT_Long    offset,
+                         FT_Byte*   buffer,
+                         FT_ULong*  length );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Header( TT_Face    face,
+                            FT_Stream  stream );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Metrics_Header( TT_Face    face,
+                                    FT_Stream  stream,
+                                    FT_Bool    vertical );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_CMap( TT_Face    face,
+                          FT_Stream  stream );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_MaxProfile( TT_Face    face,
+                                FT_Stream  stream );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Names( TT_Face    face,
+                           FT_Stream  stream );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_OS2( TT_Face    face,
+                         FT_Stream  stream );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_PostScript( TT_Face    face,
+                                FT_Stream  stream );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Hdmx( TT_Face    face,
+                          FT_Stream  stream );
+
+  LOCAL_DEF
+  FT_Error  TT_Load_PCLT( TT_Face    face,
+                          FT_Stream  stream );
+
+  LOCAL_DEF
+  void  TT_Free_Names( TT_Face  face );
+
+
+  LOCAL_DEF
+  void  TT_Free_Hdmx ( TT_Face  face );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Kern( TT_Face    face,
+                          FT_Stream  stream );
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Gasp( TT_Face    face,
+                          FT_Stream  stream );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* TTLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttpost.c b/src/freetype/sfnt/ttpost.c
new file mode 100644 (file)
index 0000000..c83205b
--- /dev/null
@@ -0,0 +1,536 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpost.c                                                               */
+/*                                                                         */
+/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    (body).                                                              */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The post table is not completely loaded by the core engine.  This     */
+  /* file loads the missing PS glyph names and implements an API to access */
+  /* them.                                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/tterrors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttpost.h"
+#include "ttload.h"
+
+#else
+
+#include <sfnt/ttpost.h>
+#include <sfnt/ttload.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttpost
+
+
+  /* If this configuration macro is defined, we rely on the `PSNames' */
+  /* module to grab the glyph names.                                  */
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+#include <freetype/internal/psnames.h>
+
+#define MAC_NAME( x )  ( (FT_String*)psnames->macintosh_name( x ) )
+
+
+#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+   /* Otherwise, we ignore the `PSNames' module, and provide our own  */
+   /* table of Mac names.  Thus, it is possible to build a version of */
+   /* FreeType without the Type 1 driver & PSNames module.            */
+
+#define  MAC_NAME( x )  TT_Post_Default_Names[x]
+
+  /* the 258 default Mac PS glyph names */
+
+  FT_String*  TT_Post_Default_Names[258] =
+  {
+    /*   0 */
+    ".notdef", ".null", "CR", "space", "exclam",
+    "quotedbl", "numbersign", "dollar", "percent", "ampersand",
+    /*  10 */
+    "quotesingle", "parenleft", "parenright", "asterisk", "plus",
+    "comma", "hyphen", "period", "slash", "zero",
+    /*  20 */
+    "one", "two", "three", "four", "five",
+    "six", "seven", "eight", "nine", "colon",
+    /*  30 */
+    "semicolon", "less", "equal", "greater", "question",
+    "at", "A", "B", "C", "D",
+    /*  40 */
+    "E", "F", "G", "H", "I",
+    "J", "K", "L", "M", "N",
+    /*  50 */
+    "O", "P", "Q", "R", "S",
+    "T", "U", "V", "W", "X",
+    /*  60 */
+    "Y", "Z", "bracketleft", "backslash", "bracketright",
+    "asciicircum", "underscore", "grave", "a", "b",
+    /*  70 */
+    "c", "d", "e", "f", "g",
+    "h", "i", "j", "k", "l",
+    /*  80 */
+    "m", "n", "o", "p", "q",
+    "r", "s", "t", "u", "v",
+    /*  90 */
+    "w", "x", "y", "z", "braceleft",
+    "bar", "braceright", "asciitilde", "Adieresis", "Aring",
+    /* 100 */
+    "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
+    "aacute", "agrave", "acircumflex", "adieresis", "atilde",
+    /* 110 */
+    "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
+    "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
+    /* 120 */
+    "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
+    "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
+    /* 130 */
+    "dagger", "degree", "cent", "sterling", "section",
+    "bullet", "paragraph", "germandbls", "registered", "copyright",
+    /* 140 */
+    "trademark", "acute", "dieresis", "notequal", "AE",
+    "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
+    /* 150 */
+    "yen", "mu", "partialdiff", "summation", "product",
+    "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
+    /* 160 */
+    "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
+    "radical", "florin", "approxequal", "Delta", "guillemotleft",
+    /* 170 */
+    "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
+    "Otilde", "OE", "oe", "endash", "emdash",
+    /* 180 */
+    "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
+    "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
+    /* 190 */
+    "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
+    "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
+    /* 200 */
+    "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
+    "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
+    /* 210 */
+    "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
+    "dotlessi", "circumflex", "tilde", "macron", "breve",
+    /* 220 */
+    "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
+    "caron", "Lslash", "lslash", "Scaron", "scaron",
+    /* 230 */
+    "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
+    "Yacute", "yacute", "Thorn", "thorn", "minus",
+    /* 240 */
+    "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
+    "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
+    /* 250 */
+    "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
+    "Ccaron", "ccaron", "dmacron",
+  };
+
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+  static
+  FT_Error  Load_Format_20( TT_Face    face,
+                            FT_Stream  stream )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error;
+
+    FT_Int     num_glyphs;
+    FT_Int     num_names;
+
+    FT_UShort* glyph_indices = 0;
+    FT_Char**  name_strings  = 0;
+
+
+    if ( READ_UShort( num_glyphs ) )
+      goto Exit;
+
+    /* UNDOCUMENTED!  The number of glyphs in this table can be smaller */
+    /* than the value in the maxp table (cf. cyberbit.ttf).             */
+
+    /* There already exist fonts which have more than 32768 glyph names */
+    /* in this table, so the test for this threshold has been dropped.  */
+
+    if ( num_glyphs > face->root.num_glyphs )
+    {
+      error = TT_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* load the indices */
+    {
+      FT_Int  n;
+
+
+      if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, FT_UShort ) ||
+           ACCESS_Frame( num_glyphs * 2L )                      )
+        goto Fail;
+
+      for ( n = 0; n < num_glyphs; n++ )
+        glyph_indices[n] = GET_UShort();
+
+      FORGET_Frame();
+    }
+
+    /* compute number of names stored in table */
+    {
+      FT_Int  n;
+
+
+      num_names = 0;
+
+      for ( n = 0; n < num_glyphs; n++ )
+      {
+        FT_Int  index;
+
+
+        index = glyph_indices[n];
+        if ( index >= 258 )
+        {
+          index -= 257;
+          if ( index > num_names )
+            num_names = index;
+        }
+      }
+    }
+
+    /* now load the name strings */
+    {
+      FT_Int  n;
+
+
+      if ( ALLOC_ARRAY( name_strings, num_names, FT_Char* ) )
+        goto Fail;
+
+      for ( n = 0; n < num_names; n++ )
+      {
+        FT_UInt  len;
+
+
+        if ( READ_Byte  ( len )                               ||
+             ALLOC_ARRAY( name_strings[n], len + 1, FT_Char ) ||
+             FILE_Read  ( name_strings[n], len )              )
+          goto Fail1;
+
+        name_strings[n][len] = '\0';
+      }
+    }
+
+    /* all right, set table fields and exit successfuly */
+    {
+      TT_Post_20*  table = &face->postscript_names.names.format_20;
+
+
+      table->num_glyphs    = num_glyphs;
+      table->num_names     = num_names;
+      table->glyph_indices = glyph_indices;
+      table->glyph_names   = name_strings;
+    }
+    return TT_Err_Ok;
+
+
+  Fail1:
+    {
+      FT_Int  n;
+
+
+      for ( n = 0; n < num_names; n++ )
+        FREE( name_strings[n] );
+    }
+
+  Fail:
+    FREE( name_strings );
+    FREE( glyph_indices );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error  Load_Format_25( TT_Face    face,
+                            FT_Stream  stream )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error;
+
+    FT_Int     num_glyphs;
+    FT_Char*   offset_table = 0;
+
+
+    /* UNDOCUMENTED!  This value appears only in the Apple TT specs. */
+    if ( READ_UShort( num_glyphs ) )
+      goto Exit;
+
+    /* check the number of glyphs */
+    if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
+    {
+      error = TT_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    if ( ALLOC    ( offset_table, num_glyphs ) ||
+         FILE_Read( offset_table, num_glyphs ) )
+      goto Fail;
+
+    /* now check the offset table */
+    {
+      FT_Int  n;
+
+
+      for ( n = 0; n < num_glyphs; n++ )
+      {
+        FT_Long  index = (FT_Long)n + offset_table[n];
+
+
+        if ( index < 0 || index > num_glyphs )
+        {
+          error = TT_Err_Invalid_File_Format;
+          goto Fail;
+        }
+      }
+    }
+
+    /* OK, set table fields and exit successfuly */
+    {
+      TT_Post_25*  table = &face->postscript_names.names.format_25;
+
+
+      table->num_glyphs = num_glyphs;
+      table->offsets    = offset_table;
+    }
+
+    return TT_Err_Ok;
+
+  Fail:
+    FREE( offset_table );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error  Load_Post_Names( TT_Face  face )
+  {
+    FT_Stream   stream;
+    FT_Error    error;
+
+    /* get a stream for the face's resource */
+    stream = face->root.stream;
+
+    /* seek to the beginning of the PS names table */
+    error = face->goto_table( face, TTAG_post, stream, 0 );
+    if ( error )
+      goto Exit;
+
+    /* now read postscript table */
+    switch ( face->postscript.FormatType )
+    {
+    case 0x00020000L:
+      error = Load_Format_20( face, stream );
+      break;
+
+    case 0x00028000L:
+      error = Load_Format_25( face, stream );
+      break;
+
+    default:
+      error = TT_Err_Invalid_File_Format;
+    }
+
+    face->postscript_names.loaded = 1;
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  TT_Free_Post_Names( TT_Face  face )
+  {
+    FT_Memory       memory = face->root.memory;
+    TT_Post_Names*  names  = &face->postscript_names;
+
+
+    if ( names->loaded )
+    {
+      switch ( face->postscript.FormatType )
+      {
+      case 0x00020000L:
+        {
+          TT_Post_20*  table = &names->names.format_20;
+          FT_UInt      n;
+
+
+          FREE( table->glyph_indices );
+          table->num_glyphs = 0;
+
+          for ( n = 0; n < table->num_names; n++ )
+            FREE( table->glyph_names[n] );
+
+          FREE( table->glyph_names );
+          table->num_names = 0;
+        }
+        break;
+
+      case 0x00028000L:
+        {
+          TT_Post_25*  table = &names->names.format_25;
+
+
+          FREE( table->offsets );
+          table->num_glyphs = 0;
+        }
+        break;
+      }
+    }
+    names->loaded = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Get_PS_Name                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Gets the PostScript glyph name of a glyph.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the parent face.                             */
+  /*                                                                       */
+  /*    index  :: The glyph index.                                         */
+  /*                                                                       */
+  /*    PSname :: The address of a string pointer.  Will be NULL in case   */
+  /*              of error, otherwise it is a pointer to the glyph name.   */
+  /*                                                                       */
+  /*              You must not modify the returned string!                 */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Get_PS_Name( TT_Face      face,
+                            FT_UInt      index,
+                            FT_String**  PSname )
+  {
+    FT_Error            error;
+    TT_Post_Names*      names;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+    PSNames_Interface*  psnames;
+#endif
+
+
+    if ( !face )
+      return TT_Err_Invalid_Face_Handle;
+
+    if ( index >= (FT_UInt)face->root.num_glyphs )
+      return TT_Err_Invalid_Glyph_Index;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+      return TT_Err_Unimplemented_Feature;
+#endif
+
+    names = &face->postscript_names;
+
+    /* `.notdef' by default */
+    *PSname = MAC_NAME( 0 );
+
+    switch ( face->postscript.FormatType )
+    {
+    case 0x00010000L:
+      if ( index < 258 )                    /* paranoid checking */
+        *PSname = MAC_NAME( index );
+      break;
+
+    case 0x00020000L:
+      {
+        TT_Post_20*  table = &names->names.format_20;
+
+
+        if ( !names->loaded )
+        {
+          error = Load_Post_Names( face );
+          if ( error )
+            break;
+        }
+
+        if ( index < table->num_glyphs )
+        {
+          FT_UShort  name_index = table->glyph_indices[index];
+
+
+          if ( name_index < 258 )
+            *PSname = MAC_NAME( name_index );
+          else
+            *PSname = (FT_String*)table->glyph_names[name_index - 258];
+        }
+      }
+      break;
+
+    case 0x00028000L:
+      {
+        TT_Post_25*  table = &names->names.format_25;
+
+
+        if ( !names->loaded )
+        {
+          error = Load_Post_Names( face );
+          if ( error )
+            break;
+        }
+
+        if ( index < table->num_glyphs )    /* paranoid checking */
+        {
+          index  += table->offsets[index];
+          *PSname = MAC_NAME( index );
+        }
+      }
+      break;
+
+    case 0x00030000L:
+      break;                                /* nothing to do */
+    }
+
+    return TT_Err_Ok;
+  }
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttpost.h b/src/freetype/sfnt/ttpost.h
new file mode 100644 (file)
index 0000000..e3da836
--- /dev/null
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpost.h                                                               */
+/*                                                                         */
+/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  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 TTPOST_H
+#define TTPOST_H
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/tttypes.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+#define TT_Err_Invalid_Post_Table_Format  0x0B00
+#define TT_Err_Invalid_Post_Table         0x0B01
+
+
+  LOCAL_DEF
+  FT_Error TT_Get_PS_Name( TT_Face      face,
+                           FT_UInt      index,
+                           FT_String**  PSname );
+
+  LOCAL_DEF
+  void  TT_Free_Post_Names( TT_Face  face );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* TTPOST_H */
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttsbit.c b/src/freetype/sfnt/ttsbit.c
new file mode 100644 (file)
index 0000000..9a5455a
--- /dev/null
@@ -0,0 +1,1444 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttsbit.c                                                               */
+/*                                                                         */
+/*    TrueType and OpenType embedded bitmap support (body).                */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/tterrors.h>
+#include <freetype/tttags.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttsbit.h"
+
+#else
+
+#include <sfnt/ttsbit.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttsbit
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    blit_sbit                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Blits a bitmap from an input stream into a given target.  Supports */
+  /*    x and y offsets as well as byte padded lines.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    target      :: The target bitmap/pixmap.                           */
+  /*                                                                       */
+  /*    source      :: The input packed bitmap data.                       */
+  /*                                                                       */
+  /*    line_bits   :: The number of bits per line.                        */
+  /*                                                                       */
+  /*    byte_padded :: A flag which is true if lines are byte-padded.      */
+  /*                                                                       */
+  /*    x_offset    :: The horizontal offset.                              */
+  /*                                                                       */
+  /*    y_offset    :: The vertical offset.                                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    IMPORTANT: The x and y offsets are relative to the top corner of   */
+  /*               the target bitmap (unlike the normal TrueType           */
+  /*               convention).  A positive y offset indicates a downwards */
+  /*               direction!                                              */
+  /*                                                                       */
+  static
+  void  blit_sbit( FT_Bitmap*  target,
+                   FT_Byte*    source,
+                   FT_Int      line_bits,
+                   FT_Bool     byte_padded,
+                   FT_Int      x_offset,
+                   FT_Int      y_offset )
+  {
+    FT_Byte*   line_buff;
+    FT_Int     line_incr;
+    FT_Int     height;
+
+    FT_UShort  acc;
+    FT_Byte    loaded;
+
+
+    /* first of all, compute starting write position */
+    line_incr = target->pitch;
+    line_buff = target->buffer;
+
+    if ( line_incr < 0 )
+      line_buff -= line_incr * ( target->rows - 1 );
+
+    line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* We use the extra-classic `accumulator' trick to extract the bits    */
+    /* from the source byte stream.                                        */
+    /*                                                                     */
+    /* Namely, the variable `acc' is a 16-bit accumulator containing the   */
+    /* last `loaded' bits from the input stream.  The bits are shifted to  */
+    /* the upmost position in `acc'.                                       */
+    /*                                                                     */
+    /***********************************************************************/
+
+    acc    = 0;  /* clear accumulator   */
+    loaded = 0;  /* no bits were loaded */
+
+    for ( height = target->rows; height > 0; height-- )
+    {
+      FT_Byte*  cur   = line_buff;    /* current write cursor          */
+      FT_Int    count = line_bits;    /* # of bits to extract per line */
+      FT_Byte   shift = x_offset & 7; /* current write shift           */
+      FT_Byte   space = 8 - shift;
+
+
+      /* first of all, read individual source bytes */
+      if ( count >= 8 )
+      {
+        count -= 8;
+        {
+          do
+          {
+            FT_Byte  val;
+
+
+            /* ensure that there are at least 8 bits in the accumulator */
+            if ( loaded < 8 )
+            {
+              acc    |= (FT_UShort)*source++ << ( 8 - loaded );
+              loaded += 8;
+            }
+
+            /* now write one byte */
+            val = (FT_Byte)( acc >> 8 );
+            if ( shift )
+            {
+              cur[0] |= val >> shift;
+              cur[1] |= val << space;
+            }
+            else
+              cur[0] |= val;
+
+            cur++;
+            acc   <<= 8;  /* remove bits from accumulator */
+            loaded -= 8;
+            count  -= 8;
+
+          } while ( count >= 0 );
+        }
+
+        /* restore `count' to correct value */
+        count += 8;
+      }
+
+      /* now write remaining bits (count < 8) */
+      if ( count > 0 )
+      {
+        FT_Byte  val;
+
+
+        /* ensure that there are at least `count' bits in the accumulator */
+        if ( loaded < count )
+        {
+          acc    |= (FT_UShort)*source++ << ( 8 - loaded );
+          loaded += 8;
+        }
+
+        /* now write remaining bits */
+        val     = ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count );
+        cur[0] |= val >> shift;
+
+        if ( count > space )
+          cur[1] |= val << space;
+
+        acc   <<= count;
+        loaded -= count;
+      }
+
+      /* now, skip to next line */
+      if ( byte_padded )
+        acc = loaded = 0;   /* clear accumulator on byte-padded lines */
+
+      line_buff += line_incr;
+    }
+  }
+
+
+  const FT_Frame_Field  sbit_metrics_fields[] =
+  {
+    FT_FRAME_START( 8 ),
+      FT_FRAME_BYTE( TT_SBit_Metrics, height ),
+      FT_FRAME_BYTE( TT_SBit_Metrics, width ),
+
+      FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingX ),
+      FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingY ),
+      FT_FRAME_BYTE( TT_SBit_Metrics, horiAdvance ),
+
+      FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingX ),
+      FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingY ),
+      FT_FRAME_BYTE( TT_SBit_Metrics, vertAdvance ),
+    FT_FRAME_END
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Const_Metrics                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the metrics for `EBLC' index tables format 2 and 5.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range  :: The target range.                                        */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Load_SBit_Const_Metrics( TT_SBit_Range*  range,
+                                     FT_Stream       stream )
+  {
+    FT_Error  error;
+
+
+    if ( READ_ULong( range->image_size ) )
+      return error;
+
+    return READ_Fields( sbit_metrics_fields, &range->metrics );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Range_Codes                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the range codes for `EBLC' index tables format 4 and 5.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range        :: The target range.                                  */
+  /*                                                                       */
+  /*    stream       :: The input stream.                                  */
+  /*                                                                       */
+  /*    load_offsets :: A flag whether to load the glyph offset table.     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Load_SBit_Range_Codes( TT_SBit_Range*  range,
+                                   FT_Stream       stream,
+                                   FT_Bool         load_offsets )
+  {
+    FT_Error   error;
+    FT_ULong   count, n, size;
+    FT_Memory  memory = stream->memory;
+
+
+    if ( READ_ULong( count ) )
+      goto Exit;
+
+    range->num_glyphs = count;
+
+    /* Allocate glyph offsets table if needed */
+    if ( load_offsets )
+    {
+      if ( ALLOC_ARRAY( range->glyph_offsets, count, FT_ULong ) )
+        goto Exit;
+
+      size = count * 4L;
+    }
+    else
+      size = count * 2L;
+
+    /* Allocate glyph codes table and access frame */
+    if ( ALLOC_ARRAY ( range->glyph_codes, count, FT_UShort ) ||
+         ACCESS_Frame( size )                                 )
+      goto Exit;
+
+    for ( n = 0; n < count; n++ )
+    {
+      range->glyph_codes[n] = GET_UShort();
+
+      if ( load_offsets )
+        range->glyph_offsets[n] = (FT_ULong)range->image_offset +
+                                  GET_UShort();
+    }
+
+    FORGET_Frame();
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Range                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given `EBLC' index/range table.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range  :: The target range.                                        */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Load_SBit_Range( TT_SBit_Range*  range,
+                             FT_Stream       stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+
+    switch( range->index_format )
+    {
+    case 1:   /* variable metrics with 4-byte offsets */
+    case 3:   /* variable metrics with 2-byte offsets */
+      {
+        FT_ULong  num_glyphs, n;
+        FT_Int    size_elem;
+        FT_Bool   large = ( range->index_format == 1 );
+
+
+        num_glyphs        = range->last_glyph - range->first_glyph + 1L;
+        range->num_glyphs = num_glyphs;
+        num_glyphs++;                       /* XXX: BEWARE - see spec */
+
+        size_elem = large ? 4 : 2;
+
+        if ( ALLOC_ARRAY( range->glyph_offsets,
+                          num_glyphs, FT_ULong )    ||
+             ACCESS_Frame( num_glyphs * size_elem ) )
+          goto Exit;
+
+        for ( n = 0; n < num_glyphs; n++ )
+          range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
+                                                  ( large ? GET_ULong()
+                                                          : GET_UShort() ) );
+        FORGET_Frame();
+      }
+      break;
+
+    case 2:   /* all glyphs have identical metrics */
+      error = Load_SBit_Const_Metrics( range, stream );
+      break;
+
+    case 4:
+      error = Load_SBit_Range_Codes( range, stream, 1 );
+      break;
+
+    case 5:
+      error = Load_SBit_Const_Metrics( range, stream ) ||
+              Load_SBit_Range_Codes( range, stream, 0  );
+      break;
+
+    default:
+      error = TT_Err_Invalid_File_Format;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Strikes                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the table of embedded bitmap sizes for this face.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: The target face object.                                  */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_SBit_Strikes( TT_Face    face,
+                                  FT_Stream  stream )
+  {
+    FT_Error   error  = 0;
+    FT_Memory  memory = stream->memory;
+    FT_Fixed   version;
+    FT_ULong   num_strikes;
+    FT_ULong   table_base;
+
+    const FT_Frame_Field  sbit_line_metrics_fields[] =
+    {
+      /* no FT_FRAME_START */
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, ascender ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, descender ),
+        FT_FRAME_BYTE( TT_SBit_Line_Metrics, max_width ),
+
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_numerator ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_denominator ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_offset ),
+
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_origin_SB ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_advance_SB ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, max_before_BL ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_after_BL ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[0] ),
+        FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[1] ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  strike_start_fields[] =
+    {
+      /* no FT_FRAME_START */
+        FT_FRAME_ULONG( TT_SBit_Strike, ranges_offset ),
+        FT_FRAME_SKIP_LONG,
+        FT_FRAME_ULONG( TT_SBit_Strike, num_ranges ),
+        FT_FRAME_ULONG( TT_SBit_Strike, color_ref ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  strike_end_fields[] =
+    {
+      /* no FT_FRAME_START */
+        FT_FRAME_USHORT( TT_SBit_Strike, start_glyph ),
+        FT_FRAME_USHORT( TT_SBit_Strike, end_glyph ),
+        FT_FRAME_BYTE  ( TT_SBit_Strike, x_ppem ),
+        FT_FRAME_BYTE  ( TT_SBit_Strike, y_ppem ),
+        FT_FRAME_BYTE  ( TT_SBit_Strike, bit_depth ),
+        FT_FRAME_CHAR  ( TT_SBit_Strike, flags ),
+      FT_FRAME_END
+    };
+
+
+    face->num_sbit_strikes = 0;
+
+    /* this table is optional */
+    error = face->goto_table( face, TTAG_EBLC, stream, 0 );
+    if (error)
+      error = face->goto_table( face, TTAG_bloc, stream, 0 );
+    if ( error )
+    {
+      error = 0;
+      goto Exit;
+    }
+
+    table_base = FILE_Pos();
+    if ( ACCESS_Frame( 8L ) )
+      goto Exit;
+
+    version     = GET_Long();
+    num_strikes = GET_ULong();
+
+    FORGET_Frame();
+
+    /* check version number and strike count */
+    if ( version     != 0x00020000L ||
+         num_strikes >= 0x10000L    )
+    {
+      FT_ERROR(( "TT_Load_SBit_Strikes: invalid table version!\n" ));
+      error = TT_Err_Invalid_File_Format;
+
+      goto Exit;
+    }
+
+    /* allocate the strikes table */
+    if ( ALLOC_ARRAY( face->sbit_strikes, num_strikes, TT_SBit_Strike ) )
+      goto Exit;
+
+    face->num_sbit_strikes = num_strikes;
+
+    /* now read each strike table separately */
+    {
+      TT_SBit_Strike*  strike = face->sbit_strikes;
+      FT_ULong         count  = num_strikes;
+
+
+      if ( ACCESS_Frame( 48L * num_strikes ) )
+        goto Exit;
+
+      while ( count > 0 )
+      {
+        (void)READ_Fields( strike_start_fields, strike );
+
+        (void)READ_Fields( sbit_line_metrics_fields, &strike->hori );
+        (void)READ_Fields( sbit_line_metrics_fields, &strike->vert );
+
+        (void)READ_Fields( strike_end_fields, strike );
+
+        count--;
+        strike++;
+      }
+
+      FORGET_Frame();
+    }
+
+    /* allocate the index ranges for each strike table */
+    {
+      TT_SBit_Strike*  strike = face->sbit_strikes;
+      FT_ULong         count  = num_strikes;
+
+
+      while ( count > 0 )
+      {
+        TT_SBit_Range*  range;
+        FT_ULong        count2 = strike->num_ranges;
+
+
+        if ( ALLOC_ARRAY( strike->sbit_ranges,
+                          strike->num_ranges,
+                          TT_SBit_Range ) )
+          goto Exit;
+
+        /* read each range */
+        if ( FILE_Seek( table_base + strike->ranges_offset ) ||
+             ACCESS_Frame( strike->num_ranges * 8L )         )
+          goto Exit;
+
+        range = strike->sbit_ranges;
+        while ( count2 > 0 )
+        {
+          range->first_glyph  = GET_UShort();
+          range->last_glyph   = GET_UShort();
+          range->table_offset = table_base + strike->ranges_offset
+                                 + GET_ULong();
+          count2--;
+          range++;
+        }
+
+        FORGET_Frame();
+
+        /* Now, read each index table */
+        count2 = strike->num_ranges;
+        range  = strike->sbit_ranges;
+        while ( count2 > 0 )
+        {
+          /* Read the header */
+          if ( FILE_Seek( range->table_offset ) ||
+               ACCESS_Frame( 8L )               )
+            goto Exit;
+
+          range->index_format = GET_UShort();
+          range->image_format = GET_UShort();
+          range->image_offset = GET_ULong();
+
+          FORGET_Frame();
+
+          error = Load_SBit_Range( range, stream );
+          if ( error )
+            goto Exit;
+
+          count2--;
+          range++;
+        }
+
+        count--;
+        strike++;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Free_SBit_Strikes                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Releases the embedded bitmap tables.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: The target face object.                                    */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  TT_Free_SBit_Strikes( TT_Face  face )
+  {
+    FT_Memory        memory       = face->root.memory;
+    TT_SBit_Strike*  strike       = face->sbit_strikes;
+    TT_SBit_Strike*  strike_limit = strike + face->num_sbit_strikes;
+
+
+    if ( strike )
+    {
+      for ( ; strike < strike_limit; strike++ )
+      {
+        TT_SBit_Range*  range       = strike->sbit_ranges;
+        TT_SBit_Range*  range_limit = range + strike->num_ranges;
+
+
+        if ( range )
+        {
+          for ( ; range < range_limit; range++ )
+          {
+            /* release the glyph offsets and codes tables */
+            /* where appropriate                          */
+            FREE( range->glyph_offsets );
+            FREE( range->glyph_codes );
+          }
+        }
+        FREE( strike->sbit_ranges );
+        strike->num_ranges = 0;
+      }
+      FREE( face->sbit_strikes );
+    }
+    face->num_sbit_strikes = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Find_SBit_Range                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Scans a given strike's ranges and return, for a given glyph        */
+  /*    index, the corresponding sbit range, and `EBDT' offset.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph_index   :: The glyph index.                                  */
+  /*    strike        :: The source/current sbit strike.                   */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    arange        :: The sbit range containing the glyph index.        */
+  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means the glyph index was found.           */
+  /*                                                                       */
+  static
+  FT_Error  Find_SBit_Range( FT_UInt          glyph_index,
+                             TT_SBit_Strike*  strike,
+                             TT_SBit_Range**  arange,
+                             FT_ULong*        aglyph_offset )
+  {
+    TT_SBit_Range  *range, *range_limit;
+
+
+    /* check whether the glyph index is within this strike's */
+    /* glyph range                                           */
+    if ( glyph_index < strike->start_glyph ||
+         glyph_index > strike->end_glyph   )
+      goto Fail;
+
+    /* scan all ranges in strike */
+    range       = strike->sbit_ranges;
+    range_limit = range + strike->num_ranges;
+    if ( !range )
+      goto Fail;
+
+    for ( ; range < range_limit; range++ )
+    {
+      if ( glyph_index >= range->first_glyph &&
+           glyph_index <= range->last_glyph  )
+      {
+        FT_UShort  delta = glyph_index - range->first_glyph;
+
+
+        switch ( range->index_format )
+        {
+        case 1:
+        case 3:
+          *aglyph_offset = range->glyph_offsets[delta];
+          break;
+
+        case 2:
+          *aglyph_offset = range->image_offset +
+                           range->image_size * delta;
+          break;
+
+        case 4:
+        case 5:
+          {
+            FT_ULong  n;
+
+
+            for ( n = 0; n < range->num_glyphs; n++ )
+            {
+              if ( range->glyph_codes[n] == glyph_index )
+              {
+                if ( range->index_format == 4 )
+                  *aglyph_offset = range->glyph_offsets[n];
+                else
+                  *aglyph_offset = range->image_offset +
+                                   n * range->image_size;
+                goto Found;
+              }
+            }
+          }
+
+          /* fall-through */
+          default:
+            goto Fail;
+        }
+
+    Found:
+        /* return successfully! */
+        *arange  = range;
+        return 0;
+      }
+    }
+
+  Fail:
+    *arange        = 0;
+    *aglyph_offset = 0;
+
+    return TT_Err_Invalid_Argument;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Find_SBit_Image                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Checks whether an embedded bitmap (an `sbit') exists for a given   */
+  /*    glyph, at given x and y ppems.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face          :: The target face object.                           */
+  /*    glyph_index   :: The glyph index.                                  */
+  /*    x_ppem        :: The horizontal resolution in points per EM.       */
+  /*    y_ppem        :: The vertical resolution in points per EM.         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    arange        :: The SBit range containing the glyph index.        */
+  /*    astrike       :: The SBit strike containing the glyph index.       */
+  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  Returns                    */
+  /*    TT_Err_Invalid_Argument if no sbit exists for the requested glyph. */
+  /*                                                                       */
+  static
+  FT_Error  Find_SBit_Image( TT_Face           face,
+                             FT_UInt           glyph_index,
+                             FT_Int            x_ppem,
+                             FT_Int            y_ppem,
+
+                             TT_SBit_Range**   arange,
+                             TT_SBit_Strike**  astrike,
+                             FT_ULong*         aglyph_offset )
+  {
+    TT_SBit_Strike*  strike       = face->sbit_strikes;
+    TT_SBit_Strike*  strike_limit = strike + face->num_sbit_strikes;
+
+
+    if ( !strike )
+      goto Fail;
+
+    for ( ; strike < strike_limit; strike++ )
+    {
+      if ( strike->x_ppem == x_ppem && strike->y_ppem == y_ppem )
+      {
+        FT_Error  error;
+
+
+        error = Find_SBit_Range( glyph_index, strike,
+                                 arange, aglyph_offset );
+        if ( error )
+          goto Fail;
+
+        *astrike = strike;
+
+        return TT_Err_Ok;
+      }
+    }
+
+  Fail:
+    /* no embedded bitmap for this glyph in face */
+    *arange        = 0;
+    *astrike       = 0;
+    *aglyph_offset = 0;
+
+    return TT_Err_Invalid_Argument;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_SBit_Metrics                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Gets the big metrics for a given SBit.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream      :: The input stream.                                   */
+  /*                                                                       */
+  /*    range       :: The SBit range containing the glyph.                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    big_metrics :: A big SBit metrics structure for the glyph.         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be positioned at the glyph's offset within  */
+  /*    the `EBDT' table before the call.                                  */
+  /*                                                                       */
+  /*    If the image format uses variable metrics, the stream cursor is    */
+  /*    positioned just after the metrics header in the `EBDT' table on    */
+  /*    function exit.                                                     */
+  /*                                                                       */
+  static
+  FT_Error  Load_SBit_Metrics( FT_Stream         stream,
+                               TT_SBit_Range*    range,
+                               TT_SBit_Metrics*  metrics )
+  {
+    FT_Error  error = TT_Err_Ok;
+
+
+    switch ( range->image_format )
+    {
+    case 1:
+    case 2:
+    case 8:
+      /* variable small metrics */
+      {
+        TT_SBit_Small_Metrics  smetrics;
+
+        const FT_Frame_Field  sbit_small_metrics_fields[] =
+        {
+          FT_FRAME_START( 5 ),
+            FT_FRAME_BYTE( TT_SBit_Small_Metrics, height ),
+            FT_FRAME_BYTE( TT_SBit_Small_Metrics, width ),
+            FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingX ),
+            FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingY ),
+            FT_FRAME_BYTE( TT_SBit_Small_Metrics, advance ),
+          FT_FRAME_END
+        };
+
+
+        /* read small metrics */
+        if ( READ_Fields( sbit_small_metrics_fields, &smetrics ) )
+          goto Exit;
+
+        /* convert it to a big metrics */
+        metrics->height       = smetrics.height;
+        metrics->width        = smetrics.width;
+        metrics->horiBearingX = smetrics.bearingX;
+        metrics->horiBearingY = smetrics.bearingY;
+        metrics->horiAdvance  = smetrics.advance;
+
+        /* these metrics are made up at a higher level when */
+        /* needed.                                          */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+      }
+      break;
+
+    case 6:
+    case 7:
+    case 9:
+      /* variable big metrics */
+      (void)READ_Fields( sbit_metrics_fields, metrics );
+      break;
+
+    case 5:
+    default:  /* constant metrics */
+      if ( range->index_format == 2 || range->index_format == 5 )
+        *metrics = range->metrics;
+      else
+        return TT_Err_Invalid_File_Format;
+   }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Crop_Bitmap                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Crops a bitmap to its tightest bounding box, and adjusts its       */
+  /*    metrics.                                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    image   :: The input glyph slot.                                   */
+  /*                                                                       */
+  /*    metrics :: The corresponding metrics structure.                    */
+  /*                                                                       */
+  static
+  void  Crop_Bitmap( FT_Bitmap*        map,
+                     TT_SBit_Metrics*  metrics )
+  {
+    /***********************************************************************/
+    /*                                                                     */
+    /* In this situation, some bounding boxes of embedded bitmaps are too  */
+    /* large.  We need to crop it to a reasonable size.                    */
+    /*                                                                     */
+    /*      ---------                                                      */
+    /*      |       |                -----                                 */
+    /*      |  ***  |                |***|                                 */
+    /*      |   *   |                | * |                                 */
+    /*      |   *   |    ------>     | * |                                 */
+    /*      |   *   |                | * |                                 */
+    /*      |   *   |                | * |                                 */
+    /*      |  ***  |                |***|                                 */
+    /*      ---------                -----                                 */
+    /*                                                                     */
+    /***********************************************************************/
+
+    FT_Int    rows, count;
+    FT_Long   line_len;
+    FT_Byte*  line;
+
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* first of all, check the top-most lines of the bitmap, and remove    */
+    /* them if they're empty.                                              */
+    /*                                                                     */
+    {
+      line     = (FT_Byte*)map->buffer;
+      rows     = map->rows;
+      line_len = map->pitch;
+
+
+      for ( count = 0; count < rows; count++ )
+      {
+        FT_Byte*  cur   = line;
+        FT_Byte*  limit = line + line_len;
+
+
+        for ( ; cur < limit; cur++ )
+          if ( cur[0] )
+            goto Found_Top;
+
+        /* the current line was empty - skip to next one */
+        line  = limit;
+      }
+
+    Found_Top:
+      /* check that we have at least one filled line */
+      if ( count >= rows )
+        goto Empty_Bitmap;
+
+      /* now, crop the empty upper lines */
+      if ( count > 0 )
+      {
+        line = (FT_Byte*)map->buffer;
+
+        MEM_Move( line, line + count * line_len,
+                  ( rows - count ) * line_len );
+
+        metrics->height       -= count;
+        metrics->horiBearingY -= count;
+        metrics->vertBearingY -= count;
+
+        map->rows -= count;
+        rows      -= count;
+      }
+    }
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* second, crop the lower lines                                        */
+    /*                                                                     */
+    {
+      line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
+
+      for ( count = 0; count < rows; count++ )
+      {
+        FT_Byte*  cur   = line;
+        FT_Byte*  limit = line + line_len;
+
+
+        for ( ; cur < limit; cur++ )
+          if ( cur[0] )
+            goto Found_Bottom;
+
+        /* the current line was empty - skip to previous one */
+        line -= line_len;
+      }
+
+    Found_Bottom:
+      if ( count > 0 )
+      {
+        metrics->height -= count;
+        rows            -= count;
+        map->rows       -= count;
+      }
+    }
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* third, get rid of the space on the left side of the glyph           */
+    /*                                                                     */
+    do
+    {
+      FT_Byte*  limit;
+
+
+      line  = (FT_Byte*)map->buffer;
+      limit = line + rows * line_len;
+
+      for ( ; line < limit; line += line_len )
+        if ( line[0] & 0x80 )
+          goto Found_Left;
+
+      /* shift the whole glyph one pixel to the left */
+      line  = (FT_Byte*)map->buffer;
+      limit = line + rows * line_len;
+
+      for ( ; line < limit; line += line_len )
+      {
+        FT_Int    n, width = map->width;
+        FT_Byte   old;
+        FT_Byte*  cur = line;
+
+
+        old = cur[0] << 1;
+        for ( n = 8; n < width; n += 8 )
+        {
+          FT_Byte  val;
+
+
+          val    = cur[1];
+          cur[0] = old | ( val >> 7 );
+          old    = val << 1;
+          cur++;
+        }
+        cur[0] = old;
+      }
+
+      map->width--;
+      metrics->horiBearingX++;
+      metrics->vertBearingX++;
+      metrics->width--;
+
+    } while ( map->width > 0 );
+
+  Found_Left:
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* finally, crop the bitmap width to get rid of the space on the right */
+    /* side of the glyph.                                                  */
+    /*                                                                     */
+    do
+    {
+      FT_Int    right = map->width - 1;
+      FT_Byte*  limit;
+      FT_Byte   mask;
+
+
+      line  = (FT_Byte*)map->buffer + ( right >> 3 );
+      limit = line + rows * line_len;
+      mask  = 0x80 >> ( right & 7 );
+
+      for ( ; line < limit; line += line_len )
+        if ( line[0] & mask )
+          goto Found_Right;
+
+      /* crop the whole glyph to the right */
+      map->width--;
+      metrics->width--;
+
+    } while ( map->width > 0 );
+
+  Found_Right:
+    /* all right, the bitmap was cropped */
+    return;
+
+  Empty_Bitmap:
+    map->width      = 0;
+    map->rows       = 0;
+    map->pitch      = 0;
+    map->pixel_mode = ft_pixel_mode_mono;
+  }
+
+
+  static
+  FT_Error Load_SBit_Single( FT_Bitmap*        map,
+                             FT_Int            x_offset,
+                             FT_Int            y_offset,
+                             FT_Int            pix_bits,
+                             FT_UShort         image_format,
+                             TT_SBit_Metrics*  metrics,
+                             FT_Stream         stream )
+  {
+    FT_Error  error;
+
+
+    /* check that the source bitmap fits into the target pixmap */
+    if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
+         y_offset < 0 || y_offset + metrics->height > map->rows  )
+    {
+      error = TT_Err_Invalid_Argument;
+
+      goto Exit;
+    }
+
+    {
+      FT_Int  glyph_width  = metrics->width;
+      FT_Int  glyph_height = metrics->height;
+      FT_Int  glyph_size;
+      FT_Int  line_bits    = pix_bits * glyph_width;
+      FT_Bool pad_bytes    = 0;
+
+
+      /* compute size of glyph image */
+      switch ( image_format )
+      {
+      case 1:  /* byte-padded formats */
+      case 6:
+        {
+          FT_Int  line_length;
+
+
+          switch ( pix_bits )
+          {
+          case 1:  line_length = ( glyph_width + 7 ) >> 3;   break;
+          case 2:  line_length = ( glyph_width + 3 ) >> 2;   break;
+          case 4:  line_length = ( glyph_width + 1 ) >> 1;   break;
+          default: line_length =   glyph_width;
+          }
+
+          glyph_size = glyph_height * line_length;
+          pad_bytes  = 1;
+        }
+        break;
+
+      case 2:
+      case 5:
+      case 7:
+        line_bits  =   glyph_width  * pix_bits;
+        glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
+        break;
+
+      default:  /* invalid format */
+        return TT_Err_Invalid_File_Format;
+      }
+
+      /* Now read data and draw glyph into target pixmap       */
+      if ( ACCESS_Frame( glyph_size ) )
+        goto Exit;
+
+      /* don't forget to multiply `x_offset' by `map->pix_bits' as */
+      /* the sbit blitter doesn't make a difference between pixmap */
+      /* depths.                                                   */
+      blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
+                 x_offset * pix_bits, y_offset );
+
+      FORGET_Frame();
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error Load_SBit_Image( TT_SBit_Strike*   strike,
+                            TT_SBit_Range*    range,
+                            FT_ULong          ebdt_pos,
+                            FT_ULong          glyph_offset,
+                            FT_Bitmap*        map,
+                            FT_Int            x_offset,
+                            FT_Int            y_offset,
+                            FT_Stream         stream,
+                            TT_SBit_Metrics*  metrics )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error;
+
+
+    /* place stream at beginning of glyph data and read metrics */
+    if ( FILE_Seek( ebdt_pos + glyph_offset ) )
+      goto Exit;
+
+    error = Load_SBit_Metrics( stream, range, metrics );
+    if ( error )
+      goto Exit;
+
+    /* this function is recursive.  At the top-level call, the */
+    /* field map.buffer is NULL.  We thus begin by finding the */
+    /* dimensions of the higher-level glyph to allocate the    */
+    /* final pixmap buffer                                     */
+    if ( map->buffer == 0 )
+    {
+      FT_Long  size;
+
+
+      map->width = metrics->width;
+      map->rows  = metrics->height;
+
+      switch ( strike->bit_depth )
+      {
+      case 1:
+        map->pixel_mode = ft_pixel_mode_mono;
+        map->pitch      = ( map->width + 7 ) >> 3;
+        break;
+
+      case 2:
+        map->pixel_mode = ft_pixel_mode_pal2;
+        map->pitch      = ( map->width + 3 ) >> 2;
+        break;
+
+      case 4:
+        map->pixel_mode = ft_pixel_mode_pal4;
+        map->pitch      = ( map->width + 1 ) >> 1;
+        break;
+
+      case 8:
+        map->pixel_mode = ft_pixel_mode_grays;
+        map->pitch      = map->width;
+        break;
+
+      default:
+        return TT_Err_Invalid_File_Format;
+      }
+
+      size = map->rows * map->pitch;
+
+      /* check that there is no empty image */
+      if ( size == 0 )
+        goto Exit;     /* exit successfully! */
+
+      if ( ALLOC( map->buffer, size ) )
+        goto Exit;
+    }
+
+    switch ( range->image_format )
+    {
+    case 1:  /* single sbit image - load it */
+    case 2:
+    case 5:
+    case 6:
+    case 7:
+      return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
+                               range->image_format, metrics, stream );
+
+    case 8:  /* compound format */
+      FT_Skip_Stream( stream, 1L );
+      /* fallthrough */
+
+    case 9:
+      break;
+
+    default: /* invalid image format */
+      return TT_Err_Invalid_File_Format;
+    }
+
+    /* All right, we have a compound format.  First of all, read */
+    /* the array of elements.                                    */
+    {
+      TT_SBit_Component*  components;
+      TT_SBit_Component*  comp;
+      FT_UShort           num_components, count;
+
+
+      if ( READ_UShort( num_components )                                ||
+           ALLOC_ARRAY( components, num_components, TT_SBit_Component ) )
+        goto Exit;
+
+      count = num_components;
+
+      if ( ACCESS_Frame( 4L * num_components ) )
+        goto Fail_Memory;
+
+      for ( comp = components; count > 0; count--, comp++ )
+      {
+        comp->glyph_code = GET_UShort();
+        comp->x_offset   = GET_Char();
+        comp->y_offset   = GET_Char();
+      }
+
+      FORGET_Frame();
+
+      /* Now recursively load each element glyph */
+      count = num_components;
+      comp  = components;
+      for ( ; count > 0; count--, comp++ )
+      {
+        TT_SBit_Range*   elem_range;
+        TT_SBit_Metrics  elem_metrics;
+        FT_ULong         elem_offset;
+
+
+        /* find the range for this element */
+        error = Find_SBit_Range( comp->glyph_code,
+                                 strike,
+                                 &elem_range,
+                                 &elem_offset );
+        if ( error )
+          goto Fail_Memory;
+
+        /* now load the element, recursively */
+        error = Load_SBit_Image( strike,
+                                 elem_range,
+                                 ebdt_pos,
+                                 elem_offset,
+                                 map,
+                                 x_offset + comp->x_offset,
+                                 y_offset + comp->y_offset,
+                                 stream,
+                                 &elem_metrics );
+        if ( error )
+          goto Fail_Memory;
+      }
+
+    Fail_Memory:
+      FREE( components );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Image                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given glyph sbit image from the font resource.  This also  */
+  /*    returns its metrics.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: The target face object.                             */
+  /*                                                                       */
+  /*    x_ppem      :: The horizontal resolution in points per EM.         */
+  /*                                                                       */
+  /*    y_ppem      :: The vertical resolution in points per EM.           */
+  /*                                                                       */
+  /*    glyph_index :: The current glyph index.                            */
+  /*                                                                       */
+  /*    load_flags  :: The glyph load flags (the code checks for the flag  */
+  /*                   FT_LOAD_CROP_BITMAP                                 */
+  /*                                                                       */
+  /*    stream      :: The input stream.                                   */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    map         :: The target pixmap.                                  */
+  /*                                                                       */
+  /*    metrics     :: A big sbit metrics structure for the glyph image.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  Returns an error if no     */
+  /*    glyph sbit exists for the index.                                   */
+  /*                                                                       */
+  /*  <Note>                                                               */
+  /*    The `map.buffer' field is always freed before the glyph is loaded. */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_SBit_Image( TT_Face           face,
+                                FT_Int            x_ppem,
+                                FT_Int            y_ppem,
+                                FT_UInt           glyph_index,
+                                FT_UInt           load_flags,
+                                FT_Stream         stream,
+                                FT_Bitmap*        map,
+                                TT_SBit_Metrics*  metrics )
+  {
+    FT_Error         error;
+    FT_Memory        memory = stream->memory;
+    FT_ULong         ebdt_pos, glyph_offset;
+
+    TT_SBit_Strike*  strike;
+    TT_SBit_Range*   range;
+
+
+    /* Check whether there is a glyph sbit for the current index */
+    error = Find_SBit_Image( face, glyph_index, x_ppem, y_ppem,
+                             &range, &strike, &glyph_offset );
+    if ( error )
+      goto Exit;
+
+    /* now, find the location of the `EBDT' table in */
+    /* the font file                                 */
+    error = face->goto_table( face, TTAG_EBDT, stream, 0 );
+    if ( error )
+      error = face->goto_table( face, TTAG_bdat, stream, 0 );
+    if (error)
+      goto Exit;
+
+    ebdt_pos = FILE_Pos();
+
+    /* clear the bitmap & load the bitmap */
+    if ( face->root.glyph->flags & ft_glyph_own_bitmap )
+      FREE( map->buffer );
+
+    map->rows = map->pitch = map->width = 0;
+
+    error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
+                             map, 0, 0, stream, metrics );
+    if ( error )
+      goto Exit;
+
+    /* the glyph slot owns this bitmap buffer */
+    face->root.glyph->flags |= ft_glyph_own_bitmap;
+
+    /* setup vertical metrics if needed */
+    if ( strike->flags & 1 )
+    {
+      /* in case of a horizontal strike only */
+      FT_Int  advance;
+      FT_Int  top;
+
+
+      advance = strike->hori.ascender - strike->hori.descender;
+      top     = advance / 10;
+
+      /* some heuristic values */
+
+      metrics->vertBearingX = -metrics->width / 2;
+      metrics->vertBearingY =  advance / 10;
+      metrics->vertAdvance  =  advance * 12 / 10;
+    }
+
+    /* Crop the bitmap now, unless specified otherwise */
+    if ( load_flags & FT_LOAD_CROP_BITMAP )
+      Crop_Bitmap( map, metrics );
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/sfnt/ttsbit.h b/src/freetype/sfnt/ttsbit.h
new file mode 100644 (file)
index 0000000..e77de53
--- /dev/null
@@ -0,0 +1,65 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttsbit.h                                                               */
+/*                                                                         */
+/*    TrueType and OpenType embedded bitmap support (specification).       */
+/*                                                                         */
+/*  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 TTSBIT_H
+#define TTSBIT_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttload.h"
+
+#else
+
+#include <sfnt/ttload.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_SBit_Strikes( TT_Face    face,
+                                  FT_Stream  stream );
+
+  LOCAL_DEF
+  void  TT_Free_SBit_Strikes( TT_Face  face );
+
+  LOCAL_DEF
+  FT_Error  TT_Load_SBit_Image( TT_Face           face,
+                                FT_Int            x_ppem,
+                                FT_Int            y_ppem,
+                                FT_UInt           glyph_index,
+                                FT_UInt           load_flags,
+                                FT_Stream         stream,
+                                FT_Bitmap*        map,
+                                TT_SBit_Metrics*  metrics );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* TTSBIT_H */
+
+
+/* END */
diff --git a/src/freetype/smooth/ftgrays.c b/src/freetype/smooth/ftgrays.c
new file mode 100644 (file)
index 0000000..7ed0838
--- /dev/null
@@ -0,0 +1,1969 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftgrays.c                                                              */
+/*                                                                         */
+/*    A new `perfect' anti-aliasing renderer (body).                       */
+/*                                                                         */
+/*  Copyright 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 can be compiled without the rest of the FreeType engine,   */
+  /*  by defining the _STANDALONE_ macro when compiling it.  You also need */
+  /*  to put the files `ftgrays.h' and `ftimage.h' into the current        */
+  /*  compilation directory.  Typically, you could do something like       */
+  /*                                                                       */
+  /*  - copy `src/base/ftgrays.c' to your current directory                */
+  /*                                                                       */
+  /*  - copy `include/freetype/ftimage.h' and                              */
+  /*    `include/freetype/ftgrays.h' to the same directory                 */
+  /*                                                                       */
+  /*  - compile `ftgrays' with the _STANDALONE_ macro defined, as in       */
+  /*                                                                       */
+  /*      cc -c -D_STANDALONE_ ftgrays.c                                   */
+  /*                                                                       */
+  /*  The renderer can be initialized with a call to                       */
+  /*  `ft_grays_raster.grays_raster_new'; an anti-aliased bitmap can be    */
+  /*  generated with a call to `ft_grays_raster.grays_raster_render'.      */
+  /*                                                                       */
+  /*  See the comments and documentation in the file `ftimage.h' for       */
+  /*  more details on how the raster works.                                */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This is a new anti-aliasing scan-converter for FreeType 2.  The      */
+  /*  algorithm used here is _very_ different from the one in the standard */
+  /*  `ftraster' module.  Actually, `ftgrays' computes the _exact_         */
+  /*  coverage of the outline on each pixel cell.                          */
+  /*                                                                       */
+  /*  It is based on ideas that I initially found in Raph Levien's         */
+  /*  excellent LibArt graphics library (see http://www.levien.com/libart  */
+  /*  for more information, though the web pages do not tell anything      */
+  /*  about the renderer; you'll have to dive into the source code to      */
+  /*  understand how it works).                                            */
+  /*                                                                       */
+  /*  Note, however, that this is a _very_ different implementation        */
+  /*  compared to Raph's.  Coverage information is stored in a very        */
+  /*  different way, and I don't use sorted vector paths.  Also, it        */
+  /*  doesn't use floating point values.                                   */
+  /*                                                                       */
+  /*  This renderer has the following advantages:                          */
+  /*                                                                       */
+  /*  - It doesn't need an intermediate bitmap.  Instead, one can supply   */
+  /*    a callback function that will be called by the renderer to draw    */
+  /*    gray spans on any target surface.  You can thus do direct          */
+  /*    composition on any kind of bitmap, provided that you give the      */
+  /*    renderer the right callback.                                       */
+  /*                                                                       */
+  /*  - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on  */
+  /*    each pixel cell                                                    */
+  /*                                                                       */
+  /*  - It performs a single pass on the outline (the `standard' FT2       */
+  /*    renderer makes two passes).                                        */
+  /*                                                                       */
+  /*  - It can easily be modified to render to _any_ number of gray levels */
+  /*    cheaply.                                                           */
+  /*                                                                       */
+  /*  - For small (< 20) pixel sizes, it is faster than the standard       */
+  /*    renderer.                                                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <string.h>             /* for memcpy() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_aaraster
+
+
+#ifdef _STANDALONE_
+
+
+#define ErrRaster_Invalid_Mode     -2
+#define ErrRaster_Invalid_Outline  -1
+
+#include "ftimage.h"
+#include "ftgrays.h"
+
+  /* This macro is used to indicate that a function parameter is unused. */
+  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
+  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+  /* ANSI compilers (e.g. LCC).                                          */
+#define FT_UNUSED( x )  (x) = (x)
+
+  /* Disable the tracing mechanism for simplicity -- developers can      */
+  /* activate it easily by redefining these two macros.                  */
+#ifndef FT_ERROR
+#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+
+#else /* _STANDALONE_ */
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftgrays.h"
+
+#else
+
+#include <smooth/ftgrays.h>
+
+#endif
+
+
+#include <freetype/internal/ftobjs.h>  /* for FT_UNUSED()               */
+#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
+#include <freetype/ftoutln.h>          /* for FT_Outline_Decompose()    */
+
+#define ErrRaster_Invalid_Mode     FT_Err_Cannot_Render_Glyph
+#define ErrRaster_Invalid_Outline  FT_Err_Invalid_Outline
+
+
+#endif /* _STANDALONE_ */
+
+
+  /* define this to dump debugging information */
+#define xxxDEBUG_GRAYS
+
+  /* as usual, for the speed hungry :-) */
+
+#ifndef FT_STATIC_RASTER
+
+
+#define RAS_ARG   PRaster  raster
+#define RAS_ARG_  PRaster  raster,
+
+#define RAS_VAR   raster
+#define RAS_VAR_  raster,
+
+#define ras       (*raster)
+
+
+#else /* FT_STATIC_RASTER */
+
+
+#define RAS_ARG   /* empty */
+#define RAS_ARG_  /* empty */
+#define RAS_VAR   /* empty */
+#define RAS_VAR_  /* empty */
+
+  static TRaster  ras;
+
+
+#endif /* FT_STATIC_RASTER */
+
+
+  /* must be at least 6 bits! */
+#define PIXEL_BITS  8
+
+#define ONE_PIXEL       ( 1L << PIXEL_BITS )
+#define PIXEL_MASK      ( -1L << PIXEL_BITS )
+#define TRUNC( x )      ( (x) >> PIXEL_BITS )
+#define SUBPIXELS( x )  ( (x) << PIXEL_BITS )
+#define FLOOR( x )      ( (x) & -ONE_PIXEL )
+#define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
+#define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+
+#if PIXEL_BITS >= 6
+#define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
+#define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
+#else
+#define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
+#endif
+
+  /* Define this if you want to use a more compact storage scheme.  This   */
+  /* increases the number of cells available in the render pool but slows  */
+  /* down the rendering a bit.  It is useful if you have a really tiny     */
+  /* render pool.                                                          */
+#define xxxGRAYS_COMPACT
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*   TYPE DEFINITIONS                                                    */
+  /*                                                                       */
+  typedef int   TScan;   /* integer scanline/pixel coordinate */
+  typedef long  TPos;    /* sub-pixel coordinate              */
+
+  /* maximal number of gray spans in a call to the span callback */
+#define FT_MAX_GRAY_SPANS  32
+
+
+#ifdef GRAYS_COMPACT
+
+  typedef struct  TCell_
+  {
+    short  x     : 14;
+    short  y     : 14;
+    int    cover : PIXEL_BITS + 2;
+    int    area  : PIXEL_BITS * 2 + 2;
+
+  } TCell, *PCell;
+
+#else /* GRAYS_COMPACT */
+
+  typedef struct  TCell_
+  {
+    TScan  x;
+    TScan  y;
+    int    cover;
+    int    area;
+
+  } TCell, *PCell;
+
+#endif /* GRAYS_COMPACT */
+
+
+  typedef struct  TRaster_
+  {
+    PCell  cells;
+    int    max_cells;
+    int    num_cells;
+
+    TScan  min_ex, max_ex;
+    TScan  min_ey, max_ey;
+
+    int    area;
+    int    cover;
+    int    invalid;
+
+    TScan  ex, ey;
+    TScan  cx, cy;
+    TPos   x,  y;
+
+    TScan  last_ey;
+
+    FT_Vector   bez_stack[32 * 3];
+    int         lev_stack[32];
+
+    FT_Outline  outline;
+    FT_Bitmap   target;
+
+    FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
+    int         num_gray_spans;
+
+    FT_Raster_Span_Func  render_span;
+    void*                render_span_data;
+    int                  span_y;
+
+    int    band_size;
+    int    band_shoot;
+    int    conic_level;
+    int    cubic_level;
+
+    void*  memory;
+
+  } TRaster, *PRaster;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Initialize the cells table.                                           */
+  /*                                                                       */
+  static
+  void  init_cells( RAS_ARG_ void*  buffer,
+                    long            byte_size )
+  {
+    ras.cells     = (PCell)buffer;
+    ras.max_cells = byte_size / sizeof ( TCell );
+    ras.num_cells = 0;
+    ras.area      = 0;
+    ras.cover     = 0;
+    ras.invalid   = 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Compute the outline bounding box.                                     */
+  /*                                                                       */
+  static
+  void  compute_cbox( RAS_ARG_ FT_Outline*  outline )
+  {
+    FT_Vector*  vec   = outline->points;
+    FT_Vector*  limit = vec + outline->n_points;
+
+
+    if ( outline->n_points <= 0 )
+    {
+      ras.min_ex = ras.max_ex = 0;
+      ras.min_ey = ras.max_ey = 0;
+      return;
+    }
+
+    ras.min_ex = ras.max_ex = vec->x;
+    ras.min_ey = ras.max_ey = vec->y;
+
+    vec++;
+
+    for ( ; vec < limit; vec++ )
+    {
+      TPos  x = vec->x;
+      TPos  y = vec->y;
+
+
+      if ( x < ras.min_ex ) ras.min_ex = x;
+      if ( x > ras.max_ex ) ras.max_ex = x;
+      if ( y < ras.min_ey ) ras.min_ey = y;
+      if ( y > ras.max_ey ) ras.max_ey = y;
+    }
+
+    /* truncate the bounding box to integer pixels */
+    ras.min_ex = ras.min_ex >> 6;
+    ras.min_ey = ras.min_ey >> 6;
+    ras.max_ex = ( ras.max_ex + 63 ) >> 6;
+    ras.max_ey = ( ras.max_ey + 63 ) >> 6;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Record the current cell in the table.                                 */
+  /*                                                                       */
+  static
+  int  record_cell( RAS_ARG )
+  {
+    PCell  cell;
+
+
+    if ( !ras.invalid && ( ras.area | ras.cover ) )
+    {
+      if ( ras.num_cells >= ras.max_cells )
+        return 1;
+
+      cell        = ras.cells + ras.num_cells++;
+      cell->x     = ras.ex - ras.min_ex;
+      cell->y     = ras.ey - ras.min_ey;
+      cell->area  = ras.area;
+      cell->cover = ras.cover;
+    }
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Set the current cell to a new position.                               */
+  /*                                                                       */
+  static
+  int  set_cell( RAS_ARG_ TScan  ex,
+                          TScan  ey )
+  {
+    int  invalid, record, clean;
+
+
+    /* Move the cell pointer to a new position.  We set the `invalid'      */
+    /* flag to indicate that the cell isn't part of those we're interested */
+    /* in during the render phase.  This means that:                       */
+    /*                                                                     */
+    /* . the new vertical position must be within min_ey..max_ey-1.        */
+    /* . the new horizontal position must be strictly less than max_ex     */
+    /*                                                                     */
+    /* Note that if a cell is to the left of the clipping region, it is    */
+    /* actually set to the (min_ex-1) horizontal position.                 */
+
+    record  = 0;
+    clean   = 1;
+
+    invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
+    if ( !invalid )
+    {
+      /* All cells that are on the left of the clipping region go to the */
+      /* min_ex - 1 horizontal position.                                 */
+      if ( ex < ras.min_ex )
+        ex = ras.min_ex - 1;
+
+      /* if our position is new, then record the previous cell */
+      if ( ex != ras.ex || ey != ras.ey )
+        record = 1;
+      else
+        clean = ras.invalid;  /* do not clean if we didn't move from */
+                              /* a valid cell                        */
+    }
+
+    /* record the previous cell if needed (i.e., if we changed the cell */
+    /* position, of changed the `invalid' flag)                         */
+    if ( ( ras.invalid != invalid || record ) && record_cell( RAS_VAR ) )
+      return 1;
+
+    if ( clean )
+    {
+      ras.area  = 0;
+      ras.cover = 0;
+    }
+
+    ras.invalid = invalid;
+    ras.ex      = ex;
+    ras.ey      = ey;
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Start a new contour at a given cell.                                  */
+  /*                                                                       */
+  static
+  void  start_cell( RAS_ARG_  TScan  ex,
+                              TScan  ey )
+  {
+    if ( ex < ras.min_ex )
+      ex = ras.min_ex - 1;
+
+    ras.area    = 0;
+    ras.cover   = 0;
+    ras.ex      = ex;
+    ras.ey      = ey;
+    ras.last_ey = SUBPIXELS( ey );
+    ras.invalid = 0;
+
+    (void)set_cell( RAS_VAR_ ex, ey );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Render a scanline as one or more cells.                               */
+  /*                                                                       */
+  static
+  int  render_scanline( RAS_ARG_  TScan  ey,
+                                  TPos   x1,
+                                  TScan  y1,
+                                  TPos   x2,
+                                  TScan  y2 )
+  {
+    TScan  ex1, ex2, fx1, fx2, delta;
+    long   p, first, dx;
+    int    incr, lift, mod, rem;
+
+
+    dx = x2 - x1;
+
+    ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */
+    ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */
+    fx1 = x1 - SUBPIXELS( ex1 );
+    fx2 = x2 - SUBPIXELS( ex2 );
+
+    /* trivial case.  Happens often */
+    if ( y1 == y2 )
+      return set_cell( RAS_VAR_ ex2, ey );
+
+    /* everything is located in a single cell.  That is easy! */
+    /*                                                        */
+    if ( ex1 == ex2 )
+    {
+      delta      = y2 - y1;
+      ras.area  += ( fx1 + fx2 ) * delta;
+      ras.cover += delta;
+      return 0;
+    }
+
+    /* ok, we'll have to render a run of adjacent cells on the same */
+    /* scanline...                                                  */
+    /*                                                              */
+    p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
+    first = ONE_PIXEL;
+    incr  = 1;
+
+    if ( dx < 0 )
+    {
+      p     = fx1 * ( y2 - y1 );
+      first = 0;
+      incr  = -1;
+      dx    = -dx;
+    }
+
+    delta = p / dx;
+    mod   = p % dx;
+    if ( mod < 0 )
+    {
+      delta--;
+      mod += dx;
+    }
+
+    ras.area  += ( fx1 + first ) * delta;
+    ras.cover += delta;
+
+    ex1 += incr;
+    if ( set_cell( RAS_VAR_ ex1, ey ) )
+      goto Error;
+    y1  += delta;
+
+    if ( ex1 != ex2 )
+    {
+      p     = ONE_PIXEL * ( y2 - y1 );
+      lift  = p / dx;
+      rem   = p % dx;
+      if ( rem < 0 )
+      {
+        lift--;
+        rem += dx;
+      }
+
+      mod -= dx;
+
+      while ( ex1 != ex2 )
+      {
+        delta = lift;
+        mod  += rem;
+        if ( mod >= 0 )
+        {
+          mod -= dx;
+          delta++;
+        }
+
+        ras.area  += ONE_PIXEL * delta;
+        ras.cover += delta;
+        y1        += delta;
+        ex1       += incr;
+        if ( set_cell( RAS_VAR_ ex1, ey ) )
+          goto Error;
+      }
+    }
+
+    delta      = y2 - y1;
+    ras.area  += ( fx2 + ONE_PIXEL - first ) * delta;
+    ras.cover += delta;
+
+    return 0;
+
+  Error:
+    return 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Render a given line as a series of scanlines.                         */
+  /*                                                                       */
+  static
+  int  render_line( RAS_ARG_ TPos  to_x,
+                             TPos  to_y )
+  {
+    TScan  ey1, ey2, fy1, fy2;
+    TPos   dx, dy, x, x2;
+    int    p, rem, mod, lift, delta, first, incr;
+
+
+    ey1 = TRUNC( ras.last_ey );
+    ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
+    fy1 = ras.y - ras.last_ey;
+    fy2 = to_y - SUBPIXELS( ey2 );
+
+    dx = to_x - ras.x;
+    dy = to_y - ras.y;
+
+    /* XXX: we should do something about the trivial case where dx == 0, */
+    /*      as it happens very often!                                    */
+
+    /* perform vertical clipping */
+    {
+      TScan  min, max;
+
+
+      min = ey1;
+      max = ey2;
+      if ( ey1 > ey2 )
+      {
+        min = ey2;
+        max = ey1;
+      }
+      if ( min >= ras.max_ey || max < ras.min_ey )
+        goto End;
+    }
+
+    /* everything is on a single scanline */
+    if ( ey1 == ey2 )
+    {
+      if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ) )
+        goto Error;
+      goto End;
+    }
+
+    /* ok, we have to render several scanlines */
+    p     = ( ONE_PIXEL - fy1 ) * dx;
+    first = ONE_PIXEL;
+    incr  = 1;
+
+    if ( dy < 0 )
+    {
+      p     = fy1 * dx;
+      first = 0;
+      incr  = -1;
+      dy    = -dy;
+    }
+
+    delta = p / dy;
+    mod   = p % dy;
+    if ( mod < 0 )
+    {
+      delta--;
+      mod += dy;
+    }
+
+    x = ras.x + delta;
+    if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first ) )
+      goto Error;
+
+    ey1 += incr;
+    if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
+      goto Error;
+
+    if ( ey1 != ey2 )
+    {
+      p     = ONE_PIXEL * dx;
+      lift  = p / dy;
+      rem   = p % dy;
+      if ( rem < 0 )
+      {
+        lift--;
+        rem += dy;
+      }
+      mod -= dy;
+
+      while ( ey1 != ey2 )
+      {
+        delta = lift;
+        mod  += rem;
+        if ( mod >= 0 )
+        {
+          mod -= dy;
+          delta++;
+        }
+
+        x2 = x + delta;
+        if ( render_scanline( RAS_VAR_ ey1,
+                              x, ONE_PIXEL - first, x2, first ) )
+          goto Error;
+        x = x2;
+        ey1 += incr;
+        if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
+          goto Error;
+      }
+    }
+
+    if ( render_scanline( RAS_VAR_ ey1,
+                          x, ONE_PIXEL - first, to_x, fy2 ) )
+      goto Error;
+
+  End:
+    ras.x       = to_x;
+    ras.y       = to_y;
+    ras.last_ey = SUBPIXELS( ey2 );
+
+    return 0;
+
+  Error:
+    return 1;
+  }
+
+
+  static
+  void  split_conic( FT_Vector*  base )
+  {
+    TPos  a, b;
+
+
+    base[4].x = base[2].x;
+    b = base[1].x;
+    a = base[3].x = ( base[2].x + b ) / 2;
+    b = base[1].x = ( base[0].x + b ) / 2;
+    base[2].x = ( a + b ) / 2;
+
+    base[4].y = base[2].y;
+    b = base[1].y;
+    a = base[3].y = ( base[2].y + b ) / 2;
+    b = base[1].y = ( base[0].y + b ) / 2;
+    base[2].y = ( a + b ) / 2;
+  }
+
+
+  static
+  int  render_conic( RAS_ARG_ FT_Vector*  control,
+                              FT_Vector*  to )
+  {
+    TPos        dx, dy;
+    int         top, level;
+    int*        levels;
+    FT_Vector*  arc;
+
+
+    dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
+    if ( dx < 0 )
+      dx = -dx;
+    dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
+    if ( dy < 0 )
+      dy = -dy;
+    if ( dx < dy )
+      dx = dy;
+
+    level = 1;
+    dx = dx / ras.conic_level;
+    while ( dx > 0 )
+    {
+      dx >>= 1;
+      level++;
+    }
+
+    /* a shortcut to speed things up */
+    if ( level <= 1 )
+    {
+      /* we compute the mid-point directly in order to avoid */
+      /* calling split_conic()                               */
+      TPos   to_x, to_y, mid_x, mid_y;
+
+
+      to_x  = UPSCALE( to->x );
+      to_y  = UPSCALE( to->y );
+      mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
+      mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
+
+      return render_line( RAS_VAR_ mid_x, mid_y ) ||
+             render_line( RAS_VAR_ to_x, to_y );
+    }
+
+    arc       = ras.bez_stack;
+    levels    = ras.lev_stack;
+    top       = 0;
+    levels[0] = level;
+
+    arc[0].x = UPSCALE( to->x );
+    arc[0].y = UPSCALE( to->y );
+    arc[1].x = UPSCALE( control->x );
+    arc[1].y = UPSCALE( control->y );
+    arc[2].x = ras.x;
+    arc[2].y = ras.y;
+
+    while ( top >= 0 )
+    {
+      level = levels[top];
+      if ( level > 1 )
+      {
+        /* check that the arc crosses the current band */
+        TPos  min, max, y;
+
+
+        min = max = arc[0].y;
+
+        y = arc[1].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+
+        y = arc[2].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+
+        if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+          goto Draw;
+
+        split_conic( arc );
+        arc += 2;
+        top++;
+        levels[top] = levels[top - 1] = level - 1;
+        continue;
+      }
+
+    Draw:
+      {
+        TPos  to_x, to_y, mid_x, mid_y;
+
+
+        to_x  = arc[0].x;
+        to_y  = arc[0].y;
+        mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
+        mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
+
+        if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
+             render_line( RAS_VAR_ to_x, to_y )   )
+          return 1;
+
+        top--;
+        arc -= 2;
+      }
+    }
+    return 0;
+  }
+
+
+  static
+  void  split_cubic( FT_Vector*  base )
+  {
+    TPos  a, b, c, d;
+
+
+    base[6].x = base[3].x;
+    c = base[1].x;
+    d = base[2].x;
+    base[1].x = a = ( base[0].x + c ) / 2;
+    base[5].x = b = ( base[3].x + d ) / 2;
+    c = ( c + d ) / 2;
+    base[2].x = a = ( a + c ) / 2;
+    base[4].x = b = ( b + c ) / 2;
+    base[3].x = ( a + b ) / 2;
+
+    base[6].y = base[3].y;
+    c = base[1].y;
+    d = base[2].y;
+    base[1].y = a = ( base[0].y + c ) / 2;
+    base[5].y = b = ( base[3].y + d ) / 2;
+    c = ( c + d ) / 2;
+    base[2].y = a = ( a + c ) / 2;
+    base[4].y = b = ( b + c ) / 2;
+    base[3].y = ( a + b ) / 2;
+  }
+
+
+  static
+  int  render_cubic( RAS_ARG_ FT_Vector*  control1,
+                              FT_Vector*  control2,
+                              FT_Vector*  to )
+  {
+    TPos        dx, dy, da, db;
+    int         top, level;
+    int*        levels;
+    FT_Vector*  arc;
+
+
+    dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
+    if ( dx < 0 )
+      dx = -dx;
+    dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
+    if ( dy < 0 )
+      dy = -dy;
+    if ( dx < dy )
+      dx = dy;
+    da = dx;
+
+    dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
+    if ( dx < 0 )
+      dx = -dx;
+    dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
+    if ( dy < 0 )
+      dy = -dy;
+    if ( dx < dy )
+      dx = dy;
+    db = dx;
+
+    level = 1;
+    da    = da / ras.cubic_level;
+    db    = db / ras.conic_level;
+    while ( da > 0 || db > 0 )
+    {
+      da >>= 1;
+      db >>= 2;
+      level++;
+    }
+
+    if ( level <= 1 )
+    {
+      TPos   to_x, to_y, mid_x, mid_y;
+
+
+      to_x  = UPSCALE( to->x );
+      to_y  = UPSCALE( to->y );
+      mid_x = ( ras.x + to_x +
+                3 * UPSCALE( control1->x + control2->x ) ) / 8;
+      mid_y = ( ras.y + to_y +
+                3 * UPSCALE( control1->y + control2->y ) ) / 8;
+
+      return render_line( RAS_VAR_ mid_x, mid_y ) ||
+             render_line( RAS_VAR_ to_x, to_y );
+    }
+
+    arc      = ras.bez_stack;
+    arc[0].x = UPSCALE( to->x );
+    arc[0].y = UPSCALE( to->y );
+    arc[1].x = UPSCALE( control2->x );
+    arc[1].y = UPSCALE( control2->y );
+    arc[2].x = UPSCALE( control1->x );
+    arc[2].y = UPSCALE( control1->y );
+    arc[3].x = ras.x;
+    arc[3].y = ras.y;
+
+    levels    = ras.lev_stack;
+    top       = 0;
+    levels[0] = level;
+
+    while ( top >= 0 )
+    {
+      level = levels[top];
+      if ( level > 1 )
+      {
+        /* check that the arc crosses the current band */
+        TPos  min, max, y;
+
+
+        min = max = arc[0].y;
+        y = arc[1].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+        y = arc[2].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+        y = arc[3].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+        if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+          goto Draw;
+        split_cubic( arc );
+        arc += 3;
+        top ++;
+        levels[top] = levels[top - 1] = level - 1;
+        continue;
+      }
+
+    Draw:
+      {
+        TPos  to_x, to_y, mid_x, mid_y;
+
+
+        to_x  = arc[0].x;
+        to_y  = arc[0].y;
+        mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
+        mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+
+        if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
+             render_line( RAS_VAR_ to_x, to_y )   )
+          return 1;
+        top --;
+        arc -= 3;
+      }
+    }
+    return 0;
+  }
+
+
+  /* a macro comparing two cell pointers.  Returns true if a <= b. */
+#if 1
+
+#define PACK( a )          ( ( (long)(a)->y << 16 ) + (a)->x )
+#define LESS_THAN( a, b )  ( PACK( a ) < PACK( b ) )
+
+#else /* 1 */
+
+#define LESS_THAN( a, b )  ( (a)->y < (b)->y || \
+                             ( (a)->y == (b)->y && (a)->x < (b)->x ) )
+
+#endif /* 1 */
+
+#define SWAP_CELLS( a, b, temp )  do             \
+                                  {              \
+                                    temp = *(a); \
+                                    *(a) = *(b); \
+                                    *(b) = temp; \
+                                  } while ( 0 )
+#define DEBUG_SORT
+#define QUICK_SORT
+
+#ifdef SHELL_SORT
+
+  /* a simple shell sort algorithm that works directly on our */
+  /* cells table                                              */
+  static
+  void  shell_sort ( PCell  cells,
+                     int    count )
+  {
+    PCell  i, j, limit = cells + count;
+    TCell  temp;
+    int    gap;
+
+
+    /* compute initial gap */
+    for ( gap = 0; ++gap < count; gap *= 3 )
+      ;
+
+    while ( gap /= 3 )
+    {
+      for ( i = cells + gap; i < limit; i++ )
+      {
+        for ( j = i - gap; ; j -= gap )
+        {
+          PCell  k = j + gap;
+
+
+          if ( LESS_THAN( j, k ) )
+            break;
+
+          SWAP_CELLS( j, k, temp );
+
+          if ( j < cells + gap )
+            break;
+        }
+      }
+    }
+  }
+
+#endif /* SHELL_SORT */
+
+
+#ifdef QUICK_SORT
+
+  /* This is a non-recursive quicksort that directly process our cells     */
+  /* array.  It should be faster than calling the stdlib qsort(), and we   */
+  /* can even tailor our insertion threshold...                            */
+
+#define QSORT_THRESHOLD  9  /* below this size, a sub-array will be sorted */
+                            /* through a normal insertion sort             */
+
+  static
+  void  quick_sort( PCell  cells,
+                    int    count )
+  {
+    PCell   stack[40];  /* should be enough ;-) */
+    PCell*  top;        /* top of stack */
+    PCell   base, limit;
+    TCell   temp;
+
+
+    limit = cells + count;
+    base  = cells;
+    top   = stack;
+
+    for (;;)
+    {
+      int    len = limit - base;
+      PCell  i, j, pivot;
+
+
+      if ( len > QSORT_THRESHOLD )
+      {
+        /* we use base + len/2 as the pivot */
+        pivot = base + len / 2;
+        SWAP_CELLS( base, pivot, temp );
+
+        i = base + 1;
+        j = limit - 1;
+
+        /* now ensure that *i <= *base <= *j */
+        if ( LESS_THAN( j, i ) )
+          SWAP_CELLS( i, j, temp );
+
+        if ( LESS_THAN( base, i ) )
+          SWAP_CELLS( base, i, temp );
+
+        if ( LESS_THAN( j, base ) )
+          SWAP_CELLS( base, j, temp );
+
+        for (;;)
+        {
+          do i++; while ( LESS_THAN( i, base ) );
+          do j--; while ( LESS_THAN( base, j ) );
+
+          if ( i > j )
+            break;
+
+          SWAP_CELLS( i, j, temp );
+        }
+
+        SWAP_CELLS( base, j, temp );
+
+        /* now, push the largest sub-array */
+        if ( j - base > limit - i )
+        {
+          top[0] = base;
+          top[1] = j;
+          base   = i;
+        }
+        else
+        {
+          top[0] = i;
+          top[1] = limit;
+          limit  = j;
+        }
+        top += 2;
+      }
+      else
+      {
+        /* the sub-array is small, perform insertion sort */
+        j = base;
+        i = j + 1;
+
+        for ( ; i < limit; j = i, i++ )
+        {
+          for ( ; LESS_THAN( j + 1, j ); j-- )
+          {
+            SWAP_CELLS( j + 1, j, temp );
+            if ( j == base )
+              break;
+          }
+        }
+        if ( top > stack )
+        {
+          top  -= 2;
+          base  = top[0];
+          limit = top[1];
+        }
+        else
+          break;
+      }
+    }
+  }
+
+#endif /* QUICK_SORT */
+
+
+#ifdef DEBUG_GRAYS
+#ifdef DEBUG_SORT
+
+  static
+  int  check_sort( PCell  cells,
+                   int    count )
+  {
+    PCell  p, q;
+
+
+    for ( p = cells + count - 2; p >= cells; p-- )
+    {
+      q = p + 1;
+      if ( !LESS_THAN( p, q ) )
+        return 0;
+    }
+    return 1;
+  }
+
+#endif /* DEBUG_SORT */
+#endif /* DEBUG_GRAYS */
+
+
+  static
+  int  Move_To( FT_Vector*  to,
+                FT_Raster   raster )
+  {
+    TPos  x, y;
+
+
+    /* record current cell, if any */
+    record_cell( (PRaster)raster );
+
+    /* start to a new position */
+    x = UPSCALE( to->x );
+    y = UPSCALE( to->y );
+    start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) );
+    ((PRaster)raster)->x = x;
+    ((PRaster)raster)->y = y;
+    return 0;
+  }
+
+
+  static
+  int  Line_To( FT_Vector*  to,
+                FT_Raster   raster )
+  {
+    return render_line( (PRaster)raster,
+                        UPSCALE( to->x ), UPSCALE( to->y ) );
+  }
+
+
+  static
+  int  Conic_To( FT_Vector*  control,
+                 FT_Vector*  to,
+                 FT_Raster   raster )
+  {
+    return render_conic( (PRaster)raster, control, to );
+  }
+
+
+  static
+  int  Cubic_To( FT_Vector*  control1,
+                 FT_Vector*  control2,
+                 FT_Vector*  to,
+                 FT_Raster   raster )
+  {
+    return render_cubic( (PRaster)raster, control1, control2, to );
+  }
+
+
+  static
+  void  grays_render_span( int       y,
+                           int       count,
+                           FT_Span*  spans,
+                           PRaster   raster )
+  {
+    unsigned char*  p;
+    FT_Bitmap*      map = &raster->target;
+
+
+    /* first of all, compute the scanline offset */
+    p = (unsigned char*)map->buffer - y * map->pitch;
+    if ( map->pitch >= 0 )
+      p += ( map->rows - 1 ) * map->pitch;
+
+    for ( ; count > 0; count--, spans++ )
+    {
+      if ( spans->coverage )
+#if 1
+        memset( p + spans->x, (unsigned char)spans->coverage, spans->len );
+#else /* 1 */
+      {
+        q     = p + spans->x;
+        limit = q + spans->len;
+        for ( ; q < limit; q++ )
+          q[0] = (unsigned char)spans->coverage;
+      }
+#endif /* 1 */
+    }
+  }
+
+
+#ifdef DEBUG_GRAYS
+
+#include <stdio.h>
+
+  static
+  void  dump_cells( RAS_ARG )
+  {
+    PCell  cell, limit;
+    int    y = -1;
+
+
+    cell  = ras.cells;
+    limit = cell + ras.num_cells;
+
+    for ( ; cell < limit; cell++ )
+    {
+      if ( cell->y != y )
+      {
+        fprintf( stderr, "\n%2d: ", cell->y );
+        y = cell->y;
+      }
+      fprintf( stderr, "[%d %d %d]",
+               cell->x, cell->area, cell->cover );
+    }
+    fprintf(stderr, "\n" );
+  }
+
+#endif /* DEBUG_GRAYS */
+
+
+  static
+  void  grays_hline( RAS_ARG_ TScan  x,
+                              TScan  y,
+                              TPos   area,
+                              int    acount )
+  {
+    FT_Span*   span;
+    int        count;
+    int        coverage;
+
+
+    /* compute the coverage line's coverage, depending on the    */
+    /* outline fill rule                                         */
+    /*                                                           */
+    /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
+    /*                                                           */
+    coverage = area >> ( PIXEL_BITS * 2 + 1 - 8);  /* use range 0..256 */
+
+    if ( ras.outline.flags & ft_outline_even_odd_fill )
+    {
+      if ( coverage < 0 )
+        coverage = -coverage;
+
+      while ( coverage >= 512 )
+        coverage -= 512;
+
+      if ( coverage > 256 )
+        coverage = 512 - coverage;
+      else if ( coverage == 256 )
+        coverage = 255;
+    }
+    else
+    {
+      /* normal non-zero winding rule */
+      if ( coverage < 0 )
+        coverage = -coverage;
+
+      if ( coverage >= 256 )
+        coverage = 255;
+    }
+
+    y += ras.min_ey;
+    x += ras.min_ex;
+
+    if ( coverage )
+    {
+      /* see if we can add this span to the current list */
+      count = ras.num_gray_spans;
+      span  = ras.gray_spans + count - 1;
+      if ( count > 0                          &&
+           ras.span_y == y                    &&
+           (int)span->x + span->len == (int)x &&
+           span->coverage == coverage )
+      {
+        span->len += acount;
+        return;
+      }
+
+      if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
+      {
+        if ( ras.render_span )
+          ras.render_span( ras.span_y, count, ras.gray_spans,
+                           ras.render_span_data );
+        /* ras.render_span( span->y, ras.gray_spans, count ); */
+
+#ifdef DEBUG_GRAYS
+
+        if ( ras.span_y >= 0 )
+        {
+          int  n;
+
+
+          fprintf( stderr, "y=%3d ", ras.span_y );
+          span = ras.gray_spans;
+          for ( n = 0; n < count; n++, span++ )
+            fprintf( stderr, "[%d..%d]:%02x ",
+                     span->x, span->x + span->len - 1, span->coverage );
+          fprintf( stderr, "\n" );
+        }
+
+#endif /* DEBUG_GRAYS */
+
+        ras.num_gray_spans = 0;
+        ras.span_y         = y;
+
+        count = 0;
+        span  = ras.gray_spans;
+      }
+      else
+        span++;
+
+      /* add a gray span to the current list */
+      span->x        = (short)x;
+      span->len      = (unsigned short)acount;
+      span->coverage = (unsigned char)coverage;
+      ras.num_gray_spans++;
+    }
+  }
+
+
+  static
+  void  grays_sweep( RAS_ARG_ FT_Bitmap*  target )
+  {
+    TScan  x, y, cover, area;
+    PCell  start, cur, limit;
+
+    FT_UNUSED( target );
+
+
+    cur   = ras.cells;
+    limit = cur + ras.num_cells;
+
+    cover              = 0;
+    ras.span_y         = -1;
+    ras.num_gray_spans = 0;
+
+    for (;;)
+    {
+      start  = cur;
+      y      = start->y;
+      x      = start->x;
+
+      area   = start->area;
+      cover += start->cover;
+
+      /* accumulate all start cells */
+      for (;;)
+      {
+        ++cur;
+        if ( cur >= limit || cur->y != start->y || cur->x != start->x )
+          break;
+
+        area  += cur->area;
+        cover += cur->cover;
+      }
+
+      /* if the start cell has a non-null area, we must draw an */
+      /* individual gray pixel there                            */
+      if ( area && x >= 0 )
+      {
+        grays_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 );
+        x++;
+      }
+
+      if ( x < 0 )
+        x = 0;
+
+      if ( cur < limit && start->y == cur->y )
+      {
+        /* draw a gray span between the start cell and the current one */
+        if ( cur->x > x )
+          grays_hline( RAS_VAR_ x, y,
+                       cover * ( ONE_PIXEL * 2 ), cur->x - x );
+      }
+      else
+      {
+        /* draw a gray span until the end of the clipping region */
+        if ( cover && x < ras.max_ex - ras.min_ex )
+          grays_hline( RAS_VAR_ x, y,
+                       cover * ( ONE_PIXEL * 2 ),
+                       ras.max_ex - x - ras.min_ex );
+        cover = 0;
+      }
+
+      if ( cur >= limit )
+        break;
+    }
+
+    if ( ras.render_span && ras.num_gray_spans > 0 )
+      ras.render_span( ras.span_y, ras.num_gray_spans,
+                       ras.gray_spans, ras.render_span_data );
+
+#ifdef DEBUG_GRAYS
+
+    {
+      int       n;
+      FT_Span*  span;
+
+
+      fprintf( stderr, "y=%3d ", ras.span_y );
+      span = ras.gray_spans;
+      for ( n = 0; n < ras.num_gray_spans; n++, span++ )
+        fprintf( stderr, "[%d..%d]:%02x ",
+                 span->x, span->x + span->len - 1, span->coverage );
+      fprintf( stderr, "\n" );
+    }
+
+#endif /* DEBUG_GRAYS */
+
+  }
+
+
+#ifdef _STANDALONE_
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  The following function should only compile in stand_alone mode,      */
+  /*  i.e., when building this component without the rest of FreeType.     */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Decompose                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Walks over an outline's structure to decompose it into individual  */
+  /*    segments and Bezier arcs.  This function is also able to emit      */
+  /*    `move to' and `close to' operations to indicate the start and end  */
+  /*    of new contours in the outline.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline   :: A pointer to the source target.                       */
+  /*                                                                       */
+  /*    interface :: A table of `emitters', i.e,. function pointers called */
+  /*                 during decomposition to indicate path operations.     */
+  /*                                                                       */
+  /*    user      :: A typeless pointer which is passed to each emitter    */
+  /*                 during the decomposition.  It can be used to store    */
+  /*                 the state during the decomposition.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means sucess.                                       */
+  /*                                                                       */
+  static
+  int  FT_Outline_Decompose( FT_Outline*        outline,
+                             FT_Outline_Funcs*  interface,
+                             void*              user )
+  {
+#undef SCALED
+#define SCALED( x )  ( ( (x) << shift ) - delta )
+
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    int     n;         /* index of contour in outline     */
+    int     first;     /* index of first point in contour */
+    int     error;
+    char    tag;       /* current point's state           */
+
+    int     shift = interface->shift;
+    FT_Pos  delta = interface->delta;
+
+
+    first = 0;
+
+    for ( n = 0; n < outline->n_contours; n++ )
+    {
+      int  last;  /* index of last point in contour */
+
+
+      last  = outline->contours[n];
+      limit = outline->points + last;
+
+      v_start = outline->points[first];
+      v_last  = outline->points[last];
+
+      v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+      v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
+
+      v_control = v_start;
+
+      point = outline->points + first;
+      tags  = outline->tags  + first;
+      tag   = FT_CURVE_TAG( tags[0] );
+
+      /* A contour cannot start with a cubic control point! */
+      if ( tag == FT_Curve_Tag_Cubic )
+        goto Invalid_Outline;
+
+      /* check first point to determine origin */
+      if ( tag == FT_Curve_Tag_Conic )
+      {
+        /* first point is conic control.  Yes, this happens. */
+        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
+        {
+          /* start at last point if it is on the curve */
+          v_start = v_last;
+          limit--;
+        }
+        else
+        {
+          /* if both first and last points are conic,         */
+          /* start at their middle and record its position    */
+          /* for closure                                      */
+          v_start.x = ( v_start.x + v_last.x ) / 2;
+          v_start.y = ( v_start.y + v_last.y ) / 2;
+
+          v_last = v_start;
+        }
+        point--;
+        tags--;
+      }
+
+      error = interface->move_to( &v_start, user );
+      if ( error )
+        goto Exit;
+
+      while ( point < limit )
+      {
+        point++;
+        tags++;
+
+        tag = FT_CURVE_TAG( tags[0] );
+        switch ( tag )
+        {
+        case FT_Curve_Tag_On:  /* emit a single line_to */
+          {
+            FT_Vector  vec;
+
+
+            vec.x = SCALED( point->x );
+            vec.y = SCALED( point->y );
+
+            error = interface->line_to( &vec, user );
+            if ( error )
+              goto Exit;
+            continue;
+          }
+
+        case FT_Curve_Tag_Conic:  /* consume conic arcs */
+          {
+            v_control.x = SCALED( point->x );
+            v_control.y = SCALED( point->y );
+
+          Do_Conic:
+            if ( point < limit )
+            {
+              FT_Vector  vec;
+              FT_Vector  v_middle;
+
+
+              point++;
+              tags++;
+              tag = FT_CURVE_TAG( tags[0] );
+
+              vec.x = SCALED( point->x );
+              vec.y = SCALED( point->y );
+
+              if ( tag == FT_Curve_Tag_On )
+              {
+                error = interface->conic_to( &v_control, &vec, user );
+                if ( error )
+                  goto Exit;
+                continue;
+              }
+
+              if ( tag != FT_Curve_Tag_Conic )
+                goto Invalid_Outline;
+
+              v_middle.x = ( v_control.x + vec.x ) / 2;
+              v_middle.y = ( v_control.y + vec.y ) / 2;
+
+              error = interface->conic_to( &v_control, &v_middle, user );
+              if ( error )
+                goto Exit;
+
+              v_control = vec;
+              goto Do_Conic;
+            }
+
+            error = interface->conic_to( &v_control, &v_start, user );
+            goto Close;
+          }
+
+        default:  /* FT_Curve_Tag_Cubic */
+          {
+            FT_Vector  vec1, vec2;
+
+
+            if ( point + 1 > limit                             ||
+                 FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+              goto Invalid_Outline;
+
+            point += 2;
+            tags  += 2;
+
+            vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+            vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+            if ( point <= limit )
+            {
+              FT_Vector  vec;
+
+
+              vec.x = SCALED( point->x );
+              vec.y = SCALED( point->y );
+
+              error = interface->cubic_to( &vec1, &vec2, &vec, user );
+              if ( error )
+                goto Exit;
+              continue;
+            }
+
+            error = interface->cubic_to( &vec1, &vec2, &v_start, user );
+            goto Close;
+          }
+        }
+      }
+
+      /* close the contour with a line segment */
+      error = interface->line_to( &v_start, user );
+
+   Close:
+      if ( error )
+        goto Exit;
+
+      first = last + 1;
+    }
+
+    return 0;
+
+  Exit:
+    return error;
+
+  Invalid_Outline:
+    return ErrRaster_Invalid_Outline;
+  }
+
+#endif /* _STANDALONE_ */
+
+
+  typedef struct  TBand_
+  {
+    FT_Pos  min, max;
+
+  } TBand;
+
+
+  static
+  int  grays_convert_glyph( RAS_ARG_ FT_Outline*  outline )
+  {
+    static
+    FT_Outline_Funcs  interface =
+    {
+      (FT_Outline_MoveTo_Func) Move_To,
+      (FT_Outline_LineTo_Func) Line_To,
+      (FT_Outline_ConicTo_Func)Conic_To,
+      (FT_Outline_CubicTo_Func)Cubic_To,
+      0,
+      0
+    };
+
+    TBand    bands[40], *band;
+    int      n, num_bands;
+    TPos     min, max, max_y;
+
+
+    /* Set up state in the raster object */
+    compute_cbox( RAS_VAR_ outline );
+
+    /* clip to target bitmap, exit if nothing to do */
+    if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width ||
+         ras.max_ey <= 0 || ras.min_ey >= ras.target.rows  )
+      return 0;
+
+    if ( ras.min_ex < 0 ) ras.min_ex = 0;
+    if ( ras.min_ey < 0 ) ras.min_ey = 0;
+
+    if ( ras.max_ex > ras.target.width ) ras.max_ex = ras.target.width;
+    if ( ras.max_ey > ras.target.rows )  ras.max_ey = ras.target.rows;
+
+    /* simple heuristic used to speed-up the bezier decomposition -- see */
+    /* the code in render_conic() and render_cubic() for more details    */
+    ras.conic_level = 32;
+    ras.cubic_level = 16;
+
+    {
+      int level = 0;
+
+
+      if ( ras.max_ex > 24 || ras.max_ey > 24 )
+        level++;
+      if ( ras.max_ex > 120 || ras.max_ey > 120 )
+        level += 2;
+
+      ras.conic_level <<= level;
+      ras.cubic_level <<= level;
+    }
+
+    /* setup vertical bands */
+    num_bands = ( ras.max_ey - ras.min_ey ) / ras.band_size;
+    if ( num_bands == 0 )  num_bands = 1;
+    if ( num_bands >= 39 ) num_bands = 39;
+
+    ras.band_shoot = 0;
+
+    min   = ras.min_ey;
+    max_y = ras.max_ey;
+
+    for ( n = 0; n < num_bands; n++, min = max )
+    {
+      max = min + ras.band_size;
+      if ( n == num_bands - 1 || max > max_y )
+        max = max_y;
+
+      bands[0].min = min;
+      bands[0].max = max;
+      band         = bands;
+
+      while ( band >= bands )
+      {
+        FT_Pos  bottom, top, middle;
+        int     error;
+
+
+        ras.num_cells = 0;
+        ras.invalid   = 1;
+        ras.min_ey    = band->min;
+        ras.max_ey    = band->max;
+
+        error = FT_Outline_Decompose( outline, &interface, &ras ) ||
+                record_cell( RAS_VAR );
+
+        if ( !error )
+        {
+#ifdef SHELL_SORT
+          shell_sort( ras.cells, ras.num_cells );
+#else
+          quick_sort( ras.cells, ras.num_cells );
+#endif
+
+#ifdef DEBUG_GRAYS
+          check_sort( ras.cells, ras.num_cells );
+          dump_cells( RAS_VAR );
+#endif
+
+          grays_sweep( RAS_VAR_  &ras.target );
+          band--;
+          continue;
+        }
+
+        /* render pool overflow, we will reduce the render band by half */
+        bottom = band->min;
+        top    = band->max;
+        middle = bottom + ( ( top - bottom ) >> 1 );
+
+        /* waoow! This is too complex for a single scanline, something */
+        /* must be really rotten here!                                 */
+        if ( middle == bottom )
+        {
+#ifdef DEBUG_GRAYS
+          fprintf( stderr, "Rotten glyph!\n" );
+#endif
+          return 1;
+        }
+
+        if ( bottom-top >= ras.band_size )
+          ras.band_shoot++;
+
+        band[1].min = bottom;
+        band[1].max = middle;
+        band[0].min = middle;
+        band[0].max = top;
+        band++;
+      }
+    }
+
+    if ( ras.band_shoot > 8 && ras.band_size > 16 )
+      ras.band_size = ras.band_size / 2;
+
+    return 0;
+  }
+
+
+  extern
+  int  grays_raster_render( PRaster            raster,
+                            FT_Raster_Params*  params )
+  {
+    FT_Outline*  outline = (FT_Outline*)params->source;
+    FT_Bitmap*   target_map = params->target;
+
+
+    if ( !raster || !raster->cells || !raster->max_cells )
+      return -1;
+
+    /* return immediately if the outline is empty */
+    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+      return 0;
+
+    if ( !outline || !outline->contours || !outline->points )
+      return ErrRaster_Invalid_Outline;
+
+    if ( outline->n_points !=
+           outline->contours[outline->n_contours - 1] + 1 )
+      return ErrRaster_Invalid_Outline;
+
+    if ( !target_map || !target_map->buffer )
+      return -1;
+
+    /* XXX: this version does not support monochrome rendering yet! */
+    if ( !(params->flags & ft_raster_flag_aa) )
+      return ErrRaster_Invalid_Mode;
+
+    ras.outline   = *outline;
+    ras.target    = *target_map;
+    ras.num_cells = 0;
+    ras.invalid   = 1;
+
+    ras.render_span      = (FT_Raster_Span_Func)grays_render_span;
+    ras.render_span_data = &ras;
+
+    if ( params->flags & ft_raster_flag_direct )
+    {
+      ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
+      ras.render_span_data = params->user;
+    }
+
+    return grays_convert_glyph( (PRaster)raster, outline );
+  }
+
+
+  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+  /****                         a static object.                  *****/
+
+#ifdef _STANDALONE_
+
+  static
+  int  grays_raster_new( void*       memory,
+                         FT_Raster*  araster )
+  {
+    static TRaster  the_raster;
+
+    FT_UNUSED( memory );
+
+
+    *araster = (FT_Raster)&the_raster;
+    memset( &the_raster, 0, sizeof ( the_raster ) );
+
+    return 0;
+  }
+
+
+  static
+  void  grays_raster_done( FT_Raster  raster )
+  {
+    /* nothing */
+    FT_UNUSED( raster );
+  }
+
+#else /* _STANDALONE_ */
+
+  static
+  int  grays_raster_new( FT_Memory   memory,
+                         FT_Raster*  araster )
+  {
+    FT_Error  error;
+    PRaster   raster;
+
+
+    *araster = 0;
+    if ( !ALLOC( raster, sizeof ( TRaster ) ) )
+    {
+      raster->memory = memory;
+      *araster = (FT_Raster)raster;
+    }
+
+    return error;
+  }
+
+
+  static
+  void grays_raster_done( FT_Raster  raster )
+  {
+    FT_Memory  memory = (FT_Memory)((PRaster)raster)->memory;
+
+
+    FREE( raster );
+  }
+
+#endif /* _STANDALONE_ */
+
+
+  static
+  void  grays_raster_reset( FT_Raster    raster,
+                            const char*  pool_base,
+                            long         pool_size )
+  {
+    PRaster  rast = (PRaster)raster;
+
+
+    if ( raster && pool_base && pool_size >= 4096 )
+      init_cells( rast, (char*)pool_base, pool_size );
+
+    rast->band_size  = ( pool_size / sizeof ( TCell ) ) / 8;
+  }
+
+
+  FT_Raster_Funcs  ft_grays_raster =
+  {
+    ft_glyph_format_outline,
+
+    (FT_Raster_New_Func)     grays_raster_new,
+    (FT_Raster_Reset_Func)   grays_raster_reset,
+    (FT_Raster_Set_Mode_Func)0,
+    (FT_Raster_Render_Func)  grays_raster_render,
+    (FT_Raster_Done_Func)    grays_raster_done
+  };
+
+
+/* END */
diff --git a/src/freetype/smooth/ftgrays.h b/src/freetype/smooth/ftgrays.h
new file mode 100644 (file)
index 0000000..2423a0e
--- /dev/null
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftgrays.h                                                              */
+/*                                                                         */
+/*    FreeType smooth renderer declaration                                 */
+/*                                                                         */
+/*  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 FTGRAYS_H
+#define FTGRAYS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+#ifdef _STANDALONE_
+#include "ftimage.h"
+#else
+#include <freetype/ftimage.h>
+#endif
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* To make ftgrays.h independent from configuration files we check       */
+  /* whether FT_EXPORT_DEF has been defined already.                       */
+  /*                                                                       */
+  /* On some systems and compilers (Win32 mostly), an extra keyword is     */
+  /* necessary to compile the library as a DLL.                            */
+  /*                                                                       */
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x )  extern  x
+#endif
+
+  FT_EXPORT_VAR( FT_Raster_Funcs )  ft_grays_raster;
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* FTGRAYS_H */
+
+
+/* END */
diff --git a/src/freetype/smooth/ftsmooth.c b/src/freetype/smooth/ftsmooth.c
new file mode 100644 (file)
index 0000000..6f399ac
--- /dev/null
@@ -0,0 +1,220 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsmooth.c                                                             */
+/*                                                                         */
+/*    Anti-aliasing renderer interface (body).                             */
+/*                                                                         */
+/*  Copyright 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 <freetype/internal/ftobjs.h>
+#include <freetype/ftoutln.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftsmooth.h"
+#include "ftgrays.h"
+
+#else
+
+#include <smooth/ftsmooth.h>
+#include <smooth/ftgrays.h>
+
+#endif
+
+
+  /* initialize renderer -- init its raster */
+  static
+  FT_Error  ft_smooth_init( FT_Renderer  render )
+  {
+    FT_Library  library = FT_MODULE_LIBRARY( render );
+
+
+    render->clazz->raster_class->raster_reset( render->raster,
+                                               library->raster_pool,
+                                               library->raster_pool_size );
+
+    return 0;
+  }
+
+
+  /* sets render-specific mode */
+  static
+  FT_Error  ft_smooth_set_mode( FT_Renderer  render,
+                                FT_ULong     mode_tag,
+                                FT_Pointer   data )
+  {
+    /* we simply pass it to the raster */
+    return render->clazz->raster_class->raster_set_mode( render->raster,
+                                                         mode_tag,
+                                                         data );
+  }
+
+  /* transform a given glyph image */
+  static
+  FT_Error  ft_smooth_transform( FT_Renderer   render,
+                                 FT_GlyphSlot  slot,
+                                 FT_Matrix*    matrix,
+                                 FT_Vector*    delta )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    if ( matrix )
+      FT_Outline_Transform( &slot->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+  Exit:
+    return error;
+  }
+
+
+  /* return the glyph's control box */
+  static
+  void  ft_smooth_get_cbox( FT_Renderer   render,
+                            FT_GlyphSlot  slot,
+                            FT_BBox*      cbox )
+  {
+    MEM_Set( cbox, 0, sizeof ( *cbox ) );
+
+    if ( slot->format == render->glyph_format )
+      FT_Outline_Get_CBox( &slot->outline, cbox );
+  }
+
+
+  /* convert a slot's glyph image into a bitmap */
+  static
+  FT_Error  ft_smooth_render( FT_Renderer   render,
+                              FT_GlyphSlot  slot,
+                              FT_UInt       mode,
+                              FT_Vector*    origin )
+  {
+    FT_Error     error;
+    FT_Outline*  outline;
+    FT_BBox      cbox;
+    FT_UInt      width, height, pitch;
+    FT_Bitmap*   bitmap;
+    FT_Memory    memory;
+
+    FT_Raster_Params  params;
+
+
+    /* check glyph image format */
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* check mode */
+    if ( mode != ft_render_mode_normal )
+      return FT_Err_Cannot_Render_Glyph;
+
+    outline = &slot->outline;
+
+    /* translate the outline to the new origin if needed */
+    if ( origin )
+      FT_Outline_Translate( outline, origin->x, origin->y );
+
+    /* compute the control box, and grid fit it */
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    cbox.xMin &= -64;
+    cbox.yMin &= -64;
+    cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+    cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+
+    width  = ( cbox.xMax - cbox.xMin ) >> 6;
+    height = ( cbox.yMax - cbox.yMin ) >> 6;
+    bitmap = &slot->bitmap;
+    memory = render->root.memory;
+
+    /* release old bitmap buffer */
+    if ( slot->flags & ft_glyph_own_bitmap )
+    {
+      FREE( bitmap->buffer );
+      slot->flags &= ~ft_glyph_own_bitmap;
+    }
+
+    /* allocate new one, depends on pixel format */
+    pitch = width;
+    bitmap->pixel_mode = ft_pixel_mode_grays;
+    bitmap->num_grays  = 256;
+    bitmap->width      = width;
+    bitmap->rows       = height;
+    bitmap->pitch      = pitch;
+
+    if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+      goto Exit;
+
+    slot->flags |= ft_glyph_own_bitmap;
+
+    /* translate outline to render it into the bitmap */
+    FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+    /* set up parameters */
+    params.target = bitmap;
+    params.source = outline;
+    params.flags  = ft_raster_flag_aa;
+
+    /* render outline into the bitmap */
+    error = render->raster_render( render->raster, &params );
+    if ( error )
+      goto Exit;
+
+    slot->format      = ft_glyph_format_bitmap;
+    slot->bitmap_left = cbox.xMin >> 6;
+    slot->bitmap_top  = cbox.yMax >> 6;
+
+  Exit:
+    return error;
+  }
+
+
+  const FT_Renderer_Class  ft_smooth_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "smooth",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_smooth_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_smooth_render,
+    (FTRenderer_transform)ft_smooth_transform,
+    (FTRenderer_getCBox)  ft_smooth_get_cbox,
+    (FTRenderer_setMode)  ft_smooth_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_grays_raster
+  };
+
+
+/* END */
diff --git a/src/freetype/smooth/ftsmooth.h b/src/freetype/smooth/ftsmooth.h
new file mode 100644 (file)
index 0000000..4b8a533
--- /dev/null
@@ -0,0 +1,35 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsmooth.h                                                             */
+/*                                                                         */
+/*    Anti-aliasing renderer interface (specification).                    */
+/*                                                                         */
+/*  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 FTSMOOTH_H
+#define FTSMOOTH_H
+
+#include <freetype/ftrender.h>
+
+#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_std_renderer_class;
+#endif
+
+#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_smooth_renderer_class;
+#endif
+
+#endif /* FTSMOOTH_H */
+
+
+/* END */
diff --git a/src/freetype/smooth/module.mk b/src/freetype/smooth/module.mk
new file mode 100644 (file)
index 0000000..b93bc4d
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_smooth_renderer
+
+add_smooth_renderer:
+       $(OPEN_DRIVER)ft_smooth_renderer_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)smooth    $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/smooth/rules.mk b/src/freetype/smooth/rules.mk
new file mode 100644 (file)
index 0000000..a81d60a
--- /dev/null
@@ -0,0 +1,69 @@
+#
+# FreeType 2 renderer module build rules
+#
+
+
+# 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.
+
+
+# smooth driver directory
+#
+SMOOTH_DIR  := $(SRC_)smooth
+SMOOTH_DIR_ := $(SMOOTH_DIR)$(SEP)
+
+# compilation flags for the driver
+#
+SMOOTH_COMPILE := $(FT_COMPILE)
+
+
+# smooth driver sources (i.e., C files)
+#
+SMOOTH_DRV_SRC := $(SMOOTH_DIR_)ftgrays.c  \
+                  $(SMOOTH_DIR_)ftsmooth.c
+
+
+# smooth driver headers
+#
+SMOOTH_DRV_H := $(SMOOTH_DRV_SRC:%c=%h)
+
+
+# smooth driver object(s)
+#
+#   SMOOTH_DRV_OBJ_M is used during `multi' builds.
+#   SMOOTH_DRV_OBJ_S is used during `single' builds.
+#
+SMOOTH_DRV_OBJ_M := $(SMOOTH_DRV_SRC:$(SMOOTH_DIR_)%.c=$(OBJ_)%.$O)
+SMOOTH_DRV_OBJ_S := $(OBJ_)smooth.$O
+
+# smooth driver source file for single build
+#
+SMOOTH_DRV_SRC_S := $(SMOOTH_DIR_)smooth.c
+
+
+# smooth driver - single object
+#
+$(SMOOTH_DRV_OBJ_S): $(SMOOTH_DRV_SRC_S) $(SMOOTH_DRV_SRC) \
+                   $(FREETYPE_H) $(SMOOTH_DRV_H)
+       $(SMOOTH_COMPILE) $T$@ $(SMOOTH_DRV_SRC_S)
+
+
+# smooth driver - multiple objects
+#
+$(OBJ_)%.$O: $(SMOOTH_DIR_)%.c $(FREETYPE_H) $(SMOOTH_DRV_H)
+       $(SMOOTH_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(SMOOTH_DRV_OBJ_S)
+DRV_OBJS_M += $(SMOOTH_DRV_OBJ_M)
+
+
+# EOF
diff --git a/src/freetype/smooth/smooth.c b/src/freetype/smooth/smooth.c
new file mode 100644 (file)
index 0000000..41cc4ae
--- /dev/null
@@ -0,0 +1,35 @@
+/***************************************************************************/
+/*                                                                         */
+/*  smooth.c                                                               */
+/*                                                                         */
+/*    FreeType anti-aliasing rasterer module component (body only).        */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ftgrays.c"
+#include "ftsmooth.c"
+
+#else
+
+#include <smooth/ftgrays.c>
+#include <smooth/ftsmooth.c>
+
+#endif
+
+
+/* END */
diff --git a/src/freetype/truetype/module.mk b/src/freetype/truetype/module.mk
new file mode 100644 (file)
index 0000000..79072bb
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_truetype_driver
+
+add_truetype_driver:
+       $(OPEN_DRIVER)tt_driver_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)truetype  $(ECHO_DRIVER_DESC)Windows/Mac font files with extension *.ttf or *.ttc$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/truetype/rules.mk b/src/freetype/truetype/rules.mk
new file mode 100644 (file)
index 0000000..9289378
--- /dev/null
@@ -0,0 +1,70 @@
+#
+# FreeType 2 TrueType driver configuration rules
+#
+
+
+# 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.
+
+
+# TrueType driver directory
+#
+TT_DIR  := $(SRC_)truetype
+TT_DIR_ := $(TT_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+TT_COMPILE := $(FT_COMPILE)
+
+
+# TrueType driver sources (i.e., C files)
+#
+TT_DRV_SRC := $(TT_DIR_)ttobjs.c   \
+              $(TT_DIR_)ttpload.c  \
+              $(TT_DIR_)ttgload.c  \
+              $(TT_DIR_)ttinterp.c \
+              $(TT_DIR_)ttdriver.c
+
+# TrueType driver headers
+#
+TT_DRV_H := $(TT_DRV_SRC:%.c=%.h)
+
+
+# TrueType driver object(s)
+#
+#   TT_DRV_OBJ_M is used during `multi' builds
+#   TT_DRV_OBJ_S is used during `single' builds
+#
+TT_DRV_OBJ_M := $(TT_DRV_SRC:$(TT_DIR_)%.c=$(OBJ_)%.$O)
+TT_DRV_OBJ_S := $(OBJ_)truetype.$O
+
+# TrueType driver source file for single build
+#
+TT_DRV_SRC_S := $(TT_DIR_)truetype.c
+
+
+# TrueType driver - single object
+#
+$(TT_DRV_OBJ_S): $(TT_DRV_SRC_S) $(TT_DRV_SRC) $(FREETYPE_H) $(TT_DRV_H)
+       $(TT_COMPILE) $T$@ $(TT_DRV_SRC_S)
+
+
+# driver - multiple objects
+#
+$(OBJ_)%.$O: $(TT_DIR_)%.c $(FREETYPE_H) $(TT_DRV_H)
+       $(TT_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(TT_DRV_OBJ_S)
+DRV_OBJS_M += $(TT_DRV_OBJ_M)
+
+# EOF
diff --git a/src/freetype/truetype/truetype.c b/src/freetype/truetype/truetype.c
new file mode 100644 (file)
index 0000000..55ba0c9
--- /dev/null
@@ -0,0 +1,47 @@
+/***************************************************************************/
+/*                                                                         */
+/*  truetype.c                                                             */
+/*                                                                         */
+/*    FreeType TrueType driver component (body only).                      */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttdriver.c"    /* driver interface     */
+#include "ttpload.c"     /* tables loader        */
+#include "ttgload.c"     /* glyph loader         */
+#include "ttobjs.c"      /* object manager       */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.c"    /* bytecode interpreter */
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <truetype/ttdriver.c>    /* driver interface     */
+#include <truetype/ttpload.c>     /* tables loader        */
+#include <truetype/ttgload.c>     /* glyph loader         */
+#include <truetype/ttobjs.c>      /* object manager       */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include <truetype/ttinterp.c>    /* bytecode interpreter */
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
diff --git a/src/freetype/truetype/ttdriver.c b/src/freetype/truetype/ttdriver.c
new file mode 100644 (file)
index 0000000..0b3cb48
--- /dev/null
@@ -0,0 +1,511 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttdriver.c                                                             */
+/*                                                                         */
+/*    TrueType font driver implementation (body).                          */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/ttnameid.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttdriver.h"
+#include "ttgload.h"
+
+#else
+
+#include <truetype/ttdriver.h>
+#include <truetype/ttgload.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttdriver
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                          F A C E S                              ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#undef  PAIR_TAG
+#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
+                                     (FT_ULong)right        )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings, are out of scope of this method (the basic driver        */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static
+  FT_Error  Get_Kerning( TT_Face     face,
+                         FT_UInt     left_glyph,
+                         FT_UInt     right_glyph,
+                         FT_Vector*  kerning )
+  {
+    TT_Kern_0_Pair*  pair;
+
+
+    if ( !face )
+      return TT_Err_Invalid_Face_Handle;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    if ( face->kern_pairs )
+    {
+      /* there are some kerning pairs in this font file! */
+      FT_ULong  search_tag = PAIR_TAG( left_glyph, right_glyph );
+      FT_Long   left, right;
+
+
+      left  = 0;
+      right = face->num_kern_pairs - 1;
+
+      while ( left <= right )
+      {
+        FT_Int    middle = left + ( ( right - left ) >> 1 );
+        FT_ULong  cur_pair;
+
+
+        pair     = face->kern_pairs + middle;
+        cur_pair = PAIR_TAG( pair->left, pair->right );
+
+        if ( cur_pair == search_tag )
+          goto Found;
+
+        if ( cur_pair < search_tag )
+          left = middle + 1;
+        else
+          right = middle - 1;
+      }
+    }
+
+  Exit:
+    return TT_Err_Ok;
+
+  Found:
+    kerning->x = pair->value;
+    goto Exit;
+  }
+
+
+#undef PAIR_TAG
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           S I Z E S                             ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_Char_Sizes                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to reset a size's character sizes (horizontal */
+  /*    and vertical) expressed in fractional points.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_width      :: The character width expressed in 26.6           */
+  /*                       fractional points.                              */
+  /*                                                                       */
+  /*    char_height     :: The character height expressed in 26.6          */
+  /*                       fractional points.                              */
+  /*                                                                       */
+  /*    horz_resolution :: The horizontal resolution of the output device. */
+  /*                                                                       */
+  /*    vert_resolution :: The vertical resolution of the output device.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size            :: A handle to the target size object.             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Set_Char_Sizes( TT_Size     size,
+                            FT_F26Dot6  char_width,
+                            FT_F26Dot6  char_height,
+                            FT_UInt     horz_resolution,
+                            FT_UInt     vert_resolution )
+  {
+    FT_Size_Metrics*  metrics = &size->root.metrics;
+    TT_Face           face    = (TT_Face)size->root.face;
+    FT_Long           dim_x, dim_y;
+
+
+    /* This bit flag, when set, indicates that the pixel size must be */
+    /* truncated to an integer.  Nearly all TrueType fonts have this  */
+    /* bit set, as hinting won't work really well otherwise.          */
+    /*                                                                */
+    /* However, for those rare fonts who do not set it, we override   */
+    /* the default computations performed by the base layer.  I       */
+    /* really don't know whether this is useful, but hey, that's the  */
+    /* spec :-)                                                       */
+    /*                                                                */
+    if ( ( face->header.Flags & 8 ) == 0 )
+    {
+      /* Compute pixel sizes in 26.6 units */
+      dim_x = ( char_width  * horz_resolution ) / 72;
+      dim_y = ( char_height * vert_resolution ) / 72;
+
+      metrics->x_scale = FT_DivFix( dim_x, face->root.units_per_EM );
+      metrics->y_scale = FT_DivFix( dim_y, face->root.units_per_EM );
+
+      metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
+      metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
+    }
+
+    size->ttmetrics.valid = FALSE;
+
+    return TT_Reset_Size( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_Pixel_Sizes                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to reset a size's character sizes (horizontal */
+  /*    and vertical) expressed in integer pixels.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pixel_width  :: The character width expressed in integer pixels.   */
+  /*                                                                       */
+  /*    pixel_height :: The character height expressed in integer pixels.  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size         :: A handle to the target size object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Set_Pixel_Sizes( TT_Size  size,
+                             FT_UInt  pixel_width,
+                             FT_UInt  pixel_height )
+  {
+    FT_UNUSED( pixel_width );
+    FT_UNUSED( pixel_height );
+
+    /* many things have been pre-computed by the base layer */
+
+    size->ttmetrics.valid = FALSE;
+
+    return TT_Reset_Size( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_Glyph                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to load a glyph within a given glyph slot.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot        :: A handle to the target slot object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled, loaded, etc.                        */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FTLOAD_??? constants can be used to control the     */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Load_Glyph( TT_GlyphSlot  slot,
+                        TT_Size       size,
+                        FT_UShort     glyph_index,
+                        FT_UInt       load_flags )
+  {
+    FT_Error  error;
+
+
+    if ( !slot )
+      return TT_Err_Invalid_Glyph_Handle;
+
+    /* check whether we want a scaled outline or bitmap */
+    if ( !size )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    if ( load_flags & FT_LOAD_NO_SCALE )
+      size = NULL;
+
+    /* reset the size object if necessary */
+    if ( size )
+    {
+      /* these two object must have the same parent */
+      if ( size->root.face != slot->face )
+        return TT_Err_Invalid_Face_Handle;
+
+      if ( !size->ttmetrics.valid )
+      {
+        if ( FT_SET_ERROR( TT_Reset_Size( size ) ) )
+          return error;
+      }
+    }
+
+    /* now load the glyph outline if necessary */
+    error = TT_Load_Glyph( size, slot, glyph_index, load_flags );
+
+    /* force drop-out mode to 2 - irrelevant now */
+    /* slot->outline.dropout_mode = 2; */
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****             C H A R A C T E R   M A P P I N G S                 ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  FT_UInt  Get_Char_Index( TT_CharMap  charmap,
+                           FT_Long     charcode )
+  {
+    FT_Error       error;
+    TT_Face        face;
+    TT_CMapTable*  cmap;
+
+
+    cmap = &charmap->cmap;
+    face = (TT_Face)charmap->root.face;
+
+    /* Load table if needed */
+    if ( !cmap->loaded )
+    {
+      SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+
+      error = sfnt->load_charmap( face, cmap, face->root.stream );
+      if ( error )
+        return 0;
+
+      cmap->loaded = TRUE;
+    }
+
+    if ( cmap->get_index )
+      return cmap->get_index( cmap, charcode );
+    else
+      return 0;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                D R I V E R  I N T E R F A C E                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Module_Interface  tt_get_interface( TT_Driver    driver,
+                                         const char*  interface )
+  {
+    FT_Module        sfntd = FT_Get_Module( driver->root.root.library,
+                                            "sfnt" );
+    SFNT_Interface*  sfnt;
+
+
+    /* only return the default interface from the SFNT module */
+    if ( sfntd )
+    {
+      sfnt = (SFNT_Interface*)( sfntd->clazz->module_interface );
+      if ( sfnt )
+        return sfnt->get_interface( FT_MODULE( driver ), interface );
+    }
+
+    return 0;
+  }
+
+
+  /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+  const FT_Driver_Class  tt_driver_class =
+  {
+    {
+      ft_module_font_driver     |
+      ft_module_driver_scalable |
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+      ft_module_driver_has_hinter,
+#else
+      0,
+#endif            
+
+      sizeof ( TT_DriverRec ),
+
+      "truetype",      /* driver name                           */
+      0x10000L,        /* driver version == 1.0                 */
+      0x20000L,        /* driver requires FreeType 2.0 or above */
+
+      (void*)0,        /* driver specific interface */
+
+      (FT_Module_Constructor)TT_Init_Driver,
+      (FT_Module_Destructor) TT_Done_Driver,
+      (FT_Module_Requester)  tt_get_interface,
+    },
+
+    sizeof ( TT_FaceRec ),
+    sizeof ( TT_SizeRec ),
+    sizeof ( FT_GlyphSlotRec ),
+
+
+    (FTDriver_initFace)     TT_Init_Face,
+    (FTDriver_doneFace)     TT_Done_Face,
+    (FTDriver_initSize)     TT_Init_Size,
+    (FTDriver_doneSize)     TT_Done_Size,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) Set_Char_Sizes,
+    (FTDriver_setPixelSizes)Set_Pixel_Sizes,
+    (FTDriver_loadGlyph)    Load_Glyph,
+    (FTDriver_getCharIndex) Get_Char_Index,
+
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   0,
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverInterface                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  EXPORT_FUNC( const FT_Driver_Class* )  getDriverClass( void )
+  {
+    return &tt_driver_class;
+  }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/src/freetype/truetype/ttdriver.h b/src/freetype/truetype/ttdriver.h
new file mode 100644 (file)
index 0000000..9867fbc
--- /dev/null
@@ -0,0 +1,31 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttdriver.h                                                             */
+/*                                                                         */
+/*    High-level TrueType driver interface (specification).                */
+/*                                                                         */
+/*  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 TTDRIVER_H
+#define TTDRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+
+  FT_EXPORT_VAR( const FT_Driver_Class )  tt_driver_class;
+
+
+#endif /* TTDRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/truetype/ttgload.c b/src/freetype/truetype/ttgload.c
new file mode 100644 (file)
index 0000000..e9b87fa
--- /dev/null
@@ -0,0 +1,1477 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttgload.c                                                              */
+/*                                                                         */
+/*    TrueType Glyph Loader (body).                                        */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/tttags.h>
+#include <freetype/ftoutln.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttgload.h"
+
+#else
+
+#include <truetype/ttgload.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttgload
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Composite font flags.                                                 */
+  /*                                                                       */
+#define ARGS_ARE_WORDS       0x001
+#define ARGS_ARE_XY_VALUES   0x002
+#define ROUND_XY_TO_GRID     0x004
+#define WE_HAVE_A_SCALE      0x008
+/* reserved                  0x010 */
+#define MORE_COMPONENTS      0x020
+#define WE_HAVE_AN_XY_SCALE  0x040
+#define WE_HAVE_A_2X2        0x080
+#define WE_HAVE_INSTR        0x100
+#define USE_MY_METRICS       0x200
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Get_Metrics                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the horizontal or vertical metrics in font units for a     */
+  /*    given glyph.  The metrics are the left side bearing (resp. top     */
+  /*    side bearing) and advance width (resp. advance height).            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    header  :: A pointer to either the horizontal or vertical metrics  */
+  /*               structure.                                              */
+  /*                                                                       */
+  /*    index   :: The glyph index.                                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    bearing :: The bearing, either left side or top side.              */
+  /*                                                                       */
+  /*    advance :: The advance width resp. advance height.                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will much probably move to another component in the  */
+  /*    near future, but I haven't decided which yet.                      */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  TT_Get_Metrics( TT_HoriHeader*  header,
+                        FT_UInt         index,
+                        FT_Short*       bearing,
+                        FT_UShort*      advance )
+  {
+    TT_LongMetrics*  longs_m;
+    FT_UShort        k = header->number_Of_HMetrics;
+
+
+    if ( index < k )
+    {
+      longs_m  = (TT_LongMetrics*)header->long_metrics + index;
+      *bearing = longs_m->bearing;
+      *advance = longs_m->advance;
+    }
+    else
+    {
+      *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
+      *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Returns the horizontal metrics in font units for a given glyph.  If   */
+  /* `check' is true, take care of monospaced fonts by returning the       */
+  /* advance width maximum.                                                */
+  /*                                                                       */
+  static
+  void Get_HMetrics( TT_Face     face,
+                     FT_UInt     index,
+                     FT_Bool     check,
+                     FT_Short*   lsb,
+                     FT_UShort*  aw )
+  {
+    TT_Get_Metrics( &face->horizontal, index, lsb, aw );
+
+    if ( check && face->postscript.isFixedPitch )
+      *aw = face->horizontal.advance_Width_Max;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*    Returns the advance width table for a given pixel size if it is    */
+  /*    found in the font's `hdmx' table (if any).                         */
+  /*                                                                       */
+  static
+  FT_Byte*  Get_Advance_Widths( TT_Face    face,
+                                FT_UShort  ppem )
+  {
+    FT_UShort  n;
+
+    for ( n = 0; n < face->hdmx.num_records; n++ )
+      if ( face->hdmx.records[n].ppem == ppem )
+        return face->hdmx.records[n].widths;
+
+    return NULL;
+  }
+
+
+#define cur_to_org( n, zone ) \
+          MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
+
+#define org_to_cur( n, zone ) \
+          MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*    Translates an array of coordinates.                                */
+  /*                                                                       */
+  static
+  void  translate_array( FT_UInt     n,
+                         FT_Vector*  coords,
+                         FT_Pos      delta_x,
+                         FT_Pos      delta_y )
+  {
+    FT_UInt  k;
+
+
+    if ( delta_x )
+      for ( k = 0; k < n; k++ )
+        coords[k].x += delta_x;
+
+    if ( delta_y )
+      for ( k = 0; k < n; k++ )
+        coords[k].y += delta_y;
+  }
+
+
+  static
+  void  tt_prepare_zone( TT_GlyphZone*  zone,
+                         FT_GlyphLoad*  load,
+                         FT_UInt        start_point,
+                         FT_UInt        start_contour )
+  {
+    zone->n_points   = load->outline.n_points - start_point;
+    zone->n_contours = load->outline.n_contours - start_contour;
+    zone->org        = load->extra_points + start_point;
+    zone->cur        = load->outline.points + start_point;
+    zone->tags       = (FT_Byte*)load->outline.tags + start_point;
+    zone->contours   = (FT_UShort*)load->outline.contours + start_contour;
+  }
+
+
+#undef  IS_HINTED
+#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  The following functions are used by default with TrueType fonts.     */
+  /*  However, they can be replaced by alternatives if we need to support  */
+  /*  TrueType-compressed formats (like MicroType) in the future.          */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static
+  FT_Error  TT_Access_Glyph_Frame( TT_Loader*  loader,
+                                   FT_UInt     glyph_index,
+                                   FT_ULong    offset,
+                                   FT_UInt     byte_count )
+  {
+    FT_Error  error;
+    FT_Stream stream = loader->stream;
+
+
+    /* the following line sets the `error' variable through macros! */
+    (void)( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) );
+
+    FT_TRACE5(( "Glyph %ld\n", glyph_index ));
+    return error;
+  }
+
+
+  static
+  void  TT_Forget_Glyph_Frame( TT_Loader*  loader )
+  {
+    FT_Stream  stream = loader->stream;
+
+
+    FORGET_Frame();
+  }
+
+
+  static
+  FT_Error  TT_Load_Glyph_Header( TT_Loader*  loader )
+  {
+    FT_Stream   stream = loader->stream;
+
+
+    loader->n_contours = GET_Short();
+
+    loader->bbox.xMin = GET_Short();
+    loader->bbox.yMin = GET_Short();
+    loader->bbox.xMax = GET_Short();
+    loader->bbox.yMax = GET_Short();
+
+    FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
+    FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
+                                            loader->bbox.xMax ));
+    FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
+                                            loader->bbox.yMax ));
+
+    return FT_Err_Ok;
+  }
+
+
+  static
+  FT_Error  TT_Load_Simple_Glyph( TT_Loader*  load )
+  {
+    FT_Error         error;
+    FT_Stream        stream     = load->stream;
+    FT_GlyphLoader*  gloader    = load->gloader;
+    FT_Int           n_contours = load->n_contours;
+    FT_Outline*      outline;
+    TT_Face          face    = (TT_Face)load->face;
+    TT_GlyphSlot     slot    = (TT_GlyphSlot)load->glyph;
+    FT_UShort        n_ins;
+    FT_Int           n, n_points;
+
+
+    /* reading the contours endpoints & number of points */
+    {
+      short*  cur   = gloader->current.outline.contours;
+      short*  limit = cur + n_contours;
+
+
+      for ( ; cur < limit; cur++ )
+        cur[0] = GET_UShort();
+
+      n_points = 0;
+      if ( n_contours > 0 )
+        n_points = cur[-1] + 1;
+
+      error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 );
+      if ( error )
+        goto Fail;
+
+      outline = &gloader->current.outline;
+    }
+
+    /* reading the bytecode instructions */
+    slot->control_len  = 0;
+    slot->control_data = 0;
+
+    n_ins = GET_UShort();
+
+    FT_TRACE5(( "  Instructions size: %d\n", n_ins ));
+
+    if ( n_ins > face->max_profile.maxSizeOfInstructions )
+    {
+      FT_TRACE0(( "ERROR: Too many instructions!\n" ));
+      error = TT_Err_Too_Many_Ins;
+      goto Fail;
+    }
+
+    if ( stream->cursor + n_ins > stream->limit )
+    {
+      FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
+      error = TT_Err_Too_Many_Ins;
+      goto Fail;
+    }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    if ( ( load->load_flags                        &
+         ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
+           load->instructions )
+    {
+      slot->control_len  = n_ins;
+      slot->control_data = load->instructions;
+
+      MEM_Copy( load->instructions, stream->cursor, n_ins );
+    }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    stream->cursor += n_ins;
+
+    /* reading the point tags */
+
+    {
+      FT_Byte*  flag  = (FT_Byte*)outline->tags;
+      FT_Byte*  limit = flag + n_points;
+      FT_Byte   c, count;
+
+
+      for ( ; flag < limit; flag++ )
+      {
+        *flag = c = GET_Byte();
+        if ( c & 8 )
+        {
+          for ( count = GET_Byte(); count > 0; count-- )
+            *++flag = c;
+        }
+      }
+    }
+
+    /* reading the X coordinates */
+
+    {
+      FT_Vector*  vec   = outline->points;
+      FT_Vector*  limit = vec + n_points;
+      FT_Byte*    flag  = (FT_Byte*)outline->tags;
+      FT_Pos      x     = 0;
+
+
+      for ( ; vec < limit; vec++, flag++ )
+      {
+        FT_Pos  y = 0;
+
+
+        if ( *flag & 2 )
+        {
+          y = GET_Byte();
+          if ( ( *flag & 16 ) == 0 )
+            y = -y;
+        }
+        else if ( ( *flag & 16 ) == 0 )
+          y = GET_Short();
+
+        x     += y;
+        vec->x = x;
+      }
+    }
+
+    /* reading the Y coordinates */
+
+    {
+      FT_Vector*  vec   = gloader->current.outline.points;
+      FT_Vector*  limit = vec + n_points;
+      FT_Byte*    flag  = (FT_Byte*)outline->tags;
+      FT_Pos      x     = 0;
+
+
+      for ( ; vec < limit; vec++, flag++ )
+      {
+        FT_Pos  y = 0;
+
+
+        if ( *flag & 4 )
+        {
+          y = GET_Byte();
+          if ( ( *flag & 32 ) == 0 )
+            y = -y;
+        }
+        else if ( ( *flag & 32 ) == 0 )
+          y = GET_Short();
+
+        x     += y;
+        vec->y = x;
+      }
+    }
+
+    /* clear the touch tags */
+    for ( n = 0; n < n_points; n++ )
+      outline->tags[n] &= FT_Curve_Tag_On;
+
+    outline->n_points   = n_points;
+    outline->n_contours = n_contours;
+
+  Fail:
+    return error;
+  }
+
+
+  static
+  FT_Error  TT_Load_Composite_Glyph( TT_Loader*  loader )
+  {
+    FT_Error         error;
+    FT_Stream        stream  = loader->stream;
+    FT_GlyphLoader*  gloader = loader->gloader;
+    FT_SubGlyph*     subglyph;
+    FT_UInt          num_subglyphs;
+
+
+    num_subglyphs = 0;
+
+    do
+    {
+      FT_Fixed  xx, xy, yy, yx;
+
+
+      /* check that we can load a new subglyph */
+      error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 );
+      if ( error )
+        goto Fail;
+
+      subglyph = gloader->current.subglyphs + num_subglyphs;
+
+      subglyph->arg1 = subglyph->arg2 = 0;
+
+      subglyph->flags = GET_UShort();
+      subglyph->index = GET_UShort();
+
+      /* read arguments */
+      if ( subglyph->flags & ARGS_ARE_WORDS )
+      {
+        subglyph->arg1 = GET_Short();
+        subglyph->arg2 = GET_Short();
+      }
+      else
+      {
+        subglyph->arg1 = GET_Char();
+        subglyph->arg2 = GET_Char();
+      }
+
+      /* read transform */
+      xx = yy = 0x10000L;
+      xy = yx = 0;
+
+      if ( subglyph->flags & WE_HAVE_A_SCALE )
+      {
+        xx = (FT_Fixed)GET_Short() << 2;
+        yy = xx;
+      }
+      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
+      {
+        xx = (FT_Fixed)GET_Short() << 2;
+        yy = (FT_Fixed)GET_Short() << 2;
+      }
+      else if ( subglyph->flags & WE_HAVE_A_2X2 )
+      {
+        xx = (FT_Fixed)GET_Short() << 2;
+        xy = (FT_Fixed)GET_Short() << 2;
+        yx = (FT_Fixed)GET_Short() << 2;
+        yy = (FT_Fixed)GET_Short() << 2;
+      }
+
+      subglyph->transform.xx = xx;
+      subglyph->transform.xy = xy;
+      subglyph->transform.yx = yx;
+      subglyph->transform.yy = yy;
+
+      num_subglyphs++;
+
+    } while ( subglyph->flags & MORE_COMPONENTS );
+
+    gloader->current.num_subglyphs = num_subglyphs;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+    {
+      /* we must undo the ACCESS_Frame in order to point to the */
+      /* composite instructions, if we find some.               */
+      /* we will process them later...                          */
+      /*                                                        */
+      loader->ins_pos = FILE_Pos() + stream->cursor - stream->limit;
+    }
+#endif
+
+  Fail:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  TT_Init_Glyph_Loading( TT_Face  face )
+  {
+    face->access_glyph_frame   = TT_Access_Glyph_Frame;
+    face->read_glyph_header    = TT_Load_Glyph_Header;
+    face->read_simple_glyph    = TT_Load_Simple_Glyph;
+    face->read_composite_glyph = TT_Load_Composite_Glyph;
+    face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Process_Simple_Glyph                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Once a simple glyph has been loaded, it needs to be processed.     */
+  /*    Usually, this means scaling and hinting through bytecode           */
+  /*    interpretation.                                                    */
+  /*                                                                       */
+  static
+  FT_Error  TT_Process_Simple_Glyph( TT_Loader*  load,
+                                     FT_Bool     debug )
+  {
+    FT_GlyphLoader*  gloader  = load->gloader;
+    FT_Outline*      outline  = &gloader->current.outline;
+    FT_UInt          n_points = outline->n_points;
+    FT_UInt          n_ins;
+    TT_GlyphZone*    zone     = &load->zone;
+    FT_Error         error    = FT_Err_Ok;
+
+
+    n_ins = load->glyph->control_len;
+
+    /* add shadow points */
+
+    /* Now add the two shadow points at n and n + 1.    */
+    /* We need the left side bearing and advance width. */
+
+    {
+      FT_Vector*  pp1;
+      FT_Vector*  pp2;
+
+
+      /* pp1 = xMin - lsb */
+      pp1    = outline->points + n_points;
+      pp1->x = load->bbox.xMin - load->left_bearing;
+      pp1->y = 0;
+
+      /* pp2 = pp1 + aw */
+      pp2    = pp1 + 1;
+      pp2->x = pp1->x + load->advance;
+      pp2->y = 0;
+
+      outline->tags[n_points    ] = 0;
+      outline->tags[n_points + 1] = 0;
+    }
+
+    /* Note that we return two more points that are not */
+    /* part of the glyph outline.                       */
+
+    n_points += 2;
+
+    /* set up zone for hinting */
+    tt_prepare_zone( zone, &gloader->current, 0, 0 );
+
+    /* eventually scale the glyph */
+    if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
+    {
+      FT_Vector*  vec     = zone->cur;
+      FT_Vector*  limit   = vec + n_points;
+      FT_Fixed    x_scale = load->size->metrics.x_scale;
+      FT_Fixed    y_scale = load->size->metrics.y_scale;
+
+
+      /* first scale the glyph points */
+      for ( ; vec < limit; vec++ )
+      {
+        vec->x = FT_MulFix( vec->x, x_scale );
+        vec->y = FT_MulFix( vec->y, y_scale );
+      }
+    }
+
+    cur_to_org( n_points, zone );
+
+    /* eventually hint the glyph */
+    if ( IS_HINTED( load->load_flags ) )
+    {
+      FT_Pos  x = zone->org[n_points-2].x;
+
+
+      x = ( ( x + 32 ) & -64 ) - x;
+      translate_array( n_points, zone->org, x, 0 );
+
+      org_to_cur( n_points, zone );
+
+      zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+      /* now consider hinting */
+      if ( n_ins > 0 )
+      {
+        error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
+                                  load->exec->glyphIns, n_ins );
+        if ( error )
+          goto Exit;
+
+        load->exec->is_composite     = FALSE;
+        load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
+                                                  FT_LOAD_PEDANTIC );
+        load->exec->pts              = *zone;
+        load->exec->pts.n_points    += 2;
+
+        error = TT_Run_Context( load->exec, debug );
+        if ( error && load->exec->pedantic_hinting )
+          goto Exit;
+
+        error = FT_Err_Ok;  /* ignore bytecode errors in non-pedantic mode */
+      }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    }
+
+    /* save glyph phantom points */
+    if ( !load->preserve_pps )
+    {
+      load->pp1 = zone->cur[n_points - 2];
+      load->pp2 = zone->cur[n_points - 1];
+    }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+  Exit:
+#endif  
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    load_truetype_glyph                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given truetype glyph.  Handles composites and uses a       */
+  /*    TT_Loader object.                                                  */
+  /*                                                                       */
+  static
+  FT_Error  load_truetype_glyph( TT_Loader*  loader,
+                                 FT_UInt     glyph_index )
+  {
+    FT_Stream        stream = loader->stream;
+    FT_Error         error;
+    TT_Face          face   = (TT_Face)loader->face;
+    FT_ULong         offset;
+    FT_Int           contours_count;
+    FT_UInt          index, num_points, num_contours, count;
+    FT_Fixed         x_scale, y_scale;
+    FT_ULong         ins_offset;
+    FT_GlyphLoader*  gloader = loader->gloader;
+    FT_Bool          opened_frame = 0;
+
+
+    /* check glyph index */
+    index = glyph_index;
+    if ( index >= (FT_UInt)face->root.num_glyphs )
+    {
+      error = TT_Err_Invalid_Glyph_Index;
+      goto Exit;
+    }
+
+    loader->glyph_index = glyph_index;
+    num_contours = 0;
+    num_points   = 0;
+    ins_offset   = 0;
+
+    x_scale = 0x10000L;
+    y_scale = 0x10000L;
+    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+    {
+      x_scale = loader->size->metrics.x_scale;
+      y_scale = loader->size->metrics.y_scale;
+    }
+
+    /* get horizontal metrics */
+    {
+      FT_Short   left_bearing;
+      FT_UShort  advance_width;
+
+
+      Get_HMetrics( face, index,
+                    (FT_Bool)!(loader->load_flags &
+                                FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
+                    &left_bearing,
+                    &advance_width );
+
+      loader->left_bearing = left_bearing;
+      loader->advance      = advance_width;
+    }
+
+    offset = face->glyph_locations[index];
+    count  = 0;
+
+    if ( index < (FT_UInt)face->num_locations - 1 )
+       count = face->glyph_locations[index + 1] - offset;
+
+    if ( count == 0 )
+    {
+      /* as described by Frederic Loyer, these are spaces, and */
+      /* not the unknown glyph.                                */
+      loader->bbox.xMin = 0;
+      loader->bbox.xMax = 0;
+      loader->bbox.yMin = 0;
+      loader->bbox.yMax = 0;
+
+      loader->pp1.x = 0;
+      loader->pp2.x = loader->advance;
+
+      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+      if ( loader->exec )
+        loader->exec->glyphSize = 0;
+
+#endif
+
+      error = FT_Err_Ok;
+      goto Exit;
+    }
+
+    offset = loader->glyf_offset + offset;
+
+    /* access glyph frame */
+    error = face->access_glyph_frame( loader, glyph_index, offset, count );
+    if ( error )
+      goto Exit;
+
+    opened_frame = 1;
+
+    /* read first glyph header */
+    error = face->read_glyph_header( loader );
+    if ( error )
+      goto Fail;
+
+    contours_count = loader->n_contours;
+
+    count -= 10;
+
+    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
+    loader->pp1.y = 0;
+    loader->pp2.x = loader->pp1.x + loader->advance;
+    loader->pp2.y = 0;
+
+    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+    {
+      loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+      loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+    }
+
+    /***********************************************************************/
+    /***********************************************************************/
+    /***********************************************************************/
+
+    /* if it is a simple glyph, load it */
+
+    if ( contours_count >= 0 )
+    {
+      /* check that we can add the contours to the glyph */
+      error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
+      if ( error )
+        goto Fail;
+
+      error = face->read_simple_glyph( loader );
+      if ( error )
+        goto Fail;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+      {
+        TT_Size size = (TT_Size)loader->size;
+
+
+        error = TT_Process_Simple_Glyph( loader,
+                                         (FT_Bool)( size && size->debug ) );
+      }
+
+#else
+
+      error = TT_Process_Simple_Glyph( loader, 0 );
+
+#endif
+
+      if ( error )
+        goto Fail;
+
+      FT_GlyphLoader_Add( gloader );
+
+      /* Note: We could have put the simple loader source there */
+      /*       but the code is fat enough already :-)           */
+    }
+
+    /***********************************************************************/
+    /***********************************************************************/
+    /***********************************************************************/
+
+    /* otherwise, load a composite! */
+    else
+    {
+      TT_GlyphSlot  glyph = (TT_GlyphSlot)loader->glyph;
+      FT_UInt       start_point, start_contour;
+      FT_ULong      ins_pos;  /* position of composite instructions, if any */
+
+
+      /* for each subglyph, read composite header */
+      start_point   = gloader->base.outline.n_points;
+      start_contour = gloader->base.outline.n_contours;
+
+      error = face->read_composite_glyph( loader );
+      if ( error )
+        goto Fail;
+
+      ins_pos = loader->ins_pos;
+      face->forget_glyph_frame( loader );
+      opened_frame = 0;
+
+      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
+      /* `as is' in the glyph slot (the client application will be     */
+      /* responsible for interpreting this data)...                    */
+      /*                                                               */
+      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+      {
+        /* set up remaining glyph fields */
+        FT_GlyphLoader_Add( gloader );
+
+        glyph->num_subglyphs  = gloader->base.num_subglyphs;
+        glyph->format         = ft_glyph_format_composite;
+        glyph->subglyphs      = gloader->base.subglyphs;
+
+        goto Exit;
+      }
+
+      /*********************************************************************/
+      /*********************************************************************/
+      /*********************************************************************/
+
+      /* Now, read each subglyph independently. */
+      {
+        FT_Int        n, num_base_points, num_new_points;
+        FT_SubGlyph*  subglyph = 0;
+
+        FT_UInt num_subglyphs  = gloader->current.num_subglyphs;
+        FT_UInt num_base_subgs = gloader->base.num_subglyphs;
+
+
+        FT_GlyphLoader_Add( gloader );
+
+        for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
+        {
+          FT_Vector  pp1, pp2;
+          FT_Pos     x, y;
+
+
+          /* Each time we call load_truetype_glyph in this loop, the   */
+          /* value of `gloader.base.subglyphs' can change due to table */
+          /* reallocations.  We thus need to recompute the subglyph    */
+          /* pointer on each iteration.                                */
+          subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+          pp1 = loader->pp1;
+          pp2 = loader->pp2;
+
+          num_base_points = gloader->base.outline.n_points;
+
+          error = load_truetype_glyph( loader, subglyph->index );
+          if ( error )
+            goto Fail;
+
+          subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+          if ( subglyph->flags & USE_MY_METRICS )
+          {
+            pp1 = loader->pp1;
+            pp2 = loader->pp2;
+          }
+          else
+          {
+            loader->pp1 = pp1;
+            loader->pp2 = pp2;
+          }
+
+          num_points = gloader->base.outline.n_points;
+
+          num_new_points = num_points - num_base_points;
+
+          /* now perform the transform required for this subglyph */
+
+          if ( subglyph->flags & ( WE_HAVE_A_SCALE     |
+                                   WE_HAVE_AN_XY_SCALE |
+                                   WE_HAVE_A_2X2       ) )
+          {
+            FT_Vector*  cur   = gloader->base.outline.points +
+                                  num_base_points;
+            FT_Vector*  org   = gloader->base.extra_points +
+                                  num_base_points;
+            FT_Vector*  limit = cur + num_new_points;
+
+
+            for ( ; cur < limit; cur++, org++ )
+            {
+              FT_Vector_Transform( cur, &subglyph->transform );
+              FT_Vector_Transform( org, &subglyph->transform );
+            }
+          }
+
+          /* apply offset */
+
+          if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
+          {
+            FT_UInt     k = subglyph->arg1;
+            FT_UInt     l = subglyph->arg2;
+            FT_Vector*  p1;
+            FT_Vector*  p2;
+
+
+            if ( start_point + k >= (FT_UInt)num_base_points ||
+                               l >= (FT_UInt)num_new_points  )
+            {
+              error = TT_Err_Invalid_Composite;
+              goto Fail;
+            }
+
+            l += num_base_points;
+
+            p1 = gloader->base.outline.points + start_point + k;
+            p2 = gloader->base.outline.points + start_point + l;
+
+            x = p1->x - p2->x;
+            y = p1->y - p2->y;
+          }
+          else
+          {
+            x = subglyph->arg1;
+            y = subglyph->arg2;
+
+            if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+            {
+              x = FT_MulFix( x, x_scale );
+              y = FT_MulFix( y, y_scale );
+
+              if ( subglyph->flags & ROUND_XY_TO_GRID )
+              {
+                x = ( x + 32 ) & -64;
+                y = ( y + 32 ) & -64;
+              }
+            }
+          }
+
+          translate_array( num_new_points, loader->zone.cur, x, y );
+          cur_to_org( num_new_points, &loader->zone );
+        }
+
+        /*******************************************************************/
+        /*******************************************************************/
+        /*******************************************************************/
+
+        /* we have finished loading all sub-glyphs; now, look for */
+        /* instructions for this composite!                       */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+        if ( num_subglyphs > 0               &&
+             loader->exec                    &&
+             ins_pos         > 0             &&
+             subglyph->flags & WE_HAVE_INSTR )
+        {
+          FT_UShort       n_ins;
+          TT_ExecContext  exec = loader->exec;
+          TT_GlyphZone*   pts;
+          FT_Vector*      pp1;
+
+
+          /* read size of instructions */
+          if ( FILE_Seek( ins_pos ) ||
+               READ_UShort( n_ins ) )
+            goto Fail;
+          FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
+
+          /* in some fonts? */
+          if ( n_ins == 0xFFFF )
+            n_ins = 0;
+
+          /* check it */
+          if ( n_ins > face->max_profile.maxSizeOfInstructions )
+          {
+            FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
+                        n_ins, subglyph->index ));
+            return TT_Err_Too_Many_Ins;
+          }
+
+          /* read the instructions */
+          if ( FILE_Read( exec->glyphIns, n_ins ) )
+            goto Fail;
+
+          glyph->control_data = exec->glyphIns;
+          glyph->control_len  = n_ins;
+
+          error = TT_Set_CodeRange( exec,
+                                    tt_coderange_glyph,
+                                    exec->glyphIns,
+                                    n_ins );
+          if ( error )
+            goto Fail;
+
+          /* prepare the execution context */
+          tt_prepare_zone( &exec->pts, &gloader->base,
+                           start_point, start_contour );
+          pts = &exec->pts;
+
+          pts->n_points   = num_points + 2;
+          pts->n_contours = gloader->base.outline.n_contours;
+
+          /* add phantom points */
+          pp1    = pts->cur + num_points;
+          pp1[0] = loader->pp1;
+          pp1[1] = loader->pp2;
+
+          pts->tags[num_points    ] = 0;
+          pts->tags[num_points + 1] = 0;
+
+          /* if hinting, round the phantom points */
+          if ( IS_HINTED( loader->load_flags ) )
+          {
+            pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
+            pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
+          }
+
+          {
+            FT_UInt  k;
+
+
+            for ( k = 0; k < num_points; k++ )
+              pts->tags[k] &= FT_Curve_Tag_On;
+          }
+
+          cur_to_org( num_points + 2, pts );
+
+          /* now consider hinting */
+          if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
+          {
+            exec->is_composite     = TRUE;
+            exec->pedantic_hinting =
+              (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
+
+            error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
+            if ( error && exec->pedantic_hinting )
+              goto Fail;
+          }
+
+          /* save glyph origin and advance points */
+          loader->pp1 = pp1[0];
+          loader->pp2 = pp1[1];
+        }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+      }
+      /* end of composite loading */
+    }
+
+    /***********************************************************************/
+    /***********************************************************************/
+    /***********************************************************************/
+
+  Fail:
+    if ( opened_frame )
+      face->forget_glyph_frame( loader );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  compute_glyph_metrics( TT_Loader*  loader,
+                               FT_UInt     glyph_index )
+  {
+    FT_BBox       bbox;
+    TT_Face       face = (TT_Face)loader->face;
+    FT_Fixed      x_scale, y_scale;
+    TT_GlyphSlot  glyph = loader->glyph;
+    TT_Size       size = (TT_Size)loader->size;
+
+
+    x_scale = 0x10000L;
+    y_scale = 0x10000L;
+    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+    {
+      x_scale = size->root.metrics.x_scale;
+      y_scale = size->root.metrics.y_scale;
+    }
+
+    if ( glyph->format != ft_glyph_format_composite )
+    {
+      glyph->outline.flags &= ~ft_outline_single_pass;
+
+      /* copy outline to our glyph slot */
+      FT_GlyphLoader_Copy_Points( glyph->loader, loader->gloader );
+      glyph->outline = glyph->loader->base.outline;
+
+      /* translate array so that (0,0) is the glyph's origin */
+      FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
+
+      FT_Outline_Get_CBox( &glyph->outline, &bbox );
+
+      if ( IS_HINTED( loader->load_flags ) )
+      {
+        /* grid-fit the bounding box */
+        bbox.xMin &= -64;
+        bbox.yMin &= -64;
+        bbox.xMax  = ( bbox.xMax + 63 ) & -64;
+        bbox.yMax  = ( bbox.yMax + 63 ) & -64;
+      }
+    }
+    else
+      bbox = loader->bbox;
+
+    /* get the device-independent horizontal advance.  It is scaled later */
+    /* by the base layer.                                                 */
+    {
+      FT_Pos  advance = loader->advance;
+
+
+      /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
+      /* correctly support DynaLab fonts, which have an incorrect       */
+      /* `advance_Width_Max' field!  It is used, to my knowledge,       */
+      /* exclusively in the X-TrueType font server.                     */
+      /*                                                                */
+      if ( face->postscript.isFixedPitch                                    &&
+           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
+        advance = face->horizontal.advance_Width_Max;
+
+      /* we need to return the advance in font units in linearHoriAdvance, */
+      /* it will be scaled later by the base layer.                        */
+      glyph->linearHoriAdvance = advance;
+    }
+
+    glyph->metrics.horiBearingX = bbox.xMin;
+    glyph->metrics.horiBearingY = bbox.yMax;
+    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
+
+    /* Now take care of vertical metrics.  In the case where there is    */
+    /* no vertical information within the font (relatively common), make */
+    /* up some metrics by `hand'...                                      */
+
+    {
+      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
+      FT_UShort  advance_height; /* vertical advance height   (EM units) */
+
+      FT_Pos  left;     /* scaled vertical left side bearing         */
+      FT_Pos  Top;      /* scaled original vertical top side bearing */
+      FT_Pos  top;      /* scaled vertical top side bearing          */
+      FT_Pos  advance;  /* scaled vertical advance height            */
+
+
+      /* Get the unscaled `tsb' and `ah' */
+      if ( face->vertical_info                   &&
+           face->vertical.number_Of_VMetrics > 0 )
+      {
+        /* Don't assume that both the vertical header and vertical */
+        /* metrics are present in the same font :-)                */
+
+        TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
+                        glyph_index,
+                        &top_bearing,
+                        &advance_height );
+      }
+      else
+      {
+        /* Make up the distances from the horizontal header.   */
+
+        /* NOTE: The OS/2 values are the only `portable' ones, */
+        /*       which is why we use them, if there is an OS/2 */
+        /*       table in the font.  Otherwise, we use the     */
+        /*       values defined in the horizontal header.      */
+        /*                                                     */
+        /* NOTE2: The sTypoDescender is negative, which is why */
+        /*        we compute the baseline-to-baseline distance */
+        /*        here with:                                   */
+        /*             ascender - descender + linegap          */
+        /*                                                     */
+        if ( face->os2.version != 0xFFFF )
+        {
+          top_bearing    = face->os2.sTypoLineGap / 2;
+          advance_height = (FT_UShort)( face->os2.sTypoAscender -
+                                        face->os2.sTypoDescender +
+                                        face->os2.sTypoLineGap );
+        }
+        else
+        {
+          top_bearing    = face->horizontal.Line_Gap / 2;
+          advance_height = (FT_UShort)( face->horizontal.Ascender  +
+                                        face->horizontal.Descender +
+                                        face->horizontal.Line_Gap );
+        }
+      }
+
+      /* We must adjust the top_bearing value from the bounding box given */
+      /* in the glyph header to te bounding box calculated with           */
+      /* FT_Get_Outline_CBox().                                           */
+
+      /* scale the metrics */
+      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+      {
+        Top     = FT_MulFix( top_bearing, y_scale );
+        top     = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
+                    - bbox.yMax;
+        advance = FT_MulFix( advance_height, y_scale );
+      }
+      else
+      {
+        Top     = top_bearing;
+        top     = top_bearing + loader->bbox.yMax - bbox.yMax;
+        advance = advance_height;
+      }
+
+      /* set the advance height in design units.  It is scaled later by */
+      /* the base layer.                                                */
+      glyph->linearVertAdvance = advance_height;
+
+      /* XXX: for now, we have no better algorithm for the lsb, but it */
+      /*      should work fine.                                        */
+      /*                                                               */
+      left = ( bbox.xMin - bbox.xMax ) / 2;
+
+      /* grid-fit them if necessary */
+      if ( IS_HINTED( loader->load_flags ) )
+      {
+        left   &= -64;
+        top     = ( top + 63     ) & -64;
+        advance = ( advance + 32 ) & -64;
+      }
+
+      glyph->metrics.vertBearingX = left;
+      glyph->metrics.vertBearingY = top;
+      glyph->metrics.vertAdvance  = advance;
+    }
+
+    /* adjust advance width to the value contained in the hdmx table */
+    if ( !face->postscript.isFixedPitch && size &&
+         IS_HINTED( loader->load_flags )        )
+    {
+      FT_Byte* widths = Get_Advance_Widths( face,
+                                            size->root.metrics.x_ppem );
+
+
+      if ( widths )
+        glyph->metrics.horiAdvance = widths[glyph_index] << 6;
+    }
+
+    /* set glyph dimensions */
+    glyph->metrics.width  = bbox.xMax - bbox.xMin;
+    glyph->metrics.height = bbox.yMax - bbox.yMin;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph       :: A handle to a target slot object where the glyph    */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled/loaded.                              */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Glyph( TT_Size       size,
+                           TT_GlyphSlot  glyph,
+                           FT_UShort     glyph_index,
+                           FT_UInt       load_flags )
+  {
+    SFNT_Interface*  sfnt;
+    TT_Face          face;
+    FT_Stream        stream;
+    FT_Memory        memory;
+    FT_Error         error;
+    TT_Loader        loader;
+
+
+    face   = (TT_Face)glyph->face;
+    sfnt   = (SFNT_Interface*)face->sfnt;
+    stream = face->root.stream;
+    memory = face->root.memory;
+    error  = 0;
+
+    if ( !size || ( load_flags & FT_LOAD_NO_SCALE )   ||
+                  ( load_flags & FT_LOAD_NO_RECURSE ) )
+    {
+      size        = NULL;
+      load_flags |= FT_LOAD_NO_SCALE   |
+                    FT_LOAD_NO_HINTING |
+                    FT_LOAD_NO_BITMAP;
+    }
+
+    glyph->num_subglyphs = 0;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    /* try to load embedded bitmap if any */
+    if ( size                                    &&
+         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
+         sfnt->load_sbits                        )
+    {
+      TT_SBit_Metrics  metrics;
+
+
+      error = sfnt->load_sbit_image( face,
+                                     size->root.metrics.x_ppem,
+                                     size->root.metrics.y_ppem,
+                                     glyph_index,
+                                     load_flags,
+                                     stream,
+                                     &glyph->bitmap,
+                                     &metrics );
+      if ( !error )
+      {
+        glyph->outline.n_points   = 0;
+        glyph->outline.n_contours = 0;
+
+        glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
+        glyph->metrics.height = (FT_Pos)metrics.height << 6;
+
+        glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+        glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+        glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
+
+        glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+        glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+        glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
+
+        glyph->format = ft_glyph_format_bitmap;
+        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+        {
+          glyph->bitmap_left = metrics.vertBearingX;
+          glyph->bitmap_top  = metrics.vertBearingY;
+        }
+        else
+        {
+          glyph->bitmap_left = metrics.horiBearingX;
+          glyph->bitmap_top  = metrics.horiBearingY;
+        }
+        return error;
+      }
+    }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    /* seek to the beginning of the glyph table.  For Type 42 fonts      */
+    /* the table might be accessed from a Postscript stream or something */
+    /* else...                                                           */
+
+    error = face->goto_table( face, TTAG_glyf, stream, 0 );
+    if ( error )
+    {
+      FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
+      goto Exit;
+    }
+
+    MEM_Set( &loader, 0, sizeof ( loader ) );
+
+    /* update the glyph zone bounds */
+    {
+      FT_GlyphLoader*  gloader = FT_FACE_DRIVER(face)->glyph_loader;
+
+
+      loader.gloader = gloader;
+
+      FT_GlyphLoader_Rewind( gloader );
+
+      tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
+      tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
+    }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    if ( size )
+    {
+      /* query new execution context */
+      loader.exec = size->debug ? size->context : TT_New_Context( face );
+      if ( !loader.exec )
+        return TT_Err_Could_Not_Find_Context;
+
+      TT_Load_Context( loader.exec, face, size );
+      loader.instructions = loader.exec->glyphIns;
+
+      /* load default graphics state - if needed */
+      if ( size->GS.instruct_control & 2 )
+        loader.exec->GS = tt_default_graphics_state;
+    }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    /* clear all outline flags, except the `owner' one */
+    glyph->outline.flags = 0;
+
+    if ( size && size->root.metrics.y_ppem < 24 )
+      glyph->outline.flags |= ft_outline_high_precision;
+
+    /* let's initialize the rest of our loader now */
+
+    loader.load_flags    = load_flags;
+
+    loader.face   = (FT_Face)face;
+    loader.size   = (FT_Size)size;
+    loader.glyph  = (FT_GlyphSlot)glyph;
+    loader.stream = stream;
+
+    loader.glyf_offset  = FILE_Pos();
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    /* if the cvt program has disabled hinting, the argument */
+    /* is ignored.                                           */
+    if ( size && ( size->GS.instruct_control & 1 ) )
+      loader.load_flags |= FT_LOAD_NO_HINTING;
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    /* Main loading loop */
+    glyph->format        = ft_glyph_format_outline;
+    glyph->num_subglyphs = 0;
+    error = load_truetype_glyph( &loader, glyph_index );
+    if ( !error )
+      compute_glyph_metrics( &loader, glyph_index );
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    if ( !size || !size->debug )
+      TT_Done_Context( loader.exec );
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/truetype/ttgload.h b/src/freetype/truetype/ttgload.h
new file mode 100644 (file)
index 0000000..2f3e96b
--- /dev/null
@@ -0,0 +1,69 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttgload.h                                                              */
+/*                                                                         */
+/*    TrueType Glyph Loader (specification).                               */
+/*                                                                         */
+/*  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 TTGLOAD_H
+#define TTGLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttobjs.h"
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <truetype/ttobjs.h>
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include <truetype/ttinterp.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  LOCAL_DEF
+  void  TT_Get_Metrics( TT_HoriHeader*  header,
+                        FT_UInt         index,
+                        FT_Short*       bearing,
+                        FT_UShort*      advance );
+
+  LOCAL_DEF
+  void  TT_Init_Glyph_Loading( TT_Face  face );
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Glyph( TT_Size       size,
+                           TT_GlyphSlot  glyph,
+                           FT_UShort     glyph_index,
+                           FT_UInt       load_flags );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* TTGLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/truetype/ttinterp.c b/src/freetype/truetype/ttinterp.c
new file mode 100644 (file)
index 0000000..9dc0c19
--- /dev/null
@@ -0,0 +1,7544 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttinterp.c                                                             */
+/*                                                                         */
+/*    TrueType bytecode interpreter (body).                                */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/ftsystem.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttinterp.h"
+
+#else
+
+#include <truetype/ttinterp.h>
+
+#endif
+
+
+#include <freetype/internal/tterrors.h>
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+
+#define TT_MULFIX   FT_MulFix
+#define TT_MULDIV   FT_MulDiv
+
+#define TT_INT64    FT_Int64
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttinterp
+
+#undef  NO_APPLE_PATENT
+#define APPLE_THRESHOLD  0x4000000L
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* In order to detect infinite loops in the code, we set up a counter    */
+  /* within the run loop.  A single stroke of interpretation is now        */
+  /* limitet to a maximal number of opcodes defined below.                 */
+  /*                                                                       */
+#define MAX_RUNNABLE_OPCODES  1000000L
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* There are two kinds of implementations:                               */
+  /*                                                                       */
+  /* a. static implementation                                              */
+  /*                                                                       */
+  /*    The current execution context is a static variable, which fields   */
+  /*    are accessed directly by the interpreter during execution.  The    */
+  /*    context is named `cur'.                                            */
+  /*                                                                       */
+  /*    This version is non-reentrant, of course.                          */
+  /*                                                                       */
+  /* b. indirect implementation                                            */
+  /*                                                                       */
+  /*    The current execution context is passed to _each_ function as its  */
+  /*    first argument, and each field is thus accessed indirectly.        */
+  /*                                                                       */
+  /*    This version is fully re-entrant.                                  */
+  /*                                                                       */
+  /* The idea is that an indirect implementation may be slower to execute  */
+  /* on low-end processors that are used in some systems (like 386s or     */
+  /* even 486s).                                                           */
+  /*                                                                       */
+  /* As a consequence, the indirect implementation is now the default, as  */
+  /* its performance costs can be considered negligible in our context.    */
+  /* Note, however, that we kept the same source with macros because:      */
+  /*                                                                       */
+  /* - The code is kept very close in design to the Pascal code used for   */
+  /*   development.                                                        */
+  /*                                                                       */
+  /* - It's much more readable that way!                                   */
+  /*                                                                       */
+  /* - It's still open to experimentation and tuning.                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */
+
+#define CUR  (*exc)                             /* see ttobjs.h */
+
+#else                                           /* static implementation */
+
+#define CUR  cur
+
+  static
+  TT_ExecContextRec  cur;   /* static exec. context variable */
+
+  /* apparently, we have a _lot_ of direct indexing when accessing  */
+  /* the static `cur', which makes the code bigger (due to all the  */
+  /* four bytes addresses).                                         */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The instruction argument stack.                                       */
+  /*                                                                       */
+#define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This macro is used whenever `exec' is unused in a function, to avoid  */
+  /* stupid warnings from pedantic compilers.                              */
+  /*                                                                       */
+#define FT_UNUSED_EXEC  FT_UNUSED( CUR )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This macro is used whenever `args' is unused in a function, to avoid  */
+  /* stupid warnings from pedantic compilers.                              */
+  /*                                                                       */
+#define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
+  /* increase readabilty of the code.                                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define SKIP_Code() \
+          SkipCode( EXEC_ARG )
+
+#define GET_ShortIns() \
+          GetShortIns( EXEC_ARG )
+
+#define NORMalize( x, y, v ) \
+          Normalize( EXEC_ARG_ x, y, v )
+
+#define SET_SuperRound( scale, flags ) \
+          SetSuperRound( EXEC_ARG_ scale, flags )
+
+#define ROUND_None( d, c ) \
+          Round_None( EXEC_ARG_ d, c )
+
+#define INS_Goto_CodeRange( range, ip ) \
+          Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
+
+#define CUR_Func_project( x, y ) \
+          CUR.func_project( EXEC_ARG_ x, y )
+
+#define CUR_Func_move( z, p, d ) \
+          CUR.func_move( EXEC_ARG_ z, p, d )
+
+#define CUR_Func_dualproj( x, y ) \
+          CUR.func_dualproj( EXEC_ARG_ x, y )
+
+#define CUR_Func_freeProj( x, y ) \
+          CUR.func_freeProj( EXEC_ARG_ x, y )
+
+#define CUR_Func_round( d, c ) \
+          CUR.func_round( EXEC_ARG_ d, c )
+
+#define CUR_Func_read_cvt( index ) \
+          CUR.func_read_cvt( EXEC_ARG_ index )
+
+#define CUR_Func_write_cvt( index, val ) \
+          CUR.func_write_cvt( EXEC_ARG_ index, val )
+
+#define CUR_Func_move_cvt( index, val ) \
+          CUR.func_move_cvt( EXEC_ARG_ index, val )
+
+#define CURRENT_Ratio() \
+          Current_Ratio( EXEC_ARG )
+
+#define CURRENT_Ppem() \
+          Current_Ppem( EXEC_ARG )
+
+#define CUR_Ppem() \
+          Cur_PPEM( EXEC_ARG )
+
+#define CALC_Length() \
+          Calc_Length( EXEC_ARG )
+
+#define INS_SxVTL( a, b, c, d ) \
+          Ins_SxVTL( EXEC_ARG_ a, b, c, d )
+
+#define COMPUTE_Funcs() \
+          Compute_Funcs( EXEC_ARG )
+
+#define COMPUTE_Round( a ) \
+          Compute_Round( EXEC_ARG_ a )
+
+#define COMPUTE_Point_Displacement( a, b, c, d ) \
+          Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
+
+#define MOVE_Zp2_Point( a, b, c, t ) \
+          Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Instruction dispatch function, as used by the interpreter.            */
+  /*                                                                       */
+  typedef void  (*TInstruction_Function)( INS_ARG );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A simple bounds-checking macro.                                       */
+  /*                                                                       */
+#define BOUNDS( x, n )  ( (FT_UInt)(x) >= (FT_UInt)(n) )
+
+
+#undef  SUCCESS
+#define SUCCESS  0
+
+#undef  FAILURE
+#define FAILURE  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                        CODERANGE FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Goto_CodeRange                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Switches to a new code range (updates the code related elements in */
+  /*    `exec', and `IP').                                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range :: The new execution code range.                             */
+  /*                                                                       */
+  /*    IP    :: The new IP in the new code range.                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec  :: The target execution context.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Goto_CodeRange( TT_ExecContext  exec,
+                               FT_Int          range,
+                               FT_Long         IP )
+  {
+    TT_CodeRange*  coderange;
+
+
+    FT_Assert( range >= 1 && range <= 3 );
+
+    coderange = &exec->codeRangeTable[range - 1];
+
+    FT_Assert( coderange->base != NULL );
+
+    /* NOTE: Because the last instruction of a program may be a CALL */
+    /*       which will return to the first byte *after* the code    */
+    /*       range, we test for IP <= Size instead of IP < Size.     */
+    /*                                                               */
+    FT_Assert( (FT_ULong)IP <= coderange->size );
+
+    exec->code     = coderange->base;
+    exec->codeSize = coderange->size;
+    exec->IP       = IP;
+    exec->curRange = range;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Set_CodeRange                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets a code range.                                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range  :: The code range index.                                    */
+  /*                                                                       */
+  /*    base   :: The new code base.                                       */
+  /*                                                                       */
+  /*    length :: The range size in bytes.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec   :: The target execution context.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Set_CodeRange( TT_ExecContext  exec,
+                              FT_Int          range,
+                              void*           base,
+                              FT_Long         length )
+  {
+    FT_Assert( range >= 1 && range <= 3 );
+
+    exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
+    exec->codeRangeTable[range - 1].size = length;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Clear_CodeRange                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Clears a code range.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range :: The code range index.                                     */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec  :: The target execution context.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Does not set the Error variable.                                   */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Clear_CodeRange( TT_ExecContext  exec,
+                                FT_Int          range )
+  {
+    FT_Assert( range >= 1 && range <= 3 );
+
+    exec->codeRangeTable[range - 1].base = NULL;
+    exec->codeRangeTable[range - 1].size = 0;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                   EXECUTION CONTEXT ROUTINES                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Destroy_Context                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given context.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec   :: A handle to the target execution context.                */
+  /*                                                                       */
+  /*    memory :: A handle to the parent memory object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Destroy_Context( TT_ExecContext  exec,
+                                FT_Memory       memory )
+  {
+    /* free composite load stack */
+    FREE( exec->loadStack );
+    exec->loadSize = 0;
+
+    /* points zone */
+    exec->maxPoints   = 0;
+    exec->maxContours = 0;
+
+    /* free stack */
+    FREE( exec->stack );
+    exec->stackSize = 0;
+
+    /* free call stack */
+    FREE( exec->callStack );
+    exec->callSize = 0;
+    exec->callTop  = 0;
+
+    /* free glyph code range */
+    FREE( exec->glyphIns );
+    exec->glyphSize = 0;
+
+    exec->size = NULL;
+    exec->face = NULL;
+
+    FREE( exec );
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Init_Context                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a context object.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to the parent memory object.                    */
+  /*                                                                       */
+  /*    face   :: A handle to the source TrueType face object.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec   :: A handle to the target execution context.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Init_Context( TT_ExecContext  exec,
+                          TT_Face         face,
+                          FT_Memory       memory )
+  {
+    FT_Error  error;
+
+
+    FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n",
+                exec, face ));
+
+    exec->memory   = memory;
+    exec->callSize = 32;
+
+    if ( ALLOC_ARRAY( exec->callStack, exec->callSize, TT_CallRec ) )
+      goto Fail_Memory;
+
+    /* all values in the context are set to 0 already, but this is */
+    /* here as a remainder                                         */
+    exec->maxPoints   = 0;
+    exec->maxContours = 0;
+
+    exec->stackSize = 0;
+    exec->loadSize  = 0;
+    exec->glyphSize = 0;
+
+    exec->stack     = NULL;
+    exec->loadStack = NULL;
+    exec->glyphIns  = NULL;
+
+    exec->face = face;
+    exec->size = NULL;
+
+    return TT_Err_Ok;
+
+  Fail_Memory:
+    FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
+               (FT_Long)exec ));
+    TT_Destroy_Context( exec, memory );
+
+    return error;
+ }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Update_Max                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Checks the size of a buffer and reallocates it if necessary.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory     :: A handle to the parent memory object.                */
+  /*                                                                       */
+  /*    multiplier :: The size in bytes of each element in the buffer.     */
+  /*                                                                       */
+  /*    new_max    :: The new capacity (size) of the buffer.               */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size       :: The address of the buffer's current size expressed   */
+  /*                  in elements.                                         */
+  /*                                                                       */
+  /*    buff       :: The address of the buffer base pointer.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Update_Max( FT_Memory  memory,
+                        FT_ULong*  size,
+                        FT_Long    multiplier,
+                        void**     buff,
+                        FT_ULong   new_max )
+  {
+    FT_Error  error;
+
+
+    if ( *size < new_max )
+    {
+      FREE( *buff );
+      if ( ALLOC( *buff, new_max * multiplier ) )
+        return error;
+      *size = new_max;
+    }
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Context                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Prepare an execution context for glyph hinting.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source face object.                        */
+  /*                                                                       */
+  /*    size :: A handle to the source size object.                        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec :: A handle to the target execution context.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Context( TT_ExecContext  exec,
+                             TT_Face         face,
+                             TT_Size         size )
+  {
+    FT_Int          i;
+    FT_ULong        tmp;
+    TT_MaxProfile*  maxp;
+    FT_Error        error;
+
+
+    exec->face = face;
+    maxp       = &face->max_profile;
+    exec->size = size;
+
+    if ( size )
+    {
+      exec->numFDefs   = size->num_function_defs;
+      exec->maxFDefs   = size->max_function_defs;
+      exec->numIDefs   = size->num_instruction_defs;
+      exec->maxIDefs   = size->max_instruction_defs;
+      exec->FDefs      = size->function_defs;
+      exec->IDefs      = size->instruction_defs;
+      exec->tt_metrics = size->ttmetrics;
+      exec->metrics    = size->root.metrics;
+
+      exec->maxFunc    = size->max_func;
+      exec->maxIns     = size->max_ins;
+
+      for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+        exec->codeRangeTable[i] = size->codeRangeTable[i];
+
+      /* set graphics state */
+      exec->GS = size->GS;
+
+      exec->cvtSize = size->cvt_size;
+      exec->cvt     = size->cvt;
+
+      exec->storeSize = size->storage_size;
+      exec->storage   = size->storage;
+
+      exec->twilight  = size->twilight;
+    }
+
+    error = Update_Max( exec->memory,
+                        &exec->loadSize,
+                        sizeof ( TT_SubGlyphRec ),
+                        (void**)&exec->loadStack,
+                        exec->face->max_components + 1 );
+    if ( error )
+      return error;
+
+    /* XXX: We reserve a little more elements on the stack to deal safely */
+    /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
+    tmp = exec->stackSize;
+    error = Update_Max( exec->memory,
+                        &tmp,
+                        sizeof ( FT_F26Dot6 ),
+                        (void**)&exec->stack,
+                        maxp->maxStackElements + 32 );
+    exec->stackSize = (FT_UInt)tmp;
+    if ( error )
+      return error;
+
+    tmp = exec->glyphSize;
+    error = Update_Max( exec->memory,
+                        &tmp,
+                        sizeof ( FT_Byte ),
+                        (void**)&exec->glyphIns,
+                        maxp->maxSizeOfInstructions );
+    exec->glyphSize = (FT_UShort)tmp;
+    if ( error )
+      return error;
+
+    exec->pts.n_points   = 0;
+    exec->pts.n_contours = 0;
+
+    exec->instruction_trap = FALSE;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Save_Context                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Saves the code ranges in a `size' object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec :: A handle to the source execution context.                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Save_Context( TT_ExecContext  exec,
+                             TT_Size         size )
+  {
+    FT_Int  i;
+
+
+    /* XXXX: Will probably disappear soon with all the code range */
+    /*       management, which is now rather obsolete.            */
+    /*                                                            */
+    size->num_function_defs    = exec->numFDefs;
+    size->num_instruction_defs = exec->numIDefs;
+
+    size->max_func = exec->maxFunc;
+    size->max_ins  = exec->maxIns;
+
+    for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+      size->codeRangeTable[i] = exec->codeRangeTable[i];
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Run_Context                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Executes one or more instructions in the execution context.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    debug :: A Boolean flag.  If set, the function sets some internal  */
+  /*             variables and returns immediately, otherwise TT_RunIns()  */
+  /*             is called.                                                */
+  /*                                                                       */
+  /*             This is commented out currently.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec  :: A handle to the target execution context.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    TrueTyoe error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Run_Context( TT_ExecContext  exec,
+                            FT_Bool         debug )
+  {
+    FT_Error  error;
+
+
+    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0  ) )
+           != TT_Err_Ok )
+      return error;
+
+    exec->zp0 = exec->pts;
+    exec->zp1 = exec->pts;
+    exec->zp2 = exec->pts;
+
+    exec->GS.gep0 = 1;
+    exec->GS.gep1 = 1;
+    exec->GS.gep2 = 1;
+
+    exec->GS.projVector.x = 0x4000;
+    exec->GS.projVector.y = 0x0000;
+
+    exec->GS.freeVector = exec->GS.projVector;
+    exec->GS.dualVector = exec->GS.projVector;
+
+    exec->GS.round_state = 1;
+    exec->GS.loop        = 1;
+
+    /* some glyphs leave something on the stack. so we clean it */
+    /* before a new execution.                                  */
+    exec->top     = 0;
+    exec->callTop = 0;
+
+#if 1
+    FT_UNUSED( debug );
+
+    return exec->face->interpreter( exec );
+#else
+    if ( !debug )
+      return TT_RunIns( exec );
+    else
+      return TT_Err_Ok;
+#endif
+  }
+
+
+  const TT_GraphicsState  tt_default_graphics_state =
+  {
+    0, 0, 0,
+    { 0x4000, 0 },
+    { 0x4000, 0 },
+    { 0x4000, 0 },
+    1, 64, 1,
+    TRUE, 68, 0, 0, 9, 3,
+    0, FALSE, 2, 1, 1, 1
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_New_Context                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Queries the face context for a given font.  Note that there is     */
+  /*    now a _single_ execution context in the TrueType driver which is   */
+  /*    shared among faces.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source face object.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A handle to the execution context.  Initialized for `face'.        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  FT_EXPORT_FUNC( TT_ExecContext )  TT_New_Context( TT_Face  face )
+  {
+    TT_Driver       driver;
+    TT_ExecContext  exec;
+    FT_Memory       memory;
+
+
+    if ( !face )
+      return 0;
+
+    driver = (TT_Driver)face->root.driver;
+
+    memory = driver->root.root.memory;
+    exec   = driver->context;
+
+    if ( !driver->context )
+    {
+      FT_Error  error;
+
+
+      /* allocate object */
+      if ( ALLOC( exec, sizeof ( *exec ) ) )
+        goto Exit;
+
+      /* initialize it */
+      error = Init_Context( exec, face, memory );
+      if ( error )
+        goto Fail;
+
+      /* store it into the driver */
+      driver->context = exec;
+    }
+
+  Exit:
+    return driver->context;
+
+  Fail:
+    FREE( exec );
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Context                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards an execution context.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec :: A handle to the target execution context.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Done_Context( TT_ExecContext  exec )
+  {
+    /* Nothing at all for now */
+    FT_UNUSED( exec );
+
+    return TT_Err_Ok;
+  }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static FT_F26Dot6  Norm( FT_F26Dot6  X,
+                           FT_F26Dot6  Y )
+  {
+    TT_INT64  T1, T2;
+
+
+    MUL_64( X, X, T1 );
+    MUL_64( Y, Y, T2 );
+
+    ADD_64( T1, T2, T1 );
+
+    return (FT_F26Dot6)SQRT_64( T1 );
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Before an opcode is executed, the interpreter verifies that there are */
+  /* enough arguments on the stack, with the help of the Pop_Push_Count    */
+  /* table.                                                                */
+  /*                                                                       */
+  /* For each opcode, the first column gives the number of arguments that  */
+  /* are popped from the stack; the second one gives the number of those   */
+  /* that are pushed in result.                                            */
+  /*                                                                       */
+  /* Note that for opcodes with a varying number of parameters, either 0   */
+  /* or 1 arg is verified before execution, depending on the nature of the */
+  /* instruction:                                                          */
+  /*                                                                       */
+  /* - if the number of arguments is given by the bytecode stream or the   */
+  /*   loop variable, 0 is chosen.                                         */
+  /*                                                                       */
+  /* - if the first argument is a count n that is followed by arguments    */
+  /*   a1 .. an, then 1 is chosen.                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#undef  PACK
+#define PACK( x, y )  ( ( x << 4 ) | y )
+
+
+  static
+  const FT_Byte  Pop_Push_Count[256] =
+  {
+    /* opcodes are gathered in groups of 16 */
+    /* please keep the spaces as they are   */
+
+    /*  SVTCA  y  */  PACK( 0, 0 ),
+    /*  SVTCA  x  */  PACK( 0, 0 ),
+    /*  SPvTCA y  */  PACK( 0, 0 ),
+    /*  SPvTCA x  */  PACK( 0, 0 ),
+    /*  SFvTCA y  */  PACK( 0, 0 ),
+    /*  SFvTCA x  */  PACK( 0, 0 ),
+    /*  SPvTL //  */  PACK( 2, 0 ),
+    /*  SPvTL +   */  PACK( 2, 0 ),
+    /*  SFvTL //  */  PACK( 2, 0 ),
+    /*  SFvTL +   */  PACK( 2, 0 ),
+    /*  SPvFS     */  PACK( 2, 0 ),
+    /*  SFvFS     */  PACK( 2, 0 ),
+    /*  GPV       */  PACK( 0, 2 ),
+    /*  GFV       */  PACK( 0, 2 ),
+    /*  SFvTPv    */  PACK( 0, 0 ),
+    /*  ISECT     */  PACK( 5, 0 ),
+
+    /*  SRP0      */  PACK( 1, 0 ),
+    /*  SRP1      */  PACK( 1, 0 ),
+    /*  SRP2      */  PACK( 1, 0 ),
+    /*  SZP0      */  PACK( 1, 0 ),
+    /*  SZP1      */  PACK( 1, 0 ),
+    /*  SZP2      */  PACK( 1, 0 ),
+    /*  SZPS      */  PACK( 1, 0 ),
+    /*  SLOOP     */  PACK( 1, 0 ),
+    /*  RTG       */  PACK( 0, 0 ),
+    /*  RTHG      */  PACK( 0, 0 ),
+    /*  SMD       */  PACK( 1, 0 ),
+    /*  ELSE      */  PACK( 0, 0 ),
+    /*  JMPR      */  PACK( 1, 0 ),
+    /*  SCvTCi    */  PACK( 1, 0 ),
+    /*  SSwCi     */  PACK( 1, 0 ),
+    /*  SSW       */  PACK( 1, 0 ),
+
+    /*  DUP       */  PACK( 1, 2 ),
+    /*  POP       */  PACK( 1, 0 ),
+    /*  CLEAR     */  PACK( 0, 0 ),
+    /*  SWAP      */  PACK( 2, 2 ),
+    /*  DEPTH     */  PACK( 0, 1 ),
+    /*  CINDEX    */  PACK( 1, 1 ),
+    /*  MINDEX    */  PACK( 1, 0 ),
+    /*  AlignPTS  */  PACK( 2, 0 ),
+    /*  INS_$28   */  PACK( 0, 0 ),
+    /*  UTP       */  PACK( 1, 0 ),
+    /*  LOOPCALL  */  PACK( 2, 0 ),
+    /*  CALL      */  PACK( 1, 0 ),
+    /*  FDEF      */  PACK( 1, 0 ),
+    /*  ENDF      */  PACK( 0, 0 ),
+    /*  MDAP[0]   */  PACK( 1, 0 ),
+    /*  MDAP[1]   */  PACK( 1, 0 ),
+
+    /*  IUP[0]    */  PACK( 0, 0 ),
+    /*  IUP[1]    */  PACK( 0, 0 ),
+    /*  SHP[0]    */  PACK( 0, 0 ),
+    /*  SHP[1]    */  PACK( 0, 0 ),
+    /*  SHC[0]    */  PACK( 1, 0 ),
+    /*  SHC[1]    */  PACK( 1, 0 ),
+    /*  SHZ[0]    */  PACK( 1, 0 ),
+    /*  SHZ[1]    */  PACK( 1, 0 ),
+    /*  SHPIX     */  PACK( 1, 0 ),
+    /*  IP        */  PACK( 0, 0 ),
+    /*  MSIRP[0]  */  PACK( 2, 0 ),
+    /*  MSIRP[1]  */  PACK( 2, 0 ),
+    /*  AlignRP   */  PACK( 0, 0 ),
+    /*  RTDG      */  PACK( 0, 0 ),
+    /*  MIAP[0]   */  PACK( 2, 0 ),
+    /*  MIAP[1]   */  PACK( 2, 0 ),
+
+    /*  NPushB    */  PACK( 0, 0 ),
+    /*  NPushW    */  PACK( 0, 0 ),
+    /*  WS        */  PACK( 2, 0 ),
+    /*  RS        */  PACK( 1, 1 ),
+    /*  WCvtP     */  PACK( 2, 0 ),
+    /*  RCvt      */  PACK( 1, 1 ),
+    /*  GC[0]     */  PACK( 1, 1 ),
+    /*  GC[1]     */  PACK( 1, 1 ),
+    /*  SCFS      */  PACK( 2, 0 ),
+    /*  MD[0]     */  PACK( 2, 1 ),
+    /*  MD[1]     */  PACK( 2, 1 ),
+    /*  MPPEM     */  PACK( 0, 1 ),
+    /*  MPS       */  PACK( 0, 1 ),
+    /*  FlipON    */  PACK( 0, 0 ),
+    /*  FlipOFF   */  PACK( 0, 0 ),
+    /*  DEBUG     */  PACK( 1, 0 ),
+
+    /*  LT        */  PACK( 2, 1 ),
+    /*  LTEQ      */  PACK( 2, 1 ),
+    /*  GT        */  PACK( 2, 1 ),
+    /*  GTEQ      */  PACK( 2, 1 ),
+    /*  EQ        */  PACK( 2, 1 ),
+    /*  NEQ       */  PACK( 2, 1 ),
+    /*  ODD       */  PACK( 1, 1 ),
+    /*  EVEN      */  PACK( 1, 1 ),
+    /*  IF        */  PACK( 1, 0 ),
+    /*  EIF       */  PACK( 0, 0 ),
+    /*  AND       */  PACK( 2, 1 ),
+    /*  OR        */  PACK( 2, 1 ),
+    /*  NOT       */  PACK( 1, 1 ),
+    /*  DeltaP1   */  PACK( 1, 0 ),
+    /*  SDB       */  PACK( 1, 0 ),
+    /*  SDS       */  PACK( 1, 0 ),
+
+    /*  ADD       */  PACK( 2, 1 ),
+    /*  SUB       */  PACK( 2, 1 ),
+    /*  DIV       */  PACK( 2, 1 ),
+    /*  MUL       */  PACK( 2, 1 ),
+    /*  ABS       */  PACK( 1, 1 ),
+    /*  NEG       */  PACK( 1, 1 ),
+    /*  FLOOR     */  PACK( 1, 1 ),
+    /*  CEILING   */  PACK( 1, 1 ),
+    /*  ROUND[0]  */  PACK( 1, 1 ),
+    /*  ROUND[1]  */  PACK( 1, 1 ),
+    /*  ROUND[2]  */  PACK( 1, 1 ),
+    /*  ROUND[3]  */  PACK( 1, 1 ),
+    /*  NROUND[0] */  PACK( 1, 1 ),
+    /*  NROUND[1] */  PACK( 1, 1 ),
+    /*  NROUND[2] */  PACK( 1, 1 ),
+    /*  NROUND[3] */  PACK( 1, 1 ),
+
+    /*  WCvtF     */  PACK( 2, 0 ),
+    /*  DeltaP2   */  PACK( 1, 0 ),
+    /*  DeltaP3   */  PACK( 1, 0 ),
+    /*  DeltaCn[0] */ PACK( 1, 0 ),
+    /*  DeltaCn[1] */ PACK( 1, 0 ),
+    /*  DeltaCn[2] */ PACK( 1, 0 ),
+    /*  SROUND    */  PACK( 1, 0 ),
+    /*  S45Round  */  PACK( 1, 0 ),
+    /*  JROT      */  PACK( 2, 0 ),
+    /*  JROF      */  PACK( 2, 0 ),
+    /*  ROFF      */  PACK( 0, 0 ),
+    /*  INS_$7B   */  PACK( 0, 0 ),
+    /*  RUTG      */  PACK( 0, 0 ),
+    /*  RDTG      */  PACK( 0, 0 ),
+    /*  SANGW     */  PACK( 1, 0 ),
+    /*  AA        */  PACK( 1, 0 ),
+
+    /*  FlipPT    */  PACK( 0, 0 ),
+    /*  FlipRgON  */  PACK( 2, 0 ),
+    /*  FlipRgOFF */  PACK( 2, 0 ),
+    /*  INS_$83   */  PACK( 0, 0 ),
+    /*  INS_$84   */  PACK( 0, 0 ),
+    /*  ScanCTRL  */  PACK( 1, 0 ),
+    /*  SDVPTL[0] */  PACK( 2, 0 ),
+    /*  SDVPTL[1] */  PACK( 2, 0 ),
+    /*  GetINFO   */  PACK( 1, 1 ),
+    /*  IDEF      */  PACK( 1, 0 ),
+    /*  ROLL      */  PACK( 3, 3 ),
+    /*  MAX       */  PACK( 2, 1 ),
+    /*  MIN       */  PACK( 2, 1 ),
+    /*  ScanTYPE  */  PACK( 1, 0 ),
+    /*  InstCTRL  */  PACK( 2, 0 ),
+    /*  INS_$8F   */  PACK( 0, 0 ),
+
+    /*  INS_$90  */   PACK( 0, 0 ),
+    /*  INS_$91  */   PACK( 0, 0 ),
+    /*  INS_$92  */   PACK( 0, 0 ),
+    /*  INS_$93  */   PACK( 0, 0 ),
+    /*  INS_$94  */   PACK( 0, 0 ),
+    /*  INS_$95  */   PACK( 0, 0 ),
+    /*  INS_$96  */   PACK( 0, 0 ),
+    /*  INS_$97  */   PACK( 0, 0 ),
+    /*  INS_$98  */   PACK( 0, 0 ),
+    /*  INS_$99  */   PACK( 0, 0 ),
+    /*  INS_$9A  */   PACK( 0, 0 ),
+    /*  INS_$9B  */   PACK( 0, 0 ),
+    /*  INS_$9C  */   PACK( 0, 0 ),
+    /*  INS_$9D  */   PACK( 0, 0 ),
+    /*  INS_$9E  */   PACK( 0, 0 ),
+    /*  INS_$9F  */   PACK( 0, 0 ),
+
+    /*  INS_$A0  */   PACK( 0, 0 ),
+    /*  INS_$A1  */   PACK( 0, 0 ),
+    /*  INS_$A2  */   PACK( 0, 0 ),
+    /*  INS_$A3  */   PACK( 0, 0 ),
+    /*  INS_$A4  */   PACK( 0, 0 ),
+    /*  INS_$A5  */   PACK( 0, 0 ),
+    /*  INS_$A6  */   PACK( 0, 0 ),
+    /*  INS_$A7  */   PACK( 0, 0 ),
+    /*  INS_$A8  */   PACK( 0, 0 ),
+    /*  INS_$A9  */   PACK( 0, 0 ),
+    /*  INS_$AA  */   PACK( 0, 0 ),
+    /*  INS_$AB  */   PACK( 0, 0 ),
+    /*  INS_$AC  */   PACK( 0, 0 ),
+    /*  INS_$AD  */   PACK( 0, 0 ),
+    /*  INS_$AE  */   PACK( 0, 0 ),
+    /*  INS_$AF  */   PACK( 0, 0 ),
+
+    /*  PushB[0]  */  PACK( 0, 1 ),
+    /*  PushB[1]  */  PACK( 0, 2 ),
+    /*  PushB[2]  */  PACK( 0, 3 ),
+    /*  PushB[3]  */  PACK( 0, 4 ),
+    /*  PushB[4]  */  PACK( 0, 5 ),
+    /*  PushB[5]  */  PACK( 0, 6 ),
+    /*  PushB[6]  */  PACK( 0, 7 ),
+    /*  PushB[7]  */  PACK( 0, 8 ),
+    /*  PushW[0]  */  PACK( 0, 1 ),
+    /*  PushW[1]  */  PACK( 0, 2 ),
+    /*  PushW[2]  */  PACK( 0, 3 ),
+    /*  PushW[3]  */  PACK( 0, 4 ),
+    /*  PushW[4]  */  PACK( 0, 5 ),
+    /*  PushW[5]  */  PACK( 0, 6 ),
+    /*  PushW[6]  */  PACK( 0, 7 ),
+    /*  PushW[7]  */  PACK( 0, 8 ),
+
+    /*  MDRP[00]  */  PACK( 1, 0 ),
+    /*  MDRP[01]  */  PACK( 1, 0 ),
+    /*  MDRP[02]  */  PACK( 1, 0 ),
+    /*  MDRP[03]  */  PACK( 1, 0 ),
+    /*  MDRP[04]  */  PACK( 1, 0 ),
+    /*  MDRP[05]  */  PACK( 1, 0 ),
+    /*  MDRP[06]  */  PACK( 1, 0 ),
+    /*  MDRP[07]  */  PACK( 1, 0 ),
+    /*  MDRP[08]  */  PACK( 1, 0 ),
+    /*  MDRP[09]  */  PACK( 1, 0 ),
+    /*  MDRP[10]  */  PACK( 1, 0 ),
+    /*  MDRP[11]  */  PACK( 1, 0 ),
+    /*  MDRP[12]  */  PACK( 1, 0 ),
+    /*  MDRP[13]  */  PACK( 1, 0 ),
+    /*  MDRP[14]  */  PACK( 1, 0 ),
+    /*  MDRP[15]  */  PACK( 1, 0 ),
+
+    /*  MDRP[16]  */  PACK( 1, 0 ),
+    /*  MDRP[17]  */  PACK( 1, 0 ),
+    /*  MDRP[18]  */  PACK( 1, 0 ),
+    /*  MDRP[19]  */  PACK( 1, 0 ),
+    /*  MDRP[20]  */  PACK( 1, 0 ),
+    /*  MDRP[21]  */  PACK( 1, 0 ),
+    /*  MDRP[22]  */  PACK( 1, 0 ),
+    /*  MDRP[23]  */  PACK( 1, 0 ),
+    /*  MDRP[24]  */  PACK( 1, 0 ),
+    /*  MDRP[25]  */  PACK( 1, 0 ),
+    /*  MDRP[26]  */  PACK( 1, 0 ),
+    /*  MDRP[27]  */  PACK( 1, 0 ),
+    /*  MDRP[28]  */  PACK( 1, 0 ),
+    /*  MDRP[29]  */  PACK( 1, 0 ),
+    /*  MDRP[30]  */  PACK( 1, 0 ),
+    /*  MDRP[31]  */  PACK( 1, 0 ),
+
+    /*  MIRP[00]  */  PACK( 2, 0 ),
+    /*  MIRP[01]  */  PACK( 2, 0 ),
+    /*  MIRP[02]  */  PACK( 2, 0 ),
+    /*  MIRP[03]  */  PACK( 2, 0 ),
+    /*  MIRP[04]  */  PACK( 2, 0 ),
+    /*  MIRP[05]  */  PACK( 2, 0 ),
+    /*  MIRP[06]  */  PACK( 2, 0 ),
+    /*  MIRP[07]  */  PACK( 2, 0 ),
+    /*  MIRP[08]  */  PACK( 2, 0 ),
+    /*  MIRP[09]  */  PACK( 2, 0 ),
+    /*  MIRP[10]  */  PACK( 2, 0 ),
+    /*  MIRP[11]  */  PACK( 2, 0 ),
+    /*  MIRP[12]  */  PACK( 2, 0 ),
+    /*  MIRP[13]  */  PACK( 2, 0 ),
+    /*  MIRP[14]  */  PACK( 2, 0 ),
+    /*  MIRP[15]  */  PACK( 2, 0 ),
+
+    /*  MIRP[16]  */  PACK( 2, 0 ),
+    /*  MIRP[17]  */  PACK( 2, 0 ),
+    /*  MIRP[18]  */  PACK( 2, 0 ),
+    /*  MIRP[19]  */  PACK( 2, 0 ),
+    /*  MIRP[20]  */  PACK( 2, 0 ),
+    /*  MIRP[21]  */  PACK( 2, 0 ),
+    /*  MIRP[22]  */  PACK( 2, 0 ),
+    /*  MIRP[23]  */  PACK( 2, 0 ),
+    /*  MIRP[24]  */  PACK( 2, 0 ),
+    /*  MIRP[25]  */  PACK( 2, 0 ),
+    /*  MIRP[26]  */  PACK( 2, 0 ),
+    /*  MIRP[27]  */  PACK( 2, 0 ),
+    /*  MIRP[28]  */  PACK( 2, 0 ),
+    /*  MIRP[29]  */  PACK( 2, 0 ),
+    /*  MIRP[30]  */  PACK( 2, 0 ),
+    /*  MIRP[31]  */  PACK( 2, 0 )
+  };
+
+
+  static
+  const FT_Char  opcode_length[256] =
+  {
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+
+   -1,-1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,
+
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
+  };
+
+  static
+  const FT_Vector  Null_Vector = {0,0};
+
+
+#undef PACK
+
+
+#undef  NULL_Vector
+#define NULL_Vector  (FT_Vector*)&Null_Vector
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Current_Ratio                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the current aspect ratio scaling factor depending on the   */
+  /*    projection vector's state and device resolutions.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */
+  /*                                                                       */
+  static
+  FT_Long  Current_Ratio( EXEC_OP )
+  {
+    if ( CUR.tt_metrics.ratio )
+      return CUR.tt_metrics.ratio;
+
+    if ( CUR.GS.projVector.y == 0 )
+      CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+
+    else if ( CUR.GS.projVector.x == 0 )
+      CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+
+    else
+    {
+      FT_Long  x, y;
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+      x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 );
+      y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 );
+      CUR.tt_metrics.ratio = Norm( x, y );
+
+#else
+
+      x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x8000 );
+      y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x8000 );
+      CUR.tt_metrics.ratio = FT_Sqrt32( x * x + y * y ) << 1;
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+    }
+
+    return CUR.tt_metrics.ratio;
+  }
+
+
+  static
+  FT_Long  Current_Ppem( EXEC_OP )
+  {
+    return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Functions related to the control value table (CVT).                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static
+  FT_F26Dot6  Read_CVT( EXEC_OP_ FT_ULong  index )
+  {
+    return CUR.cvt[index];
+  }
+
+
+  static
+  FT_F26Dot6  Read_CVT_Stretched( EXEC_OP_ FT_ULong  index )
+  {
+    return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() );
+  }
+
+
+  static
+  void  Write_CVT( EXEC_OP_ FT_ULong    index,
+                            FT_F26Dot6  value )
+  {
+    CUR.cvt[index] = value;
+  }
+
+
+  static
+  void  Write_CVT_Stretched( EXEC_OP_ FT_ULong    index,
+                                      FT_F26Dot6  value )
+  {
+    CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() );
+  }
+
+
+  static
+  void  Move_CVT( EXEC_OP_ FT_ULong    index,
+                           FT_F26Dot6  value )
+  {
+    CUR.cvt[index] += value;
+  }
+
+
+  static
+  void  Move_CVT_Stretched( EXEC_OP_ FT_ULong    index,
+                                     FT_F26Dot6  value )
+  {
+    CUR.cvt[index] += FT_DivFix( value, CURRENT_Ratio() );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    GetShortIns                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a short integer taken from the instruction stream at       */
+  /*    address IP.                                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Short read at code[IP].                                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This one could become a macro.                                     */
+  /*                                                                       */
+  static FT_Short  GetShortIns( EXEC_OP )
+  {
+    /* Reading a byte stream so there is no endianess (DaveP) */
+    CUR.IP += 2;
+    return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
+                         CUR.code[CUR.IP - 1]      );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Ins_Goto_CodeRange                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Goes to a certain code range in the instruction stream.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    aRange :: The index of the code range.                             */
+  /*                                                                       */
+  /*    aIP    :: The new IP address in the code range.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS or FAILURE.                                                */
+  /*                                                                       */
+  static
+  FT_Bool  Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,
+                                        FT_ULong  aIP )
+  {
+    TT_CodeRange*  range;
+
+
+    if ( aRange < 1 || aRange > 3 )
+    {
+      CUR.error = TT_Err_Bad_Argument;
+      return FAILURE;
+    }
+
+    range = &CUR.codeRangeTable[aRange - 1];
+
+    if ( range->base == NULL )     /* invalid coderange */
+    {
+      CUR.error = TT_Err_Invalid_CodeRange;
+      return FAILURE;
+    }
+
+    /* NOTE: Because the last instruction of a program may be a CALL */
+    /*       which will return to the first byte *after* the code    */
+    /*       range, we test for AIP <= Size, instead of AIP < Size.  */
+
+    if ( aIP > range->size )
+    {
+      CUR.error = TT_Err_Code_Overflow;
+      return FAILURE;
+    }
+
+    CUR.code     = range->base;
+    CUR.codeSize = range->size;
+    CUR.IP       = aIP;
+    CUR.curRange = aRange;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Direct_Move                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Moves a point by a given distance along the freedom vector.  The   */
+  /*    point will be `touched'.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    point    :: The index of the point to move.                        */
+  /*                                                                       */
+  /*    distance :: The distance to apply.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    zone     :: The affected glyph zone.                               */
+  /*                                                                       */
+  static
+  void  Direct_Move( EXEC_OP_ TT_GlyphZone*  zone,
+                              FT_UShort      point,
+                              FT_F26Dot6     distance )
+  {
+    FT_F26Dot6 v;
+
+
+    v = CUR.GS.freeVector.x;
+
+    if ( v != 0 )
+    {
+
+#ifdef NO_APPLE_PATENT
+
+      if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
+        zone->cur[point].x += distance;
+
+#else
+
+      zone->cur[point].x += TT_MULDIV( distance,
+                                       v * 0x10000L,
+                                       CUR.F_dot_P );
+
+#endif
+
+      zone->tags[point] |= FT_Curve_Tag_Touch_X;
+    }
+
+    v = CUR.GS.freeVector.y;
+
+    if ( v != 0 )
+    {
+
+#ifdef NO_APPLE_PATENT
+
+      if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
+        zone->cur[point].y += distance;
+
+#else
+
+      zone->cur[point].y += TT_MULDIV( distance,
+                                       v * 0x10000L,
+                                       CUR.F_dot_P );
+
+#endif
+
+      zone->tags[point] |= FT_Curve_Tag_Touch_Y;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Special versions of Direct_Move()                                     */
+  /*                                                                       */
+  /*   The following versions are used whenever both vectors are both      */
+  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static
+  void  Direct_Move_X( EXEC_OP_ TT_GlyphZone*  zone,
+                                FT_UShort      point,
+                                FT_F26Dot6     distance )
+  {
+    FT_UNUSED_EXEC;
+
+    zone->cur[point].x += distance;
+    zone->tags[point]  |= FT_Curve_Tag_Touch_X;
+  }
+
+
+  static
+  void  Direct_Move_Y( EXEC_OP_ TT_GlyphZone*  zone,
+                                FT_UShort      point,
+                                FT_F26Dot6     distance )
+  {
+    FT_UNUSED_EXEC;
+
+    zone->cur[point].y += distance;
+    zone->tags[point]  |= FT_Curve_Tag_Touch_Y;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_None                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Does not round, but adds engine compensation.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance (not) to round.                       */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The compensated distance.                                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The TrueType specification says very few about the relationship    */
+  /*    between rounding and engine compensation.  However, it seems from  */
+  /*    the description of super round that we should add the compensation */
+  /*    before rounding.                                                   */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_None( EXEC_OP_ FT_F26Dot6  distance,
+                                   FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation;
+      if ( val < 0 )
+        val = 0;
+    }
+    else {
+      val = distance - compensation;
+      if ( val > 0 )
+        val = 0;
+    }
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_To_Grid                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value to grid after adding engine compensation.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                                      FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation + 32;
+      if ( val > 0 )
+        val &= ~63;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance + 32 ) & -64 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return  val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_To_Half_Grid                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value to half grid after adding engine compensation.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                                           FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = ( ( distance + compensation ) & -64 ) + 32;
+      if ( val < 0 )
+        val = 0;
+    }
+    else
+    {
+      val = -( ( (compensation - distance) & -64 ) + 32 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Down_To_Grid                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value down to grid after adding engine compensation.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                                           FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation;
+      if ( val > 0 )
+        val &= ~63;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance ) & -64 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Up_To_Grid                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value up to grid after adding engine compensation.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                                         FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+
+    FT_UNUSED_EXEC;
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation + 63;
+      if ( val > 0 )
+        val &= ~63;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance + 63 ) & -64 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_To_Double_Grid                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value to double grid after adding engine compensation.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                                             FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6 val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation + 16;
+      if ( val > 0 )
+        val &= ~31;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance + 16 ) & -32 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Super                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Super-rounds value to grid after adding engine compensation.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The TrueType specification says very few about the relationship    */
+  /*    between rounding and engine compensation.  However, it seems from  */
+  /*    the description of super round that we should add the compensation */
+  /*    before rounding.                                                   */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_Super( EXEC_OP_ FT_F26Dot6  distance,
+                                    FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+
+    if ( distance >= 0 )
+    {
+      val = ( distance - CUR.phase + CUR.threshold + compensation ) &
+              -CUR.period;
+      if ( val < 0 )
+        val = 0;
+      val += CUR.phase;
+    }
+    else
+    {
+      val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
+               -CUR.period );
+      if ( val > 0 )
+        val = 0;
+      val -= CUR.phase;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Super_45                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Super-rounds value to grid after adding engine compensation.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    There is a separate function for Round_Super_45() as we may need   */
+  /*    greater precision.                                                 */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,
+                                       FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+
+    if ( distance >= 0 )
+    {
+      val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
+                CUR.period ) * CUR.period;
+      if ( val < 0 )
+        val = 0;
+      val += CUR.phase;
+    }
+    else
+    {
+      val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
+                   CUR.period ) * CUR.period );
+      if ( val > 0 )
+        val = 0;
+      val -= CUR.phase;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Compute_Round                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the rounding mode.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    round_mode :: The rounding mode to be used.                        */
+  /*                                                                       */
+  static
+  void  Compute_Round( EXEC_OP_ FT_Byte  round_mode )
+  {
+    switch ( round_mode )
+    {
+    case TT_Round_Off:
+      CUR.func_round = (TT_Round_Func)Round_None;
+      break;
+
+    case TT_Round_To_Grid:
+      CUR.func_round = (TT_Round_Func)Round_To_Grid;
+      break;
+
+    case TT_Round_Up_To_Grid:
+      CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+      break;
+
+    case TT_Round_Down_To_Grid:
+      CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+      break;
+
+    case TT_Round_To_Half_Grid:
+      CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+      break;
+
+    case TT_Round_To_Double_Grid:
+      CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+      break;
+
+    case TT_Round_Super:
+      CUR.func_round = (TT_Round_Func)Round_Super;
+      break;
+
+    case TT_Round_Super_45:
+      CUR.func_round = (TT_Round_Func)Round_Super_45;
+      break;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    SetSuperRound                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets Super Round parameters.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    GridPeriod :: Grid period                                          */
+  /*    selector   :: SROUND opcode                                        */
+  /*                                                                       */
+  static
+  void  SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
+                                FT_Long     selector )
+  {
+    switch ( (FT_Int)( selector & 0xC0 ) )
+    {
+      case 0:
+        CUR.period = GridPeriod / 2;
+        break;
+
+      case 0x40:
+        CUR.period = GridPeriod;
+        break;
+
+      case 0x80:
+        CUR.period = GridPeriod * 2;
+        break;
+
+      /* This opcode is reserved, but... */
+
+      case 0xC0:
+        CUR.period = GridPeriod;
+        break;
+    }
+
+    switch ( (FT_Int)( selector & 0x30 ) )
+    {
+    case 0:
+      CUR.phase = 0;
+      break;
+
+    case 0x10:
+      CUR.phase = CUR.period / 4;
+      break;
+
+    case 0x20:
+      CUR.phase = CUR.period / 2;
+      break;
+
+    case 0x30:
+      CUR.phase = GridPeriod * 3 / 4;
+      break;
+    }
+
+    if ( (selector & 0x0F) == 0 )
+      CUR.threshold = CUR.period - 1;
+    else
+      CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
+
+    CUR.period    /= 256;
+    CUR.phase     /= 256;
+    CUR.threshold /= 256;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Project                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of vector given by (v2-v1) along the       */
+  /*    current projection vector.                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Project( EXEC_OP_ FT_Vector*  v1,
+                                FT_Vector*  v2 )
+  {
+    return TT_MULDIV( v1->x - v2->x, CUR.GS.projVector.x, 0x4000 ) +
+           TT_MULDIV( v1->y - v2->y, CUR.GS.projVector.y, 0x4000 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Dual_Project                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    current dual vector.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Dual_Project( EXEC_OP_ FT_Vector*  v1,
+                                     FT_Vector*  v2 )
+  {
+    return TT_MULDIV( v1->x - v2->x, CUR.GS.dualVector.x, 0x4000 ) +
+           TT_MULDIV( v1->y - v2->y, CUR.GS.dualVector.y, 0x4000 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Free_Project                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    current freedom vector.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Free_Project( EXEC_OP_ FT_Vector*  v1,
+                                     FT_Vector*  v2 )
+  {
+    return TT_MULDIV( v1->x - v2->x, CUR.GS.freeVector.x, 0x4000 ) +
+           TT_MULDIV( v1->y - v2->y, CUR.GS.freeVector.y, 0x4000 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Project_x                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    horizontal axis.                                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Project_x( EXEC_OP_ FT_Vector*  v1,
+                                  FT_Vector*  v2 )
+  {
+    FT_UNUSED_EXEC;
+
+    return ( v1->x - v2->x );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Project_y                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    vertical axis.                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static
+  FT_F26Dot6  Project_y( EXEC_OP_ FT_Vector*  v1,
+                                  FT_Vector*  v2 )
+  {
+    FT_UNUSED_EXEC;
+
+   return ( v1->y - v2->y );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Compute_Funcs                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection and movement function pointers according   */
+  /*    to the current graphics state.                                     */
+  /*                                                                       */
+  static
+  void  Compute_Funcs( EXEC_OP )
+  {
+    if ( CUR.GS.freeVector.x == 0x4000 )
+    {
+      CUR.func_freeProj = (TT_Project_Func)Project_x;
+      CUR.F_dot_P       = CUR.GS.projVector.x * 0x10000L;
+    }
+    else
+    {
+      if ( CUR.GS.freeVector.y == 0x4000 )
+      {
+        CUR.func_freeProj = (TT_Project_Func)Project_y;
+        CUR.F_dot_P       = CUR.GS.projVector.y * 0x10000L;
+      }
+      else
+      {
+        CUR.func_freeProj = (TT_Project_Func)Free_Project;
+        CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
+                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
+      }
+    }
+
+    if ( CUR.GS.projVector.x == 0x4000 )
+      CUR.func_project = (TT_Project_Func)Project_x;
+    else
+    {
+      if ( CUR.GS.projVector.y == 0x4000 )
+        CUR.func_project = (TT_Project_Func)Project_y;
+      else
+        CUR.func_project = (TT_Project_Func)Project;
+    }
+
+    if ( CUR.GS.dualVector.x == 0x4000 )
+      CUR.func_dualproj = (TT_Project_Func)Project_x;
+    else
+    {
+      if ( CUR.GS.dualVector.y == 0x4000 )
+        CUR.func_dualproj = (TT_Project_Func)Project_y;
+      else
+        CUR.func_dualproj = (TT_Project_Func)Dual_Project;
+    }
+
+    CUR.func_move = (TT_Move_Func)Direct_Move;
+
+    if ( CUR.F_dot_P == 0x40000000L )
+    {
+      if ( CUR.GS.freeVector.x == 0x4000 )
+        CUR.func_move = (TT_Move_Func)Direct_Move_X;
+      else
+      {
+        if ( CUR.GS.freeVector.y == 0x4000 )
+          CUR.func_move = (TT_Move_Func)Direct_Move_Y;
+      }
+    }
+
+    /* at small sizes, F_dot_P can become too small, resulting   */
+    /* in overflows and `spikes' in a number of glyphs like `w'. */
+
+    if ( ABS( CUR.F_dot_P ) < 0x4000000L )
+      CUR.F_dot_P = 0x40000000L;
+
+    /* Disable cached aspect ratio */
+    CUR.tt_metrics.ratio = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Normalize                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Norms a vector.                                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    Vx :: The horizontal input vector coordinate.                      */
+  /*    Vy :: The vertical input vector coordinate.                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    R  :: The normed unit vector.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Returns FAILURE if a vector parameter is zero.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
+  /*    R is undefined.                                                    */
+  /*                                                                       */
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static
+  FT_Bool  Normalize( EXEC_OP_ FT_F26Dot6      Vx,
+                               FT_F26Dot6      Vy,
+                               FT_UnitVector*  R )
+  {
+    FT_F26Dot6  W;
+    FT_Bool     S1, S2;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L )
+    {
+      Vx *= 0x100;
+      Vy *= 0x100;
+
+      W = Norm( Vx, Vy );
+
+      if ( W == 0 )
+      {
+        /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
+        /*      to normalize the vector (0,0).  Return immediately. */
+        return SUCCESS;
+      }
+
+      R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
+      R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
+
+      return SUCCESS;
+    }
+
+    W = Norm( Vx, Vy );
+
+    Vx = FT_MulDiv( Vx, 0x4000L, W );
+    Vy = FT_MulDiv( Vy, 0x4000L, W );
+
+    W = Vx * Vx + Vy * Vy;
+
+    /* Now, we want that Sqrt( W ) = 0x4000 */
+    /* Or 0x1000000 <= W < 0x1004000        */
+
+    if ( Vx < 0 )
+    {
+      Vx = -Vx;
+      S1 = TRUE;
+    }
+    else
+      S1 = FALSE;
+
+    if ( Vy < 0 )
+    {
+      Vy = -Vy;
+      S2 = TRUE;
+    }
+    else
+      S2 = FALSE;
+
+    while ( W < 0x1000000L )
+    {
+      /* We need to increase W by a minimal amount */
+      if ( Vx < Vy )
+        Vx++;
+      else
+        Vy++;
+
+      W = Vx * Vx + Vy * Vy;
+    }
+
+    while ( W >= 0x1004000L )
+    {
+      /* We need to decrease W by a minimal amount */
+      if ( Vx < Vy )
+        Vx--;
+      else
+        Vy--;
+
+      W = Vx * Vx + Vy * Vy;
+    }
+
+    /* Note that in various cases, we can only  */
+    /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
+
+    if ( S1 )
+      Vx = -Vx;
+
+    if ( S2 )
+      Vy = -Vy;
+
+    R->x = (FT_F2Dot14)Vx;   /* Type conversion */
+    R->y = (FT_F2Dot14)Vy;   /* Type conversion */
+
+    return SUCCESS;
+  }
+
+#else
+
+  static
+  FT_Bool  Normalize( EXEC_OP_ FT_F26Dot6      Vx,
+                               FT_F26Dot6      Vy,
+                               FT_UnitVector*  R )
+  {
+    FT_F26Dot6  u, v, d;
+    FT_Int      shift;
+    FT_ULong    H, L, L2, hi, lo, med;
+
+
+    u = ABS( Vx );
+    v = ABS( Vy );
+
+    if ( u < v )
+    {
+      d = u;
+      u = v;
+      v = d;
+    }
+
+    R->x = 0;
+    R->y = 0;
+
+    /* check that we are not trying to normalise zero! */
+    if ( u == 0 )
+      return SUCCESS;
+
+    /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
+    hi  = (FT_ULong)u >> 16;
+    lo  = (FT_ULong)u & 0xFFFF;
+    med = hi * lo;
+
+    H     = hi * hi + ( med >> 15 );
+    med <<= 17;
+    L     = lo * lo + med;
+    if ( L < med )
+      H++;
+
+    hi  = (FT_ULong)v >> 16;
+    lo  = (FT_ULong)v & 0xFFFF;
+    med = hi * lo;
+
+    H    += hi * hi + ( med >> 15 );
+    med <<= 17;
+    L2    = lo * lo + med;
+    if ( L2 < med )
+      H++;
+
+    L += L2;
+    if ( L < L2 )
+      H++;
+
+    /* if the value is smaller than 32-bits */
+    if ( H == 0 )
+    {
+      shift = 0;
+      while ( ( L & 0xC0000000L ) == 0 )
+      {
+        L <<= 2;
+        shift++;
+      }
+
+      d = FT_Sqrt32( L );
+      R->x = (FT_F2Dot14)TT_MULDIV( Vx << shift, 0x4000, d );
+      R->y = (FT_F2Dot14)TT_MULDIV( Vy << shift, 0x4000, d );
+    }
+    /* if the value is greater than 64-bits */
+    else
+    {
+      shift = 0;
+      while ( H )
+      {
+        L   = ( L >> 2 ) | ( H << 30 );
+        H >>= 2;
+        shift++;
+      }
+
+      d = FT_Sqrt32( L );
+      R->x = (FT_F2Dot14)TT_MULDIV( Vx >> shift, 0x4000, d );
+      R->y = (FT_F2Dot14)TT_MULDIV( Vy >> shift, 0x4000, d );
+    }
+
+    {
+      FT_ULong  x, y, w;
+      FT_Int    sx, sy;
+
+
+      sx = R->x >= 0 ? 1 : -1;
+      sy = R->y >= 0 ? 1 : -1;
+      x  = (FT_ULong)sx * R->x;
+      y  = (FT_ULong)sy * R->y;
+
+      w = x * x + y * y;
+
+      /* we now want to adjust (x,y) in order to have sqrt(w) == 0x4000 */
+      /* which means 0x1000000 <= w < 0x1004000                         */
+      while ( w <= 0x10000000L )
+      {
+        /* increment the smallest coordinate */
+        if ( x < y )
+          x++;
+        else
+          y++;
+
+        w = x * x + y * y;
+      }
+
+      while ( w >= 0x10040000L )
+      {
+        /* decrement the smallest coordinate */
+        if ( x < y )
+          x--;
+        else
+          y--;
+
+        w = x * x + y * y;
+      }
+
+      R->x = sx * x;
+      R->y = sy * y;
+    }
+
+    return SUCCESS;
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Here we start with the implementation of the various opcodes.         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static
+  FT_Bool  Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,
+                               FT_UShort       aIdx2,
+                               FT_Int          aOpc,
+                               FT_UnitVector*  Vec )
+  {
+    FT_Long     A, B, C;
+    FT_Vector*  p1;
+    FT_Vector*  p2;
+
+
+    if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
+         BOUNDS( aIdx2, CUR.zp1.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return FAILURE;
+    }
+
+    p1 = CUR.zp1.cur + aIdx2;
+    p2 = CUR.zp2.cur + aIdx1;
+
+    A = p1->x - p2->x;
+    B = p1->y - p2->y;
+
+    if ( ( aOpc & 1 ) != 0 )
+    {
+      C =  B;   /* counter clockwise rotation */
+      B =  A;
+      A = -C;
+    }
+
+    NORMalize( A, B, Vec );
+
+    return SUCCESS;
+  }
+
+
+  /* When not using the big switch statements, the interpreter uses a */
+  /* call table defined later below in this source.  Each opcode must */
+  /* thus have a corresponding function, even trivial ones.           */
+  /*                                                                  */
+  /* They are all defined there.                                      */
+
+#define DO_SVTCA                            \
+  {                                         \
+    FT_Short  A, B;                         \
+                                            \
+                                            \
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+    B = A ^ (FT_Short)0x4000;               \
+                                            \
+    CUR.GS.freeVector.x = A;                \
+    CUR.GS.projVector.x = A;                \
+    CUR.GS.dualVector.x = A;                \
+                                            \
+    CUR.GS.freeVector.y = B;                \
+    CUR.GS.projVector.y = B;                \
+    CUR.GS.dualVector.y = B;                \
+                                            \
+    COMPUTE_Funcs();                        \
+  }
+
+
+#define DO_SPVTCA                           \
+  {                                         \
+    FT_Short  A, B;                         \
+                                            \
+                                            \
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+    B = A ^ (FT_Short)0x4000;               \
+                                            \
+    CUR.GS.projVector.x = A;                \
+    CUR.GS.dualVector.x = A;                \
+                                            \
+    CUR.GS.projVector.y = B;                \
+    CUR.GS.dualVector.y = B;                \
+                                            \
+    COMPUTE_Funcs();                        \
+  }
+
+
+#define DO_SFVTCA                           \
+  {                                         \
+    FT_Short  A, B;                         \
+                                            \
+                                            \
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+    B = A ^ (FT_Short)0x4000;               \
+                                            \
+    CUR.GS.freeVector.x = A;                \
+    CUR.GS.freeVector.y = B;                \
+                                            \
+    COMPUTE_Funcs();                        \
+  }
+
+
+#define DO_SPVTL                                      \
+    if ( INS_SxVTL( (FT_UShort)args[1],               \
+                    (FT_UShort)args[0],               \
+                    CUR.opcode,                       \
+                    &CUR.GS.projVector ) == SUCCESS ) \
+    {                                                 \
+      CUR.GS.dualVector = CUR.GS.projVector;          \
+      COMPUTE_Funcs();                                \
+    }
+
+
+#define DO_SFVTL                                      \
+    if ( INS_SxVTL( (FT_UShort)args[1],               \
+                    (FT_UShort)args[0],               \
+                    CUR.opcode,                       \
+                    &CUR.GS.freeVector ) == SUCCESS ) \
+      COMPUTE_Funcs();
+
+
+#define DO_SFVTPV                          \
+    CUR.GS.freeVector = CUR.GS.projVector; \
+    COMPUTE_Funcs();
+
+
+#define DO_SPVFS                                \
+  {                                             \
+    FT_Short  S;                                \
+    FT_Long   X, Y;                             \
+                                                \
+                                                \
+    /* Only use low 16bits, then sign extend */ \
+    S = (FT_Short)args[1];                      \
+    Y = (FT_Long)S;                             \
+    S = (FT_Short)args[0];                      \
+    X = (FT_Long)S;                             \
+                                                \
+    NORMalize( X, Y, &CUR.GS.projVector );      \
+                                                \
+    CUR.GS.dualVector = CUR.GS.projVector;      \
+    COMPUTE_Funcs();                            \
+  }
+
+
+#define DO_SFVFS                                \
+  {                                             \
+    FT_Short  S;                                \
+    FT_Long   X, Y;                             \
+                                                \
+                                                \
+    /* Only use low 16bits, then sign extend */ \
+    S = (FT_Short)args[1];                      \
+    Y = (FT_Long)S;                             \
+    S = (FT_Short)args[0];                      \
+    X = S;                                      \
+                                                \
+    NORMalize( X, Y, &CUR.GS.freeVector );      \
+    COMPUTE_Funcs();                            \
+  }
+
+
+#define DO_GPV                     \
+    args[0] = CUR.GS.projVector.x; \
+    args[1] = CUR.GS.projVector.y;
+
+
+#define DO_GFV                     \
+    args[0] = CUR.GS.freeVector.x; \
+    args[1] = CUR.GS.freeVector.y;
+
+
+#define DO_SRP0                      \
+    CUR.GS.rp0 = (FT_UShort)args[0];
+
+
+#define DO_SRP1                      \
+    CUR.GS.rp1 = (FT_UShort)args[0];
+
+
+#define DO_SRP2                      \
+    CUR.GS.rp2 = (FT_UShort)args[0];
+
+
+#define DO_RTHG                                         \
+    CUR.GS.round_state = TT_Round_To_Half_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+
+
+#define DO_RTG                                     \
+    CUR.GS.round_state = TT_Round_To_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_To_Grid;
+
+
+#define DO_RTDG                                           \
+    CUR.GS.round_state = TT_Round_To_Double_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+
+
+#define DO_RUTG                                       \
+    CUR.GS.round_state = TT_Round_Up_To_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+
+
+#define DO_RDTG                                         \
+    CUR.GS.round_state = TT_Round_Down_To_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+
+
+#define DO_ROFF                                 \
+    CUR.GS.round_state = TT_Round_Off;          \
+    CUR.func_round = (TT_Round_Func)Round_None;
+
+
+#define DO_SROUND                                \
+    SET_SuperRound( 0x4000, args[0] );           \
+    CUR.GS.round_state = TT_Round_Super;         \
+    CUR.func_round = (TT_Round_Func)Round_Super;
+
+
+#define DO_S45ROUND                                 \
+    SET_SuperRound( 0x2D41, args[0] );              \
+    CUR.GS.round_state = TT_Round_Super_45;         \
+    CUR.func_round = (TT_Round_Func)Round_Super_45;
+
+
+#define DO_SLOOP                       \
+    if ( args[0] < 0 )                 \
+      CUR.error = TT_Err_Bad_Argument; \
+    else                               \
+      CUR.GS.loop = args[0];
+
+
+#define DO_SMD                         \
+    CUR.GS.minimum_distance = args[0];
+
+
+#define DO_SCVTCI                                     \
+    CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
+
+
+#define DO_SSWCI                                     \
+    CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
+
+
+    /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
+    /*                                                  */
+    /* It seems that the value that is read here is     */
+    /* expressed in 16.16 format rather than in font    */
+    /* units.                                           */
+    /*                                                  */
+#define DO_SSW                                                 \
+    CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
+
+
+#define DO_FLIPON            \
+    CUR.GS.auto_flip = TRUE;
+
+
+#define DO_FLIPOFF            \
+    CUR.GS.auto_flip = FALSE;
+
+
+#define DO_SDB                             \
+    CUR.GS.delta_base = (FT_Short)args[0];
+
+
+#define DO_SDS                              \
+    CUR.GS.delta_shift = (FT_Short)args[0];
+
+
+#define DO_MD  /* nothing */
+
+
+#define DO_MPPEM              \
+    args[0] = CURRENT_Ppem();
+
+
+  /* Note: The pointSize should be irrelevant in a given font program; */
+  /*       we thus decide to return only the ppem.                     */
+#if 0
+
+#define DO_MPS                       \
+    args[0] = CUR.metrics.pointSize;
+
+#else
+
+#define DO_MPS                \
+    args[0] = CURRENT_Ppem();
+
+#endif /* 0 */
+
+
+#define DO_DUP         \
+    args[1] = args[0];
+
+
+#define DO_CLEAR     \
+    CUR.new_top = 0;
+
+
+#define DO_SWAP        \
+  {                    \
+    FT_Long  L;        \
+                       \
+                       \
+    L       = args[0]; \
+    args[0] = args[1]; \
+    args[1] = L;       \
+  }
+
+
+#define DO_DEPTH       \
+    args[0] = CUR.top;
+
+
+#define DO_CINDEX                           \
+  {                                         \
+    FT_Long  L;                             \
+                                            \
+                                            \
+    L = args[0];                            \
+                                            \
+    if ( L <= 0 || L > CUR.args )           \
+      CUR.error = TT_Err_Invalid_Reference; \
+    else                                    \
+      args[0] = CUR.stack[CUR.args - L];    \
+  }
+
+
+#define DO_JROT               \
+    if ( args[1] != 0 )       \
+    {                         \
+      CUR.IP      += args[0]; \
+      CUR.step_ins = FALSE;   \
+    }
+
+
+#define DO_JMPR             \
+    CUR.IP      += args[0]; \
+    CUR.step_ins = FALSE;
+
+
+#define DO_JROF               \
+    if ( args[1] == 0 )       \
+    {                         \
+      CUR.IP      += args[0]; \
+      CUR.step_ins = FALSE;   \
+    }
+
+
+#define DO_LT                        \
+    args[0] = ( args[0] < args[1] );
+
+
+#define DO_LTEQ                       \
+    args[0] = ( args[0] <= args[1] );
+
+
+#define DO_GT                        \
+    args[0] = ( args[0] > args[1] );
+
+
+#define DO_GTEQ                       \
+    args[0] = ( args[0] >= args[1] );
+
+
+#define DO_EQ                         \
+    args[0] = ( args[0] == args[1] );
+
+
+#define DO_NEQ                        \
+    args[0] = ( args[0] != args[1] );
+
+
+#define DO_ODD                                                  \
+    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
+
+
+#define DO_EVEN                                                \
+    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
+
+
+#define DO_AND                        \
+    args[0] = ( args[0] && args[1] );
+
+
+#define DO_OR                         \
+    args[0] = ( args[0] || args[1] );
+
+
+#define DO_NOT          \
+    args[0] = !args[0];
+
+
+#define DO_ADD          \
+    args[0] += args[1];
+
+
+#define DO_SUB          \
+    args[0] -= args[1];
+
+
+#define DO_DIV                                      \
+    if ( args[1] == 0 )                             \
+      CUR.error = TT_Err_Divide_By_Zero;            \
+    else                                            \
+      args[0] = TT_MULDIV( args[0], 64L, args[1] );
+
+
+#define DO_MUL                                    \
+    args[0] = TT_MULDIV( args[0], args[1], 64L );
+
+
+#define DO_ABS                \
+    args[0] = ABS( args[0] );
+
+
+#define DO_NEG          \
+    args[0] = -args[0];
+
+
+#define DO_FLOOR    \
+    args[0] &= -64;
+
+
+#define DO_CEILING                    \
+    args[0] = ( args[0] + 63 ) & -64;
+
+
+#define DO_RS                          \
+   {                                   \
+     FT_ULong  I = (FT_ULong)args[0];  \
+                                       \
+                                       \
+     if ( BOUNDS( I, CUR.storeSize ) ) \
+     {                                 \
+       if ( CUR.pedantic_hinting )     \
+       {                               \
+         ARRAY_BOUND_ERROR;            \
+       }                               \
+       else                            \
+         args[0] = 0;                  \
+     }                                 \
+     else                              \
+       args[0] = CUR.storage[I];       \
+   }
+
+
+#define DO_WS                          \
+   {                                   \
+     FT_ULong  I = (FT_ULong)args[0];  \
+                                       \
+                                       \
+     if ( BOUNDS( I, CUR.storeSize ) ) \
+     {                                 \
+       if ( CUR.pedantic_hinting )     \
+       {                               \
+         ARRAY_BOUND_ERROR;            \
+       }                               \
+     }                                 \
+     else                              \
+       CUR.storage[I] = args[1];       \
+   }
+
+
+#define DO_RCVT                          \
+   {                                     \
+     FT_ULong  I = (FT_ULong)args[0];    \
+                                         \
+                                         \
+     if ( BOUNDS( I, CUR.cvtSize ) )     \
+     {                                   \
+       if ( CUR.pedantic_hinting )       \
+       {                                 \
+         ARRAY_BOUND_ERROR;              \
+       }                                 \
+       else                              \
+         args[0] = 0;                    \
+     }                                   \
+     else                                \
+       args[0] = CUR_Func_read_cvt( I ); \
+   }
+
+
+#define DO_WCVTP                         \
+   {                                     \
+     FT_ULong  I = (FT_ULong)args[0];    \
+                                         \
+                                         \
+     if ( BOUNDS( I, CUR.cvtSize ) )     \
+     {                                   \
+       if ( CUR.pedantic_hinting )       \
+       {                                 \
+         ARRAY_BOUND_ERROR;              \
+       }                                 \
+     }                                   \
+     else                                \
+       CUR_Func_write_cvt( I, args[1] ); \
+   }
+
+
+#define DO_WCVTF                                                \
+   {                                                            \
+     FT_ULong  I = (FT_ULong)args[0];                           \
+                                                                \
+                                                                \
+     if ( BOUNDS( I, CUR.cvtSize ) )                            \
+     {                                                          \
+       if ( CUR.pedantic_hinting )                              \
+       {                                                        \
+         ARRAY_BOUND_ERROR;                                     \
+       }                                                        \
+     }                                                          \
+     else                                                       \
+       CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
+   }
+
+
+#define DO_DEBUG                     \
+    CUR.error = TT_Err_Debug_OpCode;
+
+
+#define DO_ROUND                                                   \
+    args[0] = CUR_Func_round(                                      \
+                args[0],                                           \
+                CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
+
+
+#define DO_NROUND                                                            \
+    args[0] = ROUND_None( args[0],                                           \
+                          CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
+
+
+#define DO_MAX               \
+    if ( args[1] > args[0] ) \
+      args[0] = args[1];
+
+
+#define DO_MIN               \
+    if ( args[1] < args[0] ) \
+      args[0] = args[1];
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+#undef  ARRAY_BOUND_ERROR
+#define ARRAY_BOUND_ERROR                   \
+    {                                       \
+      CUR.error = TT_Err_Invalid_Reference; \
+      return;                               \
+    }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */
+  /* Opcode range: 0x00-0x01                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_SVTCA( INS_ARG )
+  {
+    DO_SVTCA
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPVTCA[a]:    Set PVector to Coordinate Axis                          */
+  /* Opcode range: 0x02-0x03                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_SPVTCA( INS_ARG )
+  {
+    DO_SPVTCA
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVTCA[a]:    Set FVector to Coordinate Axis                          */
+  /* Opcode range: 0x04-0x05                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_SFVTCA( INS_ARG )
+  {
+    DO_SFVTCA
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPVTL[a]:     Set PVector To Line                                     */
+  /* Opcode range: 0x06-0x07                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_SPVTL( INS_ARG )
+  {
+    DO_SPVTL
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVTL[a]:     Set FVector To Line                                     */
+  /* Opcode range: 0x08-0x09                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_SFVTL( INS_ARG )
+  {
+    DO_SFVTL
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVTPV[]:     Set FVector To PVector                                  */
+  /* Opcode range: 0x0E                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_SFVTPV( INS_ARG )
+  {
+    DO_SFVTPV
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPVFS[]:      Set PVector From Stack                                  */
+  /* Opcode range: 0x0A                                                    */
+  /* Stack:        f2.14 f2.14 -->                                         */
+  /*                                                                       */
+  static
+  void  Ins_SPVFS( INS_ARG )
+  {
+    DO_SPVFS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVFS[]:      Set FVector From Stack                                  */
+  /* Opcode range: 0x0B                                                    */
+  /* Stack:        f2.14 f2.14 -->                                         */
+  /*                                                                       */
+  static
+  void  Ins_SFVFS( INS_ARG )
+  {
+    DO_SFVFS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GPV[]:        Get Projection Vector                                   */
+  /* Opcode range: 0x0C                                                    */
+  /* Stack:        ef2.14 --> ef2.14                                       */
+  /*                                                                       */
+  static
+  void  Ins_GPV( INS_ARG )
+  {
+    DO_GPV
+  }
+
+
+  /*************************************************************************/
+  /* GFV[]:        Get Freedom Vector                                      */
+  /* Opcode range: 0x0D                                                    */
+  /* Stack:        ef2.14 --> ef2.14                                       */
+  /*                                                                       */
+  static
+  void  Ins_GFV( INS_ARG )
+  {
+    DO_GFV
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP0[]:       Set Reference Point 0                                   */
+  /* Opcode range: 0x10                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SRP0( INS_ARG )
+  {
+    DO_SRP0
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP1[]:       Set Reference Point 1                                   */
+  /* Opcode range: 0x11                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SRP1( INS_ARG )
+  {
+    DO_SRP1
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP2[]:       Set Reference Point 2                                   */
+  /* Opcode range: 0x12                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SRP2( INS_ARG )
+  {
+    DO_SRP2
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RTHG[]:       Round To Half Grid                                      */
+  /* Opcode range: 0x19                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_RTHG( INS_ARG )
+  {
+    DO_RTHG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RTG[]:        Round To Grid                                           */
+  /* Opcode range: 0x18                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_RTG( INS_ARG )
+  {
+    DO_RTG
+  }
+
+
+  /*************************************************************************/
+  /* RTDG[]:       Round To Double Grid                                    */
+  /* Opcode range: 0x3D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_RTDG( INS_ARG )
+  {
+    DO_RTDG
+  }
+
+
+  /*************************************************************************/
+  /* RUTG[]:       Round Up To Grid                                        */
+  /* Opcode range: 0x7C                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_RUTG( INS_ARG )
+  {
+    DO_RUTG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RDTG[]:       Round Down To Grid                                      */
+  /* Opcode range: 0x7D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_RDTG( INS_ARG )
+  {
+    DO_RDTG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ROFF[]:       Round OFF                                               */
+  /* Opcode range: 0x7A                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_ROFF( INS_ARG )
+  {
+    DO_ROFF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SROUND[]:     Super ROUND                                             */
+  /* Opcode range: 0x76                                                    */
+  /* Stack:        Eint8 -->                                               */
+  /*                                                                       */
+  static
+  void  Ins_SROUND( INS_ARG )
+  {
+    DO_SROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* S45ROUND[]:   Super ROUND 45 degrees                                  */
+  /* Opcode range: 0x77                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_S45ROUND( INS_ARG )
+  {
+    DO_S45ROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SLOOP[]:      Set LOOP variable                                       */
+  /* Opcode range: 0x17                                                    */
+  /* Stack:        int32? -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SLOOP( INS_ARG )
+  {
+    DO_SLOOP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SMD[]:        Set Minimum Distance                                    */
+  /* Opcode range: 0x1A                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static
+  void  Ins_SMD( INS_ARG )
+  {
+    DO_SMD
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCVTCI[]:     Set Control Value Table Cut In                          */
+  /* Opcode range: 0x1D                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static
+  void  Ins_SCVTCI( INS_ARG )
+  {
+    DO_SCVTCI
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SSWCI[]:      Set Single Width Cut In                                 */
+  /* Opcode range: 0x1E                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static
+  void  Ins_SSWCI( INS_ARG )
+  {
+    DO_SSWCI
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SSW[]:        Set Single Width                                        */
+  /* Opcode range: 0x1F                                                    */
+  /* Stack:        int32? -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SSW( INS_ARG )
+  {
+    DO_SSW
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPON[]:     Set auto-FLIP to ON                                     */
+  /* Opcode range: 0x4D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_FLIPON( INS_ARG )
+  {
+    DO_FLIPON
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
+  /* Opcode range: 0x4E                                                    */
+  /* Stack: -->                                                            */
+  /*                                                                       */
+  static
+  void  Ins_FLIPOFF( INS_ARG )
+  {
+    DO_FLIPOFF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SANGW[]:      Set ANGle Weight                                        */
+  /* Opcode range: 0x7E                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SANGW( INS_ARG )
+  {
+    /* instruction not supported anymore */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDB[]:        Set Delta Base                                          */
+  /* Opcode range: 0x5E                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SDB( INS_ARG )
+  {
+    DO_SDB
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDS[]:        Set Delta Shift                                         */
+  /* Opcode range: 0x5F                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SDS( INS_ARG )
+  {
+    DO_SDS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MPPEM[]:      Measure Pixel Per EM                                    */
+  /* Opcode range: 0x4B                                                    */
+  /* Stack:        --> Euint16                                             */
+  /*                                                                       */
+  static
+  void  Ins_MPPEM( INS_ARG )
+  {
+    DO_MPPEM
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MPS[]:        Measure Point Size                                      */
+  /* Opcode range: 0x4C                                                    */
+  /* Stack:        --> Euint16                                             */
+  /*                                                                       */
+  static
+  void  Ins_MPS( INS_ARG )
+  {
+    DO_MPS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DUP[]:        DUPlicate the top stack's element                       */
+  /* Opcode range: 0x20                                                    */
+  /* Stack:        StkElt --> StkElt StkElt                                */
+  /*                                                                       */
+  static
+  void  Ins_DUP( INS_ARG )
+  {
+    DO_DUP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* POP[]:        POP the stack's top element                             */
+  /* Opcode range: 0x21                                                    */
+  /* Stack:        StkElt -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_POP( INS_ARG )
+  {
+    /* nothing to do */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CLEAR[]:      CLEAR the entire stack                                  */
+  /* Opcode range: 0x22                                                    */
+  /* Stack:        StkElt... -->                                           */
+  /*                                                                       */
+  static
+  void  Ins_CLEAR( INS_ARG )
+  {
+    DO_CLEAR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SWAP[]:       SWAP the stack's top two elements                       */
+  /* Opcode range: 0x23                                                    */
+  /* Stack:        2 * StkElt --> 2 * StkElt                               */
+  /*                                                                       */
+  static
+  void  Ins_SWAP( INS_ARG )
+  {
+    DO_SWAP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DEPTH[]:      return the stack DEPTH                                  */
+  /* Opcode range: 0x24                                                    */
+  /* Stack:        --> uint32                                              */
+  /*                                                                       */
+  static
+  void  Ins_DEPTH( INS_ARG )
+  {
+    DO_DEPTH
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CINDEX[]:     Copy INDEXed element                                    */
+  /* Opcode range: 0x25                                                    */
+  /* Stack:        int32 --> StkElt                                        */
+  /*                                                                       */
+  static
+  void  Ins_CINDEX( INS_ARG )
+  {
+    DO_CINDEX
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* EIF[]:        End IF                                                  */
+  /* Opcode range: 0x59                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_EIF( INS_ARG )
+  {
+    /* nothing to do */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JROT[]:       Jump Relative On True                                   */
+  /* Opcode range: 0x78                                                    */
+  /* Stack:        StkElt int32 -->                                        */
+  /*                                                                       */
+  static
+  void  Ins_JROT( INS_ARG )
+  {
+    DO_JROT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JMPR[]:       JuMP Relative                                           */
+  /* Opcode range: 0x1C                                                    */
+  /* Stack:        int32 -->                                               */
+  /*                                                                       */
+  static
+  void  Ins_JMPR( INS_ARG )
+  {
+    DO_JMPR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JROF[]:       Jump Relative On False                                  */
+  /* Opcode range: 0x79                                                    */
+  /* Stack:        StkElt int32 -->                                        */
+  /*                                                                       */
+  static
+  void  Ins_JROF( INS_ARG )
+  {
+    DO_JROF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* LT[]:         Less Than                                               */
+  /* Opcode range: 0x50                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static
+  void  Ins_LT( INS_ARG )
+  {
+    DO_LT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* LTEQ[]:       Less Than or EQual                                      */
+  /* Opcode range: 0x51                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static
+  void  Ins_LTEQ( INS_ARG )
+  {
+    DO_LTEQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GT[]:         Greater Than                                            */
+  /* Opcode range: 0x52                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static
+  void  Ins_GT( INS_ARG )
+  {
+    DO_GT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GTEQ[]:       Greater Than or EQual                                   */
+  /* Opcode range: 0x53                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static
+  void  Ins_GTEQ( INS_ARG )
+  {
+    DO_GTEQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* EQ[]:         EQual                                                   */
+  /* Opcode range: 0x54                                                    */
+  /* Stack:        StkElt StkElt --> bool                                  */
+  /*                                                                       */
+  static
+  void  Ins_EQ( INS_ARG )
+  {
+    DO_EQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NEQ[]:        Not EQual                                               */
+  /* Opcode range: 0x55                                                    */
+  /* Stack:        StkElt StkElt --> bool                                  */
+  /*                                                                       */
+  static
+  void  Ins_NEQ( INS_ARG )
+  {
+    DO_NEQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ODD[]:        Is ODD                                                  */
+  /* Opcode range: 0x56                                                    */
+  /* Stack:        f26.6 --> bool                                          */
+  /*                                                                       */
+  static
+  void  Ins_ODD( INS_ARG )
+  {
+    DO_ODD
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* EVEN[]:       Is EVEN                                                 */
+  /* Opcode range: 0x57                                                    */
+  /* Stack:        f26.6 --> bool                                          */
+  /*                                                                       */
+  static
+  void  Ins_EVEN( INS_ARG )
+  {
+    DO_EVEN
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* AND[]:        logical AND                                             */
+  /* Opcode range: 0x5A                                                    */
+  /* Stack:        uint32 uint32 --> uint32                                */
+  /*                                                                       */
+  static
+  void  Ins_AND( INS_ARG )
+  {
+    DO_AND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* OR[]:         logical OR                                              */
+  /* Opcode range: 0x5B                                                    */
+  /* Stack:        uint32 uint32 --> uint32                                */
+  /*                                                                       */
+  static
+  void  Ins_OR( INS_ARG )
+  {
+    DO_OR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NOT[]:        logical NOT                                             */
+  /* Opcode range: 0x5C                                                    */
+  /* Stack:        StkElt --> uint32                                       */
+  /*                                                                       */
+  static
+  void  Ins_NOT( INS_ARG )
+  {
+    DO_NOT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ADD[]:        ADD                                                     */
+  /* Opcode range: 0x60                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static
+  void  Ins_ADD( INS_ARG )
+  {
+    DO_ADD
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SUB[]:        SUBtract                                                */
+  /* Opcode range: 0x61                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static
+  void  Ins_SUB( INS_ARG )
+  {
+    DO_SUB
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DIV[]:        DIVide                                                  */
+  /* Opcode range: 0x62                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static
+  void  Ins_DIV( INS_ARG )
+  {
+    DO_DIV
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MUL[]:        MULtiply                                                */
+  /* Opcode range: 0x63                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static
+  void  Ins_MUL( INS_ARG )
+  {
+    DO_MUL
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ABS[]:        ABSolute value                                          */
+  /* Opcode range: 0x64                                                    */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static
+  void  Ins_ABS( INS_ARG )
+  {
+    DO_ABS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NEG[]:        NEGate                                                  */
+  /* Opcode range: 0x65                                                    */
+  /* Stack: f26.6 --> f26.6                                                */
+  /*                                                                       */
+  static
+  void  Ins_NEG( INS_ARG )
+  {
+    DO_NEG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLOOR[]:      FLOOR                                                   */
+  /* Opcode range: 0x66                                                    */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static
+  void  Ins_FLOOR( INS_ARG )
+  {
+    DO_FLOOR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CEILING[]:    CEILING                                                 */
+  /* Opcode range: 0x67                                                    */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static
+  void  Ins_CEILING( INS_ARG )
+  {
+    DO_CEILING
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RS[]:         Read Store                                              */
+  /* Opcode range: 0x43                                                    */
+  /* Stack:        uint32 --> uint32                                       */
+  /*                                                                       */
+  static
+  void  Ins_RS( INS_ARG )
+  {
+    DO_RS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* WS[]:         Write Store                                             */
+  /* Opcode range: 0x42                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_WS( INS_ARG )
+  {
+    DO_WS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* WCVTP[]:      Write CVT in Pixel units                                */
+  /* Opcode range: 0x44                                                    */
+  /* Stack:        f26.6 uint32 -->                                        */
+  /*                                                                       */
+  static
+  void  Ins_WCVTP( INS_ARG )
+  {
+    DO_WCVTP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* WCVTF[]:      Write CVT in Funits                                     */
+  /* Opcode range: 0x70                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_WCVTF( INS_ARG )
+  {
+    DO_WCVTF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RCVT[]:       Read CVT                                                */
+  /* Opcode range: 0x45                                                    */
+  /* Stack:        uint32 --> f26.6                                        */
+  /*                                                                       */
+  static
+  void  Ins_RCVT( INS_ARG )
+  {
+    DO_RCVT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* AA[]:         Adjust Angle                                            */
+  /* Opcode range: 0x7F                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_AA( INS_ARG )
+  {
+    /* intentionally no longer supported */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DEBUG[]:      DEBUG.  Unsupported.                                    */
+  /* Opcode range: 0x4F                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  /* Note: The original instruction pops a value from the stack.           */
+  /*                                                                       */
+  static
+  void  Ins_DEBUG( INS_ARG )
+  {
+    DO_DEBUG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ROUND[ab]:    ROUND value                                             */
+  /* Opcode range: 0x68-0x6B                                               */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static
+  void  Ins_ROUND( INS_ARG )
+  {
+    DO_ROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NROUND[ab]:   No ROUNDing of value                                    */
+  /* Opcode range: 0x6C-0x6F                                               */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static
+  void  Ins_NROUND( INS_ARG )
+  {
+    DO_NROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MAX[]:        MAXimum                                                 */
+  /* Opcode range: 0x68                                                    */
+  /* Stack:        int32? int32? --> int32                                 */
+  /*                                                                       */
+  static
+  void  Ins_MAX( INS_ARG )
+  {
+    DO_MAX
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MIN[]:        MINimum                                                 */
+  /* Opcode range: 0x69                                                    */
+  /* Stack:        int32? int32? --> int32                                 */
+  /*                                                                       */
+  static
+  void  Ins_MIN( INS_ARG )
+  {
+    DO_MIN
+  }
+
+
+#endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The following functions are called as is within the switch statement. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MINDEX[]:     Move INDEXed element                                    */
+  /* Opcode range: 0x26                                                    */
+  /* Stack:        int32? --> StkElt                                       */
+  /*                                                                       */
+  static
+  void  Ins_MINDEX( INS_ARG )
+  {
+    FT_Long  L, K;
+
+
+    L = args[0];
+
+    if ( L <= 0 || L > CUR.args )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    K = CUR.stack[CUR.args - L];
+
+    MEM_Move( &CUR.stack[CUR.args - L    ],
+              &CUR.stack[CUR.args - L + 1],
+              ( L - 1 ) * sizeof ( FT_Long ) );
+
+    CUR.stack[CUR.args - 1] = K;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ROLL[]:       ROLL top three elements                                 */
+  /* Opcode range: 0x8A                                                    */
+  /* Stack:        3 * StkElt --> 3 * StkElt                               */
+  /*                                                                       */
+  static
+  void  Ins_ROLL( INS_ARG )
+  {
+    FT_Long  A, B, C;
+
+    FT_UNUSED_EXEC;
+
+
+    A = args[2];
+    B = args[1];
+    C = args[0];
+
+    args[2] = C;
+    args[1] = A;
+    args[0] = B;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MANAGING THE FLOW OF CONTROL                                          */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static
+  FT_Bool  SkipCode( EXEC_OP )
+  {
+    CUR.IP += CUR.length;
+
+    if ( CUR.IP < CUR.codeSize )
+    {
+      CUR.opcode = CUR.code[CUR.IP];
+
+      CUR.length = opcode_length[CUR.opcode];
+      if ( CUR.length < 0 )
+      {
+        if ( CUR.IP + 1 > CUR.codeSize )
+          goto Fail_Overflow;
+        CUR.length = CUR.code[CUR.IP + 1] + 2;
+      }
+
+      if ( CUR.IP + CUR.length <= CUR.codeSize )
+        return SUCCESS;
+    }
+
+  Fail_Overflow:
+    CUR.error = TT_Err_Code_Overflow;
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IF[]:         IF test                                                 */
+  /* Opcode range: 0x58                                                    */
+  /* Stack:        StkElt -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_IF( INS_ARG )
+  {
+    FT_Int   nIfs;
+    FT_Bool  Out;
+
+
+    if ( args[0] != 0 )
+      return;
+
+    nIfs = 1;
+    Out = 0;
+
+    do
+    {
+      if ( SKIP_Code() == FAILURE )
+        return;
+
+      switch ( CUR.opcode )
+      {
+      case 0x58:      /* IF */
+        nIfs++;
+        break;
+
+      case 0x1B:      /* ELSE */
+        Out = ( nIfs == 1 );
+        break;
+
+      case 0x59:      /* EIF */
+        nIfs--;
+        Out = ( nIfs == 0 );
+        break;
+      }
+    } while ( Out == 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ELSE[]:       ELSE                                                    */
+  /* Opcode range: 0x1B                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_ELSE( INS_ARG )
+  {
+    FT_Int  nIfs;
+
+    FT_UNUSED_ARG;
+
+
+    nIfs = 1;
+
+    do
+    {
+      if ( SKIP_Code() == FAILURE )
+        return;
+
+      switch ( CUR.opcode )
+      {
+      case 0x58:    /* IF */
+        nIfs++;
+        break;
+
+      case 0x59:    /* EIF */
+        nIfs--;
+        break;
+      }
+    } while ( nIfs != 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FDEF[]:       Function DEFinition                                     */
+  /* Opcode range: 0x2C                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_FDEF( INS_ARG )
+  {
+    FT_ULong       n;
+    TT_DefRecord*  rec;
+    TT_DefRecord*  limit;
+
+
+    /* some font programs are broken enough to redefine functions! */
+    /* We will then parse the current table.                       */
+
+    rec   = CUR.FDefs;
+    limit = rec + CUR.numFDefs;
+    n     = args[0];
+
+    for ( ; rec < limit; rec++ )
+    {
+      if ( rec->opc == n )
+        break;
+    }
+
+    if ( rec == limit )
+    {
+      /* check that there is enough room for new functions */
+      if ( CUR.numFDefs >= CUR.maxFDefs )
+      {
+        CUR.error = TT_Err_Too_Many_Function_Defs;
+        return;
+      }
+      CUR.numFDefs++;
+    }
+
+    rec->range  = CUR.curRange;
+    rec->opc    = n;
+    rec->start  = CUR.IP + 1;
+    rec->active = TRUE;
+
+    if ( n > CUR.maxFunc )
+      CUR.maxFunc = n;
+
+    /* Now skip the whole function definition. */
+    /* We don't allow nested IDEFS & FDEFs.    */
+
+    while ( SKIP_Code() == SUCCESS )
+    {
+      switch ( CUR.opcode )
+      {
+      case 0x89:    /* IDEF */
+      case 0x2C:    /* FDEF */
+        CUR.error = TT_Err_Nested_DEFS;
+        return;
+
+      case 0x2D:   /* ENDF */
+        return;
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ENDF[]:       END Function definition                                 */
+  /* Opcode range: 0x2D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_ENDF( INS_ARG )
+  {
+    TT_CallRec*  pRec;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
+    {
+      CUR.error = TT_Err_ENDF_In_Exec_Stream;
+      return;
+    }
+
+    CUR.callTop--;
+
+    pRec = &CUR.callStack[CUR.callTop];
+
+    pRec->Cur_Count--;
+
+    CUR.step_ins = FALSE;
+
+    if ( pRec->Cur_Count > 0 )
+    {
+      CUR.callTop++;
+      CUR.IP = pRec->Cur_Restart;
+    }
+    else
+      /* Loop through the current function */
+      INS_Goto_CodeRange( pRec->Caller_Range,
+                          pRec->Caller_IP );
+
+    /* Exit the current call frame.                      */
+
+    /* NOTE: If the last intruction of a program is a    */
+    /*       CALL or LOOPCALL, the return address is     */
+    /*       always out of the code range.  This is a    */
+    /*       valid address, and it is why we do not test */
+    /*       the result of Ins_Goto_CodeRange() here!    */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CALL[]:       CALL function                                           */
+  /* Opcode range: 0x2B                                                    */
+  /* Stack:        uint32? -->                                             */
+  /*                                                                       */
+  static
+  void  Ins_CALL( INS_ARG )
+  {
+    FT_ULong       F;
+    TT_CallRec*    pCrec;
+    TT_DefRecord*  def;
+
+
+    /* first of all, check the index */
+
+    F = args[0];
+    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+      goto Fail;
+
+    /* Except for some old Apple fonts, all functions in a TrueType */
+    /* font are defined in increasing order, starting from 0.  This */
+    /* means that we normally have                                  */
+    /*                                                              */
+    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
+    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
+    /*                                                              */
+    /* If this isn't true, we need to look up the function table.   */
+
+    def = CUR.FDefs + F;
+    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+    {
+      /* look up the FDefs table */
+      TT_DefRecord*  limit;
+
+
+      def   = CUR.FDefs;
+      limit = def + CUR.numFDefs;
+
+      while ( def < limit && def->opc != F )
+        def++;
+
+      if ( def == limit )
+        goto Fail;
+    }
+
+    /* check that the function is active */
+    if ( !def->active )
+      goto Fail;
+
+    /* check the call stack */
+    if ( CUR.callTop >= CUR.callSize )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    pCrec = CUR.callStack + CUR.callTop;
+
+    pCrec->Caller_Range = CUR.curRange;
+    pCrec->Caller_IP    = CUR.IP + 1;
+    pCrec->Cur_Count    = 1;
+    pCrec->Cur_Restart  = def->start;
+
+    CUR.callTop++;
+
+    INS_Goto_CodeRange( def->range,
+                        def->start );
+
+    CUR.step_ins = FALSE;
+    return;
+
+  Fail:
+    CUR.error = TT_Err_Invalid_Reference;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* LOOPCALL[]:   LOOP and CALL function                                  */
+  /* Opcode range: 0x2A                                                    */
+  /* Stack:        uint32? Eint16? -->                                     */
+  /*                                                                       */
+  static
+  void  Ins_LOOPCALL( INS_ARG )
+  {
+    FT_ULong       F;
+    TT_CallRec*    pCrec;
+    TT_DefRecord*  def;
+
+
+    /* first of all, check the index */
+    F = args[1];
+    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+      goto Fail;
+
+    /* Except for some old Apple fonts, all functions in a TrueType */
+    /* font are defined in increasing order, starting from 0.  This */
+    /* means that we normally have                                  */
+    /*                                                              */
+    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
+    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
+    /*                                                              */
+    /* If this isn't true, we need to look up the function table.   */
+
+    def = CUR.FDefs + F;
+    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+    {
+      /* look up the FDefs table */
+      TT_DefRecord*  limit;
+
+
+      def   = CUR.FDefs;
+      limit = def + CUR.numFDefs;
+
+      while ( def < limit && def->opc != F )
+        def++;
+
+      if ( def == limit )
+        goto Fail;
+    }
+
+    /* check that the function is active */
+    if ( !def->active )
+      goto Fail;
+
+    /* check stack */
+    if ( CUR.callTop >= CUR.callSize )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    if ( args[0] > 0 )
+    {
+      pCrec = CUR.callStack + CUR.callTop;
+
+      pCrec->Caller_Range = CUR.curRange;
+      pCrec->Caller_IP    = CUR.IP + 1;
+      pCrec->Cur_Count    = (FT_Int)args[0];
+      pCrec->Cur_Restart  = def->start;
+
+      CUR.callTop++;
+
+      INS_Goto_CodeRange( def->range, def->start );
+
+      CUR.step_ins = FALSE;
+    }
+    return;
+
+  Fail:
+    CUR.error = TT_Err_Invalid_Reference;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IDEF[]:       Instruction DEFinition                                  */
+  /* Opcode range: 0x89                                                    */
+  /* Stack:        Eint8 -->                                               */
+  /*                                                                       */
+  static
+  void Ins_IDEF( INS_ARG )
+  {
+    TT_DefRecord*  def;
+    TT_DefRecord*  limit;
+
+
+    /*  First of all, look for the same function in our table */
+
+    def   = CUR.IDefs;
+    limit = def + CUR.numIDefs;
+
+    for ( ; def < limit; def++ )
+      if ( def->opc == (FT_ULong)args[0] )
+        break;
+
+    if ( def == limit )
+    {
+      /* check that there is enough room for a new instruction */
+      if ( CUR.numIDefs >= CUR.maxIDefs )
+      {
+        CUR.error = TT_Err_Too_Many_Instruction_Defs;
+        return;
+      }
+      CUR.numIDefs++;
+    }
+
+    def->opc    = args[0];
+    def->start  = CUR.IP+1;
+    def->range  = CUR.curRange;
+    def->active = TRUE;
+
+    if ( (FT_ULong)args[0] > CUR.maxIns )
+      CUR.maxIns = args[0];
+
+    /* Now skip the whole function definition. */
+    /* We don't allow nested IDEFs & FDEFs.    */
+
+    while ( SKIP_Code() == SUCCESS )
+    {
+      switch ( CUR.opcode )
+      {
+      case 0x89:   /* IDEF */
+      case 0x2C:   /* FDEF */
+        CUR.error = TT_Err_Nested_DEFS;
+        return;
+      case 0x2D:   /* ENDF */
+        return;
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* PUSHING DATA ONTO THE INTERPRETER STACK                               */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NPUSHB[]:     PUSH N Bytes                                            */
+  /* Opcode range: 0x40                                                    */
+  /* Stack:        --> uint32...                                           */
+  /*                                                                       */
+  static
+  void  Ins_NPUSHB( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    for ( K = 1; K <= L; K++ )
+      args[K - 1] = CUR.code[CUR.IP + K + 1];
+
+    CUR.new_top += L;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NPUSHW[]:     PUSH N Words                                            */
+  /* Opcode range: 0x41                                                    */
+  /* Stack:        --> int32...                                            */
+  /*                                                                       */
+  static
+  void  Ins_NPUSHW( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    CUR.IP += 2;
+
+    for ( K = 0; K < L; K++ )
+      args[K] = GET_ShortIns();
+
+    CUR.step_ins = FALSE;
+    CUR.new_top += L;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* PUSHB[abc]:   PUSH Bytes                                              */
+  /* Opcode range: 0xB0-0xB7                                               */
+  /* Stack:        --> uint32...                                           */
+  /*                                                                       */
+  static
+  void  Ins_PUSHB( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)CUR.opcode - 0xB0 + 1;
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    for ( K = 1; K <= L; K++ )
+      args[K - 1] = CUR.code[CUR.IP + K];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* PUSHW[abc]:   PUSH Words                                              */
+  /* Opcode range: 0xB8-0xBF                                               */
+  /* Stack:        --> int32...                                            */
+  /*                                                                       */
+  static
+  void  Ins_PUSHW( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)CUR.opcode - 0xB8 + 1;
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    CUR.IP++;
+
+    for ( K = 0; K < L; K++ )
+      args[K] = GET_ShortIns();
+
+    CUR.step_ins = FALSE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MANAGING THE GRAPHICS STATE                                           */
+  /*                                                                       */
+  /*  Instructions appear in the specs' order.                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GC[a]:        Get Coordinate projected onto                           */
+  /* Opcode range: 0x46-0x47                                               */
+  /* Stack:        uint32 --> f26.6                                        */
+  /*                                                                       */
+  /* BULLSHIT: Measures from the original glyph must be taken along the    */
+  /*           dual projection vector!                                     */
+  /*                                                                       */
+  static void  Ins_GC( INS_ARG )
+  {
+    FT_ULong    L;
+    FT_F26Dot6  R;
+
+
+    L = (FT_ULong)args[0];
+
+    if ( BOUNDS( L, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+      {
+        CUR.error = TT_Err_Invalid_Reference;
+        return;
+      }
+      else
+        R = 0;
+    }
+    else
+    {
+      if ( CUR.opcode & 1 )
+        R = CUR_Func_dualproj( CUR.zp2.org + L, NULL_Vector );
+      else
+        R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
+    }
+
+    args[0] = R;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCFS[]:       Set Coordinate From Stack                               */
+  /* Opcode range: 0x48                                                    */
+  /* Stack:        f26.6 uint32 -->                                        */
+  /*                                                                       */
+  /* Formula:                                                              */
+  /*                                                                       */
+  /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */
+  /*                                                                       */
+  static
+  void  Ins_SCFS( INS_ARG )
+  {
+    FT_Long    K;
+    FT_UShort  L;
+
+
+    L = (FT_UShort)args[0];
+
+    if ( BOUNDS( L, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
+
+    CUR_Func_move( &CUR.zp2, L, args[1] - K );
+
+    /* not part of the specs, but here for safety */
+
+    if ( CUR.GS.gep2 == 0 )
+      CUR.zp2.org[L] = CUR.zp2.cur[L];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MD[a]:        Measure Distance                                        */
+  /* Opcode range: 0x49-0x4A                                               */
+  /* Stack:        uint32 uint32 --> f26.6                                 */
+  /*                                                                       */
+  /* BULLSHIT: Measure taken in the original glyph must be along the dual  */
+  /*           projection vector.                                          */
+  /*                                                                       */
+  /* Second BULLSHIT: Flag attributes are inverted!                        */
+  /*                  0 => measure distance in original outline            */
+  /*                  1 => measure distance in grid-fitted outline         */
+  /*                                                                       */
+  /* Third one: `zp0 - zp1', and not `zp2 - zp1!                           */
+  /*                                                                       */
+  static
+  void  Ins_MD( INS_ARG )
+  {
+    FT_UShort   K, L;
+    FT_F26Dot6  D;
+
+
+    K = (FT_UShort)args[1];
+    L = (FT_UShort)args[0];
+
+    if( BOUNDS( L, CUR.zp0.n_points ) ||
+        BOUNDS( K, CUR.zp1.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+      {
+        CUR.error = TT_Err_Invalid_Reference;
+        return;
+      }
+      D = 0;
+    }
+    else
+    {
+      if ( CUR.opcode & 1 )
+        D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
+      else
+        D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
+    }
+
+    args[0] = D;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDPVTL[a]:    Set Dual PVector to Line                                */
+  /* Opcode range: 0x86-0x87                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_SDPVTL( INS_ARG )
+  {
+    FT_Long    A, B, C;
+    FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */
+
+
+    p1 = (FT_UShort)args[1];
+    p2 = (FT_UShort)args[0];
+
+    if ( BOUNDS( p2, CUR.zp1.n_points ) ||
+         BOUNDS( p1, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    {
+      FT_Vector* v1 = CUR.zp1.org + p2;
+      FT_Vector* v2 = CUR.zp2.org + p1;
+
+
+      A = v1->x - v2->x;
+      B = v1->y - v2->y;
+    }
+
+    if ( ( CUR.opcode & 1 ) != 0 )
+    {
+      C =  B;   /* counter clockwise rotation */
+      B =  A;
+      A = -C;
+    }
+
+    NORMalize( A, B, &CUR.GS.dualVector );
+
+    {
+      FT_Vector*  v1 = CUR.zp1.cur + p2;
+      FT_Vector*  v2 = CUR.zp2.cur + p1;
+
+
+      A = v1->x - v2->x;
+      B = v1->y - v2->y;
+    }
+
+    if ( ( CUR.opcode & 1 ) != 0 )
+    {
+      C =  B;   /* counter clockwise rotation */
+      B =  A;
+      A = -C;
+    }
+
+    NORMalize( A, B, &CUR.GS.projVector );
+
+    COMPUTE_Funcs();
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZP0[]:       Set Zone Pointer 0                                      */
+  /* Opcode range: 0x13                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SZP0( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp0 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp0 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.GS.gep0 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZP1[]:       Set Zone Pointer 1                                      */
+  /* Opcode range: 0x14                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SZP1( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp1 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp1 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.GS.gep1 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZP2[]:       Set Zone Pointer 2                                      */
+  /* Opcode range: 0x15                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SZP2( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp2 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp2 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.GS.gep2 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZPS[]:       Set Zone PointerS                                       */
+  /* Opcode range: 0x16                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SZPS( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp0 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp0 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.zp1 = CUR.zp0;
+    CUR.zp2 = CUR.zp0;
+
+    CUR.GS.gep0 = (FT_UShort)args[0];
+    CUR.GS.gep1 = (FT_UShort)args[0];
+    CUR.GS.gep2 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* INSTCTRL[]:   INSTruction ConTRoL                                     */
+  /* Opcode range: 0x8e                                                    */
+  /* Stack:        int32 int32 -->                                         */
+  /*                                                                       */
+  static
+  void  Ins_INSTCTRL( INS_ARG )
+  {
+    FT_Long  K, L;
+
+
+    K = args[1];
+    L = args[0];
+
+    if ( K < 1 || K > 2 )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( L != 0 )
+        L = K;
+
+    CUR.GS.instruct_control =
+      (FT_Byte)( CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCANCTRL[]:   SCAN ConTRoL                                            */
+  /* Opcode range: 0x85                                                    */
+  /* Stack:        uint32? -->                                             */
+  /*                                                                       */
+  static
+  void  Ins_SCANCTRL( INS_ARG )
+  {
+    FT_Int  A;
+
+
+    /* Get Threshold */
+    A = (FT_Int)( args[0] & 0xFF );
+
+    if ( A == 0xFF )
+    {
+      CUR.GS.scan_control = TRUE;
+      return;
+    }
+    else if ( A == 0 )
+    {
+      CUR.GS.scan_control = FALSE;
+      return;
+    }
+
+    A *= 64;
+
+#if 0
+    if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A )
+      CUR.GS.scan_control = TRUE;
+#endif
+
+    if ( (args[0] & 0x200) != 0 && CUR.tt_metrics.rotated )
+      CUR.GS.scan_control = TRUE;
+
+    if ( (args[0] & 0x400) != 0 && CUR.tt_metrics.stretched )
+      CUR.GS.scan_control = TRUE;
+
+#if 0
+    if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A )
+      CUR.GS.scan_control = FALSE;
+#endif
+
+    if ( (args[0] & 0x1000) != 0 && CUR.tt_metrics.rotated )
+      CUR.GS.scan_control = FALSE;
+
+    if ( (args[0] & 0x2000) != 0 && CUR.tt_metrics.stretched )
+      CUR.GS.scan_control = FALSE;
+}
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCANTYPE[]:   SCAN TYPE                                               */
+  /* Opcode range: 0x8D                                                    */
+  /* Stack:        uint32? -->                                             */
+  /*                                                                       */
+  static
+  void  Ins_SCANTYPE( INS_ARG )
+  {
+    /* for compatibility with future enhancements, */
+    /* we must ignore new modes                    */
+
+    if ( args[0] >= 0 && args[0] <= 5 )
+    {
+      if ( args[0] == 3 )
+        args[0] = 2;
+
+      CUR.GS.scan_type = (FT_Int)args[0];
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MANAGING OUTLINES                                                     */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPPT[]:     FLIP PoinT                                              */
+  /* Opcode range: 0x80                                                    */
+  /* Stack:        uint32... -->                                           */
+  /*                                                                       */
+  static
+  void  Ins_FLIPPT( INS_ARG )
+  {
+    FT_UShort  point;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop )
+    {
+      CUR.error = TT_Err_Too_Few_Arguments;
+      return;
+    }
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.pts.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+        CUR.pts.tags[point] ^= FT_Curve_Tag_On;
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPRGON[]:   FLIP RanGe ON                                           */
+  /* Opcode range: 0x81                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_FLIPRGON( INS_ARG )
+  {
+    FT_UShort  I, K, L;
+
+
+    K = (FT_UShort)args[1];
+    L = (FT_UShort)args[0];
+
+    if ( BOUNDS( K, CUR.pts.n_points ) ||
+         BOUNDS( L, CUR.pts.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    for ( I = L; I <= K; I++ )
+      CUR.pts.tags[I] |= FT_Curve_Tag_On;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPRGOFF:    FLIP RanGe OFF                                          */
+  /* Opcode range: 0x82                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_FLIPRGOFF( INS_ARG )
+  {
+    FT_UShort  I, K, L;
+
+
+    K = (FT_UShort)args[1];
+    L = (FT_UShort)args[0];
+
+    if ( BOUNDS( K, CUR.pts.n_points ) ||
+         BOUNDS( L, CUR.pts.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    for ( I = L; I <= K; I++ )
+      CUR.pts.tags[I] &= ~FT_Curve_Tag_On;
+  }
+
+
+  static
+  FT_Bool  Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*    x,
+                                                FT_F26Dot6*    y,
+                                                TT_GlyphZone*  zone,
+                                                FT_UShort*     refp )
+  {
+    TT_GlyphZone  zp;
+    FT_UShort     p;
+    FT_F26Dot6    d;
+
+
+    if ( CUR.opcode & 1 )
+    {
+      zp = CUR.zp0;
+      p  = CUR.GS.rp1;
+    }
+    else
+    {
+      zp = CUR.zp1;
+      p  = CUR.GS.rp2;
+    }
+
+    if ( BOUNDS( p, zp.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return FAILURE;
+    }
+
+    *zone = zp;
+    *refp = p;
+
+    d = CUR_Func_project( zp.cur + p, zp.org + p );
+
+#ifdef NO_APPLE_PATENT
+
+    *x = TT_MULDIV( d, CUR.GS.freeVector.x, 0x4000 );
+    *y = TT_MULDIV( d, CUR.GS.freeVector.y, 0x4000 );
+
+#else
+
+    *x = TT_MULDIV( d,
+                    (FT_Long)CUR.GS.freeVector.x * 0x10000L,
+                    CUR.F_dot_P );
+    *y = TT_MULDIV( d,
+                    (FT_Long)CUR.GS.freeVector.y * 0x10000L,
+                    CUR.F_dot_P );
+
+#endif /* NO_APPLE_PATENT */
+
+    return SUCCESS;
+  }
+
+
+  static
+  void  Move_Zp2_Point( EXEC_OP_ FT_UShort   point,
+                                 FT_F26Dot6  dx,
+                                 FT_F26Dot6  dy,
+                                 FT_Bool     touch )
+  {
+    if ( CUR.GS.freeVector.x != 0 )
+    {
+      CUR.zp2.cur[point].x += dx;
+      if ( touch )
+        CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_X;
+    }
+
+    if ( CUR.GS.freeVector.y != 0 )
+    {
+      CUR.zp2.cur[point].y += dy;
+      if ( touch )
+        CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Y;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHP[a]:       SHift Point by the last point                           */
+  /* Opcode range: 0x32-0x33                                               */
+  /* Stack:        uint32... -->                                           */
+  /*                                                                       */
+  static
+  void  Ins_SHP( INS_ARG )
+  {
+    TT_GlyphZone  zp;
+    FT_UShort     refp;
+
+    FT_F26Dot6    dx,
+                  dy;
+    FT_UShort     point;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+      return;
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+        /* XXX: UNDOCUMENTED! SHP touches the points */
+        MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHC[a]:       SHift Contour                                           */
+  /* Opcode range: 0x34-35                                                 */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SHC( INS_ARG )
+  {
+    TT_GlyphZone zp;
+    FT_UShort    refp;
+    FT_F26Dot6   dx,
+                 dy;
+
+    FT_Short     contour;
+    FT_UShort    first_point, last_point, i;
+
+
+    contour = (FT_UShort)args[0];
+
+    if ( BOUNDS( contour, CUR.pts.n_contours ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+      return;
+
+    if ( contour == 0 )
+      first_point = 0;
+    else
+      first_point = CUR.pts.contours[contour - 1] + 1;
+
+    last_point = CUR.pts.contours[contour];
+
+    /* XXX: this is probably wrong... at least it prevents memory */
+    /*      corruption when zp2 is the twilight zone              */
+    if ( last_point > CUR.zp2.n_points )
+    {
+      if ( CUR.zp2.n_points > 0 )
+        last_point = CUR.zp2.n_points - 1;
+      else
+        last_point = 0;
+    }
+
+    /* XXX: UNDOCUMENTED! SHC doesn't touch the points */
+    for ( i = first_point; i <= last_point; i++ )
+    {
+      if ( zp.cur != CUR.zp2.cur || refp != i )
+        MOVE_Zp2_Point( i, dx, dy, FALSE );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHZ[a]:       SHift Zone                                              */
+  /* Opcode range: 0x36-37                                                 */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_SHZ( INS_ARG )
+  {
+    TT_GlyphZone zp;
+    FT_UShort    refp;
+    FT_F26Dot6   dx,
+                 dy;
+
+    FT_UShort    last_point, i;
+
+
+    if ( BOUNDS( args[0], 2 ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+      return;
+
+    if ( CUR.zp2.n_points > 0 )
+      last_point = CUR.zp2.n_points - 1;
+    else
+      last_point = 0;
+
+    /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
+    for ( i = 0; i <= last_point; i++ )
+    {
+      if ( zp.cur != CUR.zp2.cur || refp != i )
+        MOVE_Zp2_Point( i, dx, dy, FALSE );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHPIX[]:      SHift points by a PIXel amount                          */
+  /* Opcode range: 0x38                                                    */
+  /* Stack:        f26.6 uint32... -->                                     */
+  /*                                                                       */
+  static
+  void  Ins_SHPIX( INS_ARG )
+  {
+    FT_F26Dot6  dx, dy;
+    FT_UShort   point;
+
+
+    if ( CUR.top < CUR.GS.loop + 1 )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    dx = TT_MULDIV( args[0],
+                    (FT_Long)CUR.GS.freeVector.x,
+                    0x4000 );
+    dy = TT_MULDIV( args[0],
+                    (FT_Long)CUR.GS.freeVector.y,
+                    0x4000 );
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+        MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MSIRP[a]:     Move Stack Indirect Relative Position                   */
+  /* Opcode range: 0x3A-0x3B                                               */
+  /* Stack:        f26.6 uint32 -->                                        */
+  /*                                                                       */
+  static
+  void  Ins_MSIRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  distance;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: UNDOCUMENTED! behaviour */
+    if ( CUR.GS.gep0 == 0 )   /* if in twilight zone */
+    {
+      CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
+      CUR.zp1.cur[point] = CUR.zp1.org[point];
+    }
+
+    distance = CUR_Func_project( CUR.zp1.cur + point,
+                                 CUR.zp0.cur + CUR.GS.rp0 );
+
+    CUR_Func_move( &CUR.zp1, point, args[1] - distance );
+
+    CUR.GS.rp1 = CUR.GS.rp0;
+    CUR.GS.rp2 = point;
+
+    if ( (CUR.opcode & 1) != 0 )
+      CUR.GS.rp0 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MDAP[a]:      Move Direct Absolute Point                              */
+  /* Opcode range: 0x2E-0x2F                                               */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_MDAP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  cur_dist,
+                distance;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: Is there some undocumented feature while in the */
+    /*      twilight zone? ?                                */
+    if ( ( CUR.opcode & 1 ) != 0 )
+    {
+      cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
+      distance = CUR_Func_round( cur_dist,
+                                 CUR.tt_metrics.compensations[0] ) - cur_dist;
+    }
+    else
+      distance = 0;
+
+    CUR_Func_move( &CUR.zp0, point, distance );
+
+    CUR.GS.rp0 = point;
+    CUR.GS.rp1 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MIAP[a]:      Move Indirect Absolute Point                            */
+  /* Opcode range: 0x3E-0x3F                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_MIAP( INS_ARG )
+  {
+    FT_ULong    cvtEntry;
+    FT_UShort   point;
+    FT_F26Dot6  distance,
+                org_dist;
+
+
+    cvtEntry = (FT_ULong)args[1];
+    point    = (FT_UShort)args[0];
+
+    if ( BOUNDS( point,    CUR.zp0.n_points ) ||
+         BOUNDS( cvtEntry, CUR.cvtSize )      )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* UNDOCUMENTED!                                     */
+    /*                                                   */
+    /* The behaviour of an MIAP instruction is quite     */
+    /* different when used in the twilight zone.         */
+    /*                                                   */
+    /* First, no control value cutin test is performed   */
+    /* as it would fail anyway.  Second, the original    */
+    /* point, i.e. (org_x,org_y) of zp0.point, is set    */
+    /* to the absolute, unrounded distance found in      */
+    /* the CVT.                                          */
+    /*                                                   */
+    /* This is used in the CVT programs of the Microsoft */
+    /* fonts Arial, Times, etc., in order to re-adjust   */
+    /* some key font heights.  It allows the use of the  */
+    /* IP instruction in the twilight zone, which        */
+    /* otherwise would be `illegal' according to the     */
+    /* specification.                                    */
+    /*                                                   */
+    /* We implement it with a special sequence for the   */
+    /* twilight zone.  This is a bad hack, but it seems  */
+    /* to work.                                          */
+
+    distance = CUR_Func_read_cvt( cvtEntry );
+
+    if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
+    {
+      CUR.zp0.org[point].x = TT_MULDIV( CUR.GS.freeVector.x,
+                                        distance, 0x4000 );
+      CUR.zp0.org[point].y = TT_MULDIV( CUR.GS.freeVector.y,
+                                        distance, 0x4000 );
+      CUR.zp0.cur[point] = CUR.zp0.org[point];
+    }
+
+    org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
+
+    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */
+    {
+      if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
+        distance = org_dist;
+
+      distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
+    }
+
+    CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+
+    CUR.GS.rp0 = point;
+    CUR.GS.rp1 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MDRP[abcde]:  Move Direct Relative Point                              */
+  /* Opcode range: 0xC0-0xDF                                               */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_MDRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  org_dist, distance;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: Is there some undocumented feature while in the */
+    /*      twilight zone?                                  */
+
+    org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
+                                  CUR.zp0.org + CUR.GS.rp0 );
+
+    /* single width cutin test */
+
+    if ( ABS( org_dist ) < CUR.GS.single_width_cutin )
+    {
+      if ( org_dist >= 0 )
+        org_dist = CUR.GS.single_width_value;
+      else
+        org_dist = -CUR.GS.single_width_value;
+    }
+
+    /* round flag */
+
+    if ( ( CUR.opcode & 4 ) != 0 )
+      distance = CUR_Func_round(
+                   org_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+    else
+      distance = ROUND_None(
+                   org_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+    /* minimum distance flag */
+
+    if ( ( CUR.opcode & 8 ) != 0 )
+    {
+      if ( org_dist >= 0 )
+      {
+        if ( distance < CUR.GS.minimum_distance )
+          distance = CUR.GS.minimum_distance;
+      }
+      else
+      {
+        if ( distance > -CUR.GS.minimum_distance )
+          distance = -CUR.GS.minimum_distance;
+      }
+    }
+
+    /* now move the point */
+
+    org_dist = CUR_Func_project( CUR.zp1.cur + point,
+                                 CUR.zp0.cur + CUR.GS.rp0 );
+
+    CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+
+    CUR.GS.rp1 = CUR.GS.rp0;
+    CUR.GS.rp2 = point;
+
+    if ( ( CUR.opcode & 16 ) != 0 )
+      CUR.GS.rp0 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MIRP[abcde]:  Move Indirect Relative Point                            */
+  /* Opcode range: 0xE0-0xFF                                               */
+  /* Stack:        int32? uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_MIRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_ULong    cvtEntry;
+
+    FT_F26Dot6  cvt_dist,
+                distance,
+                cur_dist,
+                org_dist;
+
+
+    point    = (FT_UShort)args[0];
+    cvtEntry = (FT_ULong)( args[1] + 1 );
+
+    /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
+
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
+         BOUNDS( cvtEntry,   CUR.cvtSize + 1 )  ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( !cvtEntry )
+      cvt_dist = 0;
+    else
+      cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+
+    /* single width test */
+
+    if ( ABS( cvt_dist ) < CUR.GS.single_width_cutin )
+    {
+      if ( cvt_dist >= 0 )
+        cvt_dist =  CUR.GS.single_width_value;
+      else
+        cvt_dist = -CUR.GS.single_width_value;
+    }
+
+    /* XXX: UNDOCUMENTED! -- twilight zone */
+
+    if ( CUR.GS.gep1 == 0 )
+    {
+      CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
+                             TT_MULDIV( cvt_dist,
+                                        CUR.GS.freeVector.x,
+                                        0x4000 );
+
+      CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
+                             TT_MULDIV( cvt_dist,
+                                        CUR.GS.freeVector.y,
+                                        0x4000 );
+
+      CUR.zp1.cur[point] = CUR.zp1.org[point];
+    }
+
+    org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
+                                  CUR.zp0.org + CUR.GS.rp0 );
+
+    cur_dist = CUR_Func_project( CUR.zp1.cur + point,
+                                 CUR.zp0.cur + CUR.GS.rp0 );
+
+    /* auto-flip test */
+
+    if ( CUR.GS.auto_flip )
+    {
+      if ( ( org_dist ^ cvt_dist ) < 0 )
+        cvt_dist = -cvt_dist;
+    }
+
+    /* control value cutin and round */
+
+    if ( ( CUR.opcode & 4 ) != 0 )
+    {
+      /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
+      /*      refer to the same zone.                                  */
+
+      if ( CUR.GS.gep0 == CUR.GS.gep1 )
+        if ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+          cvt_dist = org_dist;
+
+      distance = CUR_Func_round(
+                   cvt_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+    }
+    else
+      distance = ROUND_None(
+                   cvt_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+    /* minimum distance test */
+
+    if ( ( CUR.opcode & 8 ) != 0 )
+    {
+      if ( org_dist >= 0 )
+      {
+        if ( distance < CUR.GS.minimum_distance )
+          distance = CUR.GS.minimum_distance;
+      }
+      else
+      {
+        if ( distance > -CUR.GS.minimum_distance )
+          distance = -CUR.GS.minimum_distance;
+      }
+    }
+
+    CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+
+    CUR.GS.rp1 = CUR.GS.rp0;
+
+    if ( ( CUR.opcode & 16 ) != 0 )
+      CUR.GS.rp0 = point;
+
+    /* XXX: UNDOCUMENTED! */
+
+    CUR.GS.rp2 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ALIGNRP[]:    ALIGN Relative Point                                    */
+  /* Opcode range: 0x3C                                                    */
+  /* Stack:        uint32 uint32... -->                                    */
+  /*                                                                       */
+  static
+  void  Ins_ALIGNRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  distance;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.zp1.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+      {
+        distance = CUR_Func_project( CUR.zp1.cur + point,
+                                     CUR.zp0.cur + CUR.GS.rp0 );
+
+        CUR_Func_move( &CUR.zp1, point, -distance );
+      }
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ISECT[]:      moves point to InterSECTion                             */
+  /* Opcode range: 0x0F                                                    */
+  /* Stack:        5 * uint32 -->                                          */
+  /*                                                                       */
+  static
+  void  Ins_ISECT( INS_ARG )
+  {
+    FT_UShort   point,
+                a0, a1,
+                b0, b1;
+
+    FT_F26Dot6  discriminant;
+
+    FT_F26Dot6  dx,  dy,
+                dax, day,
+                dbx, dby;
+
+    FT_F26Dot6  val;
+
+    FT_Vector   R;
+
+
+    point = (FT_UShort)args[0];
+
+    a0 = (FT_UShort)args[1];
+    a1 = (FT_UShort)args[2];
+    b0 = (FT_UShort)args[3];
+    b1 = (FT_UShort)args[4];
+
+    if ( BOUNDS( b0, CUR.zp0.n_points )  ||
+         BOUNDS( b1, CUR.zp0.n_points )  ||
+         BOUNDS( a0, CUR.zp1.n_points )  ||
+         BOUNDS( a1, CUR.zp1.n_points )  ||
+         BOUNDS( point, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
+    dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
+
+    dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
+    day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
+
+    dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
+    dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
+
+    CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Both;
+
+    discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
+                   TT_MULDIV( day, dbx, 0x40 );
+
+    if ( ABS( discriminant ) >= 0x40 )
+    {
+      val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
+
+      R.x = TT_MULDIV( val, dax, discriminant );
+      R.y = TT_MULDIV( val, day, discriminant );
+
+      CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
+      CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
+    }
+    else
+    {
+      /* else, take the middle of the middles of A and B */
+
+      CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
+                               CUR.zp1.cur[a1].x +
+                               CUR.zp0.cur[b0].x +
+                               CUR.zp0.cur[b1].x ) / 4;
+      CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
+                               CUR.zp1.cur[a1].y +
+                               CUR.zp0.cur[b0].y +
+                               CUR.zp0.cur[b1].y ) / 4;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ALIGNPTS[]:   ALIGN PoinTS                                            */
+  /* Opcode range: 0x27                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static
+  void  Ins_ALIGNPTS( INS_ARG )
+  {
+    FT_UShort   p1, p2;
+    FT_F26Dot6  distance;
+
+
+    p1 = (FT_UShort)args[0];
+    p2 = (FT_UShort)args[1];
+
+    if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
+         BOUNDS( args[1], CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    distance = CUR_Func_project( CUR.zp0.cur + p2,
+                                 CUR.zp1.cur + p1 ) / 2;
+
+    CUR_Func_move( &CUR.zp1, p1, distance );
+    CUR_Func_move( &CUR.zp0, p2, -distance );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IP[]:         Interpolate Point                                       */
+  /* Opcode range: 0x39                                                    */
+  /* Stack:        uint32... -->                                           */
+  /*                                                                       */
+  static
+  void  Ins_IP( INS_ARG )
+  {
+    FT_F26Dot6  org_a, org_b, org_x,
+                cur_a, cur_b, cur_x,
+                distance;
+    FT_UShort   point;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: There are some glyphs in some braindead but popular  */
+    /*      fonts out there (e.g. [aeu]grave in monotype.ttf)    */
+    /*      calling IP[] with bad values of rp[12].              */
+    /*      Do something sane when this odd thing happens.       */
+
+    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
+         BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
+    {
+      org_a = cur_a = 0;
+      org_b = cur_b = 0;
+    }
+    else
+    {
+      org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector );
+      org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector );
+
+      cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector );
+      cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector );
+    }
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+      {
+        org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector );
+        cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector );
+
+        if ( ( org_a <= org_b && org_x <= org_a ) ||
+             ( org_a >  org_b && org_x >= org_a ) )
+
+          distance = ( cur_a - org_a ) + ( org_x - cur_x );
+
+        else if ( ( org_a <= org_b  &&  org_x >= org_b ) ||
+                  ( org_a >  org_b  &&  org_x <  org_b ) )
+
+          distance = ( cur_b - org_b ) + ( org_x - cur_x );
+
+        else
+           /* note: it seems that rounding this value isn't a good */
+           /*       idea (cf. width of capital `S' in Times)       */
+
+           distance = TT_MULDIV( cur_b - cur_a,
+                                 org_x - org_a,
+                                 org_b - org_a ) + ( cur_a - cur_x );
+
+        CUR_Func_move( &CUR.zp2, point, distance );
+      }
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* UTP[a]:       UnTouch Point                                           */
+  /* Opcode range: 0x29                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static
+  void  Ins_UTP( INS_ARG )
+  {
+    FT_UShort  point;
+    FT_Byte    mask;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    mask = 0xFF;
+
+    if ( CUR.GS.freeVector.x != 0 )
+      mask &= ~FT_Curve_Tag_Touch_X;
+
+    if ( CUR.GS.freeVector.y != 0 )
+      mask &= ~FT_Curve_Tag_Touch_Y;
+
+    CUR.zp0.tags[point] &= mask;
+  }
+
+
+  /* Local variables for Ins_IUP: */
+  struct  LOC_Ins_IUP
+  {
+    FT_Vector*  orgs;   /* original and current coordinate */
+    FT_Vector*  curs;   /* arrays                          */
+  };
+
+
+  static
+  void  Shift( FT_UInt              p1,
+               FT_UInt              p2,
+               FT_UInt              p,
+               struct LOC_Ins_IUP*  LINK )
+  {
+    FT_UInt     i;
+    FT_F26Dot6  x;
+
+
+    x = LINK->curs[p].x - LINK->orgs[p].x;
+
+    for ( i = p1; i < p; i++ )
+      LINK->curs[i].x += x;
+
+    for ( i = p + 1; i <= p2; i++ )
+      LINK->curs[i].x += x;
+  }
+
+
+  static
+  void  Interp( FT_UInt              p1,
+                FT_UInt              p2,
+                FT_UInt              ref1,
+                FT_UInt              ref2,
+                struct LOC_Ins_IUP*  LINK )
+  {
+    FT_UInt     i;
+    FT_F26Dot6  x, x1, x2, d1, d2;
+
+
+    if ( p1 > p2 )
+      return;
+
+    x1 = LINK->orgs[ref1].x;
+    d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x;
+    x2 = LINK->orgs[ref2].x;
+    d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x;
+
+    if ( x1 == x2 )
+    {
+      for ( i = p1; i <= p2; i++ )
+      {
+        x = LINK->orgs[i].x;
+
+        if ( x <= x1 )
+          x += d1;
+        else
+          x += d2;
+
+        LINK->curs[i].x = x;
+      }
+      return;
+    }
+
+    if ( x1 < x2 )
+    {
+      for ( i = p1; i <= p2; i++ )
+      {
+        x = LINK->orgs[i].x;
+
+        if ( x <= x1 )
+          x += d1;
+        else
+        {
+          if ( x >= x2 )
+            x += d2;
+          else
+            x = LINK->curs[ref1].x +
+                  TT_MULDIV( x - x1,
+                             LINK->curs[ref2].x - LINK->curs[ref1].x,
+                             x2 - x1 );
+        }
+        LINK->curs[i].x = x;
+      }
+      return;
+    }
+
+    /* x2 < x1 */
+
+    for ( i = p1; i <= p2; i++ )
+    {
+      x = LINK->orgs[i].x;
+      if ( x <= x2 )
+        x += d2;
+      else
+      {
+        if ( x >= x1 )
+          x += d1;
+        else
+          x = LINK->curs[ref1].x +
+              TT_MULDIV( x - x1,
+                         LINK->curs[ref2].x - LINK->curs[ref1].x,
+                         x2 - x1 );
+      }
+      LINK->curs[i].x = x;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IUP[a]:       Interpolate Untouched Points                            */
+  /* Opcode range: 0x30-0x31                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static
+  void  Ins_IUP( INS_ARG )
+  {
+    struct LOC_Ins_IUP  V;
+    FT_Byte             mask;
+
+    FT_UInt   first_point;   /* first point of contour        */
+    FT_UInt   end_point;     /* end point (last+1) of contour */
+
+    FT_UInt   first_touched; /* first touched point in contour   */
+    FT_UInt   cur_touched;   /* current touched point in contour */
+
+    FT_UInt   point;         /* current point   */
+    FT_Short  contour;       /* current contour */
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.opcode & 1 )
+    {
+      mask   = FT_Curve_Tag_Touch_X;
+      V.orgs = CUR.pts.org;
+      V.curs = CUR.pts.cur;
+    }
+    else
+    {
+      mask   = FT_Curve_Tag_Touch_Y;
+      V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
+      V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
+    }
+
+    contour = 0;
+    point   = 0;
+
+    do
+    {
+      end_point   = CUR.pts.contours[contour];
+      first_point = point;
+
+      while ( point <= end_point && (CUR.pts.tags[point] & mask) == 0 )
+        point++;
+
+      if ( point <= end_point )
+      {
+        first_touched = point;
+        cur_touched   = point;
+
+        point++;
+
+        while ( point <= end_point )
+        {
+          if ( ( CUR.pts.tags[point] & mask ) != 0 )
+          {
+            if ( point > 0 )
+              Interp( cur_touched + 1,
+                      point - 1,
+                      cur_touched,
+                      point,
+                      &V );
+            cur_touched = point;
+          }
+
+          point++;
+        }
+
+        if ( cur_touched == first_touched )
+          Shift( first_point, end_point, cur_touched, &V );
+        else
+        {
+          Interp( (FT_UShort)( cur_touched + 1 ),
+                  end_point,
+                  cur_touched,
+                  first_touched,
+                  &V );
+
+          if ( first_touched > 0 )
+            Interp( first_point,
+                    first_touched - 1,
+                    cur_touched,
+                    first_touched,
+                    &V );
+        }
+      }
+      contour++;
+    } while ( contour < CUR.pts.n_contours );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DELTAPn[]:    DELTA exceptions P1, P2, P3                             */
+  /* Opcode range: 0x5D,0x71,0x72                                          */
+  /* Stack:        uint32 (2 * uint32)... -->                              */
+  /*                                                                       */
+  static
+  void  Ins_DELTAP( INS_ARG )
+  {
+    FT_ULong   k, nump;
+    FT_UShort  A;
+    FT_ULong   C;
+    FT_Long    B;
+
+
+    nump = (FT_ULong)args[0];   /* some points theoretically may occur more
+                                   than once, thus UShort isn't enough */
+
+    for ( k = 1; k <= nump; k++ )
+    {
+      if ( CUR.args < 2 )
+      {
+        CUR.error = TT_Err_Too_Few_Arguments;
+        return;
+      }
+
+      CUR.args -= 2;
+
+      A = (FT_UShort)CUR.stack[CUR.args + 1];
+      B = CUR.stack[CUR.args];
+
+      /* XXX: Because some popular fonts contain some invalid DeltaP */
+      /*      instructions, we simply ignore them when the stacked   */
+      /*      point reference is off limit, rather than returning an */
+      /*      error.  As a delta instruction doesn't change a glyph  */
+      /*      in great ways, this shouldn't be a problem.            */
+
+      if ( !BOUNDS( A, CUR.zp0.n_points ) )
+      {
+        C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+        switch ( CUR.opcode )
+        {
+        case 0x5D:
+          break;
+
+        case 0x71:
+          C += 16;
+          break;
+
+        case 0x72:
+          C += 32;
+          break;
+        }
+
+        C += CUR.GS.delta_base;
+
+        if ( CURRENT_Ppem() == (FT_Long)C )
+        {
+          B = ( (FT_ULong)B & 0xF ) - 8;
+          if ( B >= 0 )
+            B++;
+          B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+          CUR_Func_move( &CUR.zp0, A, B );
+        }
+      }
+      else
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Invalid_Reference;
+    }
+
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DELTACn[]:    DELTA exceptions C1, C2, C3                             */
+  /* Opcode range: 0x73,0x74,0x75                                          */
+  /* Stack:        uint32 (2 * uint32)... -->                              */
+  /*                                                                       */
+  static
+  void  Ins_DELTAC( INS_ARG )
+  {
+    FT_ULong  nump, k;
+    FT_ULong  A, C;
+    FT_Long   B;
+
+
+    nump = (FT_ULong)args[0];
+
+    for ( k = 1; k <= nump; k++ )
+    {
+      if ( CUR.args < 2 )
+      {
+        CUR.error = TT_Err_Too_Few_Arguments;
+        return;
+      }
+
+      CUR.args -= 2;
+
+      A = (FT_ULong)CUR.stack[CUR.args + 1];
+      B = CUR.stack[CUR.args];
+
+      if ( BOUNDS( A, CUR.cvtSize ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+      {
+        C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+        switch ( CUR.opcode )
+        {
+        case 0x73:
+          break;
+
+        case 0x74:
+          C += 16;
+          break;
+
+        case 0x75:
+          C += 32;
+          break;
+        }
+
+        C += CUR.GS.delta_base;
+
+        if ( CURRENT_Ppem() == (FT_Long)C )
+        {
+          B = ( (FT_ULong)B & 0xF ) - 8;
+          if ( B >= 0 )
+            B++;
+          B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+          CUR_Func_move_cvt( A, B );
+        }
+      }
+    }
+
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MISC. INSTRUCTIONS                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GETINFO[]:    GET INFOrmation                                         */
+  /* Opcode range: 0x88                                                    */
+  /* Stack:        uint32 --> uint32                                       */
+  /*                                                                       */
+  /* XXX: According to Apple specs, bits 1 & 2 of the argument ought to be */
+  /*      consulted before rotated/stretched info is returned.             */
+  static
+  void  Ins_GETINFO( INS_ARG )
+  {
+    FT_Long  K;
+
+
+    K = 0;
+
+    /* We return then Windows 3.1 version number */
+    /* for the font scaler                       */
+    if ( ( args[0] & 1 ) != 0 )
+      K = 3;
+
+    /* Has the glyph been rotated ? */
+    if ( CUR.tt_metrics.rotated )
+      K |= 0x80;
+
+    /* Has the glyph been stretched ? */
+    if ( CUR.tt_metrics.stretched )
+      K |= 0x100;
+
+    args[0] = K;
+  }
+
+
+  static
+  void  Ins_UNKNOWN( INS_ARG )
+  {
+    TT_DefRecord*  def   = CUR.IDefs;
+    TT_DefRecord*  limit = def + CUR.numIDefs;
+
+    FT_UNUSED_ARG;
+
+
+    for ( ; def < limit; def++ )
+    {
+      if ( def->opc == CUR.opcode && def->active )
+      {
+        TT_CallRec*  call;
+
+
+        if ( CUR.callTop >= CUR.callSize )
+        {
+          CUR.error = TT_Err_Stack_Overflow;
+          return;
+        }
+
+        call = CUR.callStack + CUR.callTop++;
+
+        call->Caller_Range = CUR.curRange;
+        call->Caller_IP    = CUR.IP+1;
+        call->Cur_Count    = 1;
+        call->Cur_Restart  = def->start;
+
+        INS_Goto_CodeRange( def->range, def->start );
+
+        CUR.step_ins = FALSE;
+        return;
+      }
+    }
+
+    CUR.error = TT_Err_Invalid_Opcode;
+  }
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+  static
+  TInstruction_Function  Instruct_Dispatch[256] =
+  {
+    /* Opcodes are gathered in groups of 16. */
+    /* Please keep the spaces as they are.   */
+
+    /*  SVTCA  y  */  Ins_SVTCA,
+    /*  SVTCA  x  */  Ins_SVTCA,
+    /*  SPvTCA y  */  Ins_SPVTCA,
+    /*  SPvTCA x  */  Ins_SPVTCA,
+    /*  SFvTCA y  */  Ins_SFVTCA,
+    /*  SFvTCA x  */  Ins_SFVTCA,
+    /*  SPvTL //  */  Ins_SPVTL,
+    /*  SPvTL +   */  Ins_SPVTL,
+    /*  SFvTL //  */  Ins_SFVTL,
+    /*  SFvTL +   */  Ins_SFVTL,
+    /*  SPvFS     */  Ins_SPVFS,
+    /*  SFvFS     */  Ins_SFVFS,
+    /*  GPV       */  Ins_GPV,
+    /*  GFV       */  Ins_GFV,
+    /*  SFvTPv    */  Ins_SFVTPV,
+    /*  ISECT     */  Ins_ISECT,
+
+    /*  SRP0      */  Ins_SRP0,
+    /*  SRP1      */  Ins_SRP1,
+    /*  SRP2      */  Ins_SRP2,
+    /*  SZP0      */  Ins_SZP0,
+    /*  SZP1      */  Ins_SZP1,
+    /*  SZP2      */  Ins_SZP2,
+    /*  SZPS      */  Ins_SZPS,
+    /*  SLOOP     */  Ins_SLOOP,
+    /*  RTG       */  Ins_RTG,
+    /*  RTHG      */  Ins_RTHG,
+    /*  SMD       */  Ins_SMD,
+    /*  ELSE      */  Ins_ELSE,
+    /*  JMPR      */  Ins_JMPR,
+    /*  SCvTCi    */  Ins_SCVTCI,
+    /*  SSwCi     */  Ins_SSWCI,
+    /*  SSW       */  Ins_SSW,
+
+    /*  DUP       */  Ins_DUP,
+    /*  POP       */  Ins_POP,
+    /*  CLEAR     */  Ins_CLEAR,
+    /*  SWAP      */  Ins_SWAP,
+    /*  DEPTH     */  Ins_DEPTH,
+    /*  CINDEX    */  Ins_CINDEX,
+    /*  MINDEX    */  Ins_MINDEX,
+    /*  AlignPTS  */  Ins_ALIGNPTS,
+    /*  INS_0x28  */  Ins_UNKNOWN,
+    /*  UTP       */  Ins_UTP,
+    /*  LOOPCALL  */  Ins_LOOPCALL,
+    /*  CALL      */  Ins_CALL,
+    /*  FDEF      */  Ins_FDEF,
+    /*  ENDF      */  Ins_ENDF,
+    /*  MDAP[0]   */  Ins_MDAP,
+    /*  MDAP[1]   */  Ins_MDAP,
+
+    /*  IUP[0]    */  Ins_IUP,
+    /*  IUP[1]    */  Ins_IUP,
+    /*  SHP[0]    */  Ins_SHP,
+    /*  SHP[1]    */  Ins_SHP,
+    /*  SHC[0]    */  Ins_SHC,
+    /*  SHC[1]    */  Ins_SHC,
+    /*  SHZ[0]    */  Ins_SHZ,
+    /*  SHZ[1]    */  Ins_SHZ,
+    /*  SHPIX     */  Ins_SHPIX,
+    /*  IP        */  Ins_IP,
+    /*  MSIRP[0]  */  Ins_MSIRP,
+    /*  MSIRP[1]  */  Ins_MSIRP,
+    /*  AlignRP   */  Ins_ALIGNRP,
+    /*  RTDG      */  Ins_RTDG,
+    /*  MIAP[0]   */  Ins_MIAP,
+    /*  MIAP[1]   */  Ins_MIAP,
+
+    /*  NPushB    */  Ins_NPUSHB,
+    /*  NPushW    */  Ins_NPUSHW,
+    /*  WS        */  Ins_WS,
+    /*  RS        */  Ins_RS,
+    /*  WCvtP     */  Ins_WCVTP,
+    /*  RCvt      */  Ins_RCVT,
+    /*  GC[0]     */  Ins_GC,
+    /*  GC[1]     */  Ins_GC,
+    /*  SCFS      */  Ins_SCFS,
+    /*  MD[0]     */  Ins_MD,
+    /*  MD[1]     */  Ins_MD,
+    /*  MPPEM     */  Ins_MPPEM,
+    /*  MPS       */  Ins_MPS,
+    /*  FlipON    */  Ins_FLIPON,
+    /*  FlipOFF   */  Ins_FLIPOFF,
+    /*  DEBUG     */  Ins_DEBUG,
+
+    /*  LT        */  Ins_LT,
+    /*  LTEQ      */  Ins_LTEQ,
+    /*  GT        */  Ins_GT,
+    /*  GTEQ      */  Ins_GTEQ,
+    /*  EQ        */  Ins_EQ,
+    /*  NEQ       */  Ins_NEQ,
+    /*  ODD       */  Ins_ODD,
+    /*  EVEN      */  Ins_EVEN,
+    /*  IF        */  Ins_IF,
+    /*  EIF       */  Ins_EIF,
+    /*  AND       */  Ins_AND,
+    /*  OR        */  Ins_OR,
+    /*  NOT       */  Ins_NOT,
+    /*  DeltaP1   */  Ins_DELTAP,
+    /*  SDB       */  Ins_SDB,
+    /*  SDS       */  Ins_SDS,
+
+    /*  ADD       */  Ins_ADD,
+    /*  SUB       */  Ins_SUB,
+    /*  DIV       */  Ins_DIV,
+    /*  MUL       */  Ins_MUL,
+    /*  ABS       */  Ins_ABS,
+    /*  NEG       */  Ins_NEG,
+    /*  FLOOR     */  Ins_FLOOR,
+    /*  CEILING   */  Ins_CEILING,
+    /*  ROUND[0]  */  Ins_ROUND,
+    /*  ROUND[1]  */  Ins_ROUND,
+    /*  ROUND[2]  */  Ins_ROUND,
+    /*  ROUND[3]  */  Ins_ROUND,
+    /*  NROUND[0] */  Ins_NROUND,
+    /*  NROUND[1] */  Ins_NROUND,
+    /*  NROUND[2] */  Ins_NROUND,
+    /*  NROUND[3] */  Ins_NROUND,
+
+    /*  WCvtF     */  Ins_WCVTF,
+    /*  DeltaP2   */  Ins_DELTAP,
+    /*  DeltaP3   */  Ins_DELTAP,
+    /*  DeltaCn[0] */ Ins_DELTAC,
+    /*  DeltaCn[1] */ Ins_DELTAC,
+    /*  DeltaCn[2] */ Ins_DELTAC,
+    /*  SROUND    */  Ins_SROUND,
+    /*  S45Round  */  Ins_S45ROUND,
+    /*  JROT      */  Ins_JROT,
+    /*  JROF      */  Ins_JROF,
+    /*  ROFF      */  Ins_ROFF,
+    /*  INS_0x7B  */  Ins_UNKNOWN,
+    /*  RUTG      */  Ins_RUTG,
+    /*  RDTG      */  Ins_RDTG,
+    /*  SANGW     */  Ins_SANGW,
+    /*  AA        */  Ins_AA,
+
+    /*  FlipPT    */  Ins_FLIPPT,
+    /*  FlipRgON  */  Ins_FLIPRGON,
+    /*  FlipRgOFF */  Ins_FLIPRGOFF,
+    /*  INS_0x83  */  Ins_UNKNOWN,
+    /*  INS_0x84  */  Ins_UNKNOWN,
+    /*  ScanCTRL  */  Ins_SCANCTRL,
+    /*  SDPVTL[0] */  Ins_SDPVTL,
+    /*  SDPVTL[1] */  Ins_SDPVTL,
+    /*  GetINFO   */  Ins_GETINFO,
+    /*  IDEF      */  Ins_IDEF,
+    /*  ROLL      */  Ins_ROLL,
+    /*  MAX       */  Ins_MAX,
+    /*  MIN       */  Ins_MIN,
+    /*  ScanTYPE  */  Ins_SCANTYPE,
+    /*  InstCTRL  */  Ins_INSTCTRL,
+    /*  INS_0x8F  */  Ins_UNKNOWN,
+
+    /*  INS_0x90  */   Ins_UNKNOWN,
+    /*  INS_0x91  */   Ins_UNKNOWN,
+    /*  INS_0x92  */   Ins_UNKNOWN,
+    /*  INS_0x93  */   Ins_UNKNOWN,
+    /*  INS_0x94  */   Ins_UNKNOWN,
+    /*  INS_0x95  */   Ins_UNKNOWN,
+    /*  INS_0x96  */   Ins_UNKNOWN,
+    /*  INS_0x97  */   Ins_UNKNOWN,
+    /*  INS_0x98  */   Ins_UNKNOWN,
+    /*  INS_0x99  */   Ins_UNKNOWN,
+    /*  INS_0x9A  */   Ins_UNKNOWN,
+    /*  INS_0x9B  */   Ins_UNKNOWN,
+    /*  INS_0x9C  */   Ins_UNKNOWN,
+    /*  INS_0x9D  */   Ins_UNKNOWN,
+    /*  INS_0x9E  */   Ins_UNKNOWN,
+    /*  INS_0x9F  */   Ins_UNKNOWN,
+
+    /*  INS_0xA0  */   Ins_UNKNOWN,
+    /*  INS_0xA1  */   Ins_UNKNOWN,
+    /*  INS_0xA2  */   Ins_UNKNOWN,
+    /*  INS_0xA3  */   Ins_UNKNOWN,
+    /*  INS_0xA4  */   Ins_UNKNOWN,
+    /*  INS_0xA5  */   Ins_UNKNOWN,
+    /*  INS_0xA6  */   Ins_UNKNOWN,
+    /*  INS_0xA7  */   Ins_UNKNOWN,
+    /*  INS_0xA8  */   Ins_UNKNOWN,
+    /*  INS_0xA9  */   Ins_UNKNOWN,
+    /*  INS_0xAA  */   Ins_UNKNOWN,
+    /*  INS_0xAB  */   Ins_UNKNOWN,
+    /*  INS_0xAC  */   Ins_UNKNOWN,
+    /*  INS_0xAD  */   Ins_UNKNOWN,
+    /*  INS_0xAE  */   Ins_UNKNOWN,
+    /*  INS_0xAF  */   Ins_UNKNOWN,
+
+    /*  PushB[0]  */  Ins_PUSHB,
+    /*  PushB[1]  */  Ins_PUSHB,
+    /*  PushB[2]  */  Ins_PUSHB,
+    /*  PushB[3]  */  Ins_PUSHB,
+    /*  PushB[4]  */  Ins_PUSHB,
+    /*  PushB[5]  */  Ins_PUSHB,
+    /*  PushB[6]  */  Ins_PUSHB,
+    /*  PushB[7]  */  Ins_PUSHB,
+    /*  PushW[0]  */  Ins_PUSHW,
+    /*  PushW[1]  */  Ins_PUSHW,
+    /*  PushW[2]  */  Ins_PUSHW,
+    /*  PushW[3]  */  Ins_PUSHW,
+    /*  PushW[4]  */  Ins_PUSHW,
+    /*  PushW[5]  */  Ins_PUSHW,
+    /*  PushW[6]  */  Ins_PUSHW,
+    /*  PushW[7]  */  Ins_PUSHW,
+
+    /*  MDRP[00]  */  Ins_MDRP,
+    /*  MDRP[01]  */  Ins_MDRP,
+    /*  MDRP[02]  */  Ins_MDRP,
+    /*  MDRP[03]  */  Ins_MDRP,
+    /*  MDRP[04]  */  Ins_MDRP,
+    /*  MDRP[05]  */  Ins_MDRP,
+    /*  MDRP[06]  */  Ins_MDRP,
+    /*  MDRP[07]  */  Ins_MDRP,
+    /*  MDRP[08]  */  Ins_MDRP,
+    /*  MDRP[09]  */  Ins_MDRP,
+    /*  MDRP[10]  */  Ins_MDRP,
+    /*  MDRP[11]  */  Ins_MDRP,
+    /*  MDRP[12]  */  Ins_MDRP,
+    /*  MDRP[13]  */  Ins_MDRP,
+    /*  MDRP[14]  */  Ins_MDRP,
+    /*  MDRP[15]  */  Ins_MDRP,
+
+    /*  MDRP[16]  */  Ins_MDRP,
+    /*  MDRP[17]  */  Ins_MDRP,
+    /*  MDRP[18]  */  Ins_MDRP,
+    /*  MDRP[19]  */  Ins_MDRP,
+    /*  MDRP[20]  */  Ins_MDRP,
+    /*  MDRP[21]  */  Ins_MDRP,
+    /*  MDRP[22]  */  Ins_MDRP,
+    /*  MDRP[23]  */  Ins_MDRP,
+    /*  MDRP[24]  */  Ins_MDRP,
+    /*  MDRP[25]  */  Ins_MDRP,
+    /*  MDRP[26]  */  Ins_MDRP,
+    /*  MDRP[27]  */  Ins_MDRP,
+    /*  MDRP[28]  */  Ins_MDRP,
+    /*  MDRP[29]  */  Ins_MDRP,
+    /*  MDRP[30]  */  Ins_MDRP,
+    /*  MDRP[31]  */  Ins_MDRP,
+
+    /*  MIRP[00]  */  Ins_MIRP,
+    /*  MIRP[01]  */  Ins_MIRP,
+    /*  MIRP[02]  */  Ins_MIRP,
+    /*  MIRP[03]  */  Ins_MIRP,
+    /*  MIRP[04]  */  Ins_MIRP,
+    /*  MIRP[05]  */  Ins_MIRP,
+    /*  MIRP[06]  */  Ins_MIRP,
+    /*  MIRP[07]  */  Ins_MIRP,
+    /*  MIRP[08]  */  Ins_MIRP,
+    /*  MIRP[09]  */  Ins_MIRP,
+    /*  MIRP[10]  */  Ins_MIRP,
+    /*  MIRP[11]  */  Ins_MIRP,
+    /*  MIRP[12]  */  Ins_MIRP,
+    /*  MIRP[13]  */  Ins_MIRP,
+    /*  MIRP[14]  */  Ins_MIRP,
+    /*  MIRP[15]  */  Ins_MIRP,
+
+    /*  MIRP[16]  */  Ins_MIRP,
+    /*  MIRP[17]  */  Ins_MIRP,
+    /*  MIRP[18]  */  Ins_MIRP,
+    /*  MIRP[19]  */  Ins_MIRP,
+    /*  MIRP[20]  */  Ins_MIRP,
+    /*  MIRP[21]  */  Ins_MIRP,
+    /*  MIRP[22]  */  Ins_MIRP,
+    /*  MIRP[23]  */  Ins_MIRP,
+    /*  MIRP[24]  */  Ins_MIRP,
+    /*  MIRP[25]  */  Ins_MIRP,
+    /*  MIRP[26]  */  Ins_MIRP,
+    /*  MIRP[27]  */  Ins_MIRP,
+    /*  MIRP[28]  */  Ins_MIRP,
+    /*  MIRP[29]  */  Ins_MIRP,
+    /*  MIRP[30]  */  Ins_MIRP,
+    /*  MIRP[31]  */  Ins_MIRP
+  };
+
+
+#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RUN                                                                   */
+  /*                                                                       */
+  /*  This function executes a run of opcodes.  It will exit in the        */
+  /*  following cases:                                                     */
+  /*                                                                       */
+  /*  - Errors (in which case it returns FALSE).                           */
+  /*                                                                       */
+  /*  - Reaching the end of the main code range (returns TRUE).            */
+  /*    Reaching the end of a code range within a function call is an      */
+  /*    error.                                                             */
+  /*                                                                       */
+  /*  - After executing one single opcode, if the flag `Instruction_Trap'  */
+  /*    is set to TRUE (returns TRUE).                                     */
+  /*                                                                       */
+  /*  On exit whith TRUE, test IP < CodeSize to know wether it comes from  */
+  /*  an instruction trap or a normal termination.                         */
+  /*                                                                       */
+  /*                                                                       */
+  /*  Note: The documented DEBUG opcode pops a value from the stack.  This */
+  /*        behaviour is unsupported; here a DEBUG opcode is always an     */
+  /*        error.                                                         */
+  /*                                                                       */
+  /*                                                                       */
+  /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */
+  /*                                                                       */
+  /*  Instructions appear in the specification's order.                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_RunIns                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Executes one or more instruction in the execution context.  This   */
+  /*    is the main function of the TrueType opcode interpreter.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec :: A handle to the target execution context.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the object manager and debugger should call this function.    */
+  /*                                                                       */
+  /*    This function is publicly exported because it is directly          */
+  /*    invoked by the TrueType debugger.                                  */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  TT_RunIns( TT_ExecContext  exc )
+  {
+    FT_Long  ins_counter = 0;  /* executed instructions counter */
+
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+    cur = *exc;
+#endif
+
+    /* set CVT functions */
+    CUR.tt_metrics.ratio = 0;
+    if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
+    {
+      /* non-square pixels, use the stretched routines */
+      CUR.func_read_cvt  = Read_CVT_Stretched;
+      CUR.func_write_cvt = Write_CVT_Stretched;
+      CUR.func_move_cvt  = Move_CVT_Stretched;
+    }
+    else
+    {
+      /* square pixels, use normal routines */
+      CUR.func_read_cvt  = Read_CVT;
+      CUR.func_write_cvt = Write_CVT;
+      CUR.func_move_cvt  = Move_CVT;
+    }
+
+    COMPUTE_Funcs();
+    COMPUTE_Round( (FT_Byte)exc->GS.round_state );
+
+    do
+    {
+      CUR.opcode = CUR.code[CUR.IP];
+
+      if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
+      {
+        if ( CUR.IP + 1 > CUR.codeSize )
+          goto LErrorCodeOverflow_;
+
+        CUR.length = CUR.code[CUR.IP + 1] + 2;
+      }
+
+      if ( CUR.IP + CUR.length > CUR.codeSize )
+        goto LErrorCodeOverflow_;
+
+      /* First, let's check for empty stack and overflow */
+      CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
+
+      /* `args' is the top of the stack once arguments have been popped. */
+      /* One can also interpret it as the index of the last argument.    */
+      if ( CUR.args < 0 )
+      {
+        CUR.error = TT_Err_Too_Few_Arguments;
+        goto LErrorLabel_;
+      }
+
+      CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
+
+      /* `new_top' is the new top of the stack, after the instruction's */
+      /* execution.  `top' will be set to `new_top' after the `switch'  */
+      /* statement.                                                     */
+      if ( CUR.new_top > CUR.stackSize )
+      {
+        CUR.error = TT_Err_Stack_Overflow;
+        goto LErrorLabel_;
+      }
+
+      CUR.step_ins = TRUE;
+      CUR.error    = TT_Err_Ok;
+
+#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+      {
+        FT_Long*  args   = CUR.stack + CUR.args;
+        FT_Byte   opcode = CUR.opcode;
+
+
+#undef   ARRAY_BOUND_ERROR
+#define  ARRAY_BOUND_ERROR  goto Set_Invalid_Ref
+
+
+        switch ( opcode )
+        {
+        case 0x00:  /* SVTCA y  */
+        case 0x01:  /* SVTCA x  */
+        case 0x02:  /* SPvTCA y */
+        case 0x03:  /* SPvTCA x */
+        case 0x04:  /* SFvTCA y */
+        case 0x05:  /* SFvTCA x */
+          {
+            FT_Short AA, BB;
+
+
+            AA = (FT_Short)( opcode & 1 ) << 14;
+            BB = AA ^ (FT_Short)0x4000;
+
+            if ( opcode < 4 )
+            {
+              CUR.GS.projVector.x = AA;
+              CUR.GS.projVector.y = BB;
+
+              CUR.GS.dualVector.x = AA;
+              CUR.GS.dualVector.y = BB;
+            }
+
+            if ( ( opcode & 2 ) == 0 )
+            {
+              CUR.GS.freeVector.x = AA;
+              CUR.GS.freeVector.y = BB;
+            }
+
+            COMPUTE_Funcs();
+          }
+          break;
+
+        case 0x06:  /* SPvTL // */
+        case 0x07:  /* SPvTL +  */
+          DO_SPVTL
+          break;
+
+        case 0x08:  /* SFvTL // */
+        case 0x09:  /* SFvTL +  */
+          DO_SFVTL
+          break;
+
+        case 0x0A:  /* SPvFS */
+          DO_SPVFS
+          break;
+
+        case 0x0B:  /* SFvFS */
+          DO_SFVFS
+          break;
+
+        case 0x0C:  /* GPV */
+          DO_GPV
+          break;
+
+        case 0x0D:  /* GFV */
+          DO_GFV
+          break;
+
+        case 0x0E:  /* SFvTPv */
+          DO_SFVTPV
+          break;
+
+        case 0x0F:  /* ISECT  */
+          Ins_ISECT( EXEC_ARG_ args );
+          break;
+
+        case 0x10:  /* SRP0 */
+          DO_SRP0
+          break;
+
+        case 0x11:  /* SRP1 */
+          DO_SRP1
+          break;
+
+        case 0x12:  /* SRP2 */
+          DO_SRP2
+          break;
+
+        case 0x13:  /* SZP0 */
+          Ins_SZP0( EXEC_ARG_ args );
+          break;
+
+        case 0x14:  /* SZP1 */
+          Ins_SZP1( EXEC_ARG_ args );
+          break;
+
+        case 0x15:  /* SZP2 */
+          Ins_SZP2( EXEC_ARG_ args );
+          break;
+
+        case 0x16:  /* SZPS */
+          Ins_SZPS( EXEC_ARG_ args );
+          break;
+
+        case 0x17:  /* SLOOP */
+          DO_SLOOP
+          break;
+
+        case 0x18:  /* RTG */
+          DO_RTG
+          break;
+
+        case 0x19:  /* RTHG */
+          DO_RTHG
+          break;
+
+        case 0x1A:  /* SMD */
+          DO_SMD
+          break;
+
+        case 0x1B:  /* ELSE */
+          Ins_ELSE( EXEC_ARG_ args );
+          break;
+
+        case 0x1C:  /* JMPR */
+          DO_JMPR
+          break;
+
+        case 0x1D:  /* SCVTCI */
+          DO_SCVTCI
+          break;
+
+        case 0x1E:  /* SSWCI */
+          DO_SSWCI
+          break;
+
+        case 0x1F:  /* SSW */
+          DO_SSW
+          break;
+
+        case 0x20:  /* DUP */
+          DO_DUP
+          break;
+
+        case 0x21:  /* POP */
+          /* nothing :-) */
+          break;
+
+        case 0x22:  /* CLEAR */
+          DO_CLEAR
+          break;
+
+        case 0x23:  /* SWAP */
+          DO_SWAP
+          break;
+
+        case 0x24:  /* DEPTH */
+          DO_DEPTH
+          break;
+
+        case 0x25:  /* CINDEX */
+          DO_CINDEX
+          break;
+
+        case 0x26:  /* MINDEX */
+          Ins_MINDEX( EXEC_ARG_ args );
+          break;
+
+        case 0x27:  /* ALIGNPTS */
+          Ins_ALIGNPTS( EXEC_ARG_ args );
+          break;
+
+        case 0x28:  /* ???? */
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        case 0x29:  /* UTP */
+          Ins_UTP( EXEC_ARG_ args );
+          break;
+
+        case 0x2A:  /* LOOPCALL */
+          Ins_LOOPCALL( EXEC_ARG_ args );
+          break;
+
+        case 0x2B:  /* CALL */
+          Ins_CALL( EXEC_ARG_ args );
+          break;
+
+        case 0x2C:  /* FDEF */
+          Ins_FDEF( EXEC_ARG_ args );
+          break;
+
+        case 0x2D:  /* ENDF */
+          Ins_ENDF( EXEC_ARG_ args );
+          break;
+
+        case 0x2E:  /* MDAP */
+        case 0x2F:  /* MDAP */
+          Ins_MDAP( EXEC_ARG_ args );
+          break;
+
+
+        case 0x30:  /* IUP */
+        case 0x31:  /* IUP */
+          Ins_IUP( EXEC_ARG_ args );
+          break;
+
+        case 0x32:  /* SHP */
+        case 0x33:  /* SHP */
+          Ins_SHP( EXEC_ARG_ args );
+          break;
+
+        case 0x34:  /* SHC */
+        case 0x35:  /* SHC */
+          Ins_SHC( EXEC_ARG_ args );
+          break;
+
+        case 0x36:  /* SHZ */
+        case 0x37:  /* SHZ */
+          Ins_SHZ( EXEC_ARG_ args );
+          break;
+
+        case 0x38:  /* SHPIX */
+          Ins_SHPIX( EXEC_ARG_ args );
+          break;
+
+        case 0x39:  /* IP    */
+          Ins_IP( EXEC_ARG_ args );
+          break;
+
+        case 0x3A:  /* MSIRP */
+        case 0x3B:  /* MSIRP */
+          Ins_MSIRP( EXEC_ARG_ args );
+          break;
+
+        case 0x3C:  /* AlignRP */
+          Ins_ALIGNRP( EXEC_ARG_ args );
+          break;
+
+        case 0x3D:  /* RTDG */
+          DO_RTDG
+          break;
+
+        case 0x3E:  /* MIAP */
+        case 0x3F:  /* MIAP */
+          Ins_MIAP( EXEC_ARG_ args );
+          break;
+
+        case 0x40:  /* NPUSHB */
+          Ins_NPUSHB( EXEC_ARG_ args );
+          break;
+
+        case 0x41:  /* NPUSHW */
+          Ins_NPUSHW( EXEC_ARG_ args );
+          break;
+
+        case 0x42:  /* WS */
+          DO_WS
+          break;
+
+      Set_Invalid_Ref:
+            CUR.error = TT_Err_Invalid_Reference;
+          break;
+
+        case 0x43:  /* RS */
+          DO_RS
+          break;
+
+        case 0x44:  /* WCVTP */
+          DO_WCVTP
+          break;
+
+        case 0x45:  /* RCVT */
+          DO_RCVT
+          break;
+
+        case 0x46:  /* GC */
+        case 0x47:  /* GC */
+          Ins_GC( EXEC_ARG_ args );
+          break;
+
+        case 0x48:  /* SCFS */
+          Ins_SCFS( EXEC_ARG_ args );
+          break;
+
+        case 0x49:  /* MD */
+        case 0x4A:  /* MD */
+          Ins_MD( EXEC_ARG_ args );
+          break;
+
+        case 0x4B:  /* MPPEM */
+          DO_MPPEM
+          break;
+
+        case 0x4C:  /* MPS */
+          DO_MPS
+          break;
+
+        case 0x4D:  /* FLIPON */
+          DO_FLIPON
+          break;
+
+        case 0x4E:  /* FLIPOFF */
+          DO_FLIPOFF
+          break;
+
+        case 0x4F:  /* DEBUG */
+          DO_DEBUG
+          break;
+
+        case 0x50:  /* LT */
+          DO_LT
+          break;
+
+        case 0x51:  /* LTEQ */
+          DO_LTEQ
+          break;
+
+        case 0x52:  /* GT */
+          DO_GT
+          break;
+
+        case 0x53:  /* GTEQ */
+          DO_GTEQ
+          break;
+
+        case 0x54:  /* EQ */
+          DO_EQ
+          break;
+
+        case 0x55:  /* NEQ */
+          DO_NEQ
+          break;
+
+        case 0x56:  /* ODD */
+          DO_ODD
+          break;
+
+        case 0x57:  /* EVEN */
+          DO_EVEN
+          break;
+
+        case 0x58:  /* IF */
+          Ins_IF( EXEC_ARG_ args );
+          break;
+
+        case 0x59:  /* EIF */
+          /* do nothing */
+          break;
+
+        case 0x5A:  /* AND */
+          DO_AND
+          break;
+
+        case 0x5B:  /* OR */
+          DO_OR
+          break;
+
+        case 0x5C:  /* NOT */
+          DO_NOT
+          break;
+
+        case 0x5D:  /* DELTAP1 */
+          Ins_DELTAP( EXEC_ARG_ args );
+          break;
+
+        case 0x5E:  /* SDB */
+          DO_SDB
+          break;
+
+        case 0x5F:  /* SDS */
+          DO_SDS
+          break;
+
+        case 0x60:  /* ADD */
+          DO_ADD
+          break;
+
+        case 0x61:  /* SUB */
+          DO_SUB
+          break;
+
+        case 0x62:  /* DIV */
+          DO_DIV
+          break;
+
+        case 0x63:  /* MUL */
+          DO_MUL
+          break;
+
+        case 0x64:  /* ABS */
+          DO_ABS
+          break;
+
+        case 0x65:  /* NEG */
+          DO_NEG
+          break;
+
+        case 0x66:  /* FLOOR */
+          DO_FLOOR
+          break;
+
+        case 0x67:  /* CEILING */
+          DO_CEILING
+          break;
+
+        case 0x68:  /* ROUND */
+        case 0x69:  /* ROUND */
+        case 0x6A:  /* ROUND */
+        case 0x6B:  /* ROUND */
+          DO_ROUND
+          break;
+
+        case 0x6C:  /* NROUND */
+        case 0x6D:  /* NROUND */
+        case 0x6E:  /* NRRUND */
+        case 0x6F:  /* NROUND */
+          DO_NROUND
+          break;
+
+        case 0x70:  /* WCVTF */
+          DO_WCVTF
+          break;
+
+        case 0x71:  /* DELTAP2 */
+        case 0x72:  /* DELTAP3 */
+          Ins_DELTAP( EXEC_ARG_ args );
+          break;
+
+        case 0x73:  /* DELTAC0 */
+        case 0x74:  /* DELTAC1 */
+        case 0x75:  /* DELTAC2 */
+          Ins_DELTAC( EXEC_ARG_ args );
+          break;
+
+        case 0x76:  /* SROUND */
+          DO_SROUND
+          break;
+
+        case 0x77:  /* S45Round */
+          DO_S45ROUND
+          break;
+
+        case 0x78:  /* JROT */
+          DO_JROT
+          break;
+
+        case 0x79:  /* JROF */
+          DO_JROF
+          break;
+
+        case 0x7A:  /* ROFF */
+          DO_ROFF
+          break;
+
+        case 0x7B:  /* ???? */
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        case 0x7C:  /* RUTG */
+          DO_RUTG
+          break;
+
+        case 0x7D:  /* RDTG */
+          DO_RDTG
+          break;
+
+        case 0x7E:  /* SANGW */
+        case 0x7F:  /* AA    */
+          /* nothing - obsolete */
+          break;
+
+        case 0x80:  /* FLIPPT */
+          Ins_FLIPPT( EXEC_ARG_ args );
+          break;
+
+        case 0x81:  /* FLIPRGON */
+          Ins_FLIPRGON( EXEC_ARG_ args );
+          break;
+
+        case 0x82:  /* FLIPRGOFF */
+          Ins_FLIPRGOFF( EXEC_ARG_ args );
+          break;
+
+        case 0x83:  /* UNKNOWN */
+        case 0x84:  /* UNKNOWN */
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        case 0x85:  /* SCANCTRL */
+          Ins_SCANCTRL( EXEC_ARG_ args );
+          break;
+
+        case 0x86:  /* SDPVTL */
+        case 0x87:  /* SDPVTL */
+          Ins_SDPVTL( EXEC_ARG_ args );
+          break;
+
+        case 0x88:  /* GETINFO */
+          Ins_GETINFO( EXEC_ARG_ args );
+          break;
+
+        case 0x89:  /* IDEF */
+          Ins_IDEF( EXEC_ARG_ args );
+          break;
+
+        case 0x8A:  /* ROLL */
+          Ins_ROLL( EXEC_ARG_ args );
+          break;
+
+        case 0x8B:  /* MAX */
+          DO_MAX
+          break;
+
+        case 0x8C:  /* MIN */
+          DO_MIN
+          break;
+
+        case 0x8D:  /* SCANTYPE */
+          Ins_SCANTYPE( EXEC_ARG_ args );
+          break;
+
+        case 0x8E:  /* INSTCTRL */
+          Ins_INSTCTRL( EXEC_ARG_ args );
+          break;
+
+        case 0x8F:
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        default:
+          if ( opcode >= 0xE0 )
+            Ins_MIRP( EXEC_ARG_ args );
+          else if ( opcode >= 0xC0 )
+            Ins_MDRP( EXEC_ARG_ args );
+          else if ( opcode >= 0xB8 )
+            Ins_PUSHW( EXEC_ARG_ args );
+          else if ( opcode >= 0xB0 )
+            Ins_PUSHB( EXEC_ARG_ args );
+          else
+            Ins_UNKNOWN( EXEC_ARG_ args );
+        }
+
+      }
+
+#else
+
+      Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
+
+#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+      if ( CUR.error != TT_Err_Ok )
+      {
+        switch ( CUR.error )
+        {
+        case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
+          {
+            TT_DefRecord*  def   = CUR.IDefs;
+            TT_DefRecord*  limit = def + CUR.numIDefs;
+
+
+            for ( ; def < limit; def++ )
+            {
+              if ( def->active && CUR.opcode == def->opc )
+              {
+                TT_CallRec*  callrec;
+
+
+                if ( CUR.callTop >= CUR.callSize )
+                {
+                  CUR.error = TT_Err_Invalid_Reference;
+                  goto LErrorLabel_;
+                }
+
+                callrec = &CUR.callStack[CUR.callTop];
+
+                callrec->Caller_Range = CUR.curRange;
+                callrec->Caller_IP    = CUR.IP + 1;
+                callrec->Cur_Count    = 1;
+                callrec->Cur_Restart  = def->start;
+
+                if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
+                  goto LErrorLabel_;
+
+                goto LSuiteLabel_;
+              }
+            }
+          }
+
+          CUR.error = TT_Err_Invalid_Opcode;
+          goto LErrorLabel_;
+
+#if 0
+          break;   /* Unreachable code warning suppression.             */
+                   /* Leave to remind in case a later change the editor */
+                   /* to consider break;                                */
+#endif
+
+        default:
+          goto LErrorLabel_;
+
+#if 0
+        break;
+#endif
+        }
+      }
+
+      CUR.top = CUR.new_top;
+
+      if ( CUR.step_ins )
+        CUR.IP += CUR.length;
+
+      /* increment instruction counter and check if we didn't */
+      /* run this program for too long (e.g. infinite loops). */
+      if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
+        return TT_Err_Execution_Too_Long;
+
+    LSuiteLabel_:
+      if ( CUR.IP >= CUR.codeSize )
+      {
+        if ( CUR.callTop > 0 )
+        {
+          CUR.error = TT_Err_Code_Overflow;
+          goto LErrorLabel_;
+        }
+        else
+          goto LNo_Error_;
+      }
+    } while ( !CUR.instruction_trap );
+
+  LNo_Error_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+    *exc = cur;
+#endif
+
+    return TT_Err_Ok;
+
+  LErrorCodeOverflow_:
+    CUR.error = TT_Err_Code_Overflow;
+
+  LErrorLabel_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+    *exc = cur;
+#endif
+
+    return CUR.error;
+  }
+
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+
+/* END */
diff --git a/src/freetype/truetype/ttinterp.h b/src/freetype/truetype/ttinterp.h
new file mode 100644 (file)
index 0000000..6e92699
--- /dev/null
@@ -0,0 +1,278 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttinterp.h                                                             */
+/*                                                                         */
+/*    TrueType bytecode interpreter (specification).                       */
+/*                                                                         */
+/*  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 TTINTERP_H
+#define TTINTERP_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttobjs.h"
+
+#else
+
+#include <truetype/ttobjs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTEPRETER  /* indirect implementation */
+
+#define EXEC_OP_   TT_ExecContext  exc,
+#define EXEC_OP    TT_ExecContext  exc
+#define EXEC_ARG_  exc,
+#define EXEC_ARG   exc
+
+#else                                       /* static implementation */
+
+#define EXEC_OP_   /* void */
+#define EXEC_OP    /* void */
+#define EXEC_ARG_  /* void */
+#define EXEC_ARG   /* void */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Rounding mode constants.                                              */
+  /*                                                                       */
+#define TT_Round_Off             5
+#define TT_Round_To_Half_Grid    0
+#define TT_Round_To_Grid         1
+#define TT_Round_To_Double_Grid  2
+#define TT_Round_Up_To_Grid      4
+#define TT_Round_Down_To_Grid    3
+#define TT_Round_Super           6
+#define TT_Round_Super_45        7
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Function types used by the interpreter, depending on various modes    */
+  /* (e.g. the rounding mode, whether to render a vertical or horizontal   */
+  /* line etc).                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /* Rounding function */
+  typedef FT_F26Dot6  (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6  distance,
+                                                 FT_F26Dot6  compensation );
+
+  /* Point displacement along the freedom vector routine */
+  typedef void  (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone*  zone,
+                                          FT_UInt        point,
+                                          FT_F26Dot6     distance );
+
+  /* Distance projection along one of the projection vectors */
+  typedef FT_F26Dot6  (*TT_Project_Func)( EXEC_OP_ FT_Vector*  v1,
+                                                   FT_Vector*  v2 );
+
+  /* reading a cvt value.  Take care of non-square pixels if necessary */
+  typedef FT_F26Dot6  (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong  index );
+
+  /* setting or moving a cvt value.  Take care of non-square pixels  */
+  /* if necessary                                                    */
+  typedef void  (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong    index,
+                                             FT_F26Dot6  value );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This structure defines a call record, used to manage function calls.  */
+  /*                                                                       */
+  typedef struct  TT_CallRec_
+  {
+    FT_Int   Caller_Range;
+    FT_Long  Caller_IP;
+    FT_Long  Cur_Count;
+    FT_Long  Cur_Restart;
+
+  } TT_CallRec, *TT_CallStack;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The main structure for the interpreter which collects all necessary   */
+  /* variables and states.                                                 */
+  /*                                                                       */
+  typedef struct  TT_ExecContextRec_
+  {
+    TT_Face         face;
+    TT_Size         size;
+    FT_Memory       memory;
+
+    /* instructions state */
+
+    FT_Error        error;      /* last execution error */
+
+    FT_Long         top;        /* top of exec. stack   */
+
+    FT_UInt         stackSize;  /* size of exec. stack  */
+    FT_Long*        stack;      /* current exec. stack  */
+
+    FT_Long         args;
+    FT_UInt         new_top;    /* new top after exec.  */
+
+    TT_GlyphZone    zp0,        /* zone records */
+                    zp1,
+                    zp2,
+                    pts,
+                    twilight;
+
+    FT_Size_Metrics  metrics;
+    TT_Size_Metrics  tt_metrics; /* size metrics */
+
+    TT_GraphicsState  GS;         /* current graphics state */
+
+    FT_Int          curRange;  /* current code range number   */
+    FT_Byte*        code;      /* current code range          */
+    FT_Long         IP;        /* current instruction pointer */
+    FT_Long         codeSize;  /* size of current range       */
+
+    FT_Byte         opcode;    /* current opcode              */
+    FT_Int          length;    /* length of current opcode    */
+
+    FT_Bool         step_ins;  /* true if the interpreter must */
+                               /* increment IP after ins. exec */
+    FT_Long         cvtSize;
+    FT_Long*        cvt;
+
+    FT_UInt         glyphSize; /* glyph instructions buffer size */
+    FT_Byte*        glyphIns;  /* glyph instructions buffer */
+
+    FT_UInt         numFDefs;  /* number of function defs         */
+    FT_UInt         maxFDefs;  /* maximum number of function defs */
+    TT_DefArray     FDefs;     /* table of FDefs entries          */
+
+    FT_UInt         numIDefs;  /* number of instruction defs */
+    FT_UInt         maxIDefs;  /* maximum number of ins defs */
+    TT_DefArray     IDefs;     /* table of IDefs entries     */
+
+    FT_UInt         maxFunc;   /* maximum function index     */
+    FT_UInt         maxIns;    /* maximum instruction index  */
+
+    FT_Int          callTop,    /* top of call stack during execution */
+                    callSize;   /* size of call stack */
+    TT_CallStack    callStack;  /* call stack */
+
+    FT_UShort       maxPoints;    /* capacity of this context's `pts' */
+    FT_Short        maxContours;  /* record, expressed in points and  */
+                                  /* contours.                        */
+
+    TT_CodeRangeTable  codeRangeTable;  /* table of valid code ranges */
+                                        /* useful for the debugger   */
+
+    FT_UShort       storeSize;  /* size of current storage */
+    FT_Long*        storage;    /* storage area            */
+
+    FT_F26Dot6      period;     /* values used for the */
+    FT_F26Dot6      phase;      /* `SuperRounding'     */
+    FT_F26Dot6      threshold;
+
+#if 0
+    /* this seems to be unused */
+    FT_Int          cur_ppem;       /* ppem along the current proj vector */
+#endif
+
+    FT_Bool         instruction_trap;  /* If `True', the interpreter will */
+                                       /* exit after each instruction     */
+
+    TT_GraphicsState  default_GS;      /* graphics state resulting from    */
+                                       /* the prep program                 */
+    FT_Bool          is_composite;     /* true if the glyph is composite   */
+    FT_Bool          pedantic_hinting; /* true for pedantic interpretation */
+
+    /* latest interpreter additions */
+
+    FT_Long            F_dot_P;    /* dot product of freedom and projection */
+                                   /* vectors                               */
+    TT_Round_Func      func_round; /* current rounding function             */
+
+    TT_Project_Func    func_project,   /* current projection function */
+                       func_dualproj,  /* current dual proj. function */
+                       func_freeProj;  /* current freedom proj. func  */
+
+    TT_Move_Func       func_move;      /* current point move function */
+
+    TT_Get_CVT_Func    func_read_cvt;  /* read a cvt entry              */
+    TT_Set_CVT_Func    func_write_cvt; /* write a cvt entry (in pixels) */
+    TT_Set_CVT_Func    func_move_cvt;  /* incr a cvt entry (in pixels)  */
+
+    FT_ULong           loadSize;
+    TT_SubGlyph_Stack  loadStack;      /* loading subglyph stack */
+
+  } TT_ExecContextRec;
+
+
+  extern const TT_GraphicsState  tt_default_graphics_state;
+
+
+  LOCAL_DEF
+  FT_Error  TT_Goto_CodeRange( TT_ExecContext  exec,
+                               FT_Int          range,
+                               FT_Long         IP );
+
+  LOCAL_DEF
+  FT_Error  TT_Set_CodeRange( TT_ExecContext  exec,
+                              FT_Int          range,
+                              void*           base,
+                              FT_Long         length );
+
+  LOCAL_DEF
+  FT_Error  TT_Clear_CodeRange( TT_ExecContext  exec,
+                                FT_Int          range );
+
+  FT_EXPORT_DEF( TT_ExecContext )  TT_New_Context( TT_Face  face );
+
+  LOCAL_DEF
+  FT_Error  TT_Done_Context( TT_ExecContext  exec );
+
+  LOCAL_DEF
+  FT_Error  TT_Destroy_Context( TT_ExecContext  exec,
+                                FT_Memory       memory );
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Context( TT_ExecContext  exec,
+                             TT_Face         face,
+                             TT_Size         size );
+
+  LOCAL_DEF
+  FT_Error  TT_Save_Context( TT_ExecContext  exec,
+                             TT_Size         ins );
+
+  LOCAL_DEF
+  FT_Error  TT_Run_Context( TT_ExecContext  exec,
+                            FT_Bool         debug );
+
+  FT_EXPORT_DEF( FT_Error )  TT_RunIns( TT_ExecContext  exec );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* TTINTERP_H */
+
+
+/* END */
diff --git a/src/freetype/truetype/ttobjs.c b/src/freetype/truetype/ttobjs.c
new file mode 100644 (file)
index 0000000..2ba715d
--- /dev/null
@@ -0,0 +1,734 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttobjs.c                                                               */
+/*                                                                         */
+/*    Objects manager (body).                                              */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ttnameid.h>
+#include <freetype/tttags.h>
+
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "ttgload.h"
+#include "ttpload.h"
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <truetype/ttgload.h>
+#include <truetype/ttpload.h>
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include <truetype/ttinterp.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#include <freetype/internal/tterrors.h>
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttobjs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       GLYPH ZONE FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_GlyphZone                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Deallocates a glyph zone.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    zone :: A pointer to the target glyph zone.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  TT_Done_GlyphZone( TT_GlyphZone*  zone )
+  {
+    FT_Memory  memory = zone->memory;
+
+
+    FREE( zone->contours );
+    FREE( zone->tags );
+    FREE( zone->cur );
+    FREE( zone->org );
+
+    zone->max_points   = zone->n_points   = 0;
+    zone->max_contours = zone->n_contours = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_New_GlyphZone                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Allocates a new glyph zone.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory      :: A handle to the current memory object.              */
+  /*                                                                       */
+  /*    maxPoints   :: The capacity of glyph zone in points.               */
+  /*                                                                       */
+  /*    maxContours :: The capacity of glyph zone in contours.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    zone        :: A pointer to the target glyph zone record.          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error TT_New_GlyphZone( FT_Memory      memory,
+                             FT_UShort      maxPoints,
+                             FT_Short       maxContours,
+                             TT_GlyphZone*  zone )
+  {
+    FT_Error  error;
+
+
+    if ( maxPoints > 0 )
+      maxPoints += 2;
+
+    MEM_Set( zone, 0, sizeof ( *zone ) );
+    zone->memory = memory;
+
+    if ( ALLOC_ARRAY( zone->org,      maxPoints * 2, FT_F26Dot6 ) ||
+         ALLOC_ARRAY( zone->cur,      maxPoints * 2, FT_F26Dot6 ) ||
+         ALLOC_ARRAY( zone->tags,     maxPoints,     FT_Byte    ) ||
+         ALLOC_ARRAY( zone->contours, maxContours,   FT_UShort  ) )
+    {
+      TT_Done_GlyphZone( zone );
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given TrueType face object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The source font stream.                              */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The newly built face object.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  TT_Init_Face( FT_Stream      stream,
+                          TT_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params )
+  {
+    FT_Error         error;
+    FT_Library       library;
+    SFNT_Interface*  sfnt;
+
+
+    library = face->root.driver->root.library;
+    sfnt    = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
+    if ( !sfnt )
+      goto Bad_Format;
+
+    /* create input stream from resource */
+    if ( FILE_Seek( 0 ) )
+      goto Exit;
+
+    /* check that we have a valid TrueType file */
+    error = sfnt->init_face( stream, face, face_index, num_params, params );
+    if ( error )
+      goto Exit;
+
+    /* We must also be able to accept Mac/GX fonts, as well as OT ones */
+    if ( face->format_tag != 0x00010000L &&    /* MS fonts  */
+         face->format_tag != TTAG_true   )     /* Mac fonts */
+    {
+      FT_TRACE2(( "[not a valid TTF font]\n" ));
+      goto Bad_Format;
+    }
+
+    /* If we are performing a simple font format check, exit immediately */
+    if ( face_index < 0 )
+      return TT_Err_Ok;
+
+    /* Load font directory */
+    error = sfnt->load_face( stream, face, face_index, num_params, params );
+    if ( error )
+      goto Exit;
+
+    error = TT_Load_Locations( face, stream ) ||
+            TT_Load_CVT      ( face, stream ) ||
+            TT_Load_Programs ( face, stream );
+
+    /* initialize standard glyph loading routines */
+    TT_Init_Glyph_Loading( face );
+
+  Exit:
+    return error;
+
+  Bad_Format:
+    error = FT_Err_Unknown_File_Format;
+    goto Exit;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given face object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A pointer to the face object to destroy.                   */
+  /*                                                                       */
+  LOCAL_DEF
+  void  TT_Done_Face( TT_Face  face )
+  {
+    FT_Memory  memory = face->root.memory;
+    FT_Stream  stream = face->root.stream;
+
+    SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+
+    /* for `extended TrueType formats' (i.e. compressed versions) */
+    if ( face->extra.finalizer )
+      face->extra.finalizer( face->extra.data );
+
+    if ( sfnt )
+      sfnt->done_face( face );
+
+    /* freeing the locations table */
+    FREE( face->glyph_locations );
+    face->num_locations = 0;
+
+    /* freeing the CVT */
+    FREE( face->cvt );
+    face->cvt_size = 0;
+
+    /* freeing the programs */
+    RELEASE_Frame( face->font_program );
+    RELEASE_Frame( face->cvt_program );
+    face->font_program_size = 0;
+    face->cvt_program_size  = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           SIZE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Init_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a new TrueType size object.                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the size object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  TT_Init_Size( TT_Size  size )
+  {
+    FT_Error  error = TT_Err_Ok;
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    TT_Face    face   = (TT_Face)size->root.face;
+    FT_Memory  memory = face->root.memory;
+    FT_Int     i;
+
+    TT_ExecContext  exec;
+    FT_UShort       n_twilight;
+    TT_MaxProfile*  maxp = &face->max_profile;
+
+
+    size->ttmetrics.valid = FALSE;
+
+    size->max_function_defs    = maxp->maxFunctionDefs;
+    size->max_instruction_defs = maxp->maxInstructionDefs;
+
+    size->num_function_defs    = 0;
+    size->num_instruction_defs = 0;
+
+    size->max_func = 0;
+    size->max_ins  = 0;
+
+    size->cvt_size     = face->cvt_size;
+    size->storage_size = maxp->maxStorage;
+
+    /* Set default metrics */
+    {
+      FT_Size_Metrics*  metrics  = &size->root.metrics;
+      TT_Size_Metrics*  metrics2 = &size->ttmetrics;
+
+
+      metrics->x_ppem = 0;
+      metrics->y_ppem = 0;
+
+      metrics2->rotated   = FALSE;
+      metrics2->stretched = FALSE;
+
+      /* set default compensation (all 0) */
+      for ( i = 0; i < 4; i++ )
+        metrics2->compensations[i] = 0;
+    }
+
+    /* allocate function defs, instruction defs, cvt, and storage area */
+    if ( ALLOC_ARRAY( size->function_defs,
+                      size->max_function_defs,
+                      TT_DefRecord )                ||
+
+         ALLOC_ARRAY( size->instruction_defs,
+                      size->max_instruction_defs,
+                      TT_DefRecord )                ||
+
+         ALLOC_ARRAY( size->cvt,
+                      size->cvt_size, FT_Long )     ||
+
+         ALLOC_ARRAY( size->storage,
+                      size->storage_size, FT_Long ) )
+
+      goto Fail_Memory;
+
+    /* reserve twilight zone */
+    n_twilight = maxp->maxTwilightPoints;
+    error = TT_New_GlyphZone( memory, n_twilight, 0, &size->twilight );
+    if ( error )
+      goto Fail_Memory;
+
+    size->twilight.n_points = n_twilight;
+
+    /* set `face->interpreter' according to the debug hook present */
+    {
+      FT_Library  library = face->root.driver->root.library;
+
+
+      face->interpreter = (TT_Interpreter)
+                            library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
+      if ( !face->interpreter )
+        face->interpreter = (TT_Interpreter)TT_RunIns;
+    }
+
+    /* Fine, now execute the font program! */
+    exec = size->context;
+    /* size objects used during debugging have their own context */
+    if ( !size->debug )
+      exec = TT_New_Context( face );
+
+    if ( !exec )
+    {
+      error = TT_Err_Could_Not_Find_Context;
+      goto Fail_Memory;
+    }
+
+    size->GS = tt_default_graphics_state;
+    TT_Load_Context( exec, face, size );
+
+    exec->callTop   = 0;
+    exec->top       = 0;
+
+    exec->period    = 64;
+    exec->phase     = 0;
+    exec->threshold = 0;
+
+    {
+      FT_Size_Metrics*  metrics    = &exec->metrics;
+      TT_Size_Metrics*  tt_metrics = &exec->tt_metrics;
+
+
+      metrics->x_ppem   = 0;
+      metrics->y_ppem   = 0;
+      metrics->x_scale  = 0;
+      metrics->y_scale  = 0;
+
+      tt_metrics->ppem  = 0;
+      tt_metrics->scale = 0;
+      tt_metrics->ratio = 0x10000L;
+    }
+
+    exec->instruction_trap = FALSE;
+
+    exec->cvtSize = size->cvt_size;
+    exec->cvt     = size->cvt;
+
+    exec->F_dot_P = 0x10000L;
+
+    /* allow font program execution */
+    TT_Set_CodeRange( exec,
+                      tt_coderange_font,
+                      face->font_program,
+                      face->font_program_size );
+
+    /* disable CVT and glyph programs coderange */
+    TT_Clear_CodeRange( exec, tt_coderange_cvt );
+    TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+    if ( face->font_program_size > 0 )
+    {
+      error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
+      if ( !error )
+        error = face->interpreter( exec );
+
+      if ( error )
+        goto Fail_Exec;
+    }
+    else
+      error = TT_Err_Ok;
+
+    TT_Save_Context( exec, size );
+
+    if ( !size->debug )
+      TT_Done_Context( exec );
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    size->ttmetrics.valid = FALSE;
+    return error;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+  Fail_Exec:
+    if ( !size->debug )
+      TT_Done_Context( exec );
+
+  Fail_Memory:
+
+#endif
+
+    TT_Done_Size( size );
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType size object finalizer.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  TT_Done_Size( TT_Size  size )
+  {
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    FT_Memory  memory = size->root.face->memory;
+
+
+    if ( size->debug )
+    {
+      /* the debug context must be deleted by the debugger itself */
+      size->context = NULL;
+      size->debug   = FALSE;
+    }
+
+    FREE( size->cvt );
+    size->cvt_size = 0;
+
+    /* free storage area */
+    FREE( size->storage );
+    size->storage_size = 0;
+
+    /* twilight zone */
+    TT_Done_GlyphZone( &size->twilight );
+
+    FREE( size->function_defs );
+    FREE( size->instruction_defs );
+
+    size->num_function_defs    = 0;
+    size->max_function_defs    = 0;
+    size->num_instruction_defs = 0;
+    size->max_instruction_defs = 0;
+
+    size->max_func = 0;
+    size->max_ins  = 0;
+
+#endif
+
+    size->ttmetrics.valid = FALSE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Reset_Size                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Resets a TrueType size when resolutions and character dimensions   */
+  /*    have been changed.                                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  TT_Reset_Size( TT_Size  size )
+  {
+    TT_Face   face;
+    FT_Error  error = TT_Err_Ok;
+
+    FT_Size_Metrics*  metrics;
+
+
+    if ( size->ttmetrics.valid )
+      return TT_Err_Ok;
+
+    face = (TT_Face)size->root.face;
+
+    metrics = &size->root.metrics;
+
+    if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
+      return TT_Err_Invalid_PPem;
+
+    /* compute new transformation */
+    if ( metrics->x_ppem >= metrics->y_ppem )
+    {
+      size->ttmetrics.scale   = metrics->x_scale;
+      size->ttmetrics.ppem    = metrics->x_ppem;
+      size->ttmetrics.x_ratio = 0x10000L;
+      size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem,
+                                           0x10000L,
+                                           metrics->x_ppem );
+    }
+    else
+    {
+      size->ttmetrics.scale   = metrics->y_scale;
+      size->ttmetrics.ppem    = metrics->y_ppem;
+      size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem,
+                                           0x10000L,
+                                           metrics->y_ppem );
+      size->ttmetrics.y_ratio = 0x10000L;
+    }
+
+    /* Compute root ascender, descender, test height, and max_advance */
+    metrics->ascender    = ( FT_MulFix( face->root.ascender,
+                                          metrics->y_scale ) + 32 ) & -64;
+    metrics->descender   = ( FT_MulFix( face->root.descender,
+                                          metrics->y_scale ) + 32 ) & -64;
+    metrics->height      = ( FT_MulFix( face->root.height,
+                                          metrics->y_scale ) + 32 ) & -64;
+    metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
+                                          metrics->x_scale ) + 32 ) & -64;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    {
+      TT_ExecContext  exec;
+      FT_UInt         i, j;
+
+
+      /* Scale the cvt values to the new ppem.          */
+      /* We use by default the y ppem to scale the CVT. */
+      for ( i = 0; i < size->cvt_size; i++ )
+        size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
+
+      /* All twilight points are originally zero */
+      for ( j = 0; j < size->twilight.n_points; j++ )
+      {
+        size->twilight.org[j].x = 0;
+        size->twilight.org[j].y = 0;
+        size->twilight.cur[j].x = 0;
+        size->twilight.cur[j].y = 0;
+      }
+
+      /* clear storage area */
+      for ( i = 0; i < size->storage_size; i++ )
+        size->storage[i] = 0;
+
+      size->GS = tt_default_graphics_state;
+
+      /* get execution context and run prep program */
+      if ( size->debug )
+        exec = size->context;
+      else
+        exec = TT_New_Context( face );
+      /* debugging instances have their own context */
+
+      if ( !exec )
+        return TT_Err_Could_Not_Find_Context;
+
+      TT_Load_Context( exec, face, size );
+
+      TT_Set_CodeRange( exec,
+                        tt_coderange_cvt,
+                        face->cvt_program,
+                        face->cvt_program_size );
+
+      TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+      exec->instruction_trap = FALSE;
+
+      exec->top     = 0;
+      exec->callTop = 0;
+
+      if ( face->cvt_program_size > 0 )
+      {
+        error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
+        if ( error )
+          goto End;
+
+        if ( !size->debug )
+          error = face->interpreter( exec );
+      }
+      else
+        error = TT_Err_Ok;
+
+      size->GS = exec->GS;
+      /* save default graphics state */
+
+    End:
+      TT_Save_Context( exec, size );
+
+      if ( !size->debug )
+        TT_Done_Context( exec );
+      /* debugging instances keep their context */
+    }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    if ( !error )
+      size->ttmetrics.valid = TRUE;
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Init_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given TrueType driver object.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Init_Driver( TT_Driver  driver )
+  {
+    FT_Error  error;
+
+
+    /* set `extra' in glyph loader */
+    error = FT_GlyphLoader_Create_Extra( FT_DRIVER( driver )->glyph_loader );
+
+    /* init extension registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+    if ( !error )
+      return TT_Init_Extensions( driver );
+#endif
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given TrueType driver.                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target TrueType driver.                  */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  TT_Done_Driver( TT_Driver  driver )
+  {
+    /* destroy extensions registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+    TT_Done_Extensions( driver );
+
+#endif
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    /* destroy the execution context */
+    if ( driver->context )
+    {
+      TT_Destroy_Context( driver->context, driver->root.root.memory );
+      driver->context = NULL;
+    }
+
+#endif
+
+  }
+
+
+/* END */
diff --git a/src/freetype/truetype/ttobjs.h b/src/freetype/truetype/ttobjs.h
new file mode 100644 (file)
index 0000000..3e55de3
--- /dev/null
@@ -0,0 +1,412 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttobjs.h                                                               */
+/*                                                                         */
+/*    Objects manager (specification).                                     */
+/*                                                                         */
+/*  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 TTOBJS_H
+#define TTOBJS_H
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/tttypes.h>
+#include <freetype/internal/tterrors.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType driver object.                              */
+  /*                                                                       */
+  typedef struct TT_DriverRec_*  TT_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_Instance                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType size object.                                */
+  /*                                                                       */
+  typedef struct TT_SizeRec_*  TT_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType glyph slot object.                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This is a direct typedef of FT_GlyphSlot, as there is nothing      */
+  /*    specific about the TrueType glyph slot.                            */
+  /*                                                                       */
+  typedef FT_GlyphSlot  TT_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_GraphicsState                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType graphics state used during bytecode interpretation.   */
+  /*                                                                       */
+  typedef struct  TT_GraphicsState_
+  {
+    FT_UShort      rp0;
+    FT_UShort      rp1;
+    FT_UShort      rp2;
+
+    FT_UnitVector  dualVector;
+    FT_UnitVector  projVector;
+    FT_UnitVector  freeVector;
+
+    FT_Long        loop;
+    FT_F26Dot6     minimum_distance;
+    FT_Int         round_state;
+
+    FT_Bool        auto_flip;
+    FT_F26Dot6     control_value_cutin;
+    FT_F26Dot6     single_width_cutin;
+    FT_F26Dot6     single_width_value;
+    FT_Short       delta_base;
+    FT_Short       delta_shift;
+
+    FT_Byte        instruct_control;
+    FT_Bool        scan_control;
+    FT_Int         scan_type;
+
+    FT_UShort      gep0;
+    FT_UShort      gep1;
+    FT_UShort      gep2;
+
+  } TT_GraphicsState;
+
+
+  LOCAL_DEF void  TT_Done_GlyphZone( TT_GlyphZone*  zone );
+
+  LOCAL_DEF FT_Error TT_New_GlyphZone( FT_Memory      memory,
+                                       FT_UShort      maxPoints,
+                                       FT_Short       maxContours,
+                                       TT_GlyphZone*  zone );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  EXECUTION SUBTABLES                                                  */
+  /*                                                                       */
+  /*  These sub-tables relate to instruction execution.                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define TT_MAX_CODE_RANGES  3
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* There can only be 3 active code ranges at once:                       */
+  /*   - the Font Program                                                  */
+  /*   - the CVT Program                                                   */
+  /*   - a glyph's instructions set                                        */
+  /*                                                                       */
+  typedef enum  TT_CodeRange_Tag_
+  {
+    tt_coderange_none = 0,
+    tt_coderange_font,
+    tt_coderange_cvt,
+    tt_coderange_glyph
+
+  } TT_CodeRange_Tag;
+
+
+  typedef struct  TT_CodeRange_
+  {
+    FT_Byte*  base;
+    FT_ULong  size;
+
+  } TT_CodeRange;
+
+  typedef TT_CodeRange  TT_CodeRangeTable[TT_MAX_CODE_RANGES];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Defines a function/instruction definition record.                     */
+  /*                                                                       */
+  typedef struct  TT_DefRecord_
+  {
+    FT_Int   range;      /* in which code range is it located? */
+    FT_Long  start;      /* where does it start?               */
+    FT_UInt  opc;        /* function #, or instruction code    */
+    FT_Bool  active;     /* is it active?                      */
+
+  } TT_DefRecord, *TT_DefArray;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Subglyph transformation record.                                       */
+  /*                                                                       */
+  typedef struct  TT_Transform_
+  {
+    FT_Fixed    xx, xy;     /* transformation matrix coefficients */
+    FT_Fixed    yx, yy;
+    FT_F26Dot6  ox, oy;     /* offsets        */
+
+  } TT_Transform;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Subglyph loading record.  Used to load composite components.          */
+  /*                                                                       */
+  typedef struct  TT_SubglyphRec_
+  {
+    FT_Long       index;        /* subglyph index; initialized with -1 */
+    FT_Bool       is_scaled;    /* is the subglyph scaled?             */
+    FT_Bool       is_hinted;    /* should it be hinted?                */
+    FT_Bool       preserve_pps; /* preserve phantom points?            */
+
+    FT_Long       file_offset;
+
+    FT_BBox       bbox;
+    FT_Pos        left_bearing;
+    FT_Pos        advance;
+
+    TT_GlyphZone  zone;
+
+    FT_Long       arg1;         /* first argument                      */
+    FT_Long       arg2;         /* second argument                     */
+
+    FT_UShort     element_flag; /* current load element flag           */
+
+    TT_Transform  transform;    /* transformation matrix               */
+
+    FT_Vector     pp1, pp2;     /* phantom points                      */
+
+  } TT_SubGlyphRec, *TT_SubGlyph_Stack;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A note regarding non-squared pixels:                                  */
+  /*                                                                       */
+  /* (This text will probably go into some docs at some time; for now, it  */
+  /*  is kept here to explain some definitions in the TIns_Metrics         */
+  /*  record).                                                             */
+  /*                                                                       */
+  /* The CVT is a one-dimensional array containing values that control     */
+  /* certain important characteristics in a font, like the height of all   */
+  /* capitals, all lowercase letter, default spacing or stem width/height. */
+  /*                                                                       */
+  /* These values are found in FUnits in the font file, and must be scaled */
+  /* to pixel coordinates before being used by the CVT and glyph programs. */
+  /* Unfortunately, when using distinct x and y resolutions (or distinct x */
+  /* and y pointsizes), there are two possible scalings.                   */
+  /*                                                                       */
+  /* A first try was to implement a `lazy' scheme where all values were    */
+  /* scaled when first used.  However, while some values are always used   */
+  /* in the same direction, some others are used under many different      */
+  /* circumstances and orientations.                                       */
+  /*                                                                       */
+  /* I have found a simpler way to do the same, and it even seems to work  */
+  /* in most of the cases:                                                 */
+  /*                                                                       */
+  /* - All CVT values are scaled to the maximum ppem size.                 */
+  /*                                                                       */
+  /* - When performing a read or write in the CVT, a ratio factor is used  */
+  /*   to perform adequate scaling.  Example:                              */
+  /*                                                                       */
+  /*     x_ppem = 14                                                       */
+  /*     y_ppem = 10                                                       */
+  /*                                                                       */
+  /*   We choose ppem = x_ppem = 14 as the CVT scaling size.  All cvt      */
+  /*   entries are scaled to it.                                           */
+  /*                                                                       */
+  /*     x_ratio = 1.0                                                     */
+  /*     y_ratio = y_ppem/ppem (< 1.0)                                     */
+  /*                                                                       */
+  /*   We compute the current ratio like:                                  */
+  /*                                                                       */
+  /*   - If projVector is horizontal,                                      */
+  /*       ratio = x_ratio = 1.0                                           */
+  /*                                                                       */
+  /*   - if projVector is vertical,                                        */
+  /*       ratio = y_ratio                                                 */
+  /*                                                                       */
+  /*   - else,                                                             */
+  /*       ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
+  /*                                                                       */
+  /*   Reading a cvt value returns                                         */
+  /*     ratio * cvt[index]                                                */
+  /*                                                                       */
+  /*   Writing a cvt value in pixels:                                      */
+  /*     cvt[index] / ratio                                                */
+  /*                                                                       */
+  /*   The current ppem is simply                                          */
+  /*     ratio * ppem                                                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Metrics used by the TrueType size and context objects.                */
+  /*                                                                       */
+  typedef struct  TT_Size_Metrics_
+  {
+    /* for non-square pixels */
+    FT_Long     x_ratio;
+    FT_Long     y_ratio;
+
+    FT_UShort   ppem;               /* maximum ppem size              */
+    FT_Long     ratio;              /* current ratio                  */
+    FT_Fixed    scale;
+
+    FT_F26Dot6  compensations[4];   /* device-specific compensations  */
+
+    FT_Bool     valid;
+
+    FT_Bool     rotated;            /* `is the glyph rotated?'-flag   */
+    FT_Bool     stretched;          /* `is the glyph stretched?'-flag */
+
+  } TT_Size_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* TrueType size class.                                                  */
+  /*                                                                       */
+  typedef struct  TT_SizeRec_
+  {
+    FT_SizeRec         root;
+
+    TT_Size_Metrics    ttmetrics;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    FT_UInt            num_function_defs; /* number of function definitions */
+    FT_UInt            max_function_defs;
+    TT_DefArray        function_defs;     /* table of function definitions  */
+
+    FT_UInt            num_instruction_defs;  /* number of ins. definitions */
+    FT_UInt            max_instruction_defs;
+    TT_DefArray        instruction_defs;      /* table of ins. definitions  */
+
+    FT_UInt            max_func;
+    FT_UInt            max_ins;
+
+    TT_CodeRangeTable  codeRangeTable;
+
+    TT_GraphicsState   GS;
+
+    FT_ULong           cvt_size;      /* the scaled control value table */
+    FT_Long*           cvt;
+
+    FT_UShort          storage_size; /* The storage area is now part of */
+    FT_Long*           storage;      /* the instance                    */
+
+    TT_GlyphZone       twilight;     /* The instance's twilight zone    */
+
+    /* debugging variables */
+
+    /* When using the debugger, we must keep the */
+    /* execution context tied to the instance    */
+    /* object rather than asking it on demand.   */
+
+    FT_Bool            debug;
+    TT_ExecContext     context;
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+  } TT_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* TrueType driver class.                                                */
+  /*                                                                       */
+  typedef struct  TT_DriverRec_
+  {
+    FT_DriverRec    root;
+    TT_ExecContext  context;  /* execution context        */
+    TT_GlyphZone    zone;     /* glyph loader points zone */
+
+    void*           extension_component;
+
+  } TT_DriverRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Face functions                                                        */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  TT_Init_Face( FT_Stream      stream,
+                          TT_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  TT_Done_Face( TT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Size functions                                                        */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  TT_Init_Size( TT_Size  size );
+
+  LOCAL_DEF
+  void  TT_Done_Size( TT_Size  size );
+
+  LOCAL_DEF
+  FT_Error  TT_Reset_Size( TT_Size  size );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Driver functions                                                      */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  TT_Init_Driver( TT_Driver  driver );
+
+  LOCAL_DEF
+  void  TT_Done_Driver( TT_Driver  driver );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* TTOBJS_H */
+
+
+/* END */
diff --git a/src/freetype/truetype/ttpload.c b/src/freetype/truetype/ttpload.c
new file mode 100644 (file)
index 0000000..d82dd45
--- /dev/null
@@ -0,0 +1,273 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpload.h                                                              */
+/*                                                                         */
+/*    TrueType glyph data/program tables loader (body).                    */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/tttags.h>
+
+#ifdef FT_FLAT_COMPILE
+#include "ttpload.h"
+#else
+#include <truetype/ttpload.h>
+#endif
+
+#include <freetype/internal/tterrors.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttpload
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Locations                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the locations table.                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Locations( TT_Face    face,
+                               FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_Short   LongOffsets;
+    FT_ULong   table_len;
+
+
+    FT_TRACE2(( "Locations " ));
+    LongOffsets = face->header.Index_To_Loc_Format;
+
+    error = face->goto_table( face, TTAG_loca, stream, &table_len );
+    if ( error )
+    {
+      error = TT_Err_Locations_Missing;
+      goto Exit;
+    }
+
+    if ( LongOffsets != 0 )
+    {
+      face->num_locations = (FT_UShort)( table_len >> 2 );
+
+      FT_TRACE2(( "(32bit offsets): %12d ", face->num_locations ));
+
+      if ( ALLOC_ARRAY( face->glyph_locations,
+                        face->num_locations,
+                        FT_Long ) )
+        goto Exit;
+
+      if ( ACCESS_Frame( face->num_locations * 4L ) )
+        goto Exit;
+
+      {
+        FT_Long*  loc   = face->glyph_locations;
+        FT_Long*  limit = loc + face->num_locations;
+
+
+        for ( ; loc < limit; loc++ )
+          *loc = GET_Long();
+      }
+
+      FORGET_Frame();
+    }
+    else
+    {
+      face->num_locations = (FT_UShort)( table_len >> 1 );
+
+      FT_TRACE2(( "(16bit offsets): %12d ", face->num_locations ));
+
+      if ( ALLOC_ARRAY( face->glyph_locations,
+                        face->num_locations,
+                        FT_Long ) )
+        goto Exit;
+
+      if ( ACCESS_Frame( face->num_locations * 2L ) )
+        goto Exit;
+      {
+        FT_Long*  loc   = face->glyph_locations;
+        FT_Long*  limit = loc + face->num_locations;
+
+
+        for ( ; loc < limit; loc++ )
+          *loc = (FT_Long)( (FT_ULong)GET_UShort() * 2 );
+      }
+      FORGET_Frame();
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_CVT                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the control value table into a face object.                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_CVT( TT_Face    face,
+                         FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_ULong   table_len;
+
+
+    FT_TRACE2(( "CVT " ));
+
+    error = face->goto_table( face, TTAG_cvt, stream, &table_len );
+    if ( error )
+    {
+      FT_TRACE2(( "is missing!\n" ));
+
+      face->cvt_size = 0;
+      face->cvt      = NULL;
+      error          = TT_Err_Ok;
+
+      goto Exit;
+    }
+
+    face->cvt_size = table_len / 2;
+
+    if ( ALLOC_ARRAY( face->cvt,
+                      face->cvt_size,
+                      FT_Short ) )
+      goto Exit;
+
+    if ( ACCESS_Frame( face->cvt_size * 2L ) )
+      goto Exit;
+
+    {
+      FT_Short*  cur   = face->cvt;
+      FT_Short*  limit = cur + face->cvt_size;
+
+
+      for ( ; cur <  limit; cur++ )
+        *cur = GET_Short();
+    }
+
+    FORGET_Frame();
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Progams                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the font program and the cvt program.                        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  TT_Load_Programs( TT_Face    face,
+                              FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_ULong   table_len;
+
+
+    FT_TRACE2(( "Font program " ));
+
+    /* The font program is optional */
+    error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
+    if ( error )
+    {
+      face->font_program      = NULL;
+      face->font_program_size = 0;
+
+      FT_TRACE2(( "is missing!\n" ));
+    }
+    else
+    {
+      face->font_program_size = table_len;
+      if ( EXTRACT_Frame( table_len, face->font_program ) )
+        goto Exit;
+
+      FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
+    }
+
+    FT_TRACE2(( "Prep program " ));
+
+    error = face->goto_table( face, TTAG_prep, stream, &table_len );
+    if ( error )
+    {
+      face->cvt_program      = NULL;
+      face->cvt_program_size = 0;
+      error                  = TT_Err_Ok;
+
+      FT_TRACE2(( "is missing!\n" ));
+    }
+    else
+    {
+      face->cvt_program_size = table_len;
+      if ( EXTRACT_Frame( table_len, face->cvt_program ) )
+        goto Exit;
+
+      FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
+    }
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/truetype/ttpload.h b/src/freetype/truetype/ttpload.h
new file mode 100644 (file)
index 0000000..77802a6
--- /dev/null
@@ -0,0 +1,51 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpload.h                                                              */
+/*                                                                         */
+/*    TrueType glyph data/program tables loader (specification).           */
+/*                                                                         */
+/*  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 TTPLOAD_H
+#define TTPLOAD_H
+
+#include <freetype/internal/tttypes.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Locations( TT_Face    face,
+                               FT_Stream  stream );
+
+  LOCAL_DEF
+  FT_Error  TT_Load_CVT( TT_Face    face,
+                         FT_Stream  stream );
+
+  LOCAL_DEF
+  FT_Error  TT_Load_Programs( TT_Face    face,
+                              FT_Stream  stream );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* TTPLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/type1/module.mk0 b/src/freetype/type1/module.mk0
new file mode 100644 (file)
index 0000000..af99eae
--- /dev/null
@@ -0,0 +1,6 @@
+make_module_list: add_type1_driver
+
+add_type1_driver:
+       $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)type1     $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
+
diff --git a/src/freetype/type1/rules.mk0 b/src/freetype/type1/rules.mk0
new file mode 100644 (file)
index 0000000..b544446
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# FreeType 2 Type 1 driver configuration rules
+#
+
+
+# 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.
+
+
+# Type1 driver directory
+#
+T1_DIR  := $(SRC_)type1
+T1_DIR_ := $(T1_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+T1_COMPILE := $(FT_COMPILE)
+
+
+# Type1 driver sources (i.e., C files)
+#
+T1_DRV_SRC := $(T1_DIR_)t1objs.c   \
+              $(T1_DIR_)t1load.c   \
+              $(T1_DIR_)t1parse.c  \
+              $(T1_DIR_)t1tokens.c \
+              $(T1_DIR_)t1driver.c \
+              $(T1_DIR_)t1hinter.c \
+              $(T1_DIR_)t1afm.c    \
+              $(T1_DIR_)t1gload.c
+
+# Type1 driver headers
+#
+T1_DRV_H := $(T1_DRV_SRC:%.c=%.h)
+
+
+# Type1 driver object(s)
+#
+#   T1_DRV_OBJ_M is used during `multi' builds
+#   T1_DRV_OBJ_S is used during `single' builds
+#
+T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O)
+T1_DRV_OBJ_S := $(OBJ_)type1.$O
+
+# Type1 driver source file for single build
+#
+T1_DRV_SRC_S := $(T1_DIR_)type1.c
+
+
+# Type1 driver - single object
+#
+$(T1_DRV_OBJ_S): $(T1_DRV_SRC_S) $(T1_DRV_SRC) $(FREETYPE_H) $(T1_DRV_H)
+       $(T1_COMPILE) $T$@ $(T1_DRV_SRC_S)
+
+
+# Type1 driver - multiple objects
+#
+$(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H)
+       $(T1_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T1_DRV_OBJ_S)
+DRV_OBJS_M += $(T1_DRV_OBJ_M)
+
+
+# EOF
diff --git a/src/freetype/type1/t1afm.c b/src/freetype/type1/t1afm.c
new file mode 100644 (file)
index 0000000..a6ac1b9
--- /dev/null
@@ -0,0 +1,293 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1afm.c                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (body).                                 */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1afm.h"
+
+#else
+
+#include <type1/t1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+
+#include <stdlib.h>  /* for qsort()   */
+#include <string.h>  /* for strcmp()  */
+#include <ctype.h>   /* for isalnum() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1afm
+
+
+  LOCAL_FUNC
+  void  T1_Done_AFM( FT_Memory  memory,
+                     T1_AFM*    afm )
+  {
+    FREE( afm->kern_pairs );
+    afm->num_pairs = 0;
+  }
+
+
+#undef  IS_KERN_PAIR
+#define IS_KERN_PAIR( p )  ( p[0] == 'K' && p[1] == 'P' )
+
+#define IS_ALPHANUM( c )  ( isalnum( c ) || \
+                            c == '_'     || \
+                            c == '.'     )
+
+
+  /* read a glyph name and return the equivalent glyph index */
+  static
+  FT_UInt  afm_atoindex( FT_Byte**  start,
+                         FT_Byte*   limit,
+                         T1_Font*   type1 )
+  {
+    FT_Byte*  p = *start;
+    FT_Int    len;
+    FT_UInt   result = 0;
+    char      temp[64];
+
+
+    /* skip whitespace */
+    while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
+            p < limit                                             )
+      p++;
+    *start = p;
+
+    /* now, read glyph name */
+    while ( IS_ALPHANUM( *p ) && p < limit )
+      p++;
+
+    len = p - *start;
+
+    if ( len > 0 && len < 64 )
+    {
+      FT_Int  n;
+
+
+      /* copy glyph name to intermediate array */
+      MEM_Copy( temp, *start, len );
+      temp[len] = 0;
+
+      /* lookup glyph name in face array */
+      for ( n = 0; n < type1->num_glyphs; n++ )
+      {
+        char*  gname = (char*)type1->glyph_names[n];
+
+
+        if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 )
+        {
+          result = n;
+          break;
+        }
+      }
+    }
+    *start = p;
+    return result;
+  }
+
+
+  /* read an integer */
+  static
+  int  afm_atoi( FT_Byte**  start,
+                 FT_Byte*   limit )
+  {
+    FT_Byte*  p    = *start;
+    int       sum  = 0;
+    int       sign = 1;
+
+
+    /* skip everything that is not a number */
+    while ( p < limit && !isdigit( *p ) )
+    {
+      sign = 1;
+      if ( *p == '-' )
+        sign = -1;
+
+      p++;
+    }
+
+    while ( p < limit && isdigit( *p ) )
+    {
+      sum = sum * 10 + ( *p - '0' );
+      p++;
+    }
+    *start = p;
+
+    return sum * sign;
+  }
+
+
+#undef  KERN_INDEX
+#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+
+  /* compare two kerning pairs */
+  static
+  int  compare_kern_pairs( const void*  a,
+                           const void*  b )
+  {
+    T1_Kern_Pair*  pair1 = (T1_Kern_Pair*)a;
+    T1_Kern_Pair*  pair2 = (T1_Kern_Pair*)b;
+
+    FT_ULong  index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
+    FT_ULong  index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
+
+
+    return ( index1 - index2 );
+  }
+
+
+  /* parse an AFM file -- for now, only read the kerning pairs */
+  LOCAL_FUNC
+  FT_Error  T1_Read_AFM( FT_Face    t1_face,
+                         FT_Stream  stream )
+  {
+    FT_Error       error;
+    FT_Memory      memory = stream->memory;
+    FT_Byte*       start;
+    FT_Byte*       limit;
+    FT_Byte*       p;
+    FT_Int         count = 0;
+    T1_Kern_Pair*  pair;
+    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
+    T1_AFM*        afm   = 0;
+
+
+    if ( ACCESS_Frame( stream->size ) )
+      return error;
+
+    start = (FT_Byte*)stream->cursor;
+    limit = (FT_Byte*)stream->limit;
+    p     = start;
+
+    /* we are now going to count the occurences of `KP' or `KPX' in */
+    /* the AFM file                                                 */
+    count = 0;
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+        count++;
+    }
+
+    /* Actually, kerning pairs are simply optional! */
+    if ( count == 0 )
+      goto Exit;
+
+    /* allocate the pairs */
+    if ( ALLOC( afm, sizeof ( *afm ) )                       ||
+         ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) )
+      goto Exit;
+
+    /* now, read each kern pair */
+    pair           = afm->kern_pairs;
+    afm->num_pairs = count;
+
+    /* save in face object */
+    ((T1_Face)t1_face)->afm_data = afm;
+
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+      {
+        FT_Byte*  q;
+
+
+        /* skip keyword (KP or KPX) */
+        q = p + 2;
+        if ( *q == 'X' )
+          q++;
+
+        pair->glyph1    = afm_atoindex( &q, limit, type1 );
+        pair->glyph2    = afm_atoindex( &q, limit, type1 );
+        pair->kerning.x = afm_atoi( &q, limit );
+
+        pair->kerning.y = 0;
+        if ( p[2] != 'X' )
+          pair->kerning.y = afm_atoi( &q, limit );
+
+        pair++;
+      }
+    }
+
+    /* now, sort the kern pairs according to their glyph indices */
+    qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ),
+           compare_kern_pairs );
+
+  Exit:
+    if ( error )
+      FREE( afm );
+
+    FORGET_Frame();
+
+    return error;
+  }
+
+
+  /* find the kerning for a given glyph pair */
+  LOCAL_FUNC
+  void  T1_Get_Kerning( T1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning )
+  {
+    T1_Kern_Pair  *min, *mid, *max;
+    FT_ULong      index = KERN_INDEX( glyph1, glyph2 );
+
+
+    /* simple binary search */
+    min = afm->kern_pairs;
+    max = min + afm->num_pairs - 1;
+
+    while ( min <= max )
+    {
+      FT_ULong  midi;
+
+
+      mid  = min + ( max - min ) / 2;
+      midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
+
+      if ( midi == index )
+      {
+        *kerning = mid->kerning;
+        return;
+      }
+
+      if ( midi < index )
+        min = mid + 1;
+      else
+        max = mid - 1;
+    }
+
+    kerning->x = 0;
+    kerning->y = 0;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1/t1afm.h b/src/freetype/type1/t1afm.h
new file mode 100644 (file)
index 0000000..709154e
--- /dev/null
@@ -0,0 +1,70 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1afm.h                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (specification).                        */
+/*                                                                         */
+/*  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 T1AFM_H
+#define T1AFM_H
+
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  typedef struct  T1_Kern_Pair_
+  {
+    FT_UInt    glyph1;
+    FT_UInt    glyph2;
+    FT_Vector  kerning;
+
+  } T1_Kern_Pair;
+
+
+  typedef struct  T1_AFM_
+  {
+    FT_Int         num_pairs;
+    T1_Kern_Pair*  kern_pairs;
+
+  } T1_AFM;
+
+
+  LOCAL_DEF
+  FT_Error  T1_Read_AFM( FT_Face    face,
+                         FT_Stream  stream );
+
+  LOCAL_DEF
+  void  T1_Done_AFM( FT_Memory  memory,
+                     T1_AFM*    afm );
+
+  LOCAL_DEF
+  void  T1_Get_Kerning( T1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T1AFM_H */
+
+
+/* END */
diff --git a/src/freetype/type1/t1driver.c b/src/freetype/type1/t1driver.c
new file mode 100644 (file)
index 0000000..49b5a56
--- /dev/null
@@ -0,0 +1,381 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1driver.c                                                             */
+/*                                                                         */
+/*    Type 1 driver interface (body).                                      */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1driver.h"
+#include "t1gload.h"
+#include "t1afm.h"
+
+#else
+
+#include <type1/t1driver.h>
+#include <type1/t1gload.h>
+#include <type1/t1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1driver
+
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings are out of scope of this method (the basic driver         */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static
+  FT_Error  Get_Kerning( T1_Face     face,
+                         FT_UInt     left_glyph,
+                         FT_UInt     right_glyph,
+                         FT_Vector*  kerning )
+  {
+    T1_AFM*  afm;
+
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (T1_AFM*)face->afm_data;
+    if ( afm )
+      T1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return T1_Err_Ok;
+  }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+  static
+  FT_Error  get_t1_glyph_name( T1_Face     face,
+                               FT_UInt     glyph_index,
+                               FT_Pointer  buffer,
+                               FT_UInt     buffer_max )
+  {
+    FT_String*  gname;
+    
+
+    gname = face->type1.glyph_names[glyph_index];
+
+    if ( buffer_max > 0 )
+    {
+      FT_UInt  len = strlen( gname );
+      
+
+      if ( len >= buffer_max )
+        len = buffer_max - 1;
+        
+      MEM_Copy( buffer, gname, len );
+      ((FT_Byte*)buffer)[len] = 0;
+    }
+
+    return T1_Err_Ok;
+  }                                  
+
+
+  static
+  FT_Module_Interface  T1_Get_Interface( FT_Module    module,
+                                         const char*  interface )
+  {
+    FT_UNUSED( module );
+
+    if ( strcmp( interface, "glyph_name" ) == 0 )
+      return (FT_Module_Interface)get_t1_glyph_name;
+
+    return 0;
+  }
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_Char_Sizes                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to reset a size's character sizes (horizontal */
+  /*    and vertical) expressed in fractional points.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_width      :: The character width expressed in 26.6           */
+  /*                       fractional points.                              */
+  /*                                                                       */
+  /*    char_height     :: The character height expressed in 26.6          */
+  /*                       fractional points.                              */
+  /*                                                                       */
+  /*    horz_resolution :: The horizontal resolution of the output device. */
+  /*                                                                       */
+  /*    vert_resolution :: The vertical resolution of the output device.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size            :: A handle to the target size object.             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Set_Char_Sizes( T1_Size     size,
+                            FT_F26Dot6  char_width,
+                            FT_F26Dot6  char_height,
+                            FT_UInt     horz_resolution,
+                            FT_UInt     vert_resolution )
+  {
+    FT_UNUSED( char_width );
+    FT_UNUSED( char_height );
+    FT_UNUSED( horz_resolution );
+    FT_UNUSED( vert_resolution );
+
+    size->valid = FALSE;
+
+    return T1_Reset_Size( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_Pixel_Sizes                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to reset a size's character sizes (horizontal */
+  /*    and vertical) expressed in integer pixels.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pixel_width  :: The character width expressed in integer pixels.   */
+  /*                                                                       */
+  /*    pixel_height :: The character height expressed in integer pixels.  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size         :: A handle to the target size object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Set_Pixel_Sizes( T1_Size  size,
+                             FT_Int   pixel_width,
+                             FT_Int   pixel_height )
+  {
+    FT_UNUSED( pixel_width );
+    FT_UNUSED( pixel_height );
+
+    size->valid = FALSE;
+
+    return T1_Reset_Size( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  FT_UInt  Get_Char_Index( FT_CharMap  charmap,
+                           FT_Long     charcode )
+  {
+    T1_Face             face;
+    FT_UInt             result = 0;
+    PSNames_Interface*  psnames;
+
+
+    face    = (T1_Face)charmap->face;
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( psnames )
+      switch ( charmap->encoding )
+      {
+        /*******************************************************************/
+        /*                                                                 */
+        /* Unicode encoding support                                        */
+        /*                                                                 */
+      case ft_encoding_unicode:
+        /* use the `PSNames' module to synthetize the Unicode charmap */
+        result = psnames->lookup_unicode( &face->unicode_map,
+                                          (FT_ULong)charcode );
+
+        /* the function returns 0xFFFF if the Unicode charcode has */
+        /* no corresponding glyph                                  */
+        if ( result == 0xFFFF )
+          result = 0;
+        goto Exit;
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Custom Type 1 encoding                                          */
+        /*                                                                 */
+      case ft_encoding_adobe_custom:
+        {
+          T1_Encoding*  encoding = &face->type1.encoding;
+
+
+          if ( charcode >= encoding->code_first &&
+               charcode <= encoding->code_last  )
+            result = encoding->char_index[charcode];
+          goto Exit;
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Adobe Standard & Expert encoding support                        */
+        /*                                                                 */
+      default:
+        if ( charcode < 256 )
+        {
+          FT_UInt      code;
+          FT_Int       n;
+          const char*  glyph_name;
+
+
+          code = psnames->adobe_std_encoding[charcode];
+          if ( charmap->encoding == ft_encoding_adobe_expert )
+            code = psnames->adobe_expert_encoding[charcode];
+
+          glyph_name = psnames->adobe_std_strings( code );
+          if ( !glyph_name )
+            break;
+
+          for ( n = 0; n < face->type1.num_glyphs; n++ )
+          {
+            const char*  gname = face->type1.glyph_names[n];
+
+
+            if ( gname && gname[0] == glyph_name[0] &&
+                 strcmp( gname, glyph_name ) == 0   )
+            {
+              result = n;
+              break;
+            }
+          }
+        }
+      }
+  Exit:
+    return result;
+  }
+
+
+
+  const FT_Driver_Class  t1_driver_class =
+  {
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( FT_DriverRec ),
+
+      "type1",   /* driver name        */
+      0x10000L,  /* driver version 1.0 */
+      0x20000L,  /* driver requires FreeType 2.0 or above */
+
+      0,   /* module specific interface */
+
+      (FT_Module_Constructor)0,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  T1_Get_Interface
+    },
+
+    sizeof( T1_FaceRec ),
+    sizeof( T1_SizeRec ),
+    sizeof( T1_GlyphSlotRec ),
+
+    (FTDriver_initFace)     T1_Init_Face,
+    (FTDriver_doneFace)     T1_Done_Face,
+    (FTDriver_initSize)     T1_Init_Size,
+    (FTDriver_doneSize)     T1_Done_Size,
+    (FTDriver_initGlyphSlot)T1_Init_GlyphSlot,
+    (FTDriver_doneGlyphSlot)T1_Done_GlyphSlot,
+
+    (FTDriver_setCharSizes) Set_Char_Sizes,
+    (FTDriver_setPixelSizes)Set_Pixel_Sizes,
+    (FTDriver_loadGlyph)    T1_Load_Glyph,
+    (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+#else
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   T1_Read_AFM,
+#endif
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+  EXPORT_FUNC( const FT_Driver_Class* )  getDriverClass( void )
+  {
+    return &t1_driver_class;
+  }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/src/freetype/type1/t1driver.h b/src/freetype/type1/t1driver.h
new file mode 100644 (file)
index 0000000..5d615b5
--- /dev/null
@@ -0,0 +1,30 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1driver.h                                                             */
+/*                                                                         */
+/*    High-level Type 1 driver interface (specification).                  */
+/*                                                                         */
+/*  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 T1DRIVER_H
+#define T1DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+  FT_EXPORT_VAR( const  FT_Driver_Class )  t1_driver_class;
+
+
+#endif /* T1DRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/type1/t1gload.c b/src/freetype/type1/t1gload.c
new file mode 100644 (file)
index 0000000..37cfc8c
--- /dev/null
@@ -0,0 +1,1823 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1gload.c                                                              */
+/*                                                                         */
+/*    Type 1 Glyph Loader (body).                                          */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1gload.h"
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include "t1hinter.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1/t1gload.h>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <type1/t1hinter.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1gload
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********             GENERIC CHARSTRING PARSING               *********/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  void  T1_Reset_Builder( T1_Builder*  builder,
+                          FT_Bool      reset_base )
+  {
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+
+    builder->pass       = 0;
+    builder->hint_point = 0;
+
+    if ( builder->loader )
+    {
+      if ( reset_base )
+        FT_GlyphLoader_Rewind( builder->loader );
+
+      FT_GlyphLoader_Prepare( builder->loader );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Init_Builder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph builder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    builder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    glyph   :: The current glyph object.                               */
+  /*                                                                       */
+  /*    funcs   :: Glyph builder functions (or `methods').                 */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Init_Builder( T1_Builder*              builder,
+                         T1_Face                  face,
+                         T1_Size                  size,
+                         T1_GlyphSlot             glyph,
+                         const T1_Builder_Funcs*  funcs )
+  {
+    builder->funcs       = *funcs;
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->size   = size;
+    builder->glyph  = glyph;
+    builder->memory = face->root.memory;
+
+    if ( glyph )
+    {
+      FT_GlyphLoader*  loader = FT_SLOT( glyph )->loader;
+
+
+      builder->loader  = loader;
+      builder->base    = &loader->base.outline;
+      builder->current = &loader->current.outline;
+    }
+
+    if ( size )
+    {
+      builder->scale_x = size->root.metrics.x_scale;
+      builder->scale_y = size->root.metrics.y_scale;
+    }
+
+    T1_Reset_Builder( builder, 1 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Builder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given glyph builder.  Its contents can still be used   */
+  /*    after the call, but the function saves important information       */
+  /*    within the corresponding glyph slot.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder :: A pointer to the glyph builder to finalize.             */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_Builder( T1_Builder*  builder )
+  {
+    T1_GlyphSlot  glyph = builder->glyph;
+
+
+    if ( glyph )
+      glyph->root.outline = *builder->base;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Init_Decoder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph decoder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    funcs   :: The hinting functions interface.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Init_Decoder( T1_Decoder*             decoder,
+                         const T1_Hinter_Funcs*  funcs )
+  {
+    decoder->hinter = *funcs;    /* copy hinter interface */
+    decoder->top    = 0;
+    decoder->zone   = 0;
+
+    decoder->flex_state       = 0;
+    decoder->num_flex_vectors = 0;
+
+    /* Clear loader */
+    MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    lookup_glyph_by_stdcharcode                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks up a given glyph by its StandardEncoding charcode.  Used     */
+  /*    to implement the SEAC Type 1 operator.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: The current face object.                               */
+  /*                                                                       */
+  /*    charcode :: The character code to look for.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A glyph index in the font face.  Returns -1 if the corresponding   */
+  /*    glyph wasn't found.                                                */
+  /*                                                                       */
+  static
+  FT_Int  lookup_glyph_by_stdcharcode( T1_Face  face,
+                                       FT_Int   charcode )
+  {
+    FT_Int              n;
+    const FT_String*    glyph_name;
+    PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+
+    /* check range of standard char code */
+    if ( charcode < 0 || charcode > 255 )
+      return -1;
+
+    glyph_name = psnames->adobe_std_strings(
+                   psnames->adobe_std_encoding[charcode] );
+
+    for ( n = 0; n < face->type1.num_glyphs; n++ )
+    {
+      FT_String*  name = (FT_String*)face->type1.glyph_names[n];
+
+
+      if ( name && strcmp( name, glyph_name ) == 0 )
+        return n;
+    }
+
+    return -1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1operator_seac                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder :: The current CID decoder.                                */
+  /*                                                                       */
+  /*    asb     :: The accent's side bearing.                              */
+  /*                                                                       */
+  /*    adx     :: The horizontal offset of the accent.                    */
+  /*                                                                       */
+  /*    ady     :: The vertical offset of the accent.                      */
+  /*                                                                       */
+  /*    bchar   :: The base character's StandardEncoding charcode.         */
+  /*                                                                       */
+  /*    achar   :: The accent character's StandardEncoding charcode.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  t1operator_seac( T1_Decoder*  decoder,
+                             FT_Pos       asb,
+                             FT_Pos       adx,
+                             FT_Pos       ady,
+                             FT_Int       bchar,
+                             FT_Int       achar )
+  {
+    FT_Error     error;
+    FT_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  base = decoder->builder.base;
+    FT_Vector    left_bearing, advance;
+    T1_Face      face  = decoder->builder.face;
+    T1_Font*     type1 = &face->type1;
+
+
+    bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
+    achar_index = lookup_glyph_by_stdcharcode( face, achar );
+
+    if ( bchar_index < 0 || achar_index < 0 )
+    {
+      FT_ERROR(( "t1operator_seac:" ));
+      FT_ERROR(( " invalid seac character code arguments\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* if we are trying to load a composite glyph, do not load the */
+    /* accent character and return the array of subglyphs.         */
+    if ( decoder->builder.no_recurse )
+    {
+      FT_GlyphSlot     glyph = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_GlyphLoader*  loader = glyph->loader;
+      FT_SubGlyph*     subg;
+
+
+      /* reallocate subglyph array if necessary */
+      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+      if ( error )
+        goto Exit;
+
+      subg = loader->current.subglyphs;
+
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
+
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->subglyphs     = loader->current.subglyphs;
+      glyph->format        = ft_glyph_format_composite;
+
+      loader->current.num_subglyphs = 2;
+      goto Exit;
+    }
+
+    /* First load `bchar' in builder */
+    /* now load the unscaled outline */
+
+    if ( decoder->builder.loader )
+      FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
+
+    error = T1_Parse_CharStrings( decoder,
+                                  type1->charstrings    [bchar_index],
+                                  type1->charstrings_len[bchar_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+    if ( error )
+      goto Exit;
+
+    n_base_points = base->n_points;
+
+    /* save the left bearing and width of the base character */
+    /* as they will be erased by the next load.              */
+
+    left_bearing = decoder->builder.left_bearing;
+    advance      = decoder->builder.advance;
+
+    decoder->builder.left_bearing.x = 0;
+    decoder->builder.left_bearing.y = 0;
+
+    /* Now load `achar' on top of the base outline */
+    error = T1_Parse_CharStrings( decoder,
+                                  type1->charstrings    [achar_index],
+                                  type1->charstrings_len[achar_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+    if ( error )
+      return error;
+
+    /* restore the left side bearing and */
+    /* advance width of the base character */
+
+    decoder->builder.left_bearing = left_bearing;
+    decoder->builder.advance      = advance;
+
+    /* Finally, move the accent */
+    if ( decoder->builder.load_points )
+    {
+      FT_Outline  dummy;
+
+
+      dummy.n_points = base->n_points - n_base_points;
+      dummy.points   = base->points   + n_base_points;
+
+      FT_Outline_Translate( &dummy, adx - asb, ady );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1operator_flex                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Implements the `flex' Type 1 operator for a Type 1 decoder.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder   :: The current Type 1 decoder.                           */
+  /*    threshold :: The threshold.                                        */
+  /*    end_x     :: The horizontal position of the final flex point.      */
+  /*    end_y     :: The vertical position of the final flex point.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  t1operator_flex( T1_Decoder*  decoder,
+                             FT_Pos       threshold,
+                             FT_Pos       end_x,
+                             FT_Pos       end_y )
+  {
+    FT_Vector    vec;
+    FT_Vector*   flex  = decoder->flex_vectors;
+    FT_Int       n;
+
+    FT_UNUSED( threshold );
+    FT_UNUSED( end_x );
+    FT_UNUSED( end_y );
+
+
+    /* we don't even try to test the threshold in the non-hinting   */
+    /* builder, even if the flex operator is said to be a path      */
+    /* construction statement in the specification.  This is better */
+    /* left to the hinter.                                          */
+
+    flex = decoder->flex_vectors;
+    vec  = *flex++;
+
+    for ( n = 0; n < 6; n++ )
+    {
+      flex->x += vec.x;
+      flex->y += vec.y;
+
+      vec = *flex++;
+    }
+
+    flex  = decoder->flex_vectors;
+
+    return  decoder->builder.funcs.rcurve_to( &decoder->builder,
+                                              flex[0].x, flex[0].y,
+                                              flex[1].x, flex[1].y,
+                                              flex[2].x, flex[2].y ) ||
+
+            decoder->builder.funcs.rcurve_to( &decoder->builder,
+                                              flex[3].x, flex[3].y,
+                                              flex[4].x, flex[4].y,
+                                              flex[5].x, flex[5].y );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Parse_CharStrings                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given Type 1 charstrings program.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder         :: The current Type 1 decoder.                     */
+  /*                                                                       */
+  /*    charstring_base :: The base address of the charstring stream.      */
+  /*                                                                       */
+  /*    charstring_len  :: The length in bytes of the charstring stream.   */
+  /*                                                                       */
+  /*    num_subrs       :: The number of sub-routines.                     */
+  /*                                                                       */
+  /*    subrs_base      :: An array of sub-routines addresses.             */
+  /*                                                                       */
+  /*    subrs_len       :: An array of sub-routines lengths.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Free error code.  0 means success.                                 */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Parse_CharStrings( T1_Decoder*  decoder,
+                                  FT_Byte*     charstring_base,
+                                  FT_Int       charstring_len,
+                                  FT_Int       num_subrs,
+                                  FT_Byte**    subrs_base,
+                                  FT_Int*      subrs_len )
+  {
+    FT_Error           error;
+    T1_Decoder_Zone*   zone;
+    FT_Byte*           ip;
+    FT_Byte*           limit;
+    T1_Builder*        builder = &decoder->builder;
+    T1_Builder_Funcs*  builds  = &builder->funcs;
+    T1_Hinter_Funcs*   hints   = &decoder->hinter;
+
+    static
+    const FT_Int  args_count[op_max] =
+    {
+      0, /* none */
+      0, /* endchar */
+      2, /* hsbw */
+      5, /* seac */
+      4, /* sbw */
+      0, /* closepath */
+      1, /* hlineto */
+      1, /* hmoveto */
+      4, /* hvcurveto */
+      2, /* rlineto */
+      2, /* rmoveto */
+      6, /* rrcurveto */
+      4, /* vhcurveto */
+      1, /* vlineto */
+      1, /* vmoveto */
+      0, /* dotsection */
+      2, /* hstem */
+      6, /* hstem3 */
+      2, /* vstem */
+      6, /* vstem3 */
+      2, /* div */
+     -1, /* callothersubr */
+      1, /* callsubr */
+      0, /* pop */
+      0, /* return */
+      2  /* setcurrentpoint */
+    };
+
+
+    /* First of all, initialize the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+
+    builder->path_begun  = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error = T1_Err_Ok;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      FT_Int*      top   = decoder->top;
+      T1_Operator  op    = op_none;
+      FT_Long      value = 0;
+
+
+      /* Start with the decompression of operator or value */
+      switch ( *ip++ )
+      {
+      case 1:
+        op = op_hstem;
+        break;
+
+      case 3:
+        op = op_vstem;
+        break;
+      case 4:
+        op = op_vmoveto;
+        break;
+      case 5:
+        op = op_rlineto;
+        break;
+      case 6:
+        op = op_hlineto;
+        break;
+      case 7:
+        op = op_vlineto;
+        break;
+      case 8:
+        op = op_rrcurveto;
+        break;
+      case 9:
+        op = op_closepath;
+        break;
+      case 10:
+        op = op_callsubr;
+        break;
+      case 11:
+        op = op_return;
+        break;
+
+      case 13:
+        op = op_hsbw;
+        break;
+      case 14:
+        op = op_endchar;
+        break;
+
+      case 21:
+        op = op_rmoveto;
+        break;
+      case 22:
+        op = op_hmoveto;
+        break;
+
+      case 30:
+        op = op_vhcurveto;
+        break;
+      case 31:
+        op = op_hvcurveto;
+        break;
+
+      case 12:
+        if ( ip > limit )
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
+          goto Syntax_Error;
+        }
+
+        switch ( *ip++ )
+        {
+        case 0:
+          op = op_dotsection;
+          break;
+        case 1:
+          op = op_vstem3;
+          break;
+        case 2:
+          op = op_hstem3;
+          break;
+        case 6:
+          op = op_seac;
+          break;
+        case 7:
+          op = op_sbw;
+          break;
+        case 12:
+          op = op_div;
+          break;
+        case 16:
+          op = op_callothersubr;
+          break;
+        case 17:
+          op = op_pop;
+          break;
+        case 33:
+          op = op_setcurrentpoint;
+          break;
+
+        default:
+          FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+        break;
+
+      case 255:    /* four bytes integer */
+        if ( ip + 4 > limit )
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: unexpected EOF in integer\n" ));
+          goto Syntax_Error;
+        }
+
+        value = ( (FT_Long)ip[0] << 24 ) |
+                ( (FT_Long)ip[1] << 16 ) |
+                ( (FT_Long)ip[2] << 8  ) |
+                           ip[3];
+        ip += 4;
+        break;
+
+      default:
+        if ( ip[-1] >= 32 )
+        {
+          if ( ip[-1] < 247 )
+            value = (FT_Long)ip[-1] - 139;
+          else
+          {
+            if ( ++ip > limit )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings:" ));
+              FT_ERROR(( " unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( ip[-2] < 251 )
+              value = ((FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+            else
+              value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+          }
+        }
+        else
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: invalid byte (%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+      }
+
+      /* push value if necessary */
+      if ( op == op_none )
+      {
+        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+        {
+          FT_ERROR(( "T1_Parse_CharStrings: stack overflow!\n" ));
+          goto Syntax_Error;
+        }
+
+        *top++       = value;
+        decoder->top = top;
+      }
+
+      else if ( op == op_callothersubr ) /* check arguments differently */
+      {
+        if ( top - decoder->stack < 2 )
+          goto Stack_Underflow;
+
+        top -= 2;
+
+        switch ( top[1] )
+        {
+        case 1:   /* start flex feature */
+          if ( top[0] != 0 )
+            goto Unexpected_OtherSubr;
+
+          decoder->flex_state        = 1;
+          decoder->num_flex_vectors  = 0;
+          decoder->flex_vectors[0].x = 0;
+          decoder->flex_vectors[0].y = 0;
+          break;
+
+        case 2:   /* add flex vector */
+          {
+            FT_Int      index;
+            FT_Vector*  flex;
+
+
+            if ( top[0] != 0 )
+              goto Unexpected_OtherSubr;
+
+            top -= 2;
+            if ( top < decoder->stack )
+              goto Stack_Underflow;
+
+            index = decoder->num_flex_vectors++;
+            if ( index >= 7 )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings: too many flex vectors!\n" ));
+              goto Syntax_Error;
+            }
+
+            flex = decoder->flex_vectors + index;
+            flex->x += top[0];
+            flex->y += top[1];
+          }
+          break;
+
+        case 0:   /* end flex feature */
+          if ( decoder->flex_state       == 0 ||
+               decoder->num_flex_vectors != 7 )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" ));
+            goto Syntax_Error;
+          }
+
+          if ( top[0] != 3 )
+            goto Unexpected_OtherSubr;
+
+          top -= 3;
+          if ( top < decoder->stack )
+            goto Stack_Underflow;
+
+          /* now consume the remaining `pop pop setcurrentpoint' */
+          if ( ip + 6 > limit              ||
+               ip[0] != 12  || ip[1] != 17 ||   /* pop */
+               ip[2] != 12  || ip[3] != 17 ||   /* pop */
+               ip[4] != 12  || ip[5] != 33 )    /* setcurrentpoint */
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" ));
+            goto Syntax_Error;
+          }
+
+          decoder->flex_state = 0;
+          decoder->top        = top;
+
+          error = t1operator_flex( decoder, top[0], top[1], top[2] );
+          break;
+
+        case 3:  /* change hints */
+          if ( top[0] != 1 )
+            goto Unexpected_OtherSubr;
+
+          /* eat the following `pop' */
+          if ( ip + 2 > limit )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
+                       ip[-1] ));
+            goto Syntax_Error;
+          }
+
+          if ( ip[0] != 12 || ip[1] != 17 )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings:" ));
+            FT_ERROR(( " `pop' expected, found (%d %d)\n", ip[0], ip[1] ));
+            goto Syntax_Error;
+          }
+
+          ip += 2;
+
+          error  = hints->change_hints( builder );
+          break;
+
+        default:
+          /* invalid OtherSubrs call */
+        Unexpected_OtherSubr:
+          FT_ERROR(( "T1_Parse_CharStrings: unexpected OtherSubrs [%d %d]\n",
+                     top[0], top[1] ));
+          goto Syntax_Error;
+        }
+        decoder->top = top;
+      }
+      else
+      {
+        FT_Int  num_args = args_count[op];
+
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch ( op )
+        {
+        case op_endchar:
+          error = builds->end_char( builder );
+          break;
+
+        case op_hsbw:
+          error = builds->set_bearing_point( builder, top[0], 0,
+                                                      top[1], 0 );
+          break;
+
+        case op_seac:
+          /* return immediately after the processing */
+          return t1operator_seac( decoder, top[0], top[1],
+                                           top[2], top[3], top[4] );
+
+        case op_sbw:
+          error = builds->set_bearing_point( builder, top[0], top[1],
+                                                      top[2], top[3] );
+          break;
+
+        case op_closepath:
+          error = builds->close_path( builder );
+          break;
+
+        case op_hlineto:
+          error = builds->rline_to( builder, top[0], 0 );
+          break;
+
+        case op_hmoveto:
+          error = builds->rmove_to( builder, top[0], 0 );
+          break;
+
+        case op_hvcurveto:
+          error = builds->rcurve_to( builder, top[0], 0,
+                                              top[1], top[2],
+                                              0,      top[3] );
+          break;
+
+        case op_rlineto:
+          error = builds->rline_to( builder, top[0], top[1] );
+          break;
+
+        case op_rmoveto:
+          /* ignore operator when in flex mode */
+          if ( decoder->flex_state == 0 )
+            error = builds->rmove_to( builder, top[0], top[1] );
+          else
+            top += 2;
+          break;
+
+        case op_rrcurveto:
+          error = builds->rcurve_to( builder, top[0], top[1],
+                                              top[2], top[3],
+                                              top[4], top[5] );
+          break;
+
+        case op_vhcurveto:
+          error = builds->rcurve_to( builder,      0, top[0],
+                                              top[1], top[2],
+                                              top[3],      0 );
+          break;
+
+        case op_vlineto:
+          error = builds->rline_to( builder, 0, top[0] );
+          break;
+
+        case op_vmoveto:
+          error = builds->rmove_to( builder, 0, top[0] );
+          break;
+
+        case op_dotsection:
+          error = hints->dot_section( builder );
+          break;
+
+        case op_hstem:
+          error = hints->stem( builder, top[0], top[1], 0 );
+          break;
+
+        case op_hstem3:
+          error = hints->stem3( builder, top[0], top[1], top[2],
+                                         top[3], top[4], top[5], 0 );
+          break;
+
+        case op_vstem:
+          error = hints->stem( builder, top[0], top[1], 1 );
+          break;
+
+        case op_vstem3:
+          error = hints->stem3( builder, top[0], top[1], top[2],
+                                         top[3], top[4], top[5], 1 );
+          break;
+
+        case op_div:
+          if ( top[1] )
+          {
+            *top = top[0] / top[1];
+            ++top;
+          }
+          else
+          {
+            FT_ERROR(( "T1_Parse_CHarStrings: division by 0\n" ));
+            goto Syntax_Error;
+          }
+          break;
+
+        case op_callsubr:
+          {
+            FT_Int  index = top[0];
+
+
+            if ( index < 0 || index >= num_subrs )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = subrs_base[index];
+            zone->limit  = zone->base + subrs_len[index];
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+          }
+          break;
+
+        case op_pop:
+          FT_ERROR(( "T1_Parse_CharStrings: unexpected POP\n" ));
+          goto Syntax_Error;
+
+        case op_return:
+          if ( zone <= decoder->zones )
+          {
+            FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" ));
+            goto Syntax_Error;
+          }
+
+          zone--;
+          ip            = zone->cursor;
+          limit         = zone->limit;
+          decoder->zone = zone;
+          break;
+
+        case op_setcurrentpoint:
+          FT_ERROR(( "T1_Parse_CharStrings:" ));
+          FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
+          goto Syntax_Error;
+          break;
+
+        default:
+          FT_ERROR(( "T1_Parse_CharStrings: unhandled opcode %d\n", op ));
+          goto Syntax_Error;
+        }
+
+        decoder->top = top;
+      }
+    }
+
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return T1_Err_Stack_Underflow;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Add_Points                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Checks that there is enough room in the current load glyph outline */
+  /*    to accept `num_points' additional outline points.  If not, this    */
+  /*    function grows the load outline's arrays accordingly.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder    :: A pointer to the glyph builder object.               */
+  /*                                                                       */
+  /*    num_points :: The number of points that will be added later.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT update the points count in the glyph        */
+  /*    builder.  This must be done by the caller itself, after this       */
+  /*    function has been invoked.                                         */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Add_Points( T1_Builder*  builder,
+                           FT_Int       num_points )
+  {
+    return FT_GlyphLoader_Check_Points( builder->loader, num_points, 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Add_Contours                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Checks that there is enough room in the current load glyph outline */
+  /*    to accept `num_contours' additional contours.  If not, this        */
+  /*    function grows the load outline's arrays accordingly.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder      :: A pointer to the glyph builder object.             */
+  /*                                                                       */
+  /*    num_contours :: The number of contours that will be added later.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT update the contours count in the load glyph */
+  /*    This must be done by the caller itself, after this function is     */
+  /*    invoked.                                                           */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Add_Contours( T1_Builder*  builder,
+                             FT_Int       num_contours )
+  {
+    return FT_GlyphLoader_Check_Points( builder->loader, 0, num_contours );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  maxadv_sbw( T1_Decoder*  decoder,
+                        FT_Pos       sbx,
+                        FT_Pos       sby,
+                        FT_Pos       wx,
+                        FT_Pos       wy )
+  {
+    FT_UNUSED( sbx );
+    FT_UNUSED( sby );
+    FT_UNUSED( wy );
+
+    if ( wx > decoder->builder.advance.x )
+      decoder->builder.advance.x = wx;
+
+    return -1;    /* return an error code to exit the Type 1 parser */
+                  /* immediately.                                   */
+  }
+
+
+  static
+  FT_Int  maxadv_error( void )
+  {
+    /* we should never reach this code, unless with a buggy font */
+    return -2;
+  }
+
+
+  /* the maxadv_gbuilder_interface is used when computing the maximum  */
+  /* advance width of all glyphs in a given font.  We only process the */
+  /* `sbw' operator here, and return an error for all others.          */
+
+  /* Note that `seac' is processed by the T1_Decoder.                  */
+  static
+  const T1_Builder_Funcs  maxadv_builder_interface =
+  {
+    (T1_Builder_EndChar)  maxadv_error,
+    (T1_Builder_Sbw)      maxadv_sbw,
+    (T1_Builder_ClosePath)maxadv_error,
+    (T1_Builder_RLineTo)  maxadv_error,
+    (T1_Builder_RMoveTo)  maxadv_error,
+    (T1_Builder_RCurveTo) maxadv_error
+  };
+
+
+  /* the maxadv_hinter_interface always return an error. */
+  static
+  const T1_Hinter_Funcs  maxadv_hinter_interface =
+  {
+    (T1_Hinter_DotSection) maxadv_error,
+    (T1_Hinter_ChangeHints)maxadv_error,
+    (T1_Hinter_Stem)       maxadv_error,
+    (T1_Hinter_Stem3)      maxadv_error,
+  };
+
+
+  LOCAL_FUNC
+  FT_Error  T1_Compute_Max_Advance( T1_Face  face,
+                                    FT_Int*  max_advance )
+  {
+    FT_Error    error;
+    T1_Decoder  decoder;
+    FT_Int      glyph_index;
+    T1_Font*    type1 = &face->type1;
+
+
+    *max_advance = 0;
+
+    /* Initialize load decoder */
+    T1_Init_Decoder( &decoder, &maxadv_hinter_interface );
+
+    T1_Init_Builder( &decoder.builder, face, 0, 0,
+                     &maxadv_builder_interface );
+
+    /* For each glyph, parse the glyph charstring and extract */
+    /* the advance width.                                     */
+    for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+    {
+      /* now get load the unscaled outline */
+      error = T1_Parse_CharStrings( &decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+      /* ignore the error if one occured - skip to next glyph */
+    }
+
+    *max_advance = decoder.builder.advance.x;
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********               UNHINTED GLYPH LOADER                  *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of loading a      *********/
+  /**********    single outline.  It completely ignores hinting    *********/
+  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
+  /**********                                                      *********/
+  /**********      The Type 1 hinter is located in `t1hint.c'      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  close_open_path( T1_Builder*  builder )
+  {
+    FT_Error     error;
+    FT_Outline*  cur = builder->current;
+    FT_Int       num_points;
+    FT_Int       first_point;
+
+
+    /* Some fonts, like Hershey, are made of `open paths' which are     */
+    /* now managed directly by FreeType.  In this case, it is necessary */
+    /* to close the path by duplicating its points in reverse order,    */
+    /* which is precisely the purpose of this function.                 */
+
+    /* first compute the number of points to duplicate */
+    if ( cur->n_contours > 1 )
+      first_point = cur->contours[cur->n_contours - 2] + 1;
+    else
+      first_point = 0;
+
+    num_points = cur->n_points - first_point - 2;
+    if ( num_points > 0 )
+    {
+      FT_Vector*  source_point;
+      char*       source_tags;
+      FT_Vector*  point;
+      char*       tags;
+
+
+      error = T1_Add_Points( builder, num_points );
+      if ( error )
+        return error;
+
+      point = cur->points + cur->n_points;
+      tags  = cur->tags   + cur->n_points;
+
+      source_point = point - 2;
+      source_tags  = tags - 2;
+
+      cur->n_points += num_points;
+
+      if ( builder->load_points )
+        do
+        {
+          *point++ = *source_point--;
+          *tags++  = *source_tags--;
+          num_points--;
+
+        } while ( num_points > 0 );
+    }
+
+    builder->path_begun = 0;
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  gload_closepath( T1_Builder*  builder )
+  {
+    FT_Outline*  cur = builder->current;
+
+
+    /* XXXX: We must not include the last point in the path if it */
+    /*       is located on the first point.                       */
+    if ( cur->n_points > 1 )
+    {
+      FT_Int      first = 0;
+      FT_Vector*  p1    = cur->points + first;
+      FT_Vector*  p2    = cur->points + cur->n_points - 1;
+
+
+      if ( cur->n_contours > 1 )
+      {
+        first = cur->contours[cur->n_contours - 2] + 1;
+        p1    = cur->points + first;
+      }
+
+      if ( p1->x == p2->x && p1->y == p2->y )
+        cur->n_points--;
+    }
+
+    /* save current contour, if any */
+    if ( cur->n_contours > 0 )
+      cur->contours[cur->n_contours - 1] = cur->n_points - 1;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    /* hint last points if necessary -- this is not strictly required    */
+    /* there, but it helps for debugging, and doesn't affect performance */
+    if ( builder->pass == 1 )
+      T1_Hint_Points( builder );
+#endif
+
+    builder->path_begun = 0;
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  gload_endchar( T1_Builder*  builder )
+  {
+    FT_Error  error;
+
+
+    /* close path if needed */
+    if ( builder->path_begun )
+    {
+      error = close_open_path( builder );
+      if ( error )
+        return error;
+    }
+
+    error = gload_closepath( builder );
+
+    FT_GlyphLoader_Add( builder->loader );
+
+    return error;
+  }
+
+
+  static
+  FT_Error  gload_sbw( T1_Builder*  builder,
+                       FT_Pos       sbx,
+                       FT_Pos       sby,
+                       FT_Pos       wx,
+                       FT_Pos       wy )
+  {
+    builder->left_bearing.x += sbx;
+    builder->left_bearing.y += sby;
+    builder->advance.x       = wx;
+    builder->advance.y       = wy;
+
+    builder->last.x = sbx;
+    builder->last.y = sby;
+
+    return 0;
+  }
+
+
+  static
+  FT_Error  gload_rlineto( T1_Builder*  builder,
+                           FT_Pos       dx,
+                           FT_Pos       dy )
+  {
+    FT_Error     error;
+    FT_Outline*  cur = builder->current;
+    FT_Vector    vec;
+
+
+    /* grow buffer if necessary */
+    error = T1_Add_Points( builder, 1 );
+    if ( error )
+      return error;
+
+    if ( builder->load_points )
+    {
+      /* save point */
+      vec.x = builder->last.x + dx;
+      vec.y = builder->last.y + dy;
+
+      cur->points[cur->n_points] = vec;
+      cur->tags  [cur->n_points] = FT_Curve_Tag_On;
+
+      builder->last = vec;
+    }
+    cur->n_points++;
+
+    builder->path_begun = 1;
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  gload_rmoveto( T1_Builder*  builder,
+                           FT_Pos       dx,
+                           FT_Pos       dy )
+  {
+    FT_Error     error;
+    FT_Outline*  cur = builder->current;
+    FT_Vector    vec;
+
+
+    /* in the case where `path_begun' is set, we have an `rmoveto' */
+    /* after some normal path definition. If the face's paint type */
+    /* is set to 1, this means that we have an `open path', also   */
+    /* called a `stroke'.  The FreeType raster doesn't support     */
+    /* opened paths, so we'll close it explicitely there.          */
+
+    if ( builder->path_begun && builder->face->type1.paint_type == 1 )
+    {
+      if ( builder->face->type1.paint_type == 1 )
+      {
+        error = close_open_path( builder );
+        if ( error )
+          return error;
+      }
+    }
+
+    /* grow buffer if necessary */
+    error = T1_Add_Contours( builder, 1 ) ||
+            T1_Add_Points  ( builder, 1 );
+    if ( error )
+      return error;
+
+    /* save current contour, if any */
+    if ( cur->n_contours > 0 )
+      cur->contours[cur->n_contours - 1] = cur->n_points - 1;
+
+    if ( builder->load_points )
+    {
+      /* save point */
+      vec.x = builder->last.x + dx;
+      vec.y = builder->last.y + dy;
+      cur->points[cur->n_points] = vec;
+      cur->tags  [cur->n_points] = FT_Curve_Tag_On;
+
+      builder->last = vec;
+    }
+
+    cur->n_contours++;
+    cur->n_points++;
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  gload_rrcurveto( T1_Builder*  builder,
+                             FT_Pos       dx1,
+                             FT_Pos       dy1,
+                             FT_Pos       dx2,
+                             FT_Pos       dy2,
+                             FT_Pos       dx3,
+                             FT_Pos       dy3 )
+  {
+    FT_Error     error;
+    FT_Outline*  cur = builder->current;
+    FT_Vector    vec;
+    FT_Vector*   points;
+    char*        tags;
+
+
+    /* grow buffer if necessary */
+    error = T1_Add_Points( builder, 3 );
+    if ( error )
+      return error;
+
+    if ( builder->load_points )
+    {
+      /* save point */
+      points = cur->points + cur->n_points;
+      tags   = cur->tags  + cur->n_points;
+
+      vec.x = builder->last.x + dx1;
+      vec.y = builder->last.y + dy1;
+      points[0] = vec;
+      tags[0]   = FT_Curve_Tag_Cubic;
+
+      vec.x += dx2;
+      vec.y += dy2;
+      points[1] = vec;
+      tags[1]   = FT_Curve_Tag_Cubic;
+
+      vec.x += dx3;
+      vec.y += dy3;
+      points[2] = vec;
+      tags[2]   = FT_Curve_Tag_On;
+
+      builder->last = vec;
+    }
+
+    cur->n_points      += 3;
+    builder->path_begun = 1;
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  gload_ignore( void )
+  {
+    return 0;
+  }
+
+
+  static
+  const T1_Builder_Funcs  gload_builder_interface =
+  {
+    gload_endchar,
+    gload_sbw,
+    gload_closepath,
+    gload_rlineto,
+    gload_rmoveto,
+    gload_rrcurveto
+  };
+
+
+  static
+  const T1_Builder_Funcs  gload_builder_interface_null =
+  {
+    (T1_Builder_EndChar)  gload_ignore,
+    (T1_Builder_Sbw)      gload_sbw,      /* record left bearing */
+    (T1_Builder_ClosePath)gload_ignore,
+    (T1_Builder_RLineTo)  gload_ignore,
+    (T1_Builder_RMoveTo)  gload_ignore,
+    (T1_Builder_RCurveTo) gload_ignore
+  };
+
+
+  static
+  const T1_Hinter_Funcs   gload_hinter_interface =
+  {
+    (T1_Hinter_DotSection) gload_ignore,   /* dotsection         */
+    (T1_Hinter_ChangeHints)gload_ignore,   /* changehints        */
+    (T1_Hinter_Stem)       gload_ignore,   /* hstem & vstem      */
+    (T1_Hinter_Stem3)      gload_ignore,   /* hstem3 & vestem3   */
+  };
+
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Hinter overview:                                                     */
+  /*                                                                       */
+  /*    This is a two-pass hinter.  On the first pass, the hints are all   */
+  /*    recorded by the hinter, and no point is loaded in the outline.     */
+  /*                                                                       */
+  /*    When the first pass is finished, all stems hints are grid-fitted   */
+  /*    at once.                                                           */
+  /*                                                                       */
+  /*    Then, a second pass is performed to load the outline points as     */
+  /*    well as hint/scale them correctly.                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static
+  FT_Error  t1_load_hinted_glyph( T1_Decoder*  decoder,
+                                  FT_UInt      glyph_index,
+                                  FT_Bool      recurse )
+  {
+    T1_Builder*      builder = &decoder->builder;
+    T1_GlyphSlot     glyph   = builder->glyph;
+    T1_Font*         type1   = &builder->face->type1;
+    FT_UInt          old_points, old_contours;
+    FT_GlyphLoader*  loader = decoder->builder.loader;
+    FT_Error         error;
+
+
+    /* Pass 1 -- try to load first glyph, simply recording points */
+    old_points   = loader->base.outline.n_points;
+    old_contours = loader->base.outline.n_contours;
+
+    FT_GlyphLoader_Prepare( decoder->builder.loader );
+
+    T1_Reset_Builder( builder, 0 );
+
+    builder->no_recurse                = recurse;
+    builder->pass                      = 0;
+    glyph->hints->hori_stems.num_stems = 0;
+    glyph->hints->vert_stems.num_stems = 0;
+
+    error = T1_Parse_CharStrings( decoder,
+                                  type1->charstrings    [glyph_index],
+                                  type1->charstrings_len[glyph_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+    if ( error )
+      goto Exit;
+
+    /* check for composite (i.e. `seac' operator) */
+    if ( glyph->root.format == ft_glyph_format_composite )
+    {
+      /* this is a composite glyph, we must then load the first one, */
+      /* then load the second one on top of it and translate it by a */
+      /* fixed amount.                                               */
+      FT_UInt       n_base_points;
+      FT_SubGlyph*  subglyph = loader->base.subglyphs;
+      T1_Size       size = builder->size;
+      FT_Pos        dx, dy;
+      FT_Vector     left_bearing, advance;
+
+
+      /* clean glyph format */
+      glyph->root.format = ft_glyph_format_none;
+
+      /* First load `bchar' in builder */
+      builder->no_recurse = 0;
+      error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
+      if ( error )
+        goto Exit;
+
+      /* save the left bearing and width of the base character */
+      /* as they will be erased by the next load               */
+      left_bearing = builder->left_bearing;
+      advance      = builder->advance;
+
+      /* Then load `achar' in builder */
+      n_base_points = builder->base->n_points;
+      subglyph++;
+      error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
+      if ( error )
+        goto Exit;
+
+      /* Finally, move the accent */
+      dx = FT_MulFix( subglyph->arg1, size->root.metrics.x_scale );
+      dy = FT_MulFix( subglyph->arg2, size->root.metrics.y_scale );
+      dx = ( dx + 32 ) & -64;
+      dy = ( dy + 32 ) & -64;
+      {
+        FT_Outline  dummy;
+
+
+        dummy.n_points = loader->base.outline.n_points - n_base_points;
+        dummy.points   = loader->base.outline.points   + n_base_points;
+
+        FT_Outline_Translate( &dummy, dx, dy );
+      }
+
+      /* restore the left side bearing and   */
+      /* advance width of the base character */
+      builder->left_bearing = left_bearing;
+      builder->advance      = advance;
+    }
+    else
+    {
+      /* All right, pass 1 is finished, now grid-fit all stem hints */
+      T1_Hint_Stems( &decoder->builder );
+
+      /* undo the end-char */
+      builder->base->n_points   = old_points;
+      builder->base->n_contours = old_contours;
+
+      /* Pass 2 -- record and scale/hint the points */
+      T1_Reset_Builder( builder, 0 );
+
+      builder->pass       = 1;
+      builder->no_recurse = 0;
+
+      error = T1_Parse_CharStrings( decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+    }
+
+    /* save new glyph tables */
+    if ( recurse )
+      T1_Done_Builder( builder );
+
+  Exit:
+    return error;
+  }
+
+
+#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */
+
+
+  LOCAL_FUNC
+  FT_Error  T1_Load_Glyph( T1_GlyphSlot  glyph,
+                           T1_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags )
+  {
+    FT_Error    error;
+    T1_Decoder  decoder;
+    T1_Face     face = (T1_Face)glyph->root.face;
+    FT_Bool     hinting;
+    T1_Font*    type1 = &face->type1;
+
+
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = size->root.metrics.x_scale;
+    glyph->y_scale = size->root.metrics.y_scale;
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    glyph->root.format = ft_glyph_format_outline;  /* by default */
+
+    hinting = 0;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+    hinting = ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0;
+
+    if ( hinting )
+    {
+      T1_Init_Decoder( &decoder, &t1_hinter_funcs );
+      T1_Init_Builder( &decoder.builder, face, size, glyph,
+                       &gload_builder_interface );
+
+      error = t1_load_hinted_glyph( &decoder, glyph_index, 1 );
+    }
+    else
+
+#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */
+
+    {
+      T1_Init_Decoder( &decoder, &gload_hinter_interface );
+
+      T1_Init_Builder( &decoder.builder, face, size, glyph,
+                       &gload_builder_interface );
+
+      decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
+
+      /* now load the unscaled outline */
+      error = T1_Parse_CharStrings( &decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+
+      /* save new glyph tables */
+      T1_Done_Builder( &decoder.builder );
+    }
+
+    /* Now, set the metrics -- this is rather simple, as   */
+    /* the left side bearing is the xMin, and the top side */
+    /* bearing the yMax                                    */
+    if ( !error )
+    {
+      /* for composite glyphs, return only the left side bearing and the */
+      /* advance width                                                   */
+      if ( glyph->root.format == ft_glyph_format_composite )
+      {
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
+      }
+      else
+      {
+        FT_BBox           cbox;
+        FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline,
+                              &face->type1.font_matrix );
+
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if ( hinting )
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance = decoder.builder.advance.x;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        glyph->root.outline.flags = 0;
+
+        if ( size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+        if ( hinting )
+        {
+          /* adjust the advance width               */
+          /* XXX TODO: consider stem hints grid-fit */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,
+                                             glyph->x_scale );
+        }
+        else if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur = decoder.builder.base;
+          FT_Vector*   vec = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_Fixed     y_scale = glyph->y_scale;
+
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          /* Then scale the metrics */
+          metrics->width  = FT_MulFix( metrics->width,  x_scale );
+          metrics->height = FT_MulFix( metrics->height, y_scale );
+
+          metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
+          metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+        }
+      }
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1/t1gload.h b/src/freetype/type1/t1gload.h
new file mode 100644 (file)
index 0000000..658a929
--- /dev/null
@@ -0,0 +1,326 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1gload.h                                                              */
+/*                                                                         */
+/*    Type 1 Glyph Loader (specification).                                 */
+/*                                                                         */
+/*  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 T1GLOAD_H
+#define T1GLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+
+#else
+
+#include <type1/t1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  typedef struct T1_Builder_  T1_Builder;
+
+  typedef FT_Error  (*T1_Builder_EndChar)( T1_Builder*  loader );
+
+  typedef FT_Error  (*T1_Builder_Sbw)( T1_Builder*  loader,
+                                       FT_Pos       sbx,
+                                       FT_Pos       sby,
+                                       FT_Pos       wx,
+                                       FT_Pos       wy );
+
+  typedef FT_Error  (*T1_Builder_ClosePath)( T1_Builder*  loader );
+
+  typedef FT_Error  (*T1_Builder_RLineTo)( T1_Builder*  loader,
+                                           FT_Pos       dx,
+                                           FT_Pos       dy );
+
+  typedef FT_Error  (*T1_Builder_RMoveTo)( T1_Builder*  loader,
+                                           FT_Pos       dx,
+                                           FT_Pos       dy );
+
+  typedef FT_Error  (*T1_Builder_RCurveTo)( T1_Builder*  loader,
+                                            FT_Pos       dx1,
+                                            FT_Pos       dy1,
+                                            FT_Pos       dx2,
+                                            FT_Pos       dy2,
+                                            FT_Pos       dx3,
+                                            FT_Pos       dy3 );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    T1_Builder_Funcs                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure to store the address of various functions used by a    */
+  /*    glyph builder to implement the outline's `path construction'.      */
+  /*                                                                       */
+  typedef struct  T1_Builder_Funcs_
+  {
+    T1_Builder_EndChar    end_char;
+    T1_Builder_Sbw        set_bearing_point;
+    T1_Builder_ClosePath  close_path;
+    T1_Builder_RLineTo    rline_to;
+    T1_Builder_RMoveTo    rmove_to;
+    T1_Builder_RCurveTo   rcurve_to;
+
+  } T1_Builder_Funcs;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    T1_Builder                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used during glyph loading to store its outline.        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory       :: The current memory object.                         */
+  /*                                                                       */
+  /*    face         :: The current face object.                           */
+  /*                                                                       */
+  /*    size         :: The current size object.                           */
+  /*                                                                       */
+  /*    glyph        :: The current glyph slot.                            */
+  /*                                                                       */
+  /*    loader       :: The current glyph loader.                          */
+  /*                                                                       */
+  /*    current      :: The current glyph outline.                         */
+  /*                                                                       */
+  /*    base         :: The base glyph outline.                            */
+  /*                                                                       */
+  /*    last         :: The last point position.                           */
+  /*                                                                       */
+  /*    scale_x      :: The horizontal scale (FUnits to sub-pixels).       */
+  /*                                                                       */
+  /*    scale_y      :: The vertical scale (FUnits to sub-pixels).         */
+  /*                                                                       */
+  /*    pos_x        :: The horizontal translation (for composite glyphs). */
+  /*                                                                       */
+  /*    pos_y        :: The vertical translation (for composite glyphs).   */
+  /*                                                                       */
+  /*    left_bearing :: The left side bearing point.                       */
+  /*                                                                       */
+  /*    advance      :: The horizontal advance vector.                     */
+  /*                                                                       */
+  /*    no_recurse   ::                                                    */
+  /*                                                                       */
+  /*    bbox         :: The glyph's bounding box.                          */
+  /*                                                                       */
+  /*    path_begun   :: A flag which indicates that a new path has begun.  */
+  /*                                                                       */
+  /*    load_points  :: A flag which indicates, if not set, that no points */
+  /*                    are loaded.                                        */
+  /*                                                                       */
+  /*    pass         :: The pass number for multi-pass hinters.            */
+  /*                                                                       */
+  /*    hint_point   :: The index of the next point to hint.               */
+  /*                                                                       */
+  /*    funcs        :: A table of builder functions used to perform the   */
+  /*                    outline's path construction.                       */
+  /*                                                                       */
+  struct  T1_Builder_
+  {
+    FT_Memory        memory;
+    T1_Face          face;
+    T1_Size          size;
+    T1_GlyphSlot     glyph;
+    FT_GlyphLoader*  loader;
+
+    FT_Outline*      current;       /* the current glyph outline   */
+    FT_Outline*      base;          /* the composite glyph outline */
+
+    FT_Vector        last;
+
+    FT_Fixed         scale_x;
+    FT_Fixed         scale_y;
+
+    FT_Pos           pos_x;
+    FT_Pos           pos_y;
+
+    FT_Vector        left_bearing;
+    FT_Vector        advance;
+    FT_Bool          no_recurse;
+
+    FT_BBox          bbox;          /* bounding box */
+    FT_Bool          path_begun;
+    FT_Bool          load_points;
+
+    FT_Int           pass;
+    FT_Int           hint_point;
+
+    /* path construction function interface */
+    T1_Builder_Funcs  funcs;
+  };
+
+
+  typedef FT_Error  (*T1_Hinter_ChangeHints)( T1_Builder*  builder );
+
+  typedef FT_Error  (*T1_Hinter_DotSection)( T1_Builder*  builder );
+
+  typedef FT_Error  (*T1_Hinter_Stem)( T1_Builder*  builder,
+                                       FT_Pos       pos,
+                                       FT_Pos       width,
+                                       FT_Bool      vertical );
+
+  typedef FT_Error  (*T1_Hinter_Stem3)( T1_Builder*  builder,
+                                        FT_Pos       pos0,
+                                        FT_Pos       width0,
+                                        FT_Pos       pos1,
+                                        FT_Pos       width1,
+                                        FT_Pos       pos2,
+                                        FT_Pos       width2,
+                                        FT_Bool      vertical );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    T1_Hinter_Funcs                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure to store the address of various functions used by a    */
+  /*    Type 1 hinter to perform outline hinting.                          */
+  /*                                                                       */
+  typedef struct  T1_Hinter_Func_
+  {
+    T1_Hinter_ChangeHints  change_hints;
+    T1_Hinter_DotSection   dot_section;
+    T1_Hinter_Stem         stem;
+    T1_Hinter_Stem3        stem3;
+
+  } T1_Hinter_Funcs;
+
+
+  typedef enum  T1_Operator_
+  {
+    op_none = 0,
+    op_endchar,
+    op_hsbw,
+    op_seac,
+    op_sbw,
+    op_closepath,
+    op_hlineto,
+    op_hmoveto,
+    op_hvcurveto,
+    op_rlineto,
+    op_rmoveto,
+    op_rrcurveto,
+    op_vhcurveto,
+    op_vlineto,
+    op_vmoveto,
+    op_dotsection,
+    op_hstem,
+    op_hstem3,
+    op_vstem,
+    op_vstem3,
+    op_div,
+    op_callothersubr,
+    op_callsubr,
+    op_pop,
+    op_return,
+    op_setcurrentpoint,
+
+    op_max    /* never remove this one */
+
+  } T1_Operator;
+
+
+  /* execution context charstring zone */
+  typedef struct  T1_Decoder_Zone_
+  {
+    FT_Byte*  base;
+    FT_Byte*  limit;
+    FT_Byte*  cursor;
+
+  } T1_Decoder_Zone;
+
+
+  typedef struct  T1_Decoder_
+  {
+    T1_Builder        builder;
+    T1_Hinter_Funcs   hinter;
+
+    FT_Int            stack[T1_MAX_CHARSTRINGS_OPERANDS];
+    FT_Int*           top;
+
+    T1_Decoder_Zone   zones[T1_MAX_SUBRS_CALLS + 1];
+    T1_Decoder_Zone*  zone;
+
+    FT_Int            flex_state;
+    FT_Int            num_flex_vectors;
+    FT_Vector         flex_vectors[7];
+
+  } T1_Decoder;
+
+
+  LOCAL_DEF
+  void  T1_Init_Builder( T1_Builder*              builder,
+                         T1_Face                  face,
+                         T1_Size                  size,
+                         T1_GlyphSlot             glyph,
+                         const T1_Builder_Funcs*  funcs );
+
+  LOCAL_DEF
+  void T1_Done_Builder( T1_Builder*  builder );
+
+  LOCAL_DEF
+  void  T1_Init_Decoder( T1_Decoder*             decoder,
+                         const T1_Hinter_Funcs*  funcs );
+
+  LOCAL_DEF
+  FT_Error  T1_Compute_Max_Advance( T1_Face  face,
+                                    FT_Int*  max_advance );
+
+  LOCAL_DEF
+  FT_Error  T1_Parse_CharStrings( T1_Decoder*  decoder,
+                                  FT_Byte*     charstring_base,
+                                  FT_Int       charstring_len,
+                                  FT_Int       num_subrs,
+                                  FT_Byte**    subrs_base,
+                                  FT_Int*      subrs_len );
+
+  LOCAL_DEF
+  FT_Error  T1_Add_Points( T1_Builder*  builder,
+                           FT_Int       num_points );
+
+  LOCAL_DEF
+  FT_Error  T1_Add_Contours( T1_Builder*  builder,
+                             FT_Int       num_contours );
+
+  LOCAL_DEF
+  FT_Error  T1_Load_Glyph( T1_GlyphSlot  glyph,
+                           T1_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T1GLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/type1/t1hinter.c b/src/freetype/type1/t1hinter.c
new file mode 100644 (file)
index 0000000..7ce7462
--- /dev/null
@@ -0,0 +1,1347 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1hinter.c                                                             */
+/*                                                                         */
+/*    Type 1 hinter (body).                                                */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The Hinter is in charge of fitting th scaled outline to the pixel     */
+  /* grid in order to considerably improve the quality of the Type 1 font  */
+  /* driver's output.                                                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+#include "t1hinter.h"
+
+#else
+
+#include <type1/t1objs.h>
+#include <type1/t1hinter.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1hint
+
+
+#undef  ONE_PIXEL
+#define ONE_PIXEL  64
+
+#undef  ROUND
+#define ROUND( x )    ( ( x + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+
+#undef  SCALE
+#define SCALE( val )  FT_MulFix( val, scale )
+
+/* various constants used to describe the alignment of a horizontal */
+/* stem with regards to the blue zones                              */
+
+#define T1_ALIGN_NONE    0
+#define T1_ALIGN_BOTTOM  1
+#define T1_ALIGN_TOP     2
+#define T1_ALIGN_BOTH    3
+
+
+  /* very simple bubble sort (not a lot of elements, mostly */
+  /* pre-sorted, no need for quicksort)                     */
+
+  static
+  void  t1_sort_blues( FT_Int*  blues,
+                       FT_Int   count )
+  {
+    FT_Int   i, swap;
+    FT_Int*  cur;
+
+
+    for ( i = 2; i < count; i += 2 )
+    {
+      cur = blues + i;
+      do
+      {
+        if ( cur[-1] < cur[0] )
+          break;
+
+        swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap;
+        swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap;
+        cur -= 2;
+
+      } while ( cur > blues );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_set_blue_zones                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets a size object's blue zones during reset.  This will compute   */
+  /*    the `snap' zone corresponding to each blue zone.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to target size object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This functions does the following:                                 */
+  /*                                                                       */
+  /*    1. It extracts the bottom and top blue zones from the face object. */
+  /*                                                                       */
+  /*    2. Each zone is then grown by `BlueFuzz', overlapping is           */
+  /*       eliminated by adjusting the zone edges appropriately.           */
+  /*                                                                       */
+  /*    3. For each zone, we keep its original font units position, its    */
+  /*       original scaled position, as well as its grown/adjusted edges.  */
+  /*                                                                       */
+  static
+  FT_Error  t1_set_blue_zones( T1_Size  size )
+  {
+    T1_Face         face = (T1_Face)size->root.face;
+    T1_Private*     priv = &face->type1.private_dict;
+    FT_Int          n;
+    FT_Int          blues[24];
+    FT_Int          num_bottom;
+    FT_Int          num_top;
+    FT_Int          num_blues;
+    T1_Size_Hints*  hints = size->hints;
+    T1_Snap_Zone*   zone;
+    FT_Pos          pix, orus;
+    FT_Pos          min, max, threshold;
+    FT_Fixed        scale;
+    FT_Bool         is_bottom;
+
+
+    /***********************************************************************/
+    /*                                                                     */
+    /*  copy bottom and top blue zones in local arrays                     */
+    /*                                                                     */
+
+    /* First of all, check the sizes of the /BlueValues and /OtherBlues */
+    /* tables.  They all must contain an even number of arguments.      */
+    if ( priv->num_other_blues & 1 ||
+         priv->num_blue_values & 1 )
+    {
+      FT_ERROR(( "t1_set_blue_zones: odd number of blue values\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* copy the bottom blue zones from /OtherBlues */
+    num_top    = 0;
+    num_bottom = priv->num_other_blues;
+
+    for ( n = 0; n < num_bottom; n++ )
+      blues[n] = priv->other_blues[n];
+
+    /* add the first blue zone in /BlueValues to the table */
+    num_top = priv->num_blue_values - 2;
+    if ( num_top >= 0 )
+    {
+      blues[num_bottom    ] = priv->blue_values[0];
+      blues[num_bottom + 1] = priv->blue_values[1];
+
+      num_bottom += 2;
+    }
+
+    /* sort the bottom blue zones */
+    t1_sort_blues( blues, num_bottom );
+
+    hints->num_bottom_zones = num_bottom >> 1;
+
+    /* now copy the /BlueValues to the top of the blues array */
+    if ( num_top > 0 )
+    {
+      for ( n = 0; n < num_top; n++ )
+        blues[num_bottom + n] = priv->blue_values[n + 2];
+
+      /* sort the top blue zones */
+      t1_sort_blues( blues + num_bottom, num_top );
+    }
+    else
+      num_top = 0;
+
+    num_blues             = num_top + num_bottom;
+    hints->num_blue_zones = ( num_blues ) >> 1;
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* build blue snap zones from the local blues arrays                   */
+    /*                                                                     */
+
+    scale     = size->root.metrics.y_scale;
+    zone      = hints->blue_zones;
+    threshold = ONE_PIXEL / 4;   /* 0.25 pixels */
+
+    for ( n = 0; n < num_blues; n += 2, zone++ )
+    {
+      is_bottom = n < num_bottom ? 1 : 0;
+
+      orus = blues[n + is_bottom];  /* get alignement coordinate */
+      pix  = SCALE( orus );         /* scale it                  */
+
+      min  = SCALE( blues[n    ] - priv->blue_fuzz );
+      max  = SCALE( blues[n + 1] + priv->blue_fuzz );
+
+      if ( min > pix - threshold )
+        min = pix - threshold;
+      if ( max < pix + threshold )
+        max = pix + threshold;
+
+      zone->orus = orus;
+      zone->pix  = pix;
+      zone->min  = min;
+      zone->max  = max;
+    }
+
+    /* adjust edges in case of overlap */
+    zone = hints->blue_zones;
+    for ( n = 0; n < num_blues - 2; n += 2, zone++ )
+    {
+      if ( n != num_bottom - 2       &&
+           zone[0].max > zone[1].min )
+        zone[0].max = zone[1].min = ( zone[0].pix + zone[1].pix ) / 2;
+    }
+
+    /* compare the current pixel size with the BlueScale value */
+    /* to know whether to supress overshoots                   */
+
+    hints->supress_overshoots =
+      size->root.metrics.y_ppem < FT_MulFix( 1000, priv->blue_scale );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+    /* now print the new blue values in tracing mode */
+
+    FT_TRACE2(( "Blue Zones for size object at $%08lx:\n", (long)size ));
+    FT_TRACE2(( "   orus    pix    min   max\n" ));
+    FT_TRACE2(( "-------------------------------\n" ));
+
+    zone = hints->blue_zones;
+    for ( n = 0; n < hints->num_blue_zones; n++ )
+    {
+      FT_TRACE2(( "    %3d   %.2f   %.2f  %.2f\n",
+                  zone->orus,
+                  zone->pix / 64.0,
+                  zone->min / 64.0,
+                  zone->max / 64.0 ));
+      zone++;
+    }
+    FT_TRACE2(( "\nOvershoots are %s\n\n",
+                hints->supress_overshoots ? "supressed" : "active" ));
+
+#endif /* DEBUG_LEVEL_TRACE */
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_set_snap_zones                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function set a size object's stem snap zones.                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function performs the following:                              */
+  /*                                                                       */
+  /*    1. It reads and scales the stem snap widths from the parent face.  */
+  /*                                                                       */
+  /*    2. A `snap zone' is computed for each snap width, by `growing' it  */
+  /*       with a threshold of 1/2 pixel.  Overlapping is avoided through  */
+  /*       proper edge adjustment.                                         */
+  /*                                                                       */
+  /*    3. Each width whose zone contain the scaled standard set width is  */
+  /*       removed from the table.                                         */
+  /*                                                                       */
+  /*    4. Finally, the standard set width is scaled, and its correponding */
+  /*       `snap zone' is inserted into the sorted snap zones table.       */
+  /*                                                                       */
+  static
+  FT_Error  t1_set_snap_zones( T1_Size  size )
+  {
+    FT_Int          n, direction, n_zones, num_zones;
+    T1_Snap_Zone*   zone;
+    T1_Snap_Zone*   base_zone;
+    FT_Short*       orgs;
+    FT_Pos          standard_width;
+    FT_Fixed        scale;
+
+    T1_Face         face  = (T1_Face)size->root.face;
+    T1_Private*     priv  = &face->type1.private_dict;
+    T1_Size_Hints*  hints = size->hints;
+
+
+    /* start with horizontal snap zones */
+    direction      = 0;
+    standard_width = priv->standard_width[0];
+    n_zones        = priv->num_snap_widths;
+    base_zone      = hints->snap_widths;
+    orgs           = priv->snap_widths;
+    scale          = size->root.metrics.x_scale;
+
+    while ( direction < 2 )
+    {
+      /*********************************************************************/
+      /*                                                                   */
+      /* Read and scale stem snap widths table from the physical font      */
+      /* record.                                                           */
+      /*                                                                   */
+
+      FT_Pos  prev, orus, pix, min, max, threshold;
+
+
+      threshold = ONE_PIXEL / 4;
+      zone      = base_zone;
+
+      if ( n_zones > 0 )
+      {
+        orus = *orgs++;
+        pix  = SCALE( orus );
+        min  = pix - threshold;
+        max  = pix + threshold;
+
+        zone->orus = orus;
+        zone->pix  = pix;
+        zone->min  = min;
+        prev       = pix;
+
+        for ( n = 1; n < n_zones; n++ )
+        {
+          orus = *orgs++;
+          pix  = SCALE( orus );
+
+          if ( pix - prev < 2 * threshold )
+          {
+            min = max = ( pix + prev ) / 2;
+          }
+          else
+            min = pix - threshold;
+
+          zone->max = max;
+          zone++;
+          zone->orus = orus;
+          zone->pix  = pix;
+          zone->min  = min;
+
+          max  = pix + threshold;
+          prev = pix;
+        }
+        zone->max = max;
+      }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+      /* print the scaled stem snap values in tracing mode */
+
+      FT_TRACE2(( "Set_Snap_Zones: first %s pass\n",
+                  direction ? "vertical" : "horizontal" ));
+
+      FT_TRACE2(( "Scaled original stem snap zones:\n" ));
+      FT_TRACE2(( "   orus   pix   min   max\n" ));
+      FT_TRACE2(( "-----------------------------\n" ));
+
+      zone = base_zone;
+      for ( n = 0; n < n_zones; n++, zone++ )
+        FT_TRACE2(( "  %3d  %.2f  %.2f  %.2f\n",
+                    zone->orus,
+                    zone->pix / 64.0,
+                    zone->min / 64.0,
+                    zone->max / 64.0 ));
+      FT_TRACE2(( "\n" ));
+
+      FT_TRACE2(( "Standard width = %d\n", standard_width ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Now, each snap width which is in the range of the standard set    */
+      /* width will be removed from the list.                              */
+      /*                                                                   */
+
+      if ( standard_width > 0 )
+      {
+        T1_Snap_Zone*  parent;
+        FT_Pos         std_pix, std_min, std_max;
+
+
+        std_pix = SCALE( standard_width );
+
+        std_min = std_pix - threshold;
+        std_max = std_pix + threshold;
+
+        num_zones = 0;
+        zone      = base_zone;
+        parent    = base_zone;
+
+        for ( n = 0; n < n_zones; n++ )
+        {
+          if ( zone->pix >= std_min && zone->pix <= std_max )
+          {
+            /* this zone must be removed from the list */
+            if ( std_min > zone->min )
+              std_min = zone->min;
+            if ( std_max < zone->max )
+              std_max = zone->max;
+          }
+          else
+          {
+            *parent++ = *zone;
+            num_zones++;
+          }
+          zone++;
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Now, insert the standard width zone                             */
+        /*                                                                 */
+
+        zone = base_zone + num_zones;
+        while ( zone > base_zone && zone[-1].pix > std_max )
+        {
+          zone[0] = zone[-1];
+          zone--;
+        }
+
+        /* check border zones */
+        if ( zone > base_zone && zone[-1].max > std_min )
+          zone[-1].max = std_min;
+
+        if ( zone < base_zone + num_zones && zone[1].min < std_max )
+          zone[1].min = std_max;
+
+        zone->orus = standard_width;
+        zone->pix  = std_pix;
+        zone->min  = std_min;
+        zone->max  = std_max;
+
+        num_zones++;
+      }
+      else
+        num_zones = n_zones;
+
+      /* save total number of stem snaps now */
+      if ( direction )
+        hints->num_snap_heights = num_zones;
+      else
+        hints->num_snap_widths  = num_zones;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+      /* print the scaled stem snap values in tracing mode */
+
+      FT_TRACE2(( "Set_Snap_Zones: second %s pass\n",
+                  direction ? "vertical" : "horizontal" ));
+
+      FT_TRACE2(( "Scaled clipped stem snap zones:\n" ));
+      FT_TRACE2(( "   orus   pix   min   max\n" ));
+      FT_TRACE2(( "-----------------------------\n" ));
+
+      zone = base_zone;
+      for ( n = 0; n < num_zones; n++, zone++ )
+        FT_TRACE2(( "  %3d  %.2f  %.2f  %.2f\n",
+                    zone->orus,
+                    zone->pix / 64.0,
+                    zone->min / 64.0,
+                    zone->max / 64.0 ));
+      FT_TRACE2(( "\n" ));
+
+      FT_TRACE2(( "Standard width = %d\n", standard_width ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+      /* continue with vertical snap zone */
+      direction++;
+      standard_width = priv->standard_height[0];
+      n_zones        = priv->num_snap_heights;
+      base_zone      = hints->snap_heights;
+      orgs           = priv->snap_heights;
+      scale          = size->root.metrics.y_scale;
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_New_Size_Hinter                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Allocates a new hinter structure for a given size object.          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType Error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_New_Size_Hinter( T1_Size  size )
+  {
+    FT_Memory  memory = size->root.face->memory;
+
+
+    return MEM_Alloc( size->hints, sizeof ( *size->hints ) );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Size_Hinter                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Releases a given size object's hinter structure.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_Size_Hinter( T1_Size  size )
+  {
+    FT_Memory  memory = size->root.face->memory;
+
+
+    FREE( size->hints );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Reset_Size_Hinter                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Recomputes hinting information when a given size object has        */
+  /*    changed its resolutions/char sizes/pixel sizes.                    */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the size object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Reset_Size_Hinter( T1_Size  size )
+  {
+    return t1_set_blue_zones( size ) || t1_set_snap_zones( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_New_Glyph_Hinter                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Allocates a new hinter structure for a given glyph slot.           */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    glyph :: A handle to the target glyph slot.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_New_Glyph_Hinter( T1_GlyphSlot  glyph )
+  {
+    FT_Memory  memory = glyph->root.face->memory;
+
+
+    return MEM_Alloc( glyph->hints, sizeof ( *glyph->hints ) );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Glyph_Hinter                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Releases a given glyph slot's hinter structure.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: A handle to the glyph slot.                               */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_Glyph_Hinter( T1_GlyphSlot  glyph )
+  {
+    FT_Memory  memory = glyph->root.face->memory;
+
+
+    FREE( glyph->hints );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                     **********/
+  /**********               HINTED GLYPH LOADER                   **********/
+  /**********                                                     **********/
+  /**********    The following code is in charge of the first     **********/
+  /**********    and second pass when loading a single outline    **********/
+  /**********                                                     **********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static
+  FT_Error  t1_hinter_ignore( void )
+  {
+    /* do nothing, used for `dotsection' which is unsupported for now */
+    return 0;
+  }
+
+
+  static
+  FT_Error  t1_hinter_stem( T1_Builder*  builder,
+                            FT_Pos       pos,
+                            FT_Int       width,
+                            FT_Bool      vertical )
+  {
+    T1_Stem_Table*   stem_table;
+    T1_Stem_Hint*    stems;
+    T1_Stem_Hint*    cur_stem;
+    FT_Int           min, max, n, num_stems;
+    FT_Bool          new_stem;
+    T1_Glyph_Hints*  hinter = builder->glyph->hints;
+
+
+    /* select the appropriate stem array */
+    stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems;
+    stems      = stem_table->stems;
+    num_stems  = stem_table->num_stems;
+
+    /* Compute minimum and maximum coord for the stem */
+    min = pos + ( vertical
+                ? builder->left_bearing.x
+                : builder->left_bearing.y );
+
+    if ( width >= 0 )
+      max = min + width;
+    else
+    {
+      /* a negative width indicates a `ghost' stem */
+      if ( width == -21 )
+        min += width;
+
+      max = min;
+    }
+
+    /* Now scan the array.  If we find a stem with the same borders */
+    /* simply activate it.                                          */
+    cur_stem = stems;
+    new_stem = 1;
+
+    for ( n = 0; n < num_stems; n++, cur_stem++ )
+    {
+      if ( cur_stem->min_edge.orus == min &&
+           cur_stem->max_edge.orus == max )
+      {
+        /* This stem is already in the table, simply activate it */
+        if ( ( cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE ) == 0 )
+        {
+          cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE;
+          stem_table->num_active++;
+        }
+        new_stem = 0;
+        break;
+      }
+    }
+
+    /* add a new stem to the array if necessary */
+    if ( new_stem )
+    {
+      if ( cur_stem >= stems + T1_HINTER_MAX_EDGES )
+      {
+        FT_ERROR(( "t1_hinter_stem: too many stems in glyph charstring\n" ));
+        return T1_Err_Syntax_Error;
+      }
+
+      /* on the first pass, we record the stem, otherwise, this is */
+      /* a bug in the glyph loader!                                */
+      if ( builder->pass == 0 )
+      {
+        cur_stem->min_edge.orus = min;
+        cur_stem->max_edge.orus = max;
+        cur_stem->hint_flags    = T1_HINT_FLAG_ACTIVE;
+
+        stem_table->num_stems++;
+        stem_table->num_active++;
+      }
+      else
+      {
+        FT_ERROR(( "t1_hinter_stem:" ));
+        FT_ERROR(( " fatal glyph loader bug -- pass2-stem\n" ));
+        return T1_Err_Syntax_Error;
+      }
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  t1_hinter_stem3( T1_Builder*  builder,
+                             FT_Pos       pos0,
+                             FT_Int       width0,
+                             FT_Pos       pos1,
+                             FT_Int       width1,
+                             FT_Pos       pos2,
+                             FT_Int       width2,
+                             FT_Bool      vertical )
+  {
+    /* For now, simply call `stem' 3 times */
+    return t1_hinter_stem( builder, pos0, width0, vertical ) ||
+           t1_hinter_stem( builder, pos1, width1, vertical ) ||
+           t1_hinter_stem( builder, pos2, width2, vertical );
+  }
+
+
+  static
+  FT_Error  t1_hinter_changehints( T1_Builder*  builder )
+  {
+    FT_Int           dimension;
+    T1_Stem_Table*   stem_table;
+    T1_Glyph_Hints*  hinter = builder->glyph->hints;
+
+
+    /* If we are in the second pass of glyph hinting, we must     */
+    /* call the function T1_Hint_Points() on the builder in order */
+    /* to force the fit the latest points to the pixel grid.      */
+    if ( builder->pass == 1 )
+      T1_Hint_Points( builder );
+
+    /* Simply de-activate all hints in all arrays */
+    stem_table = &hinter->hori_stems;
+
+    for ( dimension = 2; dimension > 0; dimension-- )
+    {
+      T1_Stem_Hint*  cur   = stem_table->stems;
+      T1_Stem_Hint*  limit = cur + stem_table->num_stems;
+
+
+      for ( ; cur < limit; cur++ )
+        cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE;
+
+      stem_table->num_active = 0;
+      stem_table = &hinter->vert_stems;
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  const T1_Hinter_Funcs  t1_hinter_funcs =
+  {
+    (T1_Hinter_ChangeHints)t1_hinter_changehints,
+    (T1_Hinter_DotSection) t1_hinter_ignore,
+    (T1_Hinter_Stem)       t1_hinter_stem,
+    (T1_Hinter_Stem3)      t1_hinter_stem3
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********                STEM HINTS MANAGEMENT                 *********/
+  /**********                                                      *********/
+  /**********     The following code is in charge of computing     *********/
+  /**********     the placement of each scaled stem hint.          *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_sort_hints                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sorta the list of active stems in increasing order, through the    */
+  /*    `sort' indexing table.                                             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table :: A stem hints table.                                       */
+  /*                                                                       */
+  static
+  void  t1_sort_hints( T1_Stem_Table*  table )
+  {
+    FT_Int         num_stems  = table->num_stems;
+    FT_Int         num_active = 0;
+    FT_Int*        sort       = table->sort;
+    T1_Stem_Hint*  stems      = table->stems;
+    FT_Int         n;
+
+
+    /* record active stems in sort table */
+    for ( n = 0; n < num_stems; n++ )
+    {
+      if ( stems[n].hint_flags & T1_HINT_FLAG_ACTIVE )
+        sort[num_active++] = n;
+    }
+
+    /* Now sort the indices.  There are usually very few stems, */
+    /* and they are pre-sorted in 90% cases, so we choose a     */
+    /* simple bubble sort (quicksort would be slower).          */
+    for ( n = 1; n < num_active; n++ )
+    {
+      FT_Int         p   = n - 1;
+      T1_Stem_Hint*  cur = stems + sort[n];
+
+
+      do
+      {
+        FT_Int         swap;
+        T1_Stem_Hint*  prev = stems + sort[p];
+
+
+        /* note that by definition, the active stems cannot overlap        */
+        /* so we simply compare their `min' to sort them (we could compare */
+        /* their max values also; this wouldn't change anything).          */
+        if ( prev->min_edge.orus <= cur->min_edge.orus )
+          break;
+
+        /* swap elements */
+        swap        = sort[p    ];
+        sort[p    ] = sort[p + 1];
+        sort[p + 1] = swap;
+        p--;
+
+      } while ( p >= 0 );
+    }
+
+    table->num_active = num_active;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_hint_horizontal_stems                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the location of each scaled horizontal stem hint.  This   */
+  /*    takes care of the blue zones and the horizontal stem snap table.   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    table     :: The horizontal stem hints table.                      */
+  /*                                                                       */
+  /*    hints     :: The current size's hint structure.                    */
+  /*                                                                       */
+  /*    blueShift :: The value of the /BlueShift as taken from the face    */
+  /*                 object.                                               */
+  /*                                                                       */
+  /*    scale     :: The 16.16 scale used to convert outline units to      */
+  /*                 26.6 pixels.                                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    For now, all stems are hinted independently from each other.  It   */
+  /*    might be necessary, for better performance, to introduce the       */
+  /*    notion of `controlled' hints describing things like counter-stems, */
+  /*    stem3, as well as overlapping stems control.                       */
+  /*                                                                       */
+  static
+  void  t1_hint_horizontal_stems( T1_Stem_Table*  table,
+                                  T1_Size_Hints*  hints,
+                                  FT_Pos          blueShift,
+                                  FT_Fixed        scale )
+  {
+    T1_Stem_Hint*  stem      = table->stems;
+    T1_Stem_Hint*  limit     = stem + table->num_stems;
+
+
+    /* first of all, scale the blueShift */
+    blueShift = SCALE( blueShift );
+
+    /* then scan the horizontal stem table */
+    for ( ; stem < limit; stem++ )
+    {
+      FT_Pos  bottom_orus = stem->min_edge.orus;
+      FT_Pos  top_orus    = stem->max_edge.orus;
+
+      FT_Pos  top_pix     = SCALE( top_orus );
+      FT_Pos  bottom_pix  = SCALE( bottom_orus );
+      FT_Pos  width_pix   = top_pix - bottom_pix;
+
+      FT_Pos  bottom      = bottom_pix;
+      FT_Pos  top         = top_pix;
+      FT_Int  align       = T1_ALIGN_NONE;
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Snap pixel width if in stem snap range                            */
+      /*                                                                   */
+
+      {
+        T1_Snap_Zone*  zone       = hints->snap_heights;
+        T1_Snap_Zone*  zone_limit = zone + hints->num_snap_heights;
+        FT_Pos         best_dist  = 32000;
+        T1_Snap_Zone*  best_zone  = 0;
+
+
+        for ( ; zone < zone_limit; zone++ )
+        {
+          FT_Pos  dist;
+
+
+          dist = width_pix - zone->min;
+          if ( dist < 0 )
+            dist = -dist;
+          if ( dist < best_dist )
+          {
+            best_zone = zone;
+            best_dist = dist;
+          }
+        }
+
+        if ( best_zone )
+        {
+          if ( width_pix > best_zone->pix )
+          {
+            width_pix -= 0x20;
+            if ( width_pix < best_zone->pix )
+              width_pix = best_zone->pix;
+          }
+          else
+          {
+            width_pix += 0x20;
+            if ( width_pix > best_zone->pix )
+              width_pix = best_zone->pix;
+          }
+        }
+      }
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* round width - minimum 1 pixel if this isn't a ghost stem          */
+      /*                                                                   */
+
+      if ( width_pix > 0 )
+        width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND( width_pix );
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Now check for bottom blue zones alignement                        */
+      /*                                                                   */
+
+      {
+        FT_Int         num_blues  = hints->num_bottom_zones;
+        T1_Snap_Zone*  blue       = hints->blue_zones;
+        T1_Snap_Zone*  blue_limit = blue + num_blues;
+
+
+        for ( ; blue < blue_limit; blue++ )
+        {
+          if ( bottom_pix < blue->min )
+            break;
+
+          if ( bottom_pix <= blue->max )
+          {
+            align  = T1_ALIGN_BOTTOM;
+            bottom = ROUND( blue->pix );
+
+            /* implement blue shift */
+            if ( !hints->supress_overshoots )
+            {
+              FT_Pos  delta = blue->pix - bottom_pix;
+
+
+              delta   = delta < blueShift ? 0 : ROUND( delta );
+              bottom -= delta;
+            }
+          }
+        }
+      }
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* check for top blue zones alignement                               */
+      /*                                                                   */
+
+      {
+        FT_Int         num_blues  = hints->num_blue_zones -
+                                    hints->num_bottom_zones;
+
+        T1_Snap_Zone*  blue       = hints->blue_zones +
+                                    hints->num_bottom_zones;
+
+        T1_Snap_Zone*  blue_limit = blue + num_blues;
+
+
+        for ( ; blue < blue_limit; blue++ )
+        {
+          if ( top_pix < blue->min )
+            break;
+
+          if ( top_pix <= blue->max )
+          {
+            align |= T1_ALIGN_TOP;
+            top    = ROUND( blue->pix );
+
+            /* implement blue shift */
+            if ( !hints->supress_overshoots )
+            {
+              FT_Pos  delta = top - blue->pix;
+
+
+              delta  = delta < blueShift ? 0 : ROUND( delta );
+              top   += delta;
+            }
+          }
+        }
+      }
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* compute the hinted stem position, according to its alignment      */
+      /*                                                                   */
+
+      switch ( align )
+      {
+      case T1_ALIGN_BOTTOM:  /* bottom zone alignment */
+        bottom_pix = bottom;
+        top_pix    = bottom + width_pix;
+        break;
+
+      case T1_ALIGN_TOP:     /* top zone alignment */
+        top_pix    = top;
+        bottom_pix = top - width_pix;
+        break;
+
+      case T1_ALIGN_BOTH:    /* bottom+top zone alignment */
+        bottom_pix = bottom;
+        top_pix    = top;
+        break;
+
+      default:               /* no alignment */
+        /* XXX TODO: Add management of controlled stems */
+        bottom = ( SCALE( bottom_orus + top_orus ) - width_pix ) / 2;
+
+        bottom_pix = ROUND( bottom );
+        top_pix    = bottom_pix + width_pix;
+      }
+
+      stem->min_edge.pix = bottom_pix;
+      stem->max_edge.pix = top_pix;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_hint_vertical_stems                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the location of each scaled vertical stem hint.  This     */
+  /*    takes care of the vertical stem snap table.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    table :: The vertical stem hints table.                            */
+  /*    hints :: The current size's hint structure.                        */
+  /*    scale :: The 16.16 scale used to convert outline units to          */
+  /*             26.6 pixels.                                              */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    For now, all stems are hinted independently from each other.  It   */
+  /*    might be necessary, for better performance, to introduce the       */
+  /*    notion of `controlled' hints describing things like counter-stems, */
+  /*    stem3 as well as overlapping stems control.                        */
+  /*                                                                       */
+  static
+  void  t1_hint_vertical_stems( T1_Stem_Table*  table,
+                                T1_Size_Hints*  hints,
+                                FT_Fixed        scale )
+  {
+    T1_Stem_Hint*  stem  = table->stems;
+    T1_Stem_Hint*  limit = stem + table->num_stems;
+
+
+    for ( ; stem < limit; stem++ )
+    {
+      FT_Pos  stem_left  = stem->min_edge.orus;
+      FT_Pos  stem_right = stem->max_edge.orus;
+      FT_Pos  width_pix, left;
+
+
+      width_pix = SCALE( stem_right - stem_left );
+
+      /* Snap pixel width if in stem snap range */
+      {
+        T1_Snap_Zone*  zone       = hints->snap_heights;
+        T1_Snap_Zone*  zone_limit = zone + hints->num_snap_heights;
+        FT_Pos         best_dist  = 32000;
+        T1_Snap_Zone*  best_zone  = 0;
+
+
+        for ( ; zone < zone_limit; zone++ )
+        {
+          FT_Pos  dist;
+
+
+          dist = width_pix - zone->min;
+          if ( dist < 0 )
+            dist = -dist;
+          if ( dist < best_dist )
+          {
+            best_zone = zone;
+            best_dist = dist;
+          }
+        }
+
+        if ( best_zone )
+        {
+          if ( width_pix > best_zone->pix )
+          {
+            width_pix -= 0x20;
+            if ( width_pix < best_zone->pix )
+              width_pix = best_zone->pix;
+          }
+          else
+          {
+            width_pix += 0x20;
+            if ( width_pix > best_zone->pix )
+              width_pix = best_zone->pix;
+          }
+        }
+      }
+
+      /* round width - minimum 1 pixel if this isn't a ghost stem */
+      if ( width_pix > 0 )
+        width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL
+                                          : ROUND( width_pix );
+
+      /* now place the snapped and rounded stem   */
+
+      /* XXX TODO: implement controlled stems for the overlapping */
+      /*           cases                                          */
+
+      left = ( SCALE( stem_left + stem_right ) - width_pix ) / 2;
+
+      stem->min_edge.pix = ROUND( left );
+      stem->max_edge.pix = stem->min_edge.pix + width_pix;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_hint_point                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Grid-fit a coordinate with regards to a given stem hints table.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    table :: The source stem hints table.                              */
+  /*    coord :: The original coordinate, expressed in font units.         */
+  /*    scale :: The 16.16 scale used to convert font units into           */
+  /*             26.6 pixels.                                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The hinted/scaled value in 26.6 pixels.                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    For now, all stems are hinted independently from each other.  It   */
+  /*    might be necessary, for better performance, to introduce the       */
+  /*    notion of `controlled' hints describing things like counter-stems, */
+  /*    stem3 as well as overlapping stems control.                        */
+  /*                                                                       */
+  static
+  FT_Pos  t1_hint_point( T1_Stem_Table*  table,
+                         FT_Pos          coord,
+                         FT_Fixed        scale )
+  {
+    FT_Int         num_active = table->num_active;
+    FT_Int         n;
+    T1_Stem_Hint*  prev = 0;
+    T1_Stem_Hint*  cur  = 0;
+    T1_Edge*       min;
+    T1_Edge*       max;
+    FT_Pos         delta;
+
+
+    /* only hint when there is at least one stem defined */
+    if ( num_active <= 0 )
+      return SCALE( coord );
+
+    /* scan the stem table to determine placement of coordinate */
+    /* relative to the list of sorted and stems                 */
+    for ( n = 0; n < num_active; n++, prev = cur )
+    {
+      cur = table->stems + table->sort[n];
+
+      /* is it on the left of the current edge? */
+      delta = cur->min_edge.orus - coord;
+      if ( delta == 0 )
+        return cur->min_edge.pix;
+
+      if ( delta > 0 )
+      {
+        /* if this is the left of the first edge, simply shift */
+        if ( !prev )
+          return cur->min_edge.pix - SCALE( delta );
+
+        /* otherwise, interpolate between the maximum of the */
+        /* previous stem, and the minimum of the current one */
+        min = &prev->max_edge;
+        max = &cur->min_edge;
+
+        goto Interpolate;
+      }
+
+      /* is it within the current edge? */
+      delta = cur->max_edge.orus - coord;
+      if ( delta == 0 )
+        return cur->max_edge.pix;
+
+      if ( delta > 0 )
+      {
+        /* interpolate within the stem */
+        min = &cur->min_edge;
+        max = &cur->max_edge;
+
+        goto Interpolate;
+      }
+    }
+
+    /* apparently, this coordinate is on the right of the last stem */
+    delta = coord - cur->max_edge.orus;
+    return cur->max_edge.pix + SCALE( delta );
+
+  Interpolate:
+    return min->pix + FT_MulDiv( coord     - min->orus,
+                                 max->pix  - min->pix,
+                                 max->orus - min->orus );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*   T1_Hint_Points                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   This function grid-fits several points in a given Type 1 builder    */
+  /*   at once.                                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   builder :: A handle to target Type 1 builder.                       */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Hint_Points( T1_Builder*  builder )
+  {
+    FT_Int    first   = builder->hint_point;
+    FT_Int    last    = builder->current->n_points - 1;
+
+    T1_Size   size    = builder->size;
+    FT_Fixed  scale_x = size->root.metrics.x_scale;
+    FT_Fixed  scale_y = size->root.metrics.y_scale;
+
+    T1_Glyph_Hints*  hints      = builder->glyph->hints;
+    T1_Stem_Table*   hori_stems = &hints->hori_stems;
+    T1_Stem_Table*   vert_stems = &hints->vert_stems;
+
+    FT_Vector*  cur   = builder->current->points + first;
+    FT_Vector*  limit = cur + last - first + 1;
+
+
+    /* first of all, sort the active stem hints */
+    t1_sort_hints( hori_stems );
+    t1_sort_hints( vert_stems );
+
+    for ( ; cur < limit; cur++ )
+    {
+      cur->x = t1_hint_point( vert_stems, cur->x, scale_x );
+      cur->y = t1_hint_point( hori_stems, cur->y, scale_y );
+    }
+
+    builder->hint_point = builder->current->n_points;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Hint_Stems                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to compute the location of each stem hint    */
+  /*    between the first and second passes of the glyph loader on the     */
+  /*    charstring.                                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder :: A handle to the target builder.                         */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Hint_Stems( T1_Builder*  builder )
+  {
+    T1_Glyph_Hints*  hints = builder->glyph->hints;
+    T1_Private*      priv  = &builder->face->type1.private_dict;
+
+    T1_Size   size    = builder->size;
+    FT_Fixed  scale_x = size->root.metrics.x_scale;
+    FT_Fixed  scale_y = size->root.metrics.y_scale;
+
+
+    t1_hint_horizontal_stems( &hints->hori_stems,
+                              builder->size->hints,
+                              priv->blue_shift,
+                              scale_y );
+
+    t1_hint_vertical_stems( &hints->vert_stems,
+                            builder->size->hints,
+                            scale_x );
+  }
+
+
+/* END */
diff --git a/src/freetype/type1/t1hinter.h b/src/freetype/type1/t1hinter.h
new file mode 100644 (file)
index 0000000..a82882e
--- /dev/null
@@ -0,0 +1,273 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1hinter.h                                                             */
+/*                                                                         */
+/*    Type 1 hinter (body).                                                */
+/*                                                                         */
+/*  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 T1HINTER_H
+#define T1HINTER_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+#include "t1gload.h"
+
+#else
+
+#include <type1/t1objs.h>
+#include <type1/t1gload.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*   T1_Snap_Zone                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   A `snap zone' is used to model either a blue zone or a stem width   */
+  /*   at a given character size.  It is made of a minimum and maximum     */
+  /*   edge, defined in 26.6 pixels, as well as an `original' and          */
+  /*   `scaled' position.                                                  */
+  /*                                                                       */
+  /*   The position corresponds to the stem width (for stem snap zones)    */
+  /*   or to the blue position (for blue zones).                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*   orus  :: The original position in font units.                       */
+  /*                                                                       */
+  /*   pix   :: The current position in sub-pixel units.                   */
+  /*                                                                       */
+  /*   min   :: The minimum boundary in sub-pixel units.                   */
+  /*                                                                       */
+  /*   max   :: The maximum boundary in sub-pixel units.                   */
+  /*                                                                       */
+  typedef struct  T1_Snap_Zone_
+  {
+    FT_Pos  orus;
+    FT_Pos  pix;
+    FT_Pos  min;
+    FT_Pos  max;
+
+  } T1_Snap_Zone;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*   T1_Edge                                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   A very simple structure used to model a stem edge.                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*   orus  :: The original edge position in font units.                  */
+  /*                                                                       */
+  /*   pix   :: The scaled edge position in sub-pixel units.               */
+  /*                                                                       */
+  typedef struct  T1_Edge_
+  {
+    FT_Pos  orus;
+    FT_Pos  pix;
+
+  } T1_Edge;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Stem_Hint                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to model a stem hint.                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    min_edge   :: The hint's minimum edge.                             */
+  /*                                                                       */
+  /*    max_edge   :: The hint's maximum edge.                             */
+  /*                                                                       */
+  /*    hint_flags :: Some flags describing the stem properties.           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The min and max edges of a ghost stem have the same position, even */
+  /*    if they are coded in a weird way in the charstrings.               */
+  /*                                                                       */
+  typedef struct  T1_Stem_Hint_
+  {
+    T1_Edge  min_edge;
+    T1_Edge  max_edge;
+    FT_Int   hint_flags;
+
+  } T1_Stem_Hint;
+
+
+#define T1_HINT_FLAG_ACTIVE      1    /* indicates an active stem */
+#define T1_HINT_FLAG_MIN_BORDER  2    /* unused for now           */
+#define T1_HINT_FLAG_MAX_BORDER  4    /* unused for now           */
+
+  /* hinter's configuration constants */
+#define T1_HINTER_MAX_BLUES  24    /* maximum number of blue zones      */
+#define T1_HINTER_MAX_SNAPS  16    /* maximum number of stem snap zones */
+#define T1_HINTER_MAX_EDGES  64    /* maximum number of stem hints      */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*   T1_Size_Hints                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   A structure used to model the hinting information related to a size */
+  /*   object.                                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*   supress_overshoots :: A boolean flag to tell whether overshoot      */
+  /*                         supression should occur.                      */
+  /*                                                                       */
+  /*   num_blue_zones     :: The total number of blue zones (top+bottom).  */
+  /*                                                                       */
+  /*   num_bottom_zones   :: The number of bottom zones.                   */
+  /*                                                                       */
+  /*   blue_zones         :: The blue zones table.  Bottom zones are       */
+  /*                         stored first in the table, followed by all    */
+  /*                         top zones.                                    */
+  /*                                                                       */
+  /*   num_snap_widths    :: The number of horizontal stem snap zones.     */
+  /*                                                                       */
+  /*   snap_widths        :: An array of horizontal stem snap zones.       */
+  /*                                                                       */
+  /*   num_snap_heights   :: The number of vertical stem snap zones.       */
+  /*                                                                       */
+  /*   snap_heights       :: An array of vertical stem snap zones.         */
+  /*                                                                       */
+  struct  T1_Size_Hints_
+  {
+    FT_Bool       supress_overshoots;
+
+    FT_Int        num_blue_zones;
+    FT_Int        num_bottom_zones;
+    T1_Snap_Zone  blue_zones[T1_HINTER_MAX_BLUES];
+
+    FT_Int        num_snap_widths;
+    T1_Snap_Zone  snap_widths[T1_HINTER_MAX_SNAPS];
+
+    FT_Int        num_snap_heights;
+    T1_Snap_Zone  snap_heights[T1_HINTER_MAX_SNAPS];
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Stem_Table                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to model a set of stem hints in a single   */
+  /*    direction during the loading of a given glyph outline.  Not all    */
+  /*    stem hints are active at a time.  Moreover, stems must be sorted   */
+  /*    regularly.                                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_stems  :: The total number of stems in the table.              */
+  /*                                                                       */
+  /*    num_active :: The number of active stems in the table.             */
+  /*                                                                       */
+  /*    stems      :: A table of all stems.                                */
+  /*                                                                       */
+  /*    sort       :: A table of indices into the stems table, used to     */
+  /*                  keep a sorted list of the active stems.              */
+  /*                                                                       */
+  typedef struct  T1_Stem_Table_
+  {
+    FT_Int        num_stems;
+    FT_Int        num_active;
+
+    T1_Stem_Hint  stems[T1_HINTER_MAX_EDGES];
+    FT_Int        sort [T1_HINTER_MAX_EDGES];
+
+  } T1_Stem_Table;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*   T1_Glyph_Hints                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   A structure used to model the stem hints of a given glyph outline   */
+  /*   during glyph loading.                                               */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*   hori_stems :: The horizontal stem hints table.                      */
+  /*   vert_stems :: The vertical stem hints table.                        */
+  /*                                                                       */
+  struct T1_Glyph_Hints_
+  {
+    T1_Stem_Table  hori_stems;
+    T1_Stem_Table  vert_stems;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Data>                                                                */
+  /*    t1_hinter_funcs                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A table containing the address of various functions used during    */
+  /*    the loading of an hinted scaled outline.                           */
+  /*                                                                       */
+  extern const T1_Hinter_Funcs  t1_hinter_funcs;
+
+
+  LOCAL_DEF
+  FT_Error  T1_New_Size_Hinter( T1_Size  size );
+
+  LOCAL_DEF
+  void  T1_Done_Size_Hinter( T1_Size  size );
+
+  LOCAL_DEF
+  FT_Error  T1_Reset_Size_Hinter( T1_Size  size );
+
+  LOCAL_DEF
+  FT_Error  T1_New_Glyph_Hinter( T1_GlyphSlot  glyph );
+
+  LOCAL_DEF
+  void T1_Done_Glyph_Hinter( T1_GlyphSlot  glyph );
+
+
+  LOCAL_DEF
+  void  T1_Hint_Points( T1_Builder*  builder );
+
+  LOCAL_DEF
+  void  T1_Hint_Stems( T1_Builder*  builder );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* T1HINTER_H */
+
+
+/* END */
diff --git a/src/freetype/type1/t1load.c b/src/freetype/type1/t1load.c
new file mode 100644 (file)
index 0000000..00a56a2
--- /dev/null
@@ -0,0 +1,1594 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1load.c                                                               */
+/*                                                                         */
+/*    Type 1 font loader (body).                                           */
+/*                                                                         */
+/*  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 <freetype/config/ftconfig.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/t1types.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1tokens.h"
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1tokens.h>
+#include <type1/t1parse.h>
+
+#endif
+
+
+#include <stdio.h>
+
+#include <string.h>     /* for strncpy(), strncmp(), strlen() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1load
+
+
+  typedef FT_Error  (*T1_Parse_Func)( T1_Parser*  parser );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Init_T1_Parser                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given parser object to build a given T1_Face.        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser    :: A handle to the newly built parser object.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face      :: A handle to the target Type 1 face object.            */
+  /*                                                                       */
+  /*    tokenizer :: A handle to the target Type 1 token manager.          */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  Init_T1_Parser( T1_Parser*    parser,
+                        T1_Face       face,
+                        T1_Tokenizer  tokenizer )
+  {
+    parser->error     = 0;
+    parser->face      = face;
+    parser->tokenizer = tokenizer;
+    parser->top       = parser->stack;
+    parser->limit     = parser->stack + T1_MAX_STACK_DEPTH;
+
+    parser->state_index    = 0;
+    parser->state_stack[0] = dict_none;
+
+    parser->encoding_type    = t1_encoding_none;
+    parser->encoding_names   = 0;
+    parser->encoding_offsets = 0;
+    parser->encoding_lengths = 0;
+
+    parser->dump_tokens            = 0;
+    face->type1.private_dict.lenIV = 4;  /* XXX : is it sure? */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Next_T1_Token                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Grabs the next significant token from a parser's input stream.     */
+  /*    This function ignores a number of tokens, and translates           */
+  /*    alternate forms into their common ones.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    parser :: A handle to the source parser.                           */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    token  :: The extracted token descriptor.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeTyoe error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Next_T1_Token( T1_Parser*  parser,
+                           T1_Token*   token )
+  {
+    FT_Error      error;
+    T1_Tokenizer  tokzer = parser->tokenizer;
+
+
+  L1:
+    error = Read_Token( tokzer );
+    if ( error )
+      return error;
+
+    /* we now must ignore a number of tokens like `dup', `executeonly', */
+    /* `readonly', etc.                                                 */
+    *token = tokzer->token;
+    if ( token->kind == tok_keyword )
+      switch( token->kind2 )
+      {
+      case key_dup:
+      case key_execonly:
+      case key_readonly:
+      case key_noaccess:
+      case key_userdict:
+        /* do nothing - loop */
+        goto L1;
+
+        /* we also translate some other keywords from their alternative */
+        /* to their `normal' form                                       */
+
+      case key_NP_alternate:
+        token->kind2 = key_NP;
+        break;
+
+      case key_RD_alternate:
+        token->kind2 = key_RD;
+        break;
+
+      case key_ND_alternate:
+        token->kind2 = key_ND;
+        break;
+
+      default:
+        ;
+      }
+
+#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE )
+
+    /* Dump the token when requested.  This feature is only available */
+    /* in the `error' and `trace' debug levels.                       */
+    if ( parser->dump_tokens )
+    {
+      FT_String  temp_string[128];
+      FT_Int     len;
+
+
+      len = token->len;
+      if ( len > 127 )
+        len = 127;
+      strncpy( temp_string,
+               (FT_String*)tokzer->base + token->start,
+               len );
+      temp_string[len] = '\0';
+      FT_ERROR(( "%s\n", temp_string ));
+    }
+
+#endif /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE */
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  Expect_Keyword( T1_Parser*    parser,
+                            T1_TokenType  keyword )
+  {
+    T1_Token  token;
+    FT_Error  error;
+
+
+    error = Next_T1_Token( parser, &token );
+    if ( error )
+      goto Exit;
+
+    if ( token.kind  != tok_keyword ||
+         token.kind2 != keyword     )
+    {
+      error = T1_Err_Syntax_Error;
+      FT_ERROR(( "Expect_Keyword: keyword `%s' expected.\n",
+                 t1_keywords[keyword - key_first_] ));
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error  Expect_Keyword2( T1_Parser*    parser,
+                             T1_TokenType  keyword1,
+                             T1_TokenType  keyword2 )
+  {
+    T1_Token  token;
+    FT_Error  error;
+
+
+    error = Next_T1_Token( parser, &token );
+    if ( error )
+      goto Exit;
+
+    if ( token.kind  != tok_keyword  ||
+         ( token.kind2 != keyword1 &&
+           token.kind2 != keyword2 ) )
+    {
+      error = T1_Err_Syntax_Error;
+      FT_ERROR(( "Expect_Keyword2: keyword `%s' or `%s' expected.\n",
+                 t1_keywords[keyword1 - key_first_],
+                 t1_keywords[keyword2 - key_first_] ));
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  Parse_Encoding( T1_Parser*  parser )
+  {
+    T1_Token*     token  = parser->top+1;
+    FT_Memory     memory = parser->face->root.memory;
+    T1_Encoding*  encode = &parser->face->type1.encoding;
+    FT_Error      error  = 0;
+
+
+    if ( token->kind  == tok_keyword              &&
+         ( token->kind2 == key_StandardEncoding ||
+           token->kind2 == key_ExpertEncoding   ) )
+    {
+      encode->num_chars  = 256;
+      encode->code_first = 32;
+      encode->code_last  = 255;
+
+      if ( ALLOC_ARRAY( encode->char_index, 256, FT_Short ) )
+        goto Exit;
+
+      encode->char_name = 0;  /* no need to store glyph names */
+
+      /* Now copy the encoding */
+      switch ( token->kind2 )
+      {
+      case key_ExpertEncoding:
+        parser->encoding_type = t1_encoding_expert;
+        break;
+
+      default:
+        parser->encoding_type = t1_encoding_standard;
+        break;
+      }
+    }
+    else
+    {
+      FT_ERROR(( "Parse_Encoding: invalid encoding type\n" ));
+      error = T1_Err_Syntax_Error;
+    }
+
+  Exit:
+    parser->error = error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                                                                       */
+  /*           IMPLEMENTATION OF THE `DEF' KEYWORD DEPENDING ON            */
+  /*                        CURRENT DICTIONARY STATE                       */
+  /*                                                                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Do_Def_Font                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function performs a `def' if in the Font dictionary.  Its     */
+  /*    purpose is to build the T1_Face attributes directly from the       */
+  /*    stream.                                                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the current parser.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Do_Def_Font( T1_Parser*  parser )
+  {
+    T1_Token*  top   = parser->top;
+    T1_Face    face  = parser->face;
+    T1_Font*   type1 = &face->type1;
+
+
+    switch ( top[0].kind2 )
+    {
+    case imm_FontName:
+      /* in some cases, the /FontName is an immediate like */
+      /* /TimesNewRoman.  In this case, we simply copy the */
+      /* token string (without the /).                     */
+      if ( top[1].kind == tok_immediate )
+      {
+        FT_Memory  memory = parser->tokenizer->memory;
+        FT_Error   error;
+        FT_Int     len = top[1].len;
+
+
+        if ( ALLOC( type1->font_name, len + 1 ) )
+        {
+          parser->error = error;
+          return error;
+        }
+
+        MEM_Copy( type1->font_name,
+                  parser->tokenizer->base + top[1].start,
+                  len );
+        type1->font_name[len] = '\0';
+      }
+      else
+        type1->font_name = CopyString( parser );
+      break;
+
+    case imm_Encoding:
+      Parse_Encoding( parser );
+      break;
+
+    case imm_PaintType:
+      type1->paint_type = (FT_Byte)CopyInteger( parser );
+      break;
+
+    case imm_FontType:
+      type1->font_type = (FT_Byte)CopyInteger( parser );
+      break;
+
+    case imm_FontMatrix:
+      CopyMatrix( parser, &type1->font_matrix );
+      break;
+
+    case imm_FontBBox:
+      CopyBBox( parser, &type1->font_bbox );
+      break;
+
+    case imm_UniqueID:
+      type1->private_dict.unique_id = CopyInteger( parser );
+      break;
+
+    case imm_StrokeWidth:
+      type1->stroke_width = CopyInteger( parser );
+      break;
+
+    case imm_FontID:
+      type1->font_id = CopyInteger( parser );
+      break;
+
+    default:
+      /* ignore all other things */
+      parser->error = T1_Err_Ok;
+    }
+
+    return parser->error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Do_Def_FontInfo                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function performs a `def' if in the FontInfo dictionary. Its  */
+  /*    purpose is to build the T1_FontInfo structure directly from the    */
+  /*    stream.                                                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the current parser.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeTyoe error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Do_Def_FontInfo( T1_Parser*  parser )
+  {
+    T1_Token*     top  = parser->top;
+    T1_FontInfo*  info = &parser->face->type1.font_info;
+
+
+    switch ( top[0].kind2 )
+    {
+    case imm_version:
+      info->version = CopyString( parser );
+      break;
+
+    case imm_Notice:
+      info->notice = CopyString( parser );
+      break;
+
+    case imm_FullName:
+      info->full_name = CopyString( parser );
+      break;
+
+    case imm_FamilyName:
+      info->family_name = CopyString( parser );
+      break;
+
+    case imm_Weight:
+      info->weight = CopyString( parser );
+      break;
+
+    case imm_ItalicAngle:
+      info->italic_angle = CopyInteger( parser );
+      break;
+
+    case imm_isFixedPitch:
+      info->is_fixed_pitch = CopyBoolean( parser );
+      break;
+
+    case imm_UnderlinePosition:
+      info->underline_position = (FT_Short)CopyInteger( parser );
+      break;
+
+    case imm_UnderlineThickness:
+      info->underline_thickness = (FT_Short)CopyInteger( parser );
+      break;
+
+    default:
+      /* ignore all other things */
+      parser->error = T1_Err_Ok;
+    }
+
+    return parser->error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Do_Def_Private                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function performs a `def' if in the Private dictionary.  Its  */
+  /*    purpose is to build the T1_Private structure directly from the     */
+  /*    stream.                                                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the current parser.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeTyoe error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Do_Def_Private( T1_Parser*  parser )
+  {
+    T1_Token*   top   = parser->top;
+    T1_Private* priv  = &parser->face->type1.private_dict;
+
+
+    switch ( top[0].kind2 )
+    {
+      /* Ignore the definitions of RD, NP, ND, and their alternate forms */
+    case imm_RD:
+    case imm_RD_alternate:
+    case imm_ND:
+    case imm_ND_alternate:
+    case imm_NP:
+    case imm_NP_alternate:
+      parser->error = T1_Err_Ok;
+      break;
+
+    case imm_BlueValues:
+      CopyArray( parser, &priv->num_blue_values,
+                 priv->blue_values, 14 );
+      break;
+
+    case imm_OtherBlues:
+      CopyArray( parser, &priv->num_other_blues,
+                 priv->other_blues, 10 );
+      break;
+
+    case imm_FamilyBlues:
+      CopyArray( parser, &priv->num_family_blues,
+                 priv->family_blues, 14 );
+      break;
+
+    case imm_FamilyOtherBlues:
+      CopyArray( parser, &priv->num_family_other_blues,
+                 priv->family_other_blues, 10 );
+      break;
+
+    case imm_BlueScale:
+      priv->blue_scale = CopyFloat( parser, 0x10000L );
+      break;
+
+    case imm_BlueShift:
+      priv->blue_shift = CopyInteger( parser );
+      break;
+
+    case imm_BlueFuzz:
+      priv->blue_fuzz = CopyInteger( parser );
+      break;
+
+    case imm_StdHW:
+      CopyArray( parser, 0, (FT_Short*)&priv->standard_width, 1 );
+      break;
+
+    case imm_StdVW:
+      CopyArray( parser, 0, (FT_Short*)&priv->standard_height, 1 );
+      break;
+
+    case imm_StemSnapH:
+      CopyArray( parser, &priv->num_snap_widths,
+                 priv->snap_widths, 12 );
+      break;
+
+    case imm_StemSnapV:
+      CopyArray( parser, &priv->num_snap_heights,
+                 priv->snap_heights, 12 );
+      break;
+
+    case imm_ForceBold:
+      priv->force_bold = CopyBoolean( parser );
+      break;
+
+    case imm_LanguageGroup:
+      priv->language_group = CopyInteger( parser );
+      break;
+
+    case imm_password:
+      priv->password = CopyInteger( parser );
+      break;
+
+    case imm_UniqueID:
+      priv->unique_id = CopyInteger( parser );
+      break;
+
+    case imm_lenIV:
+      priv->lenIV = CopyInteger( parser );
+      break;
+
+    case imm_MinFeature:
+      CopyArray( parser, 0, priv->min_feature, 2 );
+      break;
+
+    default:
+      /* ignore all other things */
+      parser->error = T1_Err_Ok;
+    }
+
+    return parser->error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Do_Def_Error                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function returns a simple syntax error when invoked.  It is   */
+  /*    used for the `def' keyword if in the `encoding', `subrs',          */
+  /*    `othersubrs', and `charstrings' dictionary states.                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the current parser.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Do_Def_Error( T1_Parser*  parser )
+  {
+    FT_ERROR(( "Do_Def_Error:" ));
+    FT_ERROR(( " `def' keyword encountered in bad dictionary/array\n" ));
+
+    parser->error = T1_Err_Syntax_Error;
+
+    return parser->error;
+  }
+
+
+  static
+  FT_Error  Do_Def_Ignore( T1_Parser*  parser )
+  {
+    FT_UNUSED( parser );
+    return T1_Err_Ok;
+  }
+
+
+  static
+  T1_Parse_Func  def_funcs[dict_max] =
+  {
+    Do_Def_Error,
+    Do_Def_Font,
+    Do_Def_FontInfo,
+    Do_Def_Ignore,
+    Do_Def_Private,
+    Do_Def_Ignore,
+    Do_Def_Ignore,
+    Do_Def_Ignore,
+    Do_Def_Ignore,
+    Do_Def_Ignore,
+    Do_Def_Ignore,
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                                                                       */
+  /*           IMPLEMENTATION OF THE `PUT' KEYWORD DEPENDING ON            */
+  /*                        CURRENT DICTIONARY STATE                       */
+  /*                                                                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Do_Put_Encoding                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function performs a `put' if in the Encoding array.  The      */
+  /*    glyph name is copied into the T1 recorder, and the charcode and    */
+  /*    glyph name pointer are written into the face object encoding.      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the current parser.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Do_Put_Encoding( T1_Parser*  parser )
+  {
+    FT_Error      error  = T1_Err_Ok;
+    T1_Face       face   = parser->face;
+    T1_Token*     top    = parser->top;
+    T1_Encoding*  encode = &face->type1.encoding;
+    FT_Int        index;
+
+
+    /* record and check the character code */
+    if ( top[0].kind != tok_number )
+    {
+      FT_TRACE4(( "Do_Put_Encoding: number expected\n" ));
+      goto Syntax_Error;
+    }
+    index = (FT_Int)CopyInteger( parser );
+    if ( parser->error )
+      return parser->error;
+
+    if ( index < 0 || index >= encode->num_chars )
+    {
+      FT_TRACE4(( "Do_Put_Encoding: invalid character code\n" ));
+      goto Syntax_Error;
+    }
+
+    /* record the immediate name */
+    if ( top[1].kind != tok_immediate )
+    {
+      FT_TRACE4(( "Do_Put_Encoding: immediate name expected\n" ));
+      goto Syntax_Error;
+    }
+
+    /* if the glyph name is `.notdef', store a NULL char name; */
+    /* otherwise, record the glyph name                        */
+    if ( top[1].kind == imm_notdef )
+    {
+      parser->table.elements[index] = 0;
+      parser->table.lengths [index] = 0;
+    }
+    else
+    {
+      FT_String  temp_name[128];
+      T1_Token*  token = top + 1;
+      FT_Int     len   = token->len - 1;
+
+
+      /* copy immediate name */
+      if ( len > 127 )
+        len = 127;
+      MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len );
+      temp_name[len] = '\0';
+
+      error = T1_Add_Table( &parser->table, index,
+                            (FT_Byte*)temp_name, len + 1 );
+
+      /* adjust code_first and code_last */
+      if ( index < encode->code_first ) encode->code_first = index;
+      if ( index > encode->code_last  ) encode->code_last  = index;
+    }
+    return error;
+
+  Syntax_Error:
+    /* ignore the error, and simply clear the stack */
+    FT_TRACE4(( "Do_Put_Encoding: invalid syntax encountered\n" ));
+    parser->top = parser->stack;
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                                                                       */
+  /*           IMPLEMENTATION OF THE "RD" KEYWORD DEPENDING ON             */
+  /*                        CURRENT DICTIONARY STATE                       */
+  /*                                                                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Do_RD_Subrs                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function performs an `RD' if in the Subrs dictionary.  It     */
+  /*    simply records the array of bytecodes/charstrings corresponding to */
+  /*    the sub-routine.                                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the current parser.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Do_RD_Subrs( T1_Parser*  parser )
+  {
+    FT_Error      error  = T1_Err_Ok;
+    T1_Face       face   = parser->face;
+    T1_Token*     top    = parser->top;
+    T1_Tokenizer  tokzer = parser->tokenizer;
+    FT_Int        index, count;
+
+
+    /* record and check the character code */
+    if ( top[0].kind != tok_number ||
+         top[1].kind != tok_number )
+    {
+      FT_ERROR(( "Do_RD_Subrs: number expected\n" ));
+      goto Syntax_Error;
+    }
+    index = (FT_Int)CopyInteger( parser );
+    error = parser->error;
+    if ( error )
+      goto Exit;
+
+    count = (FT_Int)CopyInteger( parser );
+    error = parser->error;
+    if ( error )
+      goto Exit;
+
+    if ( index < 0 || index >= face->type1.num_subrs )
+    {
+      FT_ERROR(( "Do_RD_Subrs: invalid character code\n" ));
+      goto Syntax_Error;
+    }
+
+    /* decrypt charstring and skip it */
+    {
+      FT_Byte*  base = tokzer->base + tokzer->cursor;
+
+
+      tokzer->cursor += count;
+
+      /* some fonts use a value of -1 for lenIV to indicate that */
+      /* the charstrings are unencoded.                          */
+      /*                                                         */
+      /* Thanks to Tom Kacvinsky for pointing this out.          */
+      /*                                                         */
+      if ( face->type1.private_dict.lenIV >= 0 )
+      {
+        t1_decrypt( base, count, 4330 );
+
+        base  += face->type1.private_dict.lenIV;
+        count -= face->type1.private_dict.lenIV;
+      }
+
+      error = T1_Add_Table( &parser->table, index, base, count );
+    }
+
+    /* consume the closing NP or `put' */
+    error = Expect_Keyword2( parser, key_NP, key_put );
+
+  Exit:
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Do_RD_CharStrings                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function performs an `RD' if in the CharStrings dictionary.   */
+  /*    It simply records the array of bytecodes/charstrings corresponding */
+  /*    to the glyph program string.                                       */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the current parser.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  Do_RD_Charstrings( T1_Parser*  parser )
+  {
+    FT_Error      error = T1_Err_Ok;
+    T1_Face       face  = parser->face;
+    T1_Token*     top   = parser->top;
+    T1_Tokenizer  tokzer = parser->tokenizer;
+    FT_Int        index, count;
+
+
+    /* check the character name argument */
+    if ( top[0].kind != tok_immediate )
+    {
+      FT_ERROR(( "Do_RD_Charstrings: immediate character name expected\n" ));
+      goto Syntax_Error;
+    }
+
+    /* check the count argument */
+    if ( top[1].kind != tok_number )
+    {
+      FT_ERROR(( "Do_RD_Charstrings: number expected\n" ));
+      goto Syntax_Error;
+    }
+
+    parser->args++;
+    count = (FT_Int)CopyInteger( parser );
+    error = parser->error;
+    if ( error )
+      goto Exit;
+
+    /* record the glyph name and get the corresponding glyph index */
+    if ( top[0].kind2 == imm_notdef )
+      index = 0;
+    else
+    {
+      FT_String  temp_name[128];
+      T1_Token*  token = top;
+      FT_Int     len   = token->len - 1;
+
+
+      /* copy immediate name */
+      if ( len > 127 )
+        len = 127;
+      MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len );
+      temp_name[len] = '\0';
+
+      index = parser->cur_name++;
+      error = T1_Add_Table( &parser->table, index * 2,
+                            (FT_Byte*)temp_name, len + 1 );
+      if ( error )
+        goto Exit;
+    }
+
+    /* decrypt and record charstring, then skip them */
+    {
+      FT_Byte*  base = tokzer->base + tokzer->cursor;
+
+
+      tokzer->cursor += count;  /* skip */
+
+      if ( face->type1.private_dict.lenIV >= 0 )
+      {
+        t1_decrypt( base, count, 4330 );
+
+        base  += face->type1.private_dict.lenIV;
+        count -= face->type1.private_dict.lenIV;
+      }
+
+      error = T1_Add_Table( &parser->table, index * 2 + 1, base, count );
+    }
+
+    /* consume the closing `ND' */
+    if ( !error )
+      error = Expect_Keyword( parser, key_ND );
+
+  Exit:
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+  }
+
+
+  static
+  FT_Error  Expect_Dict_Arguments( T1_Parser*    parser,
+                                   FT_Int        num_args,
+                                   T1_TokenType  immediate,
+                                   T1_DictState  new_state,
+                                   FT_Int*       count )
+  {
+    /* check that we have enough arguments in the stack, including */
+    /* the `dict' keyword                                          */
+    if ( parser->top - parser->stack < num_args )
+    {
+      FT_ERROR(( "Expect_Dict_Arguments: expecting at least %d arguments",
+                 num_args ));
+      goto Syntax_Error;
+    }
+
+    /* check that we have the correct immediate, if needed */
+    if ( num_args == 2 )
+    {
+      if ( parser->top[-2].kind  != tok_immediate ||
+           parser->top[-2].kind2 != immediate     )
+      {
+        FT_ERROR(( "Expect_Dict_Arguments: expecting `/%s' dictionary\n",
+                   t1_immediates[immediate - imm_first_] ));
+        goto Syntax_Error;
+      }
+    }
+
+    parser->args = parser->top-1;
+
+    /* check that the count argument is a number */
+    if ( parser->args->kind != tok_number )
+    {
+      FT_ERROR(( "Expect_Dict_Arguments:" ));
+      FT_ERROR(( " expecting numerical count argument for `dict'\n" ));
+      goto Syntax_Error;
+    }
+
+    if ( count )
+    {
+      *count = CopyInteger( parser );
+      if ( parser->error )
+        return parser->error;
+    }
+
+    /* save the dictionary state */
+    parser->state_stack[++parser->state_index] = new_state;
+
+    /* consume the `begin' keyword and clear the stack */
+    parser->top -= num_args;
+    return Expect_Keyword( parser, key_begin );
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+  }
+
+
+  static
+  FT_Error  Expect_Array_Arguments( T1_Parser*  parser )
+  {
+    T1_Token*     top   = parser->top;
+    FT_Error      error = T1_Err_Ok;
+    T1_DictState  new_state;
+    FT_Int        count;
+    T1_Face       face   = parser->face;
+    FT_Memory     memory = face->root.memory;
+
+
+    /* Check arguments format */
+    if ( top - parser->stack < 2 )
+    {
+      FT_ERROR(( "Expect_Array_Arguments: two arguments expected\n" ));
+      error = T1_Err_Stack_Underflow;
+      goto Exit;
+    }
+
+    parser->top -= 2;
+    top         -= 2;
+    parser->args = top + 1;
+
+    if ( top[0].kind != tok_immediate )
+    {
+      FT_ERROR(( "Expect_Array_Arguments:" ));
+      FT_ERROR(( " first argument must be an immediate name\n" ));
+      goto Syntax_Error;
+    }
+
+    if ( top[1].kind != tok_number )
+    {
+      FT_ERROR(( "Expect_Array_Arguments:" ));
+      FT_ERROR(( " second argument must be a number\n" ));
+      goto Syntax_Error;
+    }
+
+    count = (FT_Int)CopyInteger( parser );
+
+    /* Is this an array we know about? */
+    switch ( top[0].kind2 )
+    {
+    case imm_Encoding:
+      {
+        T1_Encoding*  encode = &face->type1.encoding;
+
+
+        new_state = dict_encoding;
+
+        encode->code_first = count;
+        encode->code_last  = 0;
+        encode->num_chars  = count;
+
+        /* Allocate the table of character indices.  The table of   */
+        /* character names is allocated through init_t1_recorder(). */
+        if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) )
+          return error;
+
+        error = T1_New_Table( &parser->table, count, memory );
+        if ( error )
+          goto Exit;
+
+        parser->encoding_type = t1_encoding_array;
+      }
+      break;
+
+    case imm_Subrs:
+      new_state             = dict_subrs;
+      face->type1.num_subrs = count;
+
+      error = T1_New_Table( &parser->table, count, memory );
+      if ( error )
+        goto Exit;
+      break;
+
+    case imm_CharStrings:
+      new_state = dict_charstrings;
+      break;
+
+    default:
+      new_state = dict_unknown_array;
+    }
+
+    parser->state_stack[++parser->state_index] = new_state;
+
+  Exit:
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+  }
+
+
+  static
+  FT_Error  Finalize_Parsing( T1_Parser*  parser )
+  {
+    T1_Face             face    = parser->face;
+    T1_Font*            type1   = &face->type1;
+    FT_Memory           memory  = face->root.memory;
+    T1_Table*           strings = &parser->table;
+    PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+    FT_Int              num_glyphs;
+    FT_Int              n;
+    FT_Error            error;
+
+
+    num_glyphs = type1->num_glyphs = parser->cur_name;
+
+    /* allocate glyph names and charstrings arrays */
+    if ( ALLOC_ARRAY( type1->glyph_names,     num_glyphs, FT_String* ) ||
+         ALLOC_ARRAY( type1->charstrings,     num_glyphs, FT_Byte* )   ||
+         ALLOC_ARRAY( type1->charstrings_len, num_glyphs, FT_Int*  )   )
+      return error;
+
+    /* copy glyph names and charstrings offsets and lengths */
+    type1->charstrings_block = strings->block;
+    for ( n = 0; n < num_glyphs; n++ )
+    {
+      type1->glyph_names[n]     = (FT_String*)strings->elements[2 * n];
+      type1->charstrings[n]     = strings->elements[2 * n + 1];
+      type1->charstrings_len[n] = strings->lengths [2 * n + 1];
+    }
+
+    /* now free the old tables */
+    FREE( strings->elements );
+    FREE( strings->lengths );
+
+    if ( !psnames )
+    {
+      FT_ERROR(( "Finalize_Parsing: `PSNames' module missing!\n" ));
+      return T1_Err_Unimplemented_Feature;
+    }
+
+    /* compute encoding if required */
+    if ( parser->encoding_type == t1_encoding_none )
+    {
+      FT_ERROR(( "Finalize_Parsing: no encoding specified in font file\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    {
+      FT_Int        n;
+      T1_Encoding*  encode = &type1->encoding;
+
+
+      encode->code_first = encode->num_chars - 1;
+      encode->code_last  = 0;
+
+      for ( n = 0; n < encode->num_chars; n++ )
+      {
+        FT_String** names;
+        FT_Int      index;
+        FT_Int      m;
+
+
+        switch ( parser->encoding_type )
+        {
+        case t1_encoding_standard:
+          index = psnames->adobe_std_encoding[n];
+          names = 0;
+          break;
+
+        case t1_encoding_expert:
+          index = psnames->adobe_expert_encoding[n];
+          names = 0;
+          break;
+
+        default:
+          index = n;
+          names = (FT_String**)parser->encoding_offsets;
+        }
+
+        encode->char_index[n] = 0;
+
+        if ( index )
+        {
+          FT_String*  name;
+
+
+          if ( names )
+            name = names[index];
+          else
+            name = (FT_String*)psnames->adobe_std_strings(index);
+
+          if ( name )
+          {
+            FT_Int  len = strlen( name );
+
+
+            /* lookup glyph index from name */
+            for ( m = 0; m < num_glyphs; m++ )
+            {
+              if ( strncmp( type1->glyph_names[m], name, len ) == 0 )
+              {
+                encode->char_index[n] = m;
+                break;
+              }
+            }
+
+            if ( n < encode->code_first ) encode->code_first = n;
+            if ( n > encode->code_last  ) encode->code_last  = n;
+          }
+        }
+      }
+
+      parser->encoding_type = t1_encoding_none;
+
+      FREE( parser->encoding_names );
+      FREE( parser->encoding_lengths );
+      FREE( parser->encoding_offsets );
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Parse_T1_FontProgram                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given Type 1 font file and builds its face object.        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    parser :: A handle to the target parser object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The parser contains a handle to the target face object.            */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Parse_T1_FontProgram( T1_Parser*  parser )
+  {
+    FT_Error  error;
+    T1_Font*  type1 = &parser->face->type1;
+
+
+    for (;;)
+    {
+      T1_Token      token;
+      T1_Token*     top;
+      T1_DictState  dict_state;
+      FT_Int        dict_index;
+
+
+      error      = Next_T1_Token( parser, &token );
+      top        = parser->top;
+      dict_index = parser->state_index;
+      dict_state = parser->state_stack[dict_index];
+
+      switch ( token.kind )
+      {
+        /* a keyword has been detected */
+      case tok_keyword:
+        switch ( token.kind2 )
+        {
+        case key_dict:
+          switch ( dict_state )
+          {
+          case dict_none:
+            /* All right, we are beginning the font dictionary.  */
+            /* Check that we only have one number argument, then */
+            /* consume the `begin' and change to `dict_font'     */
+            /* state.                                            */
+            error = Expect_Dict_Arguments( parser, 1, tok_error,
+                                           dict_font, 0 );
+            if ( error )
+              goto Exit;
+
+            /* clear stack from all the previous content.  This */
+            /* could be some stupid Postscript code.            */
+            parser->top = parser->stack;
+            break;
+
+          case dict_font:
+            /* This must be the /FontInfo dictionary, so check */
+            /* that we have at least two arguments, that they  */
+            /* are `/FontInfo' and a number, then change the   */
+            /* dictionary state.                               */
+            error = Expect_Dict_Arguments( parser, 2, imm_FontInfo,
+                                           dict_fontinfo, 0 );
+            if ( error )
+              goto Exit;
+            break;
+
+          case dict_none2:
+            error = Expect_Dict_Arguments( parser, 2, imm_Private,
+                                           dict_private, 0 );
+            if ( error )
+              goto Exit;
+            break;
+
+          case dict_private:
+            {
+              T1_Face  face = parser->face;
+              FT_Int   count;
+
+
+              error = Expect_Dict_Arguments( parser, 2, imm_CharStrings,
+                                             dict_charstrings, &count );
+              if ( error )
+                goto Exit;
+
+              type1->num_glyphs = count;
+              error = T1_New_Table( &parser->table, count * 2,
+                                    face->root.memory );
+              if ( error )
+                goto Exit;
+
+              /* record `.notdef' as the first glyph in the font */
+              error = T1_Add_Table( &parser->table, 0,
+                                    (FT_Byte*)".notdef", 8 );
+              parser->cur_name = 1;
+              /* XXX: DO SOMETHING HERE */
+            }
+            break;
+
+          default:
+            /* All other uses are invalid */
+            FT_ERROR(( "Parse_T1_FontProgram:" ));
+            FT_ERROR(( " invalid use of `dict' keyword\n" ));
+            goto Syntax_Error;
+          }
+          break;
+
+        case key_array:
+          /* Are we in an array yet?  If so, raise an error */
+          switch ( dict_state )
+          {
+          case dict_encoding:
+          case dict_subrs:
+          case dict_othersubrs:
+          case dict_charstrings:
+          case dict_unknown_array:
+            FT_ERROR(( "Parse_T1_FontProgram: nested array definitions\n" ));
+            goto Syntax_Error;
+
+          default:
+            ;
+          }
+          error = Expect_Array_Arguments( parser );
+          if ( error )
+            goto Exit;
+          break;
+
+        case key_ND:
+        case key_NP:
+        case key_def:
+          /* Are we in an array? If so, finalize it. */
+          switch ( dict_state )
+          {
+          case dict_encoding:    /* finish encoding array */
+            /* copy table names to the face object */
+            T1_Done_Table( &parser->table );
+
+            parser->encoding_names   = parser->table.block;
+            parser->encoding_lengths = parser->table.lengths;
+            parser->encoding_offsets = parser->table.elements;
+
+            parser->state_index--;
+            break;
+
+          case dict_subrs:
+            /* copy recorder sub-routines */
+            T1_Done_Table( &parser->table );
+
+            parser->subrs      = parser->table.block;
+            type1->subrs       = parser->table.elements;
+            type1->subrs_len   = parser->table.lengths;
+            type1->subrs_block = parser->table.block;
+
+            parser->state_index--;
+            break;
+
+          case dict_charstrings:
+          case dict_othersubrs:
+          case dict_unknown_array:
+            FT_ERROR(( "Parse_T1_FontProgram: unsupported array\n" ));
+            goto Syntax_Error;
+            break;
+
+          default:   /* normal `def' processing */
+            /* Check that we have sufficient operands in the stack */
+            if ( top >= parser->stack + 2 )
+            {
+              /* Now check that the first operand is an immediate. */
+              /* If so, call the appropriate `def' routine based   */
+              /* on the current parser state.                      */
+              if ( top[-2].kind == tok_immediate )
+              {
+                parser->top -= 2;
+                parser->args = parser->top + 1;
+                error = def_funcs[dict_state](parser);
+              }
+              else
+              {
+                /* This is an error, but some fonts contain  */
+                /* stupid Postscript code.  We simply ignore */
+                /* an invalid `def' by clearing the stack.   */
+#if 0
+                FT_ERROR(( "Parse_T1_FontProgram: immediate expected\n" ));
+                goto Syntax_Error;
+#else
+                parser->top = parser->stack;
+#endif
+              }
+            }
+            else
+            {
+              FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+              goto Stack_Underflow;
+            }
+          }
+          break;
+
+        case key_index:
+          if ( top <= parser->stack )
+          {
+            FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+            goto Stack_Underflow;
+          }
+
+          /* simply ignore? */
+          parser->top --;
+          break;
+
+        case key_put:
+          /* Check that we have sufficient operands in stack */
+          if ( top < parser->stack + 2 )
+          {
+            FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+            goto Stack_Underflow;
+          }
+
+          parser->top -= 2;
+          parser->args = parser->top;
+
+          switch ( dict_state )
+          {
+          case dict_encoding:
+            error = Do_Put_Encoding( parser );
+            if ( error )
+              goto Exit;
+            break;
+
+          case dict_unknown_array:   /* ignore the `put' */
+            break;
+
+          default:
+#if 0
+            FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
+            goto Syntax_Error;
+#else
+            /* invalid context; simply ignore the `put' and */
+            /* clear the stack (stupid Postscript code)     */
+            FT_TRACE4(( "Parse_T1_FontProgram: invalid context ignored.\n" ));
+            parser->top = parser->stack;
+#endif
+          }
+          break;
+
+        case key_RD:
+          /* Check that we have sufficient operands in stack */
+          if ( top < parser->stack + 2 )
+          {
+            FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+            goto Stack_Underflow;
+          }
+
+          parser->top -= 2;
+          parser->args = parser->top;
+          switch ( dict_state )
+          {
+          case dict_subrs:
+            error = Do_RD_Subrs( parser );
+            if ( error )
+              goto Exit;
+            break;
+
+          case dict_charstrings:
+            error = Do_RD_Charstrings( parser );
+            if ( error )
+              goto Exit;
+            break;
+
+          default:
+            FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
+            goto Syntax_Error;
+          }
+          break;
+
+        case key_end:
+          /* Were we in a dictionary or in an array? */
+          if ( dict_index <= 0 )
+          {
+            FT_ERROR(( "Parse_T1_FontProgram: no dictionary defined\n" ));
+            goto Syntax_Error;
+          }
+
+          switch ( dict_state )
+          {
+            /* jump to the private dictionary if we are closing the */
+            /* `/Font' dictionary                                   */
+          case dict_font:
+            goto Open_Private;
+
+            /* exit the parser when closing the CharStrings dictionary */
+          case dict_charstrings:
+            return Finalize_Parsing( parser );
+
+          default:
+            /* Pop the current dictionary state and return to previous */
+            /* one.  Consume the `def'.                                */
+
+            /* Because some buggy fonts (BitStream) have incorrect     */
+            /* syntax, we never escape from the private dictionary     */
+            if ( dict_state != dict_private )
+              parser->state_index--;
+
+            /* many fonts use `NP' instead of `def' or `put', so */
+            /* we simply ignore the next token                   */
+#if 0
+            error = Expect_Keyword2( parser, key_def, key_put );
+            if ( error )
+              goto Exit;
+#else
+            (void)Expect_Keyword2( parser, key_def, key_put );
+#endif
+          }
+          break;
+
+        case key_for:
+          /* check that we have four arguments and simply */
+          /* ignore them                                  */
+          if ( top - parser->stack < 4 )
+          {
+            FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
+            goto Stack_Underflow;
+          }
+
+          parser->top -= 4;
+          break;
+
+        case key_currentdict:
+        Open_Private:
+          parser->state_index    = 0;
+          parser->state_stack[0] = dict_none2;
+          error = Open_PrivateDict( parser->tokenizer );
+          if ( error )
+            goto Exit;
+          break;
+
+        case key_true:
+        case key_false:
+        case key_StandardEncoding:
+        case key_ExpertEncoding:
+          goto Push_Element;
+
+        default:
+          FT_ERROR(( "Parse_T1_FontProgram:" ));
+          FT_ERROR(( " invalid keyword in context\n" ));
+          error = T1_Err_Syntax_Error;
+        }
+        break;
+
+        /* check for the presence of `/BlendAxisTypes' -- we cannot deal */
+        /* with multiple master fonts, so we must return a correct error */
+        /* code to allow another driver to load them                     */
+      case tok_immediate:
+        if ( token.kind2 == imm_BlendAxisTypes )
+        {
+          error = FT_Err_Unknown_File_Format;
+          goto Exit;
+        }
+        /* fallthrough */
+
+        /* A number was detected */
+      case tok_string:
+      case tok_program:
+      case tok_array:
+      case tok_hexarray:
+      case tok_any:
+      case tok_number:                        /* push number on stack */
+
+      Push_Element:
+        if ( top >= parser->limit )
+        {
+          error = T1_Err_Stack_Overflow;
+          goto Exit;
+        }
+        else
+          *parser->top++ = token;
+        break;
+
+        /* anything else is an error per se the spec, but we     */
+        /* frequently encounter stupid postscript code in fonts, */
+        /* so just ignore them                                   */
+      default:
+        error = T1_Err_Ok;  /* ignore token */
+      }
+
+      if ( error )
+        return error;
+    }
+
+  Exit:
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return T1_Err_Stack_Underflow;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1/t1load.h b/src/freetype/type1/t1load.h
new file mode 100644 (file)
index 0000000..d278374
--- /dev/null
@@ -0,0 +1,57 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1load.h                                                               */
+/*                                                                         */
+/*    Type 1 font loader (specification).                                  */
+/*                                                                         */
+/*  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 T1LOAD_H
+#define T1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1parse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  LOCAL_DEF
+  void  Init_T1_Parser( T1_Parser*    parser,
+                        T1_Face       face,
+                        T1_Tokenizer  tokenizer );
+
+
+  LOCAL_DEF
+  FT_Error  Parse_T1_FontProgram( T1_Parser*  parser );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1LOAD_H */
+
+
+/* END */
diff --git a/src/freetype/type1/t1objs.c b/src/freetype/type1/t1objs.c
new file mode 100644 (file)
index 0000000..1e6f9ca
--- /dev/null
@@ -0,0 +1,544 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1objs.c                                                               */
+/*                                                                         */
+/*    Type 1 objects manager (body).                                       */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1gload.h"
+#include "t1load.h"
+#include "t1afm.h"
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include "t1hinter.h"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1/t1gload.h>
+#include <type1/t1load.h>
+#include <type1/t1afm.h>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <type1/t1hinter.h>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+#include <freetype/internal/psnames.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1objs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           SIZE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The Type 1 size object destructor.  Used to discard a given size   */
+  /*    object.                                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_Size( T1_Size  size )
+  {
+    if ( size )
+    {
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+      T1_Done_Size_Hinter( size );
+#endif
+
+      size->valid = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Init_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The size object initializer.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeTrue error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_DEF
+  FT_Error  T1_Init_Size( T1_Size  size )
+  {
+    FT_Error  error;
+
+
+    size->valid = 0;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    error = T1_New_Size_Hinter( size );
+
+    return error;
+#else
+
+    FT_UNUSED( error );
+
+    return T1_Err_Ok;
+
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Reset_Size                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Resets an instance to a new pointsize/transform.  This function is */
+  /*    in charge of resetting the blue zones,a s well as the stem snap    */
+  /*    tables for a given size.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: The target size object.                                    */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Reset_Size( T1_Size  size )
+  {
+    /* recompute ascender, descender, etc. */
+    T1_Face           face    = (T1_Face)size->root.face;
+    FT_Size_Metrics*  metrics = &size->root.metrics;
+
+
+    if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
+      return FT_Err_Invalid_Argument;
+
+    /* Compute root ascender, descender, test height, and max_advance */
+    metrics->ascender    = ( FT_MulFix( face->root.ascender,
+                                        metrics->y_scale ) + 32 ) & -64;
+    metrics->descender   = ( FT_MulFix( face->root.descender,
+                                        metrics->y_scale ) + 32 ) & -64;
+    metrics->height      = ( FT_MulFix( face->root.height,
+                                        metrics->y_scale ) + 32 ) & -64;
+    metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
+                                        metrics->x_scale ) + 32 ) & -64;
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+    return T1_Reset_Size_Hinter( size );
+#else
+    return 0;
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                            FACE  FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object destructor.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A typeless pointer to the face object to destroy.          */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_Face( T1_Face  face )
+  {
+    FT_Memory  memory;
+    T1_Font*   type1 = &face->type1;
+
+
+    if ( face )
+    {
+      memory = face->root.memory;
+
+      /* release font info strings */
+      {
+        T1_FontInfo*  info = &type1->font_info;
+
+
+        FREE( info->version );
+        FREE( info->notice );
+        FREE( info->full_name );
+        FREE( info->family_name );
+        FREE( info->weight );
+      }
+
+      /* release top dictionary */
+      FREE( type1->charstrings_len );
+      FREE( type1->charstrings );
+      FREE( type1->glyph_names );
+
+      FREE( type1->subrs );
+      FREE( type1->subrs_len );
+
+      FREE( type1->subrs_block );
+      FREE( type1->charstrings_block );
+      FREE( type1->glyph_names_block );
+
+      FREE( type1->encoding.char_index );
+      FREE( type1->font_name );
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+      /* release afm data if present */
+      if ( face->afm_data )
+        T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
+#endif
+
+      /* release unicode map, if any */
+      FREE( face->unicode_map.maps );
+      face->unicode_map.num_maps = 0;
+
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object constructor.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     ::  input stream where to load font data.               */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The face record to build.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Init_Face( FT_Stream      stream,
+                          T1_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params )
+  {
+    T1_Tokenizer        tokenizer;
+    FT_Error            error;
+    PSNames_Interface*  psnames;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+    FT_UNUSED( face );
+
+
+    face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+    {
+      psnames = (PSNames_Interface*)
+                 FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
+                                          "psnames" );
+
+      face->psnames = psnames;
+    }
+
+    /* open the tokenizer, this will also check the font format */
+    error = New_Tokenizer( stream, &tokenizer );
+    if ( error )
+      goto Fail;
+
+    /* if we just wanted to check the format, leave successfully now */
+    if ( face_index < 0 )
+      goto Leave;
+
+    /* check the face index */
+    if ( face_index != 0 )
+    {
+      FT_ERROR(( "T1_Init_Face: invalid face index\n" ));
+      error = T1_Err_Invalid_Argument;
+      goto Leave;
+    }
+
+    /* Now, load the font program into the face object */
+    {
+      T1_Parser  parser;
+
+
+      Init_T1_Parser( &parser, face, tokenizer );
+      error = Parse_T1_FontProgram( &parser );
+      if ( error )
+        goto Leave;
+
+      /* Init the face object fields */
+      /* Now set up root face fields */
+      {
+        FT_Face   root  = (FT_Face)&face->root;
+        T1_Font*  type1 = &face->type1;
+
+
+        root->num_glyphs   = type1->num_glyphs;
+        root->num_charmaps = 1;
+
+        root->face_index = face_index;
+        root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+        root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+        root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+        
+        if ( type1->font_info.is_fixed_pitch )
+          root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+        /* XXX: TODO -- add kerning with .afm support */
+
+        /* get style name - be careful, some broken fonts only */
+        /* have a `/FontName' dictionary entry!                */
+        root->family_name = type1->font_info.family_name;
+        if ( root->family_name )
+        {
+          char*  full   = type1->font_info.full_name;
+          char*  family = root->family_name;
+
+
+          while ( *family && *full == *family )
+          {
+            family++;
+            full++;
+          }
+
+          root->style_name = ( *full == ' ' ? full + 1
+                                            : (char *)"Regular" );
+        }
+        else
+        {
+          /* do we have a `/FontName'? */
+          if (type1->font_name)
+          {
+            root->family_name = type1->font_name;
+            root->style_name  = "Regular";
+          }
+        }
+
+        /* no embedded bitmap support */
+        root->num_fixed_sizes = 0;
+        root->available_sizes = 0;
+
+        root->bbox         = type1->font_bbox;
+        root->units_per_EM = 1000;
+        root->ascender     =  (FT_Short)type1->font_bbox.yMax;
+        root->descender    = -(FT_Short)type1->font_bbox.yMin;
+        root->height       = ( ( root->ascender + root->descender) * 12 )
+                             / 10;
+
+        /* now compute the maximum advance width */
+
+        root->max_advance_width = type1->private_dict.standard_width[0];
+
+        /* compute max advance width for proportional fonts */
+        if ( !type1->font_info.is_fixed_pitch )
+        {
+          FT_Int  max_advance;
+
+
+          error = T1_Compute_Max_Advance( face, &max_advance );
+
+          /* in case of error, keep the standard width */
+          if ( !error )
+            root->max_advance_width = max_advance;
+          else
+            error = 0;   /* clear error */
+        }
+
+        root->max_advance_height = root->height;
+
+        root->underline_position  = type1->font_info.underline_position;
+        root->underline_thickness = type1->font_info.underline_thickness;
+
+        root->max_points   = 0;
+        root->max_contours = 0;
+      }
+    }
+
+    /* charmap support - synthetize unicode charmap when possible */
+    {
+      FT_Face     root    = &face->root;
+      FT_CharMap  charmap = face->charmaprecs;
+
+
+      /* synthesize a Unicode charmap if there is support in the `PSNames' */
+      /* module..                                                          */
+      if ( face->psnames )
+      {
+        PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+
+        if ( psnames->unicode_value )
+        {
+          error = psnames->build_unicodes(
+                    root->memory,
+                    face->type1.num_glyphs,
+                    (const char**)face->type1.glyph_names,
+                    &face->unicode_map );
+          if ( !error )
+          {
+            root->charmap        = charmap;
+            charmap->face        = (FT_Face)face;
+            charmap->encoding    = ft_encoding_unicode;
+            charmap->platform_id = 3;
+            charmap->encoding_id = 1;
+            charmap++;
+          }
+
+          /* simply clear the error in case of failure (which really) */
+          /* means that out of memory or no unicode glyph names       */
+          error = 0;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encodings */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts ?? */
+
+      switch ( face->type1.encoding_type )
+      {
+      case t1_encoding_standard:
+        charmap->encoding    = ft_encoding_adobe_standard;
+        charmap->encoding_id = 0;
+        break;
+
+      case t1_encoding_expert:
+        charmap->encoding    = ft_encoding_adobe_expert;
+        charmap->encoding_id = 1;
+        break;
+
+      default:
+        charmap->encoding    = ft_encoding_adobe_custom;
+        charmap->encoding_id = 2;
+        break;
+      }
+
+      root->charmaps     = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0]  = &face->charmaprecs[0];
+      face->charmaps[1]  = &face->charmaprecs[1];
+    }
+
+  Leave:
+    Done_Tokenizer( tokenizer );
+
+  Fail:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_GlyphSlot                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The glyph slot object destructor.                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: The glyph slot handle to destroy.                         */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_GlyphSlot( T1_GlyphSlot  glyph )
+  {
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+    T1_Done_Glyph_Hinter( glyph );
+
+#else
+
+    FT_UNUSED( glyph );
+
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Init_GlyphSlot                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The glyph slot object constructor.                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: The glyph slot handle to initialize.                      */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Init_GlyphSlot( T1_GlyphSlot  glyph )
+  {
+    FT_Error    error = FT_Err_Ok;
+
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+
+    error = T1_New_Glyph_Hinter( glyph );
+
+#else
+
+    FT_UNUSED( glyph );
+
+#endif
+
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1/t1objs.h b/src/freetype/type1/t1objs.h
new file mode 100644 (file)
index 0000000..47b0a37
--- /dev/null
@@ -0,0 +1,172 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1objs.h                                                               */
+/*                                                                         */
+/*    Type 1 objects manager (specification).                              */
+/*                                                                         */
+/*  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 T1OBJS_H
+#define T1OBJS_H
+
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/t1types.h>
+
+#include <freetype/internal/t1errors.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* The following structures must be defined by the hinter */
+  typedef struct T1_Size_Hints_   T1_Size_Hints;
+  typedef struct T1_Glyph_Hints_  T1_Glyph_Hints;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 driver object.                                */
+  /*                                                                       */
+  typedef struct T1_DriverRec_*  T1_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 size object.                                  */
+  /*                                                                       */
+  typedef struct T1_SizeRec_*  T1_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 glyph slot object.                            */
+  /*                                                                       */
+  typedef struct T1_GlyphSlotRec_*  T1_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_CharMap                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 character mapping object.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The Type 1 format doesn't use a charmap but an encoding table.     */
+  /*    The driver is responsible for making up charmap objects            */
+  /*    corresponding to these tables.                                     */
+  /*                                                                       */
+  typedef struct T1_CharMapRec_*  T1_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  HERE BEGINS THE TYPE1 SPECIFIC STUFF                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_SizeRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 size record.                                                */
+  /*                                                                       */
+  typedef struct  T1_SizeRec_
+  {
+    FT_SizeRec      root;
+    FT_Bool         valid;
+    T1_Size_Hints*  hints;  /* defined in the hinter. This allows */
+                            /* us to experiment with different    */
+                            /* hinting schemes without having to  */
+                            /* change `t1objs' each time.         */
+  } T1_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_GlyphSlotRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 glyph slot record.                                          */
+  /*                                                                       */
+  typedef struct  T1_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Int           max_points;
+    FT_Int           max_contours;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+    T1_Glyph_Hints*  hints;  /* defined in the hinter */
+
+  } T1_GlyphSlotRec;
+
+
+  LOCAL_DEF
+  FT_Error  T1_Init_Face( FT_Stream      stream,
+                          T1_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  T1_Done_Face( T1_Face  face );
+
+  LOCAL_DEF
+  FT_Error  T1_Init_Size( T1_Size  size );
+
+  LOCAL_DEF
+  void  T1_Done_Size( T1_Size  size );
+
+  LOCAL_DEF
+  FT_Error  T1_Reset_Size( T1_Size  size );
+
+  LOCAL_DEF
+  FT_Error  T1_Init_GlyphSlot( T1_GlyphSlot  slot );
+
+  LOCAL_DEF
+  void  T1_Done_GlyphSlot( T1_GlyphSlot  slot );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1OBJS_H */
+
+
+/* END */
diff --git a/src/freetype/type1/t1parse.c b/src/freetype/type1/t1parse.c
new file mode 100644 (file)
index 0000000..8b7ca25
--- /dev/null
@@ -0,0 +1,761 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1parse.c                                                              */
+/*                                                                         */
+/*    Type 1 parser (body).                                                */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/t1types.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1parse.h>
+
+#endif
+
+
+#include <stdio.h>  /* for sscanf()  */
+#include <string.h> /* for strncpy() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_New_Table                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a T1_Table structure.                                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The address of the target table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    count  :: The table size (i.e. maximum number of elements).        */
+  /*    memory :: The memory object to use for all subsequent              */
+  /*              reallocations.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_New_Table( T1_Table*  table,
+                          FT_Int     count,
+                          FT_Memory  memory )
+  {
+        FT_Error  error;
+
+
+        table->memory = memory;
+
+        if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) )
+                return error;
+
+        if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
+        {
+          FREE( table->elements );
+          return error;
+       }
+
+       table->max_elems = count;
+       table->num_elems = 0;
+
+       table->block        = 0;
+       table->capacity     = 0;
+       table->cursor       = 0;
+
+       return error;
+  }
+
+
+  static
+  FT_Error  reallocate_t1_table( T1_Table*  table,
+                                 FT_Int     new_size )
+  {
+    FT_Memory  memory   = table->memory;
+    FT_Byte*   old_base = table->block;
+    FT_Error   error;
+
+
+    /* reallocate the base block */
+    if ( REALLOC( table->block, table->capacity, new_size ) )
+      return error;
+    table->capacity = new_size;
+
+    /* shift all offsets if necessary */
+    if ( old_base )
+    {
+      FT_Long    delta  = table->block - old_base;
+      FT_Byte**  offset = table->elements;
+      FT_Byte**  limit  = offset + table->max_elems;
+
+
+      if ( delta )
+        for ( ; offset < limit; offset ++ )
+          if (offset[0])
+            offset[0] += delta;
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Add_Table                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds an object to a T1_Table, possibly growing its memory block.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The target table.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    index  :: The index of the object in the table.                    */
+  /*                                                                       */
+  /*    object :: The address of the object to copy in memory.             */
+  /*                                                                       */
+  /*    length :: The length in bytes of the source object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  An error is returned if a  */
+  /*    reallocation failed.                                               */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  T1_Add_Table( T1_Table*  table,
+                          FT_Int     index,
+                          void*      object,
+                          FT_Int     length )
+  {
+       if ( index < 0 || index > table->max_elems )
+    {
+         FT_ERROR(( "T1_Add_Table: invalid index\n" ));
+         return T1_Err_Syntax_Error;
+    }
+
+    /* grow the base block if needed */
+    if ( table->cursor + length > table->capacity )
+    {
+      FT_Error  error;
+      FT_Int    new_size = table->capacity;
+
+
+      while ( new_size < table->cursor + length )
+        new_size += 1024;
+
+      error = reallocate_t1_table( table, new_size );
+      if ( error )
+        return error;
+    }
+
+    /* add the object to the base block and adjust offset */
+    table->elements[index] = table->block + table->cursor;
+    table->lengths [index] = length;
+    MEM_Copy( table->block + table->cursor, object, length );
+
+    table->cursor += length;
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Table                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalize a T1_Table (reallocate it to its current cursor).         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    table :: The target table.                                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT release the heap's memory block.  It is up  */
+  /*    to the caller to clean it, or reference it in its own structures.  */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  T1_Done_Table( T1_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+    FT_Error   error;
+    FT_Byte*   old_base;
+
+
+    /* should never fail, as rec.cursor <= rec.size */
+    old_base = table->block;
+    if ( !old_base )
+      return;
+
+    (void)REALLOC( table->block, table->capacity, table->cursor );
+    table->capacity = table->cursor;
+
+    if ( old_base != table->block )
+    {
+      FT_Long    delta   = table->block - old_base;
+      FT_Byte**  element = table->elements;
+      FT_Byte**  limit   = element + table->max_elems;
+
+
+      for ( ; element < limit; element++ )
+        if ( element[0] )
+          element[0] += delta;
+    }
+  }
+
+
+  LOCAL_FUNC
+  FT_String*  CopyString( T1_Parser*  parser )
+  {
+    FT_String*  string = NULL;
+    T1_Token*   token  = parser->args++;
+    FT_Memory   memory = parser->tokenizer->memory;
+    FT_Error    error;
+
+
+    if ( token->kind == tok_string )
+    {
+      FT_Int  len = token->len - 2;
+
+
+      if ( ALLOC( string, len + 1 ) )
+      {
+        parser->error = error;
+        return 0;
+      }
+
+      MEM_Copy( string, parser->tokenizer->base + token->start + 1, len );
+      string[len] = '\0';
+
+      parser->error = T1_Err_Ok;
+    }
+    else
+    {
+      FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" ));
+      parser->error = T1_Err_Syntax_Error;
+    }
+
+    return string;
+  }
+
+
+  static
+  FT_Error  parse_int( FT_Byte*  base,
+                       FT_Byte*  limit,
+                       FT_Long*  result )
+  {
+    FT_Bool  sign = 0;
+    FT_Long  sum  = 0;
+
+
+    if ( base >= limit )
+      goto Fail;
+
+    /* check sign */
+    if ( *base == '+' )
+      base++;
+
+    else if ( *base == '-' )
+    {
+      sign++;
+      base++;
+    }
+
+    /* parse digits */
+    if ( base >= limit )
+      goto Fail;
+
+    do
+    {
+      sum = ( 10 * sum + ( *base++ - '0' ) );
+
+    } while ( base < limit );
+
+    if ( sign )
+      sum = -sum;
+
+    *result = sum;
+    return T1_Err_Ok;
+
+  Fail:
+    FT_ERROR(( "parse_int: integer expected\n" ));
+    *result = 0;
+    return T1_Err_Syntax_Error;
+  }
+
+
+  static
+  FT_Error  parse_float( FT_Byte*  base,
+                         FT_Byte*  limit,
+                         FT_Long   scale,
+                         FT_Long*  result )
+  {
+#if 1
+
+    /* XXX: We are simply much too lazy to code this function   */
+    /*      properly for now.  We will do that when the rest of */
+    /*      the driver works properly.                          */
+    char    temp[32];
+    int     len = limit - base;
+    double  value;
+
+
+    if ( len > 31 )
+      goto Fail;
+
+    strncpy( temp, (char*)base, len );
+    temp[len] = '\0';
+    if ( sscanf( temp, "%lf", &value ) != 1 )
+      goto Fail;
+
+    *result = (FT_Long)( scale * value );
+    return 0;
+
+#else
+
+    FT_Byte*  cur;
+    FT_Bool   sign        = 0;  /* sign                        */
+    FT_Long   number_int  = 0;  /* integer part                */
+    FT_Long   number_frac = 0;  /* fractional part             */
+    FT_Long   exponent    = 0;  /* exponent value              */
+    FT_Int    num_frac    = 0;  /* number of fractional digits */
+
+
+    /* check sign */
+    if ( *base == '+' )
+      base++;
+
+    else if ( *base == '-' )
+    {
+      sign++;
+      base++;
+    }
+
+    /* find integer part */
+    cur = base;
+    while ( cur < limit )
+    {
+      FT_Byte  c = *cur;
+
+
+      if ( c == '.' || c == 'e' || c == 'E' )
+        break;
+
+      cur++;
+    }
+
+    if ( cur > base )
+    {
+      error = parse_integer( base, cur, &number_int );
+      if ( error )
+        goto Fail;
+    }
+
+    /* read fractional part, if any */
+    if ( *cur == '.' )
+    {
+      cur++;
+      base = cur;
+      while ( cur < limit )
+      {
+        FT_Byte  c = *cur;
+
+
+        if ( c == 'e' || c == 'E' )
+          break;
+        cur++;
+      }
+
+      num_frac = cur - base;
+
+      if ( cur > base )
+      {
+        error = parse_integer( base, cur, &number_frac );
+        if ( error )
+          goto Fail;
+        base = cur;
+      }
+   }
+
+    /* read exponent, if any */
+    if ( *cur == 'e' || *cur == 'E' )
+    {
+      cur++;
+      base = cur;
+      error = parse_integer( base, limit, &exponent );
+      if ( error )
+        goto Fail;
+
+      /* now check that exponent is within `correct bounds' */
+      /* i.e. between -6 and 6                              */
+      if ( exponent < -6 || exponent > 6 )
+        goto Fail;
+    }
+
+    /* now adjust integer value and exponent for fractional part */
+    while ( num_frac > 0 )
+    {
+      number_int *= 10;
+      exponent--;
+      num_frac--;
+    }
+
+    number_int += num_frac;
+
+    /* skip point if any, read fractional part */
+    if ( cur + 1 < limit )
+    {
+      if (*cur..
+    }
+
+    /* now compute scaled float value */
+    /* XXX: incomplete!               */
+
+#endif /* 1 */
+
+  Fail:
+    FT_ERROR(( "parse_float: syntax error!\n" ));
+    return T1_Err_Syntax_Error;
+  }
+
+
+  static
+  FT_Error  parse_integer( FT_Byte*  base,
+                           FT_Byte*  limit,
+                           FT_Long*  result )
+  {
+    FT_Byte*  cur;
+
+
+    /* the lexical analyser accepts floats as well as integers */
+    /* now; check that we really have an int in this token     */
+    cur = base;
+    while ( cur < limit )
+    {
+      FT_Byte  c = *cur++;
+
+
+      if ( c == '.' || c == 'e' || c == 'E' )
+        goto Float_Number;
+    }
+
+    /* now read the number's value */
+    return parse_int( base, limit, result );
+
+  Float_Number:
+    /* we really have a float there; simply call parse_float in this */
+    /* case with a scale of `10' to perform round                    */
+    {
+      FT_Error error;
+
+
+      error = parse_float( base, limit, 10, result );
+      if ( !error )
+      {
+        if ( *result >= 0 )
+          *result = ( *result + 5 ) / 10;      /* round value */
+        else
+          *result = -( ( 5 - *result ) / 10 );
+      }
+      return error;
+    }
+  }
+
+
+  LOCAL_FUNC
+  FT_Long  CopyInteger( T1_Parser*  parser )
+  {
+    FT_Long    sum   = 0;
+    T1_Token*  token = parser->args++;
+
+
+    if ( token->kind == tok_number )
+    {
+      FT_Byte*  base  = parser->tokenizer->base + token->start;
+      FT_Byte*  limit = base + token->len;
+
+
+      /* now read the number's value */
+      parser->error = parse_integer( base, limit, &sum );
+      return sum;
+    }
+
+    FT_ERROR(( "CopyInteger: number expected\n" ));
+    parser->args--;
+    parser->error = T1_Err_Syntax_Error;
+    return 0;
+  }
+
+
+  LOCAL_FUNC
+  FT_Bool   CopyBoolean( T1_Parser*  parser )
+  {
+    FT_Error   error  = T1_Err_Ok;
+    FT_Bool    result = 0;
+    T1_Token*  token  = parser->args++;
+
+
+    if ( token->kind == tok_keyword )
+    {
+      if ( token->kind2 == key_false )
+        result = 0;
+
+      else if ( token->kind2 == key_true )
+        result = !0;
+
+      else
+        goto Fail;
+    }
+    else
+    {
+      Fail:
+        FT_ERROR(( "CopyBoolean:" ));
+        FT_ERROR(( " syntax error; `false' or `true' expected\n" ));
+        error = T1_Err_Syntax_Error;
+    }
+    parser->error = error;
+    return result;
+  }
+
+
+  LOCAL_FUNC
+  FT_Long   CopyFloat( T1_Parser*  parser,
+                       FT_Int      scale )
+  {
+    FT_Error   error;
+    FT_Long    sum = 0;
+    T1_Token*  token = parser->args++;
+
+
+    if ( token->kind == tok_number )
+    {
+      FT_Byte*  base  = parser->tokenizer->base + token->start;
+      FT_Byte*  limit = base + token->len;
+
+
+      error = parser->error = parse_float( base, limit, scale, &sum );
+      if ( error )
+        goto Fail;
+
+      return sum;
+    }
+
+  Fail:
+    FT_ERROR(( "CopyFloat: syntax error!\n" ));
+    parser->error = T1_Err_Syntax_Error;
+    return 0;
+  }
+
+
+  LOCAL_FUNC
+  void  CopyBBox( T1_Parser*  parser,
+                  FT_BBox*    bbox )
+  {
+    T1_Token*  token = parser->args++;
+    FT_Int     n;
+    FT_Error   error;
+
+
+    if ( token->kind == tok_program ||
+         token->kind == tok_array   )
+    {
+      /* get rid of `['/`]', or `{'/`}' */
+      FT_Byte*  base  = parser->tokenizer->base + token->start + 1;
+      FT_Byte*  limit = base + token->len - 2;
+      FT_Byte*  cur;
+      FT_Byte*  start;
+
+
+      /* read each parameter independently */
+      cur = base;
+      for ( n = 0; n < 4; n++ )
+      {
+        FT_Long*  result;
+
+
+        /* skip whitespace */
+        while ( cur < limit && *cur == ' ' )
+          cur++;
+
+        /* skip numbers */
+        start = cur;
+        while ( cur < limit && *cur != ' ' )
+          cur++;
+
+        /* compute result address */
+        switch ( n )
+        {
+        case 0:
+          result = &bbox->xMin;
+          break;
+        case 1:
+          result = &bbox->yMin;
+          break;
+        case 2:
+          result = &bbox->xMax;
+          break;
+        default:
+          result = &bbox->yMax;
+        }
+
+        error = parse_integer( start, cur, result );
+        if ( error )
+          goto Fail;
+      }
+      parser->error = 0;
+      return;
+    }
+
+  Fail:
+    FT_ERROR(( "CopyBBox: syntax error!\n" ));
+    parser->error = T1_Err_Syntax_Error;
+  }
+
+
+  LOCAL_FUNC
+  void  CopyMatrix( T1_Parser*  parser,
+                    FT_Matrix*  matrix )
+  {
+    T1_Token* token = parser->args++;
+    FT_Error  error;
+
+
+    if ( token->kind == tok_array )
+    {
+      /* get rid of `[' and `]' */
+      FT_Byte*  base  = parser->tokenizer->base + token->start + 1;
+      FT_Byte*  limit = base + token->len - 2;
+      FT_Byte*  cur;
+      FT_Byte*  start;
+      FT_Int    n;
+
+
+      /* read each parameter independently */
+      cur = base;
+      for ( n = 0; n < 4; n++ )
+      {
+        FT_Long*  result;
+
+
+        /* skip whitespace */
+        while ( cur < limit && *cur == ' ' )
+          cur++;
+
+        /* skip numbers */
+        start = cur;
+        while ( cur < limit && *cur != ' ')
+          cur++;
+
+        /* compute result address */
+        switch ( n )
+        {
+        case 0:
+          result = &matrix->xx;
+          break;
+        case 1:
+          result = &matrix->yx;
+          break;
+        case 2:
+          result = &matrix->xy;
+          break;
+        default:
+          result = &matrix->yy;
+        }
+
+        error = parse_float( start, cur, 65536000L, result );
+        if ( error )
+          goto Fail;
+      }
+      parser->error = 0;
+      return;
+    }
+
+  Fail:
+    FT_ERROR(( "CopyMatrix: syntax error!\n" ));
+    parser->error = T1_Err_Syntax_Error;
+  }
+
+
+  LOCAL_FUNC
+  void  CopyArray( T1_Parser*  parser,
+                   FT_Byte*    num_elements,
+                   FT_Short*   elements,
+                   FT_Int      max_elements )
+  {
+    T1_Token* token = parser->args++;
+    FT_Error  error;
+
+
+    if ( token->kind == tok_array   ||
+         token->kind == tok_program )   /* in the case of MinFeature */
+    {
+      /* get rid of `['/`]', or `{'/`}' */
+      FT_Byte*  base  = parser->tokenizer->base + token->start + 1;
+      FT_Byte*  limit = base + token->len - 2;
+      FT_Byte*  cur;
+      FT_Byte*  start;
+      FT_Int    n;
+
+
+      /* read each parameter independently */
+      cur = base;
+      for ( n = 0; n < max_elements; n++ )
+      {
+        FT_Long  result;
+
+
+        /* test end of string */
+        if ( cur >= limit )
+          break;
+
+        /* skip whitespace */
+        while ( cur < limit && *cur == ' ' )
+          cur++;
+
+        /* end of list? */
+        if ( cur >= limit )
+          break;
+
+        /* skip numbers */
+        start = cur;
+        while ( cur < limit && *cur != ' ' )
+          cur++;
+
+        error = parse_integer( start, cur, &result );
+        if ( error )
+          goto Fail;
+
+        *elements++ = (FT_Short)result;
+      }
+
+      if ( num_elements )
+        *num_elements = (FT_Byte)n;
+
+      parser->error = 0;
+      return;
+    }
+
+  Fail:
+    FT_ERROR(( "CopyArray: syntax error!\n" ));
+    parser->error = T1_Err_Syntax_Error;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1/t1parse.h b/src/freetype/type1/t1parse.h
new file mode 100644 (file)
index 0000000..2c42b8c
--- /dev/null
@@ -0,0 +1,261 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1parse.h                                                              */
+/*                                                                         */
+/*    Type 1 parser (specification).                                       */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The Type1 parser component is in charge of simply parsing the font    */
+  /* input stream and convert simple tokens and elements into integers,    */
+  /* floats, matrices, strings, etc.                                       */
+  /*                                                                       */
+  /* It is used by the Type1 loader.                                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef T1PARSE_H
+#define T1PARSE_H
+
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1tokens.h"
+
+#else
+
+#include <type1/t1tokens.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    T1_DictState                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration used to describe the Type 1 parser's state, i.e.    */
+  /*    which dictionary (or array) it is scanning and processing at the   */
+  /*    current moment.                                                    */
+  /*                                                                       */
+  typedef enum  T1_DictState_
+  {
+    dict_none = 0,
+    dict_font,          /* parsing the font dictionary              */
+    dict_fontinfo,      /* parsing the font info dictionary         */
+    dict_none2,         /* beginning to parse the encrypted section */
+    dict_private,       /* parsing the private dictionary           */
+    dict_encoding,      /* parsing the encoding array               */
+    dict_subrs,         /* parsing the subrs array                  */
+    dict_othersubrs,    /* parsing the othersubrs array (?)         */
+    dict_charstrings,   /* parsing the charstrings dictionary       */
+    dict_unknown_array, /* parsing/ignoring an unknown array        */
+    dict_unknown_dict,  /* parsing/ignoring an unknown dictionary   */
+
+    dict_max    /* do not remove from list */
+
+  } T1_DictState;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Table                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A T1_Table is a simple object used to store an array of objects in */
+  /*    a single memory block.                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    block     :: The address in memory of the growheap's block.  This  */
+  /*                 can change between two object adds, due to            */
+  /*                 reallocation.                                         */
+  /*                                                                       */
+  /*    cursor    :: The current top of the grow heap within its block.    */
+  /*                                                                       */
+  /*    capacity  :: The current size of the heap block.  Increments by    */
+  /*                 1kByte chunks.                                        */
+  /*                                                                       */
+  /*    max_elems :: The maximum number of elements in table.              */
+  /*                                                                       */
+  /*    num_elems :: The current number of elements in table.              */
+  /*                                                                       */
+  /*    elements  :: A table of element addresses within the block.        */
+  /*                                                                       */
+  /*    lengths   :: A table of element sizes within the block.            */
+  /*                                                                       */
+  /*    memory    :: The object used for memory operations                 */
+  /*                 (alloc/realloc).                                      */
+  /*                                                                       */
+  typedef struct  T1_Table_
+  {
+    FT_Byte*   block;          /* current memory block           */
+    FT_Int     cursor;         /* current cursor in memory block */
+    FT_Int     capacity;       /* current size of memory block   */
+
+    FT_Int     max_elems;
+    FT_Int     num_elems;
+    FT_Byte**  elements;       /* addresses of table elements */
+    FT_Int*    lengths;        /* lengths of table elements   */
+
+    FT_Memory  memory;
+
+  } T1_Table;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Parser                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A Type 1 parser.  This object is in charge of parsing Type 1 ASCII */
+  /*    streams and builds dictionaries for a T1_Face object.              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    error            :: The current error code.  0 means success.      */
+  /*                                                                       */
+  /*    face             :: The target T1_Face object being built.         */
+  /*                                                                       */
+  /*    tokenizer        :: The tokenizer (lexical analyser) used for      */
+  /*                        processing the input stream.                   */
+  /*                                                                       */
+  /*    dump_tokens      :: XXX                                            */
+  /*                                                                       */
+  /*    stack            :: The current token stack.  Note that we don't   */
+  /*                        use intermediate Postscript objects here!      */
+  /*                                                                       */
+  /*    top              :: The current top of token stack.                */
+  /*                                                                       */
+  /*    limit            :: The current upper bound of the token stack.    */
+  /*                        Used for overflow checks.                      */
+  /*                                                                       */
+  /*    args             :: The arguments of a given operator.  Used and   */
+  /*                        increased by the various CopyXXX() functions.  */
+  /*                                                                       */
+  /*    state_index      :: The index of the top of the dictionary state   */
+  /*                        stack.                                         */
+  /*                                                                       */
+  /*    state_stack      :: The dictionary states stack.                   */
+  /*                                                                       */
+  /*    table            :: A T1_Table object used to record various kinds */
+  /*                        of dictionaries or arrays (like `/Encoding',   */
+  /*                        `/Subrs', `/CharStrings').                     */
+  /*                                                                       */
+  /*    cur_name         :: XXX                                            */
+  /*                                                                       */
+  /*    encoding_type    :: XXX                                            */
+  /*                                                                       */
+  /*    encoding_names   :: XXX                                            */
+  /*                                                                       */
+  /*    encoding_lengths :: XXX                                            */
+  /*                                                                       */
+  /*    encoding_offsets :: XXX                                            */
+  /*                                                                       */
+  /*    subrs            :: XXX                                            */
+  /*                                                                       */
+  /*    charstrings      :: XXX                                            */
+  /*                                                                       */
+  typedef  struct  T1_Parser_
+  {
+    FT_Error         error;
+    T1_Face          face;
+
+    T1_Tokenizer     tokenizer;
+    FT_Bool          dump_tokens;
+
+    T1_Token         stack[T1_MAX_STACK_DEPTH];
+    T1_Token*        top;
+    T1_Token*        limit;
+    T1_Token*        args;
+
+    FT_Int           state_index;
+    T1_DictState     state_stack[T1_MAX_DICT_DEPTH];
+
+       T1_Table         table;
+
+       FT_Int           cur_name;
+
+       T1_EncodingType  encoding_type;
+    FT_Byte*         encoding_names;
+    FT_Int*          encoding_lengths;
+    FT_Byte**        encoding_offsets;
+
+    FT_Byte*         subrs;
+    FT_Byte*         charstrings;
+
+  } T1_Parser;
+
+
+  LOCAL_DEF
+  FT_Error  T1_New_Table( T1_Table*  table,
+                          FT_Int     count,
+                          FT_Memory  memory );
+
+  LOCAL_DEF
+  FT_Error  T1_Add_Table( T1_Table*  table,
+                          FT_Int     index,
+                          void*      object,
+                          FT_Int     length );
+
+  LOCAL_DEF
+  void  T1_Done_Table( T1_Table*  table );
+
+
+  LOCAL_DEF
+  FT_String*  CopyString( T1_Parser*  parser );
+
+  LOCAL_DEF
+  FT_Long  CopyInteger( T1_Parser*  parser );
+
+  LOCAL_DEF
+  FT_Bool  CopyBoolean( T1_Parser*  parser );
+
+  LOCAL_DEF
+  FT_Long  CopyFloat( T1_Parser*  parser,
+                      FT_Int      scale );
+
+  LOCAL_DEF
+  void  CopyBBox( T1_Parser*  parser,
+                  FT_BBox*    bbox );
+
+  LOCAL_DEF
+  void  CopyMatrix( T1_Parser*  parser,
+                    FT_Matrix*  matrix );
+
+  LOCAL_DEF
+  void  CopyArray( T1_Parser*  parser,
+                   FT_Byte*    num_elements,
+                   FT_Short*   elements,
+                   FT_Int      max_elements );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1PARSE_H */
+
+
+/* END */
diff --git a/src/freetype/type1/t1tokens.c b/src/freetype/type1/t1tokens.c
new file mode 100644 (file)
index 0000000..2953322
--- /dev/null
@@ -0,0 +1,1101 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1parse.c                                                              */
+/*                                                                         */
+/*    Type 1 parser (body).                                                */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The tokenizer is in charge of loading and reading a Type1 font file   */
+  /* (either in PFB or PFA format), and extracting successive tokens and   */
+  /* keywords from its two streams (i.e. the font program, and the private */
+  /* dictionary).                                                          */
+  /*                                                                       */
+  /* Eexec decryption is performed automatically when entering the private */
+  /* dictionary, or when retrieving char strings.                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/ftdebug.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1tokens.h"
+#include "t1load.h"
+
+#else
+
+#include <type1/t1tokens.h>
+#include <type1/t1load.h>
+
+#endif
+
+
+#include <string.h>     /* for strncmp() */
+
+
+#undef  READ_BUFFER_INCREMENT
+#define READ_BUFFER_INCREMENT  0x400
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1load
+
+
+  /* An array of Type1 keywords supported by this engine.  This table */
+  /* places the keyword in lexicographical order.  It should always   */
+  /* correspond  to the enums `key_xxx'!                              */
+  /*                                                                  */
+  const char*  t1_keywords[key_max - key_first_] =
+  {
+    "-|", "ExpertEncoding", "ND", "NP", "RD", "StandardEncoding", "array",
+    "begin", "closefile", "currentdict", "currentfile", "def", "dict", "dup",
+    "eexec", "end", "executeonly", "false", "for", "index", "noaccess",
+    "put", "readonly", "true", "userdict", "|", "|-"
+  };
+
+
+  const char*  t1_immediates[imm_max - imm_first_] =
+  {
+    "-|", ".notdef", "BlendAxisTypes", "BlueFuzz", "BlueScale", "BlueShift",
+    "BlueValues", "CharStrings", "Encoding", "FamilyBlues", "FamilyName",
+    "FamilyOtherBlues", "FID", "FontBBox", "FontID", "FontInfo", "FontMatrix",
+    "FontName", "FontType", "ForceBold", "FullName", "ItalicAngle",
+    "LanguageGroup", "Metrics", "MinFeature", "ND", "NP", "Notice",
+    "OtherBlues", "OtherSubrs", "PaintType", "Private", "RD", "RndStemUp",
+    "StdHW", "StdVW", "StemSnapH", "StemSnapV", "StrokeWidth", "Subrs",
+    "UnderlinePosition", "UnderlineThickness", "UniqueID", "Weight",
+    "isFixedPitch", "lenIV", "password", "version", "|", "|-"
+  };
+
+
+  /* lexicographic comparison of two strings */
+  static
+  int  lexico_strcmp( const char*  str1,
+                      int          str1_len,
+                      const char*  str2 )
+  {
+    int  c2 = 0;
+
+
+    for ( ; str1_len > 0; str1_len-- )
+    {
+      int  c1, diff;
+
+
+      c1 = *str1++;
+      c2 = *str2++;
+
+      diff = c1 - c2;
+      if ( diff )
+        return diff;
+    };
+
+    return -*str2;
+  }
+
+
+  /* find a given token/name, performing binary search */
+  static
+  int  Find_Name( char*         base,
+                  int           length,
+                  const char**  table,
+                  int           table_len )
+  {
+    int  left, right;
+
+
+    left  = 0;
+    right = table_len - 1;
+
+    while ( right - left > 1 )
+    {
+      int  middle = left + ( ( right - left ) >> 1 );
+      int  cmp;
+
+
+      cmp = lexico_strcmp( base, length, table[middle] );
+      if ( !cmp )
+        return middle;
+
+      if ( cmp < 0 )
+        right = middle;
+      else
+        left  = middle;
+    }
+
+    if ( !lexico_strcmp( base, length, table[left ] ) )
+      return left;
+    if ( !lexico_strcmp( base, length, table[right] ) )
+      return right;
+
+    return -1;
+  }
+
+
+  /* read the small PFB section header */
+  static
+  FT_Error  Read_PFB_Tag( FT_Stream   stream,
+                          FT_UShort*  atag,
+                          FT_ULong*   asize )
+  {
+    FT_UShort  tag;
+    FT_ULong   size;
+    FT_Error   error;
+
+
+    FT_TRACE2(( "Read_PFB_Tag: reading\n" ));
+
+    if ( ACCESS_Frame( 6L ) )
+      return error;
+
+    tag  = GET_UShort();
+    size = GET_ULong();
+
+    FORGET_Frame();
+
+    *atag  = tag;
+    *asize = (   ( size         & 0xFF ) << 24 ) |
+             ( ( ( size >> 8  ) & 0xFF ) << 16 ) |
+             ( ( ( size >> 16 ) & 0xFF ) << 8 )  |
+             ( ( ( size >> 24 ) & 0xFF ) );
+
+    FT_TRACE2(( "  tag  = %04x\n", tag    ));
+    FT_TRACE4(( "  asze = %08x\n", size   ));
+    FT_TRACE2(( "  size = %08x\n", *asize ));
+
+    return T1_Err_Ok;
+  }
+
+
+  static
+  FT_Error  grow( T1_Tokenizer  tokzer )
+  {
+    FT_Error   error;
+    FT_Long    left_bytes;
+    FT_Memory  memory = tokzer->memory;
+
+
+    left_bytes = tokzer->max - tokzer->limit;
+
+    if ( left_bytes > 0 )
+    {
+      FT_Stream stream = tokzer->stream;
+
+
+      if ( left_bytes > READ_BUFFER_INCREMENT )
+        left_bytes = READ_BUFFER_INCREMENT;
+
+      FT_TRACE2(( "Growing tokenizer buffer by %d bytes\n", left_bytes ));
+
+      if ( !REALLOC( tokzer->base, tokzer->limit,
+                     tokzer->limit + left_bytes )                 &&
+           !FILE_Read( tokzer->base + tokzer->limit, left_bytes ) )
+        tokzer->limit += left_bytes;
+    }
+    else
+    {
+      FT_ERROR(( "Unexpected end of Type1 fragment!\n" ));
+      error = T1_Err_Invalid_File_Format;
+    }
+
+    tokzer->error = error;
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_decrypt                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs the Type 1 charstring decryption process.                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    buffer  :: The base address of the data to decrypt.                */
+  /*    length  :: The number of bytes to decrypt (beginning from the base */
+  /*               address.                                                */
+  /*    seed    :: The encryption seed (4330 for charstrings).             */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  t1_decrypt( FT_Byte*   buffer,
+                    FT_Int     length,
+                    FT_UShort  seed )
+  {
+    while ( length > 0 )
+    {
+      FT_Byte  plain;
+
+
+      plain     = ( *buffer ^ ( seed >> 8 ) );
+      seed      = ( *buffer + seed ) * 52845 + 22719;
+      *buffer++ = plain;
+      length--;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    New_Tokenizer                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new tokenizer from a given input stream.  This function  */
+  /*    automatically recognizes `pfa' or `pfb' files.  The function       */
+  /*    Read_Token() can then be used to extract successive tokens from    */
+  /*    the stream.                                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream    :: The input stream.                                     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    tokenizer :: A handle to a new tokenizer object.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function copies the stream handle within the object.  Callers */
+  /*    should not discard `stream'.  This is done by the Done_Tokenizer() */
+  /*    function.                                                          */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  New_Tokenizer( FT_Stream      stream,
+                           T1_Tokenizer*  tokenizer )
+  {
+    FT_Memory     memory = stream->memory;
+    T1_Tokenizer  tokzer;
+    FT_Error      error;
+    FT_UShort     tag;
+    FT_ULong      size;
+
+    FT_Byte*      tok_base;
+    FT_ULong      tok_limit;
+    FT_ULong      tok_max;
+
+
+    *tokenizer = 0;
+
+    /* allocate object */
+    if ( FILE_Seek( 0L )                     ||
+         ALLOC( tokzer, sizeof ( *tokzer ) ) )
+      return error;
+
+    tokzer->stream = stream;
+    tokzer->memory = stream->memory;
+
+    tokzer->in_pfb     = 0;
+    tokzer->in_private = 0;
+
+    tok_base  = 0;
+    tok_limit = 0;
+    tok_max   = stream->size;
+
+    error = Read_PFB_Tag( stream, &tag, &size );
+    if ( error )
+      goto Fail;
+
+    if ( tag != 0x8001 )
+    {
+      /* assume that it is a PFA file -- an error will be produced later */
+      /* if a character with value > 127 is encountered                  */
+
+      /* rewind to start of file */
+      if ( FILE_Seek( 0L ) )
+        goto Fail;
+
+      size = stream->size;
+    }
+    else
+      tokzer->in_pfb = 1;
+
+    /* if it is a memory-based resource, set up pointer */
+    if ( !stream->read )
+    {
+      tok_base  = (FT_Byte*)stream->base + stream->pos;
+      tok_limit = size;
+      tok_max   = size;
+
+      /* check that the `size' field is valid */
+      if ( FILE_Skip( size ) )
+        goto Fail;
+    }
+    else if ( tag == 0x8001 )
+    {
+      /* read segment in memory */
+      if ( ALLOC( tok_base, size ) )
+        goto Fail;
+
+      if ( FILE_Read( tok_base, size ) )
+      {
+        FREE( tok_base );
+        goto Fail;
+      }
+
+      tok_limit = size;
+      tok_max   = size;
+    }
+
+    tokzer->base   = tok_base;
+    tokzer->limit  = tok_limit;
+    tokzer->max    = tok_max;
+    tokzer->cursor = 0;
+
+    *tokenizer = tokzer;
+
+    /* now check font format; we must see `%!PS-AdobeFont-1' */
+    /* or `%!FontType'                                       */
+    {
+      if ( 16 > tokzer->limit )
+        grow( tokzer );
+
+      if ( tokzer->limit <= 16 ||
+           ( strncmp( (const char*)tokzer->base, "%!PS-AdobeFont-1", 16 )   &&
+             strncmp( (const char*)tokzer->base, "%!FontType", 10 )       ) )
+      {
+        FT_TRACE2(( "[not a Type1 font]\n" ));
+        error = FT_Err_Unknown_File_Format;
+        goto Fail;
+      }
+    }
+    return T1_Err_Ok;
+
+  Fail:
+    FREE( tokzer->base );
+    FREE( tokzer );
+    return error;
+  }
+
+
+  /* return the value of an hexadecimal digit */
+  static
+  int  hexa_value( char  c )
+  {
+   unsigned int  d;
+
+
+    d = (unsigned int)( c - '0' );
+    if ( d <= 9 )
+      return (int)d;
+
+    d = (unsigned int)( c - 'a' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    d = (unsigned int)( c - 'A' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    return -1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Done_Tokenizer                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Closes a given tokenizer.  This function will also close the       */
+  /*    stream embedded in the object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    tokenizer :: The target tokenizer object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Done_Tokenizer( T1_Tokenizer  tokenizer )
+  {
+    FT_Memory  memory = tokenizer->memory;
+
+
+    /* clear read buffer if needed (disk-based resources) */
+    if ( tokenizer->in_private || !tokenizer->stream->base )
+      FREE( tokenizer->base );
+
+    FREE( tokenizer );
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Open_PrivateDict                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function must be called to set the tokenizer to the private   */
+  /*    section of the Type1 file.  It recognizes automatically the        */
+  /*    the kind of eexec encryption used (ascii or binary).               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    tokenizer :: The target tokenizer object.                          */
+  /*    lenIV     :: The value of the `lenIV' variable.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Open_PrivateDict( T1_Tokenizer  tokenizer )
+  {
+    T1_Tokenizer  tokzer = tokenizer;
+    FT_Stream     stream = tokzer->stream;
+    FT_Memory     memory = tokzer->memory;
+    FT_Error      error = 0;
+
+    FT_UShort     tag;
+    FT_ULong      size;
+
+    FT_Byte*      private_dict;
+
+    /* are we already in the private dictionary ? */
+    if ( tokzer->in_private )
+      return 0;
+
+    if ( tokzer->in_pfb )
+    {
+      /* in the case of the PFB format, the private dictionary can be */
+      /* made of several segments.  We thus first read the number of  */
+      /* segments to compute the total size of the private dictionary */
+      /* then re-read them into memory.                               */
+      FT_Long   start_pos         = FILE_Pos();
+      FT_ULong  private_dict_size = 0;
+
+
+      for (;;)
+      {
+        error = Read_PFB_Tag( stream, &tag, &size );
+        if ( error || tag != 0x8002 )
+          break;
+
+        private_dict_size += size;
+
+        if ( FILE_Skip( size ) )
+          goto Fail;
+      }
+
+      /* check that we have a private dictionary there */
+      /* and allocate private dictionary buffer        */
+      if ( private_dict_size == 0 )
+      {
+        FT_ERROR(( "Open_PrivateDict:" ));
+        FT_ERROR(( " invalid private dictionary section\n" ));
+        error = T1_Err_Invalid_File_Format;
+        goto Fail;
+      }
+
+      if ( ALLOC( private_dict, private_dict_size ) )
+        goto Fail;
+
+      /* read all sections into buffer */
+      if ( FILE_Seek( start_pos ) )
+        goto Fail_Private;
+
+      private_dict_size = 0;
+      for (;;)
+      {
+        error = Read_PFB_Tag( stream, &tag, &size );
+        if ( error || tag != 0x8002 )
+        {
+          error = 0;
+          break;
+        }
+
+        if ( FILE_Read( private_dict + private_dict_size, size ) )
+          goto Fail_Private;
+
+        private_dict_size += size;
+      }
+
+      /* we must free the field `tokzer.base' if we are in a disk-based */
+      /* PFB file.                                                      */
+      if ( stream->read )
+        FREE( tokzer->base );
+
+      tokzer->base   = private_dict;
+      tokzer->cursor = 0;
+      tokzer->limit  = private_dict_size;
+      tokzer->max    = private_dict_size;
+    }
+    else
+    {
+      char*  base;
+
+
+      /* we are in a PFA file; read each token until we find `eexec' */
+      while ( tokzer->token.kind2 != key_eexec )
+      {
+        error = Read_Token( tokzer );
+        if ( error )
+          goto Fail;
+      }
+
+      /* now determine whether the private dictionary is encoded in binary */
+      /* or hexadecimal ASCII format.                                      */
+
+      /* we need to access the next 4 bytes (after the final \r following  */
+      /* the `eexec' keyword); if they all are hexadecimal digits, then    */
+      /* we have a case of ASCII storage.                                  */
+      while ( tokzer->cursor + 5 > tokzer->limit )
+      {
+        error = grow( tokzer );
+        if ( error )
+          goto Fail;
+      }
+
+      /* skip whitespace/line feed after `eexec' */
+      base = (char*)tokzer->base + tokzer->cursor + 1;
+      if ( ( hexa_value( base[0] ) | hexa_value( base[1] ) |
+             hexa_value( base[2] ) | hexa_value( base[3] ) ) < 0 )
+      {
+        /* binary encoding -- `simply' read the stream */
+
+        /* if it is a memory-based resource, we need to allocate a new */
+        /* storage buffer for the private dictionary, as it must be    */
+        /* decrypted later                                             */
+        if ( stream->base )
+        {
+          size = stream->size - tokzer->cursor - 1; /* remaining bytes */
+
+          if ( ALLOC( private_dict, size ) )  /* alloc private dict buffer */
+            goto Fail;
+
+          /* copy eexec-encrypted bytes */
+          MEM_Copy( private_dict, tokzer->base + tokzer->cursor + 1, size );
+
+          /* reset pointers - forget about file mapping */
+          tokzer->base   = private_dict;
+          tokzer->limit  = size;
+          tokzer->max    = size;
+          tokzer->cursor = 0;
+        }
+        /* On the opposite, for disk based resources, we simply grow  */
+        /* the current buffer until its completion, and decrypt the   */
+        /* bytes within it.  In all cases, the `base' buffer will be  */
+        /* discarded on DoneTokenizer if we are in the private dict.  */
+        else
+        {
+          /* grow the read buffer to the full file */
+          while ( tokzer->limit < tokzer->max )
+          {
+            error = grow( tokenizer );
+            if ( error )
+              goto Fail;
+          }
+
+          /* set up cursor to first encrypted byte */
+          tokzer->cursor++;
+        }
+      }
+      else
+      {
+        /* ASCII hexadecimal encoding.  This sucks... */
+        FT_Byte*  write;
+        FT_Byte*  cur;
+        FT_Byte*  limit;
+        FT_Int    count;
+
+
+        /* allocate a buffer, read each one byte at a time */
+        count = stream->size - tokzer->cursor;
+        size  = count / 2;
+
+        if ( ALLOC( private_dict, size ) )   /* alloc private dict buffer */
+          goto Fail;
+
+        write = private_dict;
+        cur   = tokzer->base + tokzer->cursor;
+        limit = tokzer->base + tokzer->limit;
+
+        /* read each bytes */
+        while ( count > 0 )
+        {
+          /* ensure that we can read the next 2 bytes! */
+          while ( cur + 2 > limit )
+          {
+            int  cursor = cur - tokzer->base;
+
+
+            error = grow( tokzer );
+            if ( error )
+              goto Fail_Private;
+            cur   = tokzer->base + cursor;
+            limit = tokzer->base + tokzer->limit;
+          }
+
+          /* check for new line */
+          if ( cur[0] == '\r' || cur[0] == '\n' )
+          {
+            cur++;
+            count--;
+          }
+          else
+          {
+            int  hex1 = hexa_value(cur[0]);
+
+
+            /* exit if we have a non-hexadecimal digit which isn't */
+            /* a new-line character                                */
+            if ( hex1 < 0 )
+              break;
+
+            /* otherwise, store byte */
+            *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
+            cur   += 2;
+            count -= 2;
+          }
+        }
+
+        /* get rid of old buffer in the case of disk-based resources */
+        if ( !stream->base )
+          FREE( tokzer->base );
+
+        /* set up pointers */
+        tokzer->base   = private_dict;
+        tokzer->limit  = size;
+        tokzer->max    = size;
+        tokzer->cursor = 0;
+      }
+    }
+
+    /* finally, decrypt the private dictionary - and skip the lenIV bytes */
+    t1_decrypt( tokzer->base, tokzer->limit, 55665 );
+    tokzer->cursor += 4;
+
+  Fail:
+    return error;
+
+  Fail_Private:
+    FREE( private_dict );
+    goto Fail;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Read_Token                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reads a new token from the current input stream.  This function    */
+  /*    extracts a token from the font program until Open_PrivateDict()    */
+  /*    has been called.  After this, it returns tokens from the           */
+  /*    (eexec-encrypted) private dictionary.                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    tokenizer :: The target tokenizer object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Use the function Read_CharStrings() to read the binary charstrings */
+  /*    from the private dict.                                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Read_Token( T1_Tokenizer  tokenizer )
+  {
+    T1_Tokenizer  tok = tokenizer;
+    FT_Long       cur, limit;
+    FT_Byte*      base;
+    char          c, starter, ender;
+    FT_Bool       token_started;
+
+    T1_TokenType  kind;
+
+
+    tok->error      = T1_Err_Ok;
+    tok->token.kind = tok_any;
+
+    base  = tok->base;
+    limit = tok->limit;
+    cur   = tok->cursor;
+
+    token_started = 0;
+
+    for (;;)
+    {
+      if ( cur >= limit )
+      {
+        if ( grow( tok ) )
+          goto Exit;
+        base  = tok->base;
+        limit = tok->limit;
+      }
+
+      c = (char)base[cur++];
+
+      /* check that we have an ASCII character */
+      if ( (FT_Byte)c > 127 )
+      {
+        FT_ERROR(( "Read_Token:" ));
+        FT_ERROR(( " unexpected binary data in Type1 fragment!\n" ));
+        tok->error = T1_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      switch ( c )
+      {
+      case '\r':
+      case '\n':
+      case ' ' :
+      case '\t':    /* skip initial whitespace => skip to next */
+        if ( token_started )
+        {
+          /* possibly a name, keyword, wathever */
+          tok->token.kind = tok_any;
+          tok->token.len  = cur-tok->token.start - 1;
+          goto Exit;
+        }
+        /* otherwise, skip everything */
+        break;
+
+      case '%':     /* this is a comment -- skip everything */
+        for (;;)
+        {
+          FT_Int  left = limit - cur;
+
+
+          while ( left > 0 )
+          {
+            c = (char)base[cur++];
+            if ( c == '\r' || c == '\n' )
+              goto Next;
+            left--;
+          }
+
+          if ( grow( tokenizer ) )
+            goto Exit;
+          base  = tok->base;
+          limit = tok->limit;
+        }
+
+      case '(':     /* a Postscript string */
+        kind  = tok_string;
+        ender = ')';
+
+      L1:
+        if ( !token_started )
+        {
+          token_started    = 1;
+          tok->token.start = cur - 1;
+        }
+
+        {
+          FT_Int  nest_level = 1;
+
+
+          starter = c;
+          for (;;)
+          {
+            FT_Int  left = limit - cur;
+
+
+            while ( left > 0 )
+            {
+              c = (char)base[cur++];
+
+              if ( c == starter )
+                nest_level++;
+
+              else if ( c == ender )
+              {
+                nest_level--;
+                if ( nest_level <= 0 )
+                {
+                  tok->token.kind = kind;
+                  tok->token.len  = cur - tok->token.start;
+                  goto Exit;
+                }
+              }
+              left--;
+            }
+
+            if ( grow( tok ) )
+              goto Exit;
+            base  = tok->base;
+            limit = tok->limit;
+          }
+        }
+
+      case '[':   /* a Postscript array */
+        if ( token_started )
+          goto Any_Token;
+
+        kind  = tok_array;
+        ender = ']';
+        goto L1;
+        break;
+
+      case '{':   /* a Postscript program */
+        if ( token_started )
+          goto Any_Token;
+
+        kind  = tok_program;
+        ender = '}';
+        goto L1;
+        break;
+
+      case '<':   /* a Postscript hex byte array? */
+        if ( token_started )
+          goto Any_Token;
+
+        kind  = tok_hexarray;
+        ender = '>';
+        goto L1;
+        break;
+
+      case '0':  /* any number */
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        if ( token_started )
+          goto Next;
+
+        tok->token.kind  = tok_number;
+        token_started    = 1;
+        tok->token.start = cur - 1;
+
+      L2:
+        for (;;)
+        {
+          FT_Int  left = limit-cur;
+
+
+          while ( left > 0 )
+          {
+            c = (char)base[cur++];
+
+            switch ( c )
+            {
+            case '[':                     /* ] */
+            case '{':                     /* } */
+            case '(':                     /* ) */
+            case '<':
+            case '/':
+              goto Any_Token;
+
+            case ' ':
+            case '\r':
+            case '\t':
+            case '\n':
+              tok->token.len = cur - tok->token.start - 1;
+              goto Exit;
+
+            default:
+              ;
+            }
+            left--;
+          }
+
+          if ( grow( tok ) )
+            goto Exit;
+          base  = tok->base;
+          limit = tok->limit;
+        }
+
+      case '.':   /* maybe a number */
+      case '-':
+      case '+':
+        if ( token_started )
+           goto Next;
+
+        token_started    = 1;
+        tok->token.start = cur - 1;
+
+        for (;;)
+        {
+          FT_Int  left = limit - cur;
+
+
+          if ( left > 0 )
+          {
+            /* test for any following digit, interpreted as number */
+            c = (char)base[cur];
+            tok->token.kind = ( c >= '0' && c <= '9' ? tok_number : tok_any );
+            goto L2;
+          }
+
+          if ( grow( tok ) )
+            goto Exit;
+          base  = tok->base;
+          limit = tok->limit;
+        }
+
+      case '/':  /* maybe an immediate name */
+        if ( !token_started )
+        {
+          token_started    = 1;
+          tok->token.start = cur - 1;
+
+          for (;;)
+          {
+            FT_Int  left = limit - cur;
+
+
+            if ( left > 0 )
+            {
+              /* test for single '/', interpreted as garbage */
+              c = (char)base[cur];
+              tok->token.kind = ( c == ' '  || c == '\t' ||
+                                  c == '\r' || c == '\n' ) ? tok_any
+                                                           : tok_immediate;
+              goto L2;
+            }
+
+            if ( grow( tok ) )
+              goto Exit;
+            base  = tok->base;
+            limit = tok->limit;
+          }
+        }
+        else
+        {
+      Any_Token:        /* possibly a name or wathever */
+          cur--;
+          tok->token.len = cur - tok->token.start;
+          goto Exit;
+        }
+
+      default:
+        if ( !token_started )
+        {
+          token_started    = 1;
+          tok->token.start = cur - 1;
+        }
+      }
+
+    Next:
+      ;
+    }
+
+  Exit:
+    tok->cursor = cur;
+
+    if ( !tok->error )
+    {
+      /* now, tries to match keywords and immediate names */
+      FT_Int  index;
+
+
+      switch ( tok->token.kind )
+      {
+      case tok_immediate:   /* immediate name */
+        index = Find_Name( (char*)( tok->base + tok->token.start + 1 ),
+                           tok->token.len - 1,
+                           t1_immediates,
+                           imm_max - imm_first_ );
+        tok->token.kind2 = ( index >= 0 )
+                              ? (T1_TokenType)( imm_first_ + index )
+                              : tok_error;
+        break;
+
+      case tok_any:         /* test for keyword */
+        index = Find_Name( (char*)( tok->base + tok->token.start ),
+                           tok->token.len,
+                           t1_keywords,
+                           key_max - key_first_ );
+        if ( index >= 0 )
+        {
+          tok->token.kind  = tok_keyword;
+          tok->token.kind2 = (T1_TokenType)( key_first_ + index );
+        }
+        else
+          tok->token.kind2 = tok_error;
+        break;
+
+      default:
+         tok->token.kind2 = tok_error;
+      }
+    }
+    return tokenizer->error;
+  }
+
+
+#if 0
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Read_CharStrings                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reads a charstrings element from the current input stream.  These  */
+  /*    are binary bytes that encode each individual glyph outline.        */
+  /*                                                                       */
+  /*    The caller is responsible for skipping the `lenIV' bytes at the    */
+  /*    start of the record.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    tokenizer :: The target tokenizer object.                          */
+  /*    num_chars :: The number of binary bytes to read.                   */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    buffer    :: The target array of bytes.  These are                 */
+  /*    eexec-decrypted.                                                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Use the function Read_CharStrings() to read binary charstrings     */
+  /*    from the private dict.                                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Read_CharStrings( T1_Tokenizer  tokenizer,
+                              FT_Int        num_chars,
+                              FT_Byte*      buffer )
+  {
+    for (;;)
+    {
+      FT_Int  left = tokenizer->limit - tokenizer->cursor;
+
+
+      if ( left >= num_chars )
+      {
+        MEM_Copy( buffer, tokenizer->base + tokenizer->cursor, num_chars );
+        t1_decrypt( buffer, num_chars, 4330 );
+        tokenizer->cursor += num_chars;
+        return T1_Err_Ok;
+      }
+
+      if ( grow( tokenizer ) )
+        return tokenizer->error;
+    }
+  }
+
+#endif /* 0 */
+
+
+/* END */
diff --git a/src/freetype/type1/t1tokens.h b/src/freetype/type1/t1tokens.h
new file mode 100644 (file)
index 0000000..119c54b
--- /dev/null
@@ -0,0 +1,258 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1tokens.h                                                             */
+/*                                                                         */
+/*    Type 1 tokenizer (specification).                                    */
+/*                                                                         */
+/*  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 T1TOKENS_H
+#define T1TOKENS_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+
+#else
+
+#include <type1/t1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* enum value of first keyword */
+#define key_first_  100
+
+  /* enum value of first immediate name */
+#define imm_first_  200
+
+
+  typedef enum  T1_TokenType_
+  {
+    tok_error = 0,
+
+    tok_eof,             /* end of file                  */
+
+    /* simple token types */
+
+    tok_keyword,         /* keyword                      */
+    tok_number,          /* number (integer or real)     */
+    tok_string,          /* postscript string            */
+    tok_program,         /* postscript program           */
+    tok_immediate,       /* any immediate name           */
+    tok_array,           /* matrix, array, etc..         */
+    tok_hexarray,        /* array of hexadecimal nibbles */
+    tok_any,             /* anything else                */
+
+    /* Postscript keywords -- placed in lexicographical order */
+
+    key_RD_alternate = key_first_,      /* `-|' = alternate form of RD */
+    key_ExpertEncoding,
+    key_ND,
+    key_NP,
+    key_RD,
+    key_StandardEncoding,
+    key_array,
+    key_begin,
+    key_closefile,
+    key_currentdict,
+    key_currentfile,
+    key_def,
+    key_dict,
+    key_dup,
+    key_eexec,
+    key_end,
+    key_execonly,
+    key_false,
+    key_for,
+    key_index,
+    key_noaccess,
+    key_put,
+    key_readonly,
+    key_true,
+    key_userdict,
+    key_NP_alternate,                   /* `|' = alternate form of NP  */
+    key_ND_alternate,                   /* `|-' = alternate form of ND */
+
+    key_max,   /* always keep this value there */
+
+    /* Postscript immediate names -- other names will be ignored, except */
+    /* in charstrings                                                    */
+
+    imm_RD_alternate = imm_first_,      /* `-|' = alternate form of RD */
+    imm_notdef,                         /* `/.notdef' immediate        */
+    imm_BlendAxisTypes,
+    imm_BlueFuzz,
+    imm_BlueScale,
+    imm_BlueShift,
+    imm_BlueValues,
+    imm_CharStrings,
+    imm_Encoding,
+    imm_FamilyBlues,
+    imm_FamilyName,
+    imm_FamilyOtherBlues,
+    imm_FID,
+    imm_FontBBox,
+    imm_FontID,
+    imm_FontInfo,
+    imm_FontMatrix,
+    imm_FontName,
+    imm_FontType,
+    imm_ForceBold,
+    imm_FullName,
+    imm_ItalicAngle,
+    imm_LanguageGroup,
+    imm_Metrics,
+    imm_MinFeature,
+    imm_ND,
+    imm_NP,
+    imm_Notice,
+    imm_OtherBlues,
+    imm_OtherSubrs,
+    imm_PaintType,
+    imm_Private,
+    imm_RD,
+    imm_RndStemUp,
+    imm_StdHW,
+    imm_StdVW,
+    imm_StemSnapH,
+    imm_StemSnapV,
+    imm_StrokeWidth,
+    imm_Subrs,
+    imm_UnderlinePosition,
+    imm_UnderlineThickness,
+    imm_UniqueID,
+    imm_Weight,
+
+    imm_isFixedPitch,
+    imm_lenIV,
+    imm_password,
+    imm_version,
+
+    imm_NP_alternate,                   /* `|'  = alternate form of NP */
+    imm_ND_alternate,                   /* `|-' = alternate form of ND */
+
+    imm_max   /* always keep this value here */
+
+  } T1_TokenType;
+
+
+  /* these arrays are visible for debugging purposes */
+  extern const char*  t1_keywords[];
+  extern const char*  t1_immediates[];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Token                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe a token in the current input stream.  */
+  /*    Note that the Type1 driver doesn't try to interpret tokens until   */
+  /*    it really needs to.                                                */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    kind  :: The token type.  Describes the token to the loader.       */
+  /*                                                                       */
+  /*    kind2 :: Detailed token type.                                      */
+  /*                                                                       */
+  /*    start :: The index of the first character of token in the input    */
+  /*             stream.                                                   */
+  /*                                                                       */
+  /*    len   :: The length of the token in characters.                    */
+  /*                                                                       */
+  typedef struct  T1_Token_
+  {
+    T1_TokenType  kind;     /* simple type                    */
+    T1_TokenType  kind2;    /* detailed type                  */
+    FT_Int        start;    /* index of first token character */
+    FT_Int        len;      /* length of token in chars       */
+
+  } T1_Token;
+
+
+  typedef struct  T1_TokenParser_
+  {
+    FT_Memory  memory;
+    FT_Stream  stream;
+
+    FT_Bool    in_pfb;      /* true if PFB file, PFA otherwise */
+    FT_Bool    in_private;  /* true if in private dictionary   */
+
+    FT_Byte*   base;        /* base address of current read buffer */
+    FT_Long    cursor;      /* current position in read buffer     */
+    FT_Long    limit;       /* limit of current read buffer        */
+    FT_Long    max;         /* maximum size of read buffer         */
+
+    FT_Error   error;       /* last error                          */
+    T1_Token   token;       /* last token read                     */
+
+  } T1_TokenParser;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_Tokenizer                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an object used to extract tokens from the input.  The  */
+  /*    object is able to perform PFA/PFB recognition, eexec decryption of */
+  /*    the private dictionary, as well as eexec decryption of the         */
+  /*    charstrings.                                                       */
+  /*                                                                       */
+  typedef T1_TokenParser*  T1_Tokenizer;
+
+
+  LOCAL_DEF
+  FT_Error  New_Tokenizer( FT_Stream      stream,
+                           T1_Tokenizer*  tokenizer );
+
+  LOCAL_DEF
+  FT_Error  Done_Tokenizer( T1_Tokenizer  tokenizer );
+
+  LOCAL_DEF
+  FT_Error  Open_PrivateDict( T1_Tokenizer  tokenizer );
+
+  LOCAL_DEF
+  FT_Error  Read_Token( T1_Tokenizer  tokenizer );
+
+
+#if 0
+  LOCAL_DEF
+  FT_Error  Read_CharStrings( T1_Tokenizer  tokenizer,
+                              FT_Int        num_chars,
+                              FT_Byte*      buffer );
+#endif /* 0 */
+
+  LOCAL_DEF
+  void  t1_decrypt( FT_Byte*   buffer,
+                    FT_Int     length,
+                    FT_UShort  seed );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* T1TOKENS_H */
+
+
+/* END */
diff --git a/src/freetype/type1/type1.c b/src/freetype/type1/type1.c
new file mode 100644 (file)
index 0000000..d2058d6
--- /dev/null
@@ -0,0 +1,59 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type1.c                                                                */
+/*                                                                         */
+/*    FreeType Type 1 driver component (body only).                        */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1driver.c"
+#include "t1objs.c"
+#include "t1load.c"
+#include "t1gload.c"
+#include "t1tokens.c"
+#include "t1parse.c"
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include "t1hinter.c"
+#endif
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.c"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1/t1driver.c>
+#include <type1/t1objs.c>
+#include <type1/t1load.c>
+#include <type1/t1gload.c>
+#include <type1/t1tokens.c>
+#include <type1/t1parse.c>
+
+#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
+#include <type1/t1hinter.c>
+#endif
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include <type1/t1afm.c>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
diff --git a/src/freetype/type1z/Readme.txt b/src/freetype/type1z/Readme.txt
new file mode 100644 (file)
index 0000000..6502fb9
--- /dev/null
@@ -0,0 +1,10 @@
+This directory contains an experimental Type 1 driver that will ultimately
+replace the "official" one in "src/type1".
+
+This driver doesn't provide a mini Postscript interpreter, but uses
+pattern matching in order to load data from fonts. It works better and
+faster than the official driver, but will replace it only when we finish
+the auto-hinting module..
+
+You don't need to compile it to support Type 1 fonts, the driver should
+co-exist peacefully with the rest of the engine however..
diff --git a/src/freetype/type1z/module.mk b/src/freetype/type1z/module.mk
new file mode 100644 (file)
index 0000000..545887d
--- /dev/null
@@ -0,0 +1,7 @@
+make_module_list: add_type1_driver
+
+add_type1_driver:
+       $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)type1     $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
+
+# EOF
diff --git a/src/freetype/type1z/rules.mk b/src/freetype/type1z/rules.mk
new file mode 100644 (file)
index 0000000..3411fd1
--- /dev/null
@@ -0,0 +1,72 @@
+#
+# FreeType 2 Type1z driver configuration rules
+#
+
+
+# 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.
+
+
+# Type1z driver directory
+#
+T1Z_DIR  := $(SRC_)type1z
+T1Z_DIR_ := $(T1Z_DIR)$(SEP)
+
+
+# compilation flags for the driver
+#
+T1Z_COMPILE := $(FT_COMPILE)
+
+
+# Type1 driver sources (i.e., C files)
+#
+T1Z_DRV_SRC := $(T1Z_DIR_)z1parse.c  \
+               $(T1Z_DIR_)z1load.c   \
+               $(T1Z_DIR_)z1driver.c \
+               $(T1Z_DIR_)z1afm.c    \
+               $(T1Z_DIR_)z1gload.c  \
+               $(T1Z_DIR_)z1objs.c
+
+# Type1 driver headers
+#
+T1Z_DRV_H := $(T1Z_DRV_SRC:%.c=%.h) \
+             $(T1Z_DIR_)z1tokens.h
+
+
+# Type1z driver object(s)
+#
+#   T1Z_DRV_OBJ_M is used during `multi' builds
+#   T1Z_DRV_OBJ_S is used during `single' builds
+#
+T1Z_DRV_OBJ_M := $(T1Z_DRV_SRC:$(T1Z_DIR_)%.c=$(OBJ_)%.$O)
+T1Z_DRV_OBJ_S := $(OBJ_)type1z.$O
+
+# Type1z driver source file for single build
+#
+T1Z_DRV_SRC_S := $(T1Z_DIR_)type1z.c
+
+
+# Type1z driver - single object
+#
+$(T1Z_DRV_OBJ_S): $(T1Z_DRV_SRC_S) $(T1Z_DRV_SRC) $(FREETYPE_H) $(T1Z_DRV_H)
+       $(T1Z_COMPILE) $T$@ $(T1Z_DRV_SRC_S)
+
+
+# Type1z driver - multiple objects
+#
+$(OBJ_)%.$O: $(T1Z_DIR_)%.c $(FREETYPE_H) $(T1Z_DRV_H)
+       $(T1Z_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(T1Z_DRV_OBJ_S)
+DRV_OBJS_M += $(T1Z_DRV_OBJ_M)
+
+# EOF
diff --git a/src/freetype/type1z/type1z.c b/src/freetype/type1z/type1z.c
new file mode 100644 (file)
index 0000000..17e89ac
--- /dev/null
@@ -0,0 +1,49 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type1z.c                                                               */
+/*                                                                         */
+/*    FreeType experimental Type 1 driver component (body only).           */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.c"
+#include "z1load.c"
+#include "z1objs.c"
+#include "z1driver.c"
+#include "z1gload.c"
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+#include "z1afm.c"
+#endif
+
+#else /* FT_FLAT_COMPILE */
+
+#include <type1z/z1parse.c>
+#include <type1z/z1load.c>
+#include <type1z/z1objs.c>
+#include <type1z/z1driver.c>
+#include <type1z/z1gload.c>
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+#include <type1z/z1afm.c>
+#endif
+
+#endif /* FT_FLAT_COMPILE */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1afm.c b/src/freetype/type1z/z1afm.c
new file mode 100644 (file)
index 0000000..b329cd3
--- /dev/null
@@ -0,0 +1,293 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1afm.c                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (body).                                 */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+
+#include <stdlib.h>  /* for qsort()   */
+#include <string.h>  /* for strcmp()  */
+#include <ctype.h>   /* for isalnum() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1afm
+
+
+  LOCAL_FUNC
+  void  Z1_Done_AFM( FT_Memory  memory,
+                     Z1_AFM*    afm )
+  {
+    FREE( afm->kern_pairs );
+    afm->num_pairs = 0;
+  }
+
+
+#undef  IS_KERN_PAIR
+#define IS_KERN_PAIR( p )  ( p[0] == 'K' && p[1] == 'P' )
+
+#define IS_ALPHANUM( c )  ( isalnum( c ) || \
+                            c == '_'     || \
+                            c == '.'     )
+
+
+  /* read a glyph name and return the equivalent glyph index */
+  static
+  FT_UInt  afm_atoindex( FT_Byte**  start,
+                         FT_Byte*   limit,
+                         T1_Font*   type1 )
+  {
+    FT_Byte*  p = *start;
+    FT_Int    len;
+    FT_UInt   result = 0;
+    char      temp[64];
+
+
+    /* skip whitespace */
+    while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
+            p < limit                                             )
+      p++;
+    *start = p;
+
+    /* now, read glyph name */
+    while ( IS_ALPHANUM( *p ) && p < limit )
+      p++;
+
+    len = p - *start;
+
+    if ( len > 0 && len < 64 )
+    {
+      FT_Int  n;
+
+
+      /* copy glyph name to intermediate array */
+      MEM_Copy( temp, *start, len );
+      temp[len] = 0;
+
+      /* lookup glyph name in face array */
+      for ( n = 0; n < type1->num_glyphs; n++ )
+      {
+        char*  gname = (char*)type1->glyph_names[n];
+
+
+        if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 )
+        {
+          result = n;
+          break;
+        }
+      }
+    }
+    *start = p;
+    return result;
+  }
+
+
+  /* read an integer */
+  static
+  int  afm_atoi( FT_Byte**  start,
+                 FT_Byte*   limit )
+  {
+    FT_Byte*  p    = *start;
+    int       sum  = 0;
+    int       sign = 1;
+
+
+    /* skip everything that is not a number */
+    while ( p < limit && !isdigit( *p ) )
+    {
+      sign = 1;
+      if ( *p == '-' )
+        sign = -1;
+
+      p++;
+    }
+
+    while ( p < limit && isdigit( *p ) )
+    {
+      sum = sum * 10 + ( *p - '0' );
+      p++;
+    }
+    *start = p;
+
+    return sum * sign;
+  }
+
+
+#undef  KERN_INDEX
+#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+
+  /* compare two kerning pairs */
+  static
+  int  compare_kern_pairs( const void*  a,
+                           const void*  b )
+  {
+    Z1_Kern_Pair*  pair1 = (Z1_Kern_Pair*)a;
+    Z1_Kern_Pair*  pair2 = (Z1_Kern_Pair*)b;
+
+    FT_ULong  index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
+    FT_ULong  index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
+
+
+    return ( index1 - index2 );
+  }
+
+
+  /* parse an AFM file -- for now, only read the kerning pairs */
+  LOCAL_FUNC
+  FT_Error  Z1_Read_AFM( FT_Face    t1_face,
+                         FT_Stream  stream )
+  {
+    FT_Error       error;
+    FT_Memory      memory = stream->memory;
+    FT_Byte*       start;
+    FT_Byte*       limit;
+    FT_Byte*       p;
+    FT_Int         count = 0;
+    Z1_Kern_Pair*  pair;
+    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
+    Z1_AFM*        afm   = 0;
+
+
+    if ( ACCESS_Frame( stream->size ) )
+      return error;
+
+    start = (FT_Byte*)stream->cursor;
+    limit = (FT_Byte*)stream->limit;
+    p     = start;
+
+    /* we are now going to count the occurences of `KP' or `KPX' in */
+    /* the AFM file                                                 */
+    count = 0;
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+        count++;
+    }
+
+    /* Actually, kerning pairs are simply optional! */
+    if ( count == 0 )
+      goto Exit;
+
+    /* allocate the pairs */
+    if ( ALLOC( afm, sizeof ( *afm ) )                       ||
+         ALLOC_ARRAY( afm->kern_pairs, count, Z1_Kern_Pair ) )
+      goto Exit;
+
+    /* now, read each kern pair */
+    pair           = afm->kern_pairs;
+    afm->num_pairs = count;
+
+    /* save in face object */
+    ((T1_Face)t1_face)->afm_data = afm;
+
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+      {
+        FT_Byte*  q;
+
+
+        /* skip keyword (KP or KPX) */
+        q = p + 2;
+        if ( *q == 'X' )
+          q++;
+
+        pair->glyph1    = afm_atoindex( &q, limit, type1 );
+        pair->glyph2    = afm_atoindex( &q, limit, type1 );
+        pair->kerning.x = afm_atoi( &q, limit );
+
+        pair->kerning.y = 0;
+        if ( p[2] != 'X' )
+          pair->kerning.y = afm_atoi( &q, limit );
+
+        pair++;
+      }
+    }
+
+    /* now, sort the kern pairs according to their glyph indices */
+    qsort( afm->kern_pairs, count, sizeof ( Z1_Kern_Pair ),
+           compare_kern_pairs );
+
+  Exit:
+    if ( error )
+      FREE( afm );
+
+    FORGET_Frame();
+
+    return error;
+  }
+
+
+  /* find the kerning for a given glyph pair */
+  LOCAL_FUNC
+  void  Z1_Get_Kerning( Z1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning )
+  {
+    Z1_Kern_Pair  *min, *mid, *max;
+    FT_ULong      index = KERN_INDEX( glyph1, glyph2 );
+
+
+    /* simple binary search */
+    min = afm->kern_pairs;
+    max = min + afm->num_pairs - 1;
+
+    while ( min <= max )
+    {
+      FT_ULong  midi;
+
+
+      mid  = min + ( max - min ) / 2;
+      midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
+
+      if ( midi == index )
+      {
+        *kerning = mid->kerning;
+        return;
+      }
+
+      if ( midi < index )
+        min = mid + 1;
+      else
+        max = mid - 1;
+    }
+
+    kerning->x = 0;
+    kerning->y = 0;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1z/z1afm.h b/src/freetype/type1z/z1afm.h
new file mode 100644 (file)
index 0000000..bfacce7
--- /dev/null
@@ -0,0 +1,79 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1afm.h                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (specification).                        */
+/*                                                                         */
+/*  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 Z1AFM_H
+#define Z1AFM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1objs.h"
+
+#else
+
+#include <type1z/z1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  typedef struct  Z1_Kern_Pair_
+  {
+    FT_UInt    glyph1;
+    FT_UInt    glyph2;
+    FT_Vector  kerning;
+
+  } Z1_Kern_Pair;
+
+
+  typedef struct  Z1_AFM_
+  {
+    FT_Int         num_pairs;
+    Z1_Kern_Pair*  kern_pairs;
+
+  } Z1_AFM;
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Read_AFM( FT_Face    face,
+                         FT_Stream  stream );
+
+  LOCAL_DEF
+  void  Z1_Done_AFM( FT_Memory  memory,
+                     Z1_AFM*    afm );
+
+  LOCAL_DEF
+  void  Z1_Get_Kerning( Z1_AFM*     afm,
+                        FT_UInt     glyph1,
+                        FT_UInt     glyph2,
+                        FT_Vector*  kerning );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* Z1AFM_H */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1driver.c b/src/freetype/type1z/z1driver.c
new file mode 100644 (file)
index 0000000..aea2c10
--- /dev/null
@@ -0,0 +1,340 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1driver.c                                                             */
+/*                                                                         */
+/*    Experimental Type 1 driver interface (body).                         */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1driver.h"
+#include "z1gload.h"
+#include "z1load.h"
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1driver.h>
+#include <type1z/z1gload.h>
+#include <type1z/z1load.h>
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1driver
+
+
+  static
+  FT_Error  get_z1_glyph_name( T1_Face     face,
+                               FT_UInt     glyph_index,
+                               FT_Pointer  buffer,
+                               FT_UInt     buffer_max )
+  {
+    FT_String*  gname;
+    
+
+    gname = face->type1.glyph_names[glyph_index];
+
+    if ( buffer_max > 0 )
+    {
+      FT_UInt  len = strlen( gname );
+      
+
+      if (len >= buffer_max)
+        len = buffer_max - 1;
+        
+      MEM_Copy( buffer, gname, len );
+      ((FT_Byte*)buffer)[len] = 0;
+    }
+
+    return T1_Err_Ok;
+  }                                  
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Interface                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each driver can provide one or more extensions to the base         */
+  /*    FreeType API.  These can be used to access format specific         */
+  /*    features (e.g., all TrueType/OpenType resources share a common     */
+  /*    file structure and common tables which can be accessed through the */
+  /*    `sfnt' interface), or more simply generic ones (e.g., the          */
+  /*    `postscript names' interface which can be used to retrieve the     */
+  /*     PostScript name of a given glyph index).                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver    :: A handle to a driver object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    interface :: A string designing the interface.  Examples are       */
+  /*                 `sfnt', `post_names', `charmaps', etc.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A typeless pointer to the extension's interface (normally a table  */
+  /*    of function pointers).  Returns NULL if the requested extension    */
+  /*    isn't available (i.e., wasn't compiled in the driver at build      */
+  /*    time).                                                             */
+  /*                                                                       */
+  static
+  FT_Module_Interface  Get_Interface( FT_Driver         driver,
+                                      const FT_String*  interface )
+  {
+    FT_UNUSED( driver );
+    FT_UNUSED( interface );
+
+    if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
+      return (FT_Module_Interface)get_z1_glyph_name;
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+    if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
+      return (FT_Module_Interface)Z1_Get_Multi_Master;
+
+    if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
+      return (FT_Module_Interface)Z1_Set_MM_Design;
+
+    if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
+      return (FT_Module_Interface)Z1_Set_MM_Blend;
+#endif
+    return 0;
+  }
+
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings are out of scope of this method (the basic driver         */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static
+  FT_Error  Get_Kerning( T1_Face     face,
+                         FT_UInt     left_glyph,
+                         FT_UInt     right_glyph,
+                         FT_Vector*  kerning )
+  {
+    Z1_AFM*  afm;
+
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (Z1_AFM*)face->afm_data;
+    if ( afm )
+      Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return T1_Err_Ok;
+  }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static
+  FT_UInt  Get_Char_Index( FT_CharMap  charmap,
+                           FT_Long     charcode )
+  {
+    T1_Face             face;
+    FT_UInt             result = 0;
+    PSNames_Interface*  psnames;
+
+
+    face    = (T1_Face)charmap->face;
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( psnames )
+      switch ( charmap->encoding )
+      {
+        /*******************************************************************/
+        /*                                                                 */
+        /* Unicode encoding support                                        */
+        /*                                                                 */
+      case ft_encoding_unicode:
+        /* use the `PSNames' module to synthetize the Unicode charmap */
+        result = psnames->lookup_unicode( &face->unicode_map,
+                                          (FT_ULong)charcode );
+
+        /* the function returns 0xFFFF if the Unicode charcode has */
+        /* no corresponding glyph                                  */
+        if ( result == 0xFFFF )
+          result = 0;
+        goto Exit;
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Custom Type 1 encoding                                          */
+        /*                                                                 */
+      case ft_encoding_adobe_custom:
+        {
+          T1_Encoding*  encoding = &face->type1.encoding;
+
+
+          if ( charcode >= encoding->code_first &&
+               charcode <= encoding->code_last  )
+            result = encoding->char_index[charcode];
+          goto Exit;
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Adobe Standard & Expert encoding support                        */
+        /*                                                                 */
+      default:
+        if ( charcode < 256 )
+        {
+          FT_UInt      code;
+          FT_Int       n;
+          const char*  glyph_name;
+
+
+          code = psnames->adobe_std_encoding[charcode];
+          if ( charmap->encoding == ft_encoding_adobe_expert )
+            code = psnames->adobe_expert_encoding[charcode];
+
+          glyph_name = psnames->adobe_std_strings( code );
+          if ( !glyph_name )
+            break;
+
+          for ( n = 0; n < face->type1.num_glyphs; n++ )
+          {
+            const char*  gname = face->type1.glyph_names[n];
+
+
+            if ( gname && gname[0] == glyph_name[0] &&
+                 strcmp( gname, glyph_name ) == 0   )
+            {
+              result = n;
+              break;
+            }
+          }
+        }
+      }
+  Exit:
+    return result;
+  }
+
+
+  const FT_Driver_Class  t1_driver_class =
+  {
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( FT_DriverRec ),
+
+      "type1",
+      0x10000L,
+      0x20000L,
+
+      0,   /* format interface */
+
+      (FT_Module_Constructor)Z1_Init_Driver,
+      (FT_Module_Destructor) Z1_Done_Driver,
+      (FT_Module_Requester)  Get_Interface,
+    },
+
+    sizeof( T1_FaceRec ),
+    sizeof( Z1_SizeRec ),
+    sizeof( Z1_GlyphSlotRec ),
+
+    (FTDriver_initFace)     Z1_Init_Face,
+    (FTDriver_doneFace)     Z1_Done_Face,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) 0,
+    (FTDriver_setPixelSizes)0,
+    (FTDriver_loadGlyph)    Z1_Load_Glyph,
+    (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef Z1_CONFIG_OPTION_NO_AFM
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+#else
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   Z1_Read_AFM,
+#endif
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+  EXPORT_FUNC( const FT_Driver_Class* )  getDriverClass( void )
+  {
+    return &t1z_driver_class;
+  }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1driver.h b/src/freetype/type1z/z1driver.h
new file mode 100644 (file)
index 0000000..08bd544
--- /dev/null
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1driver.h                                                             */
+/*                                                                         */
+/*    High-level experimental Type 1 driver interface (specification).     */
+/*                                                                         */
+/*  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 Z1DRIVER_H
+#define Z1DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+  FT_EXPORT_VAR( const  FT_Driver_Class )  t1_driver_class;
+
+#endif /* Z1DRIVER_H */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1gload.c b/src/freetype/type1z/z1gload.c
new file mode 100644 (file)
index 0000000..0b25d2e
--- /dev/null
@@ -0,0 +1,1482 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1gload.c                                                              */
+/*                                                                         */
+/*    Experimental Type 1 Glyph Loader (body).                             */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1gload.h"
+
+#else
+
+#include <type1z/z1gload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1gload
+
+
+  typedef enum  Z1_Operator_
+  {
+    op_none = 0,
+    op_endchar,
+    op_hsbw,
+    op_seac,
+    op_sbw,
+    op_closepath,
+    op_hlineto,
+    op_hmoveto,
+    op_hvcurveto,
+    op_rlineto,
+    op_rmoveto,
+    op_rrcurveto,
+    op_vhcurveto,
+    op_vlineto,
+    op_vmoveto,
+    op_dotsection,
+    op_hstem,
+    op_hstem3,
+    op_vstem,
+    op_vstem3,
+    op_div,
+    op_callothersubr,
+    op_callsubr,
+    op_pop,
+    op_return,
+    op_setcurrentpoint,
+
+    op_max    /* never remove this one */
+
+  } Z1_Operator;
+
+  static
+  const FT_Int  t1_args_count[op_max] =
+  {
+    0, /* none */
+    0, /* endchar */
+    2, /* hsbw */
+    5, /* seac */
+    4, /* sbw */
+    0, /* closepath */
+    1, /* hlineto */
+    1, /* hmoveto */
+    4, /* hvcurveto */
+    2, /* rlineto */
+    2, /* rmoveto */
+    6, /* rrcurveto */
+    4, /* vhcurveto */
+    1, /* vlineto */
+    1, /* vmoveto */
+    0, /* dotsection */
+    2, /* hstem */
+    6, /* hstem3 */
+    2, /* vstem */
+    6, /* vstem3 */
+    2, /* div */
+   -1, /* callothersubr */
+    1, /* callsubr */
+    0, /* pop */
+    0, /* return */
+    2  /* setcurrentpoint */
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********             GENERIC CHARSTRING PARSING               *********/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Init_Builder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph builder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    builder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    glyph   :: The current glyph object.                               */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  Z1_Init_Builder( Z1_Builder*   builder,
+                         T1_Face       face,
+                         Z1_Size       size,
+                         Z1_GlyphSlot  glyph )
+  {
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->glyph  = glyph;
+    builder->memory = face->root.memory;
+
+    if ( glyph )
+    {
+      FT_GlyphLoader*  loader = glyph->root.loader;
+
+
+      builder->loader  = loader;
+      builder->current = &loader->current.outline;
+      builder->base    = &loader->base.outline;
+
+      FT_GlyphLoader_Rewind( loader );
+    }
+
+    if ( size )
+    {
+      builder->scale_x = size->root.metrics.x_scale;
+      builder->scale_y = size->root.metrics.y_scale;
+    }
+
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Done_Builder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given glyph builder.  Its contents can still be used   */
+  /*    after the call, but the function saves important information       */
+  /*    within the corresponding glyph slot.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder :: A pointer to the glyph builder to finalize.             */
+  /*                                                                       */
+  LOCAL_FUNC
+  void Z1_Done_Builder( Z1_Builder*  builder )
+  {
+    Z1_GlyphSlot  glyph = builder->glyph;
+
+
+    if ( glyph )
+      glyph->root.outline = *builder->base;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Init_Decoder                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph decoder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  Z1_Init_Decoder( Z1_Decoder* decoder )
+  {
+    decoder->top              = 0;
+    decoder->zone             = 0;
+    decoder->flex_state       = 0;
+    decoder->num_flex_vectors = 0;
+    decoder->blend            = 0;
+
+    /* Clear loader */
+    MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
+  }
+
+
+  /* check that there is enough space for `count' more points */
+  static
+  FT_Error  check_points( Z1_Builder*  builder,
+                          FT_Int       count )
+  {
+    return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+  }
+
+
+  /* add a new point; do not check space */
+  static
+  void  add_point( Z1_Builder*  builder,
+                   FT_Pos       x,
+                   FT_Pos       y,
+                   FT_Byte      flag )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    if ( builder->load_points )
+    {
+      FT_Vector*  point   = outline->points + outline->n_points;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+      point->x = x;
+      point->y = y;
+      *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
+
+      builder->last = *point;
+    }
+
+    outline->n_points++;
+  }
+
+
+  /* check space for a new on-curve point, then add it */
+  static
+  FT_Error  add_point1( Z1_Builder*  builder,
+                        FT_Pos       x,
+                        FT_Pos       y )
+  {
+    FT_Error  error;
+
+
+    error = check_points( builder, 1 );
+    if ( !error )
+      add_point( builder, x, y, 1 );
+
+    return error;
+  }
+
+
+  /* check space for a new contour, then add it */
+  static
+  FT_Error  add_contour( Z1_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+    FT_Error     error;
+
+
+    if ( !builder->load_points )
+    {
+      outline->n_contours++;
+      return FT_Err_Ok;
+    }
+
+    /* reallocate contours array if necessary */
+    error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+    if ( !error )
+    {
+      if ( outline->n_contours > 0 )
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+      outline->n_contours++;
+    }
+
+    return error;
+  }
+
+
+  /* if a path was begun, add its first on-curve point */
+  static
+  FT_Error  start_point( Z1_Builder*  builder,
+                         FT_Pos       x,
+                         FT_Pos       y )
+  {
+    /* test whether we are building a new contour */
+    if ( !builder->path_begun )
+    {
+      FT_Error  error;
+
+
+      builder->path_begun = 1;
+      error = add_contour( builder );
+      if ( error )
+        return error;
+    }
+    return add_point1( builder, x, y );
+  }
+
+
+  /* close the current contour */
+  static
+  void  close_contour( Z1_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    /* XXX: we must not include the last point in the path if it */
+    /*      is located on the first point                        */
+    if ( outline->n_points > 1 )
+    {
+      FT_Int      first = 0;
+      FT_Vector*  p1    = outline->points + first;
+      FT_Vector*  p2    = outline->points + outline->n_points-1;
+
+
+      if ( outline->n_contours > 1 )
+      {
+        first = outline->contours[outline->n_contours - 2] + 1;
+        p1    = outline->points + first;
+      }
+
+      if ( p1->x == p2->x && p1->y == p2->y )
+        outline->n_points--;
+    }
+
+    if ( outline->n_contours > 0 )
+      outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    lookup_glyph_by_stdcharcode                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks up a given glyph by its StandardEncoding charcode.  Used     */
+  /*    to implement the SEAC Type 1 operator.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: The current face object.                               */
+  /*                                                                       */
+  /*    charcode :: The character code to look for.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A glyph index in the font face.  Returns -1 if the corresponding   */
+  /*    glyph wasn't found.                                                */
+  /*                                                                       */
+  static
+  FT_Int  lookup_glyph_by_stdcharcode( T1_Face  face,
+                                       FT_Int   charcode )
+  {
+    FT_Int              n;
+    const FT_String*    glyph_name;
+    PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+
+    /* check range of standard char code */
+    if ( charcode < 0 || charcode > 255 )
+      return -1;
+
+    glyph_name = psnames->adobe_std_strings(
+                   psnames->adobe_std_encoding[charcode]);
+
+    for ( n = 0; n < face->type1.num_glyphs; n++ )
+    {
+      FT_String*  name = (FT_String*)face->type1.glyph_names[n];
+
+
+      if ( name && strcmp( name,glyph_name ) == 0 )
+        return n;
+    }
+
+    return -1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1operator_seac                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder :: The current CID decoder.                                */
+  /*                                                                       */
+  /*    asb     :: The accent's side bearing.                              */
+  /*                                                                       */
+  /*    adx     :: The horizontal offset of the accent.                    */
+  /*                                                                       */
+  /*    ady     :: The vertical offset of the accent.                      */
+  /*                                                                       */
+  /*    bchar   :: The base character's StandardEncoding charcode.         */
+  /*                                                                       */
+  /*    achar   :: The accent character's StandardEncoding charcode.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static
+  FT_Error  t1operator_seac( Z1_Decoder*  decoder,
+                             FT_Pos       asb,
+                             FT_Pos       adx,
+                             FT_Pos       ady,
+                             FT_Int       bchar,
+                             FT_Int       achar )
+  {
+    FT_Error     error;
+    FT_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  base = decoder->builder.base;
+    FT_Vector    left_bearing, advance;
+    T1_Face      face  = decoder->builder.face;
+    T1_Font*     type1 = &face->type1;
+
+
+    bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
+    achar_index = lookup_glyph_by_stdcharcode( face, achar );
+
+    if ( bchar_index < 0 || achar_index < 0 )
+    {
+      FT_ERROR(( "t1operator_seac:" ));
+      FT_ERROR(( " invalid seac character code arguments\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* if we are trying to load a composite glyph, do not load the */
+    /* accent character and return the array of subglyphs.         */
+    if ( decoder->builder.no_recurse )
+    {
+      FT_GlyphSlot     glyph  = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_GlyphLoader*  loader = glyph->loader;
+      FT_SubGlyph*     subg;
+
+
+      /* reallocate subglyph array if necessary */
+      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+      if ( error )
+        goto Exit;
+
+      subg = loader->current.subglyphs;
+
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
+
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->subglyphs     = loader->base.subglyphs;
+      glyph->format        = ft_glyph_format_composite;
+
+      loader->current.num_subglyphs = 2;
+    }
+
+    /* First load `bchar' in builder */
+    /* now load the unscaled outline */
+
+    FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
+
+    error = Z1_Parse_CharStrings( decoder,
+                                  type1->charstrings    [bchar_index],
+                                  type1->charstrings_len[bchar_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+    if ( error )
+      goto Exit;
+
+    n_base_points = base->n_points;
+
+    /* save the left bearing and width of the base character */
+    /* as they will be erased by the next load.              */
+
+    left_bearing = decoder->builder.left_bearing;
+    advance      = decoder->builder.advance;
+
+    decoder->builder.left_bearing.x = 0;
+    decoder->builder.left_bearing.y = 0;
+
+    /* Now load `achar' on top of */
+    /* the base outline           */
+    error = Z1_Parse_CharStrings( decoder,
+                                  type1->charstrings    [achar_index],
+                                  type1->charstrings_len[achar_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+    if ( error )
+      return error;
+
+    /* restore the left side bearing and   */
+    /* advance width of the base character */
+
+    decoder->builder.left_bearing = left_bearing;
+    decoder->builder.advance      = advance;
+
+    /* Finally, move the accent */
+    if ( decoder->builder.load_points )
+    {
+      FT_Outline  dummy;
+
+
+      dummy.n_points = base->n_points - n_base_points;
+      dummy.points   = base->points   + n_base_points;
+      FT_Outline_Translate( &dummy, adx - asb, ady );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#define USE_ARGS( n )  do                            \
+                       {                             \
+                         top -= n;                   \
+                         if ( top < decoder->stack ) \
+                           goto Stack_Underflow;     \
+                       } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Parse_CharStrings                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given Type 1 charstrings program.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder         :: The current Type 1 decoder.                     */
+  /*                                                                       */
+  /*    charstring_base :: The base address of the charstring stream.      */
+  /*                                                                       */
+  /*    charstring_len  :: The length in bytes of the charstring stream.   */
+  /*                                                                       */
+  /*    num_subrs       :: The number of sub-routines.                     */
+  /*                                                                       */
+  /*    subrs_base      :: An array of sub-routines addresses.             */
+  /*                                                                       */
+  /*    subrs_len       :: An array of sub-routines lengths.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Free error code.  0 means success.                                 */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Z1_Parse_CharStrings( Z1_Decoder*  decoder,
+                                  FT_Byte*     charstring_base,
+                                  FT_Int       charstring_len,
+                                  FT_Int       num_subrs,
+                                  FT_Byte**    subrs_base,
+                                  FT_Int*      subrs_len )
+  {
+    FT_Error          error;
+    Z1_Decoder_Zone*  zone;
+    FT_Byte*          ip;
+    FT_Byte*          limit;
+    Z1_Builder*       builder = &decoder->builder;
+    FT_Outline*       outline;
+    FT_Pos            x, y;
+
+
+    /* First of all, initialize the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+
+    builder->path_begun  = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error   = T1_Err_Ok;
+    outline = builder->current;
+
+    x = builder->pos_x;
+    y = builder->pos_y;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      FT_Int*      top   = decoder->top;
+      Z1_Operator  op    = op_none;
+      FT_Long      value = 0;
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Decode operator or operand                                        */
+      /*                                                                   */
+      /*                                                                   */
+
+      /* first of all, decompress operator or value */
+      switch ( *ip++ )
+      {
+      case 1:
+        op = op_hstem;
+        break;
+
+      case 3:
+        op = op_vstem;
+        break;
+      case 4:
+        op = op_vmoveto;
+        break;
+      case 5:
+        op = op_rlineto;
+        break;
+      case 6:
+        op = op_hlineto;
+        break;
+      case 7:
+        op = op_vlineto;
+        break;
+      case 8:
+        op = op_rrcurveto;
+        break;
+      case 9:
+        op = op_closepath;
+        break;
+      case 10:
+        op = op_callsubr;
+        break;
+      case 11:
+        op = op_return;
+        break;
+
+      case 13:
+        op = op_hsbw;
+        break;
+      case 14:
+        op = op_endchar;
+        break;
+
+      case 21:
+        op = op_rmoveto;
+        break;
+      case 22:
+        op = op_hmoveto;
+        break;
+
+      case 30:
+        op = op_vhcurveto;
+        break;
+      case 31:
+        op = op_hvcurveto;
+        break;
+
+      case 12:
+        if ( ip > limit )
+        {
+          FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
+          goto Syntax_Error;
+        }
+
+        switch ( *ip++ )
+        {
+        case 0:
+          op = op_dotsection;
+          break;
+        case 1:
+          op = op_vstem3;
+          break;
+        case 2:
+          op = op_hstem3;
+          break;
+        case 6:
+          op = op_seac;
+          break;
+        case 7:
+          op = op_sbw;
+          break;
+        case 12:
+          op = op_div;
+          break;
+        case 16:
+          op = op_callothersubr;
+          break;
+        case 17:
+          op = op_pop;
+          break;
+        case 33:
+          op = op_setcurrentpoint;
+          break;
+
+        default:
+          FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+        break;
+
+      case 255:    /* four bytes integer */
+        if ( ip + 4 > limit )
+        {
+          FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" ));
+          goto Syntax_Error;
+        }
+
+        value = ( (FT_Long)ip[0] << 24 ) |
+                ( (FT_Long)ip[1] << 16 ) |
+                ( (FT_Long)ip[2] << 8  ) |
+                           ip[3];
+        ip += 4;
+        break;
+
+      default:
+        if ( ip[-1] >= 32 )
+        {
+          if ( ip[-1] < 247 )
+            value = (FT_Long)ip[-1] - 139;
+          else
+          {
+            if ( ++ip > limit )
+            {
+              FT_ERROR(( "Z1_Parse_CharStrings:" ));
+              FT_ERROR(( " unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+          if ( ip[-2] < 251 )
+            value =  ( (FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+          else
+            value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+          }
+        }
+        else
+        {
+          FT_ERROR(( "Z1_Parse_CharStrings: invalid byte (%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+      }
+
+      /*********************************************************************/
+      /*                                                                   */
+      /*  Push value on stack, or process operator                         */
+      /*                                                                   */
+      /*                                                                   */
+      if ( op == op_none )
+      {
+        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+        {
+          FT_ERROR(( "Z1_Parse_CharStrings: stack overflow!\n" ));
+          goto Syntax_Error;
+        }
+
+        FT_TRACE4(( " %ld", value ));
+
+        *top++       = value;
+        decoder->top = top;
+      }
+      else if ( op == op_callothersubr )  /* callothersubr */
+      {
+        FT_TRACE4(( " callothersubr" ));
+
+        if ( top - decoder->stack < 2 )
+          goto Stack_Underflow;
+
+        top -= 2;
+        switch ( top[1] )
+        {
+        case 1:                     /* start flex feature */
+          if ( top[0] != 0 )
+            goto Unexpected_OtherSubr;
+
+          decoder->flex_state        = 1;
+          decoder->num_flex_vectors  = 0;
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 6 )   )
+            goto Memory_Error;
+          break;
+
+        case 2:                     /* add flex vectors */
+          {
+            FT_Int  index;
+
+            if ( top[0] != 0 )
+              goto Unexpected_OtherSubr;
+
+            /* note that we should not add a point for index 0; */
+            /* this will move our current position to the flex  */
+            /* point without adding any point to the outline    */
+            index = decoder->num_flex_vectors++;
+            if ( index > 0 && index < 7 )
+              add_point( builder,
+                         x,
+                         y,
+                         (FT_Byte)( index == 3 || index == 6 ) );
+          }
+          break;
+
+        case 0:                     /* end flex feature */
+          if ( top[0] != 3 )
+            goto Unexpected_OtherSubr;
+
+          if ( decoder->flex_state       == 0 ||
+               decoder->num_flex_vectors != 7 )
+          {
+            FT_ERROR(( "Z1_Parse_CharStrings: unexpected flex end\n" ));
+            goto Syntax_Error;
+          }
+
+          /* now consume the remaining `pop pop setcurpoint' */
+          if ( ip + 6 > limit ||
+               ip[0] != 12 || ip[1] != 17 || /* pop */
+               ip[2] != 12 || ip[3] != 17 || /* pop */
+               ip[4] != 12 || ip[5] != 33 )  /* setcurpoint */
+          {
+            FT_ERROR(( "Z1_Parse_CharStrings: invalid flex charstring\n" ));
+            goto Syntax_Error;
+          }
+
+          ip += 6;
+          decoder->flex_state = 0;
+          break;
+
+        case 3:                     /* change hints */
+          if ( top[0] != 1 )
+            goto Unexpected_OtherSubr;
+
+          /* eat the following `pop' */
+          if ( ip + 2 > limit )
+          {
+            FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n",
+                       ip[-1] ));
+            goto Syntax_Error;
+          }
+
+          if ( ip[0] != 12 || ip[1] != 17 )
+          {
+            FT_ERROR(( "Z1_Parse_CharStrings:" ));
+            FT_ERROR(( " `pop' expected, found (%d %d)\n",
+                       ip[0], ip[1] ));
+            goto Syntax_Error;
+          }
+          ip += 2;
+          break;
+
+        case 12:
+        case 13:
+          /* counter control hints, clear stack */
+          top = decoder->stack;
+          break;
+
+        case 14:
+        case 15:
+        case 16:
+        case 17:
+        case 18:                    /* multiple masters */
+          {
+            T1_Blend*  blend = decoder->blend;
+            FT_UInt    num_points, nn, mm;
+            FT_Int*    delta;
+            FT_Int*    values;
+
+
+            if ( !blend )
+            {
+              FT_ERROR(( "Z1_Parse_CharStrings:" ));
+              FT_ERROR(( " unexpected multiple masters operator!\n" ));
+              goto Syntax_Error;
+            }
+
+            num_points = top[1] - 13 + ( top[1] == 18 );
+            if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
+            {
+              FT_ERROR(( "Z1_Parse_CharStrings:" ));
+              FT_ERROR(( " incorrect number of mm arguments\n" ));
+              goto Syntax_Error;
+            }
+
+            top -= blend->num_designs*num_points;
+            if ( top < decoder->stack )
+              goto Stack_Underflow;
+
+            /* we want to compute:                                   */
+            /*                                                       */
+            /*  a0*w0 + a1*w1 + ... + ak*wk                          */
+            /*                                                       */
+            /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
+            /* however, given that w0 + w1 + ... + wk == 1, we can   */
+            /* rewrite it easily as:                                 */
+            /*                                                       */
+            /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
+            /*                                                       */
+            /* where k == num_designs-1                              */
+            /*                                                       */
+            /* I guess that's why it's written in this `compact'     */
+            /* form.                                                 */
+            /*                                                       */
+            delta  = top + num_points;
+            values = top;
+            for ( nn = 0; nn < num_points; nn++ )
+            {
+              FT_Int  x = values[0];
+
+
+              for ( mm = 1; mm < blend->num_designs; mm++ )
+                x += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+              *values++ = x;
+            }
+            /* note that `top' will be incremented later by calls to `pop' */
+            break;
+          }
+
+        default:
+        Unexpected_OtherSubr:
+          FT_ERROR(( "Z1_Parse_CharStrings: invalid othersubr [%d %d]!\n",
+                     top[0], top[1] ));
+          goto Syntax_Error;
+        }
+        decoder->top = top;
+      }
+      else  /* general operator */
+      {
+        FT_Int  num_args = t1_args_count[op];
+
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch ( op )
+        {
+        case op_endchar:
+          FT_TRACE4(( " endchar" ));
+
+          close_contour( builder );
+
+          /* add current outline to the glyph slot */
+          FT_GlyphLoader_Add( builder->loader );
+
+          /* return now! */
+          FT_TRACE4(( "\n\n" ));
+          return T1_Err_Ok;
+
+        case op_hsbw:
+          FT_TRACE4(( " hsbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->advance.x       = top[1];
+          builder->advance.y       = 0;
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = 0;
+
+          /* the `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it; so exit immediately                           */
+          if ( builder->metrics_only )
+            return T1_Err_Ok;
+
+          break;
+
+        case op_seac:
+          /* return immediately after the processing */
+          return t1operator_seac( decoder, top[0], top[1],
+                                           top[2], top[3], top[4] );
+
+        case op_sbw:
+          FT_TRACE4(( " sbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->left_bearing.y += top[1];
+          builder->advance.x       = top[2];
+          builder->advance.y       = top[3];
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = top[1];
+
+          /* the `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it; so exit immediately                           */
+          if ( builder->metrics_only )
+            return T1_Err_Ok;
+
+          break;
+
+        case op_closepath:
+          FT_TRACE4(( " closepath" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          break;
+
+        case op_hlineto:
+          FT_TRACE4(( " hlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          goto Add_Line;
+
+        case op_hmoveto:
+          FT_TRACE4(( " hmoveto" ));
+
+          x += top[0];
+          break;
+
+        case op_hvcurveto:
+          FT_TRACE4(( " hvcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          add_point( builder, x, y, 0 );
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+          y += top[3];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_rlineto:
+          FT_TRACE4(( " rlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+
+        Add_Line:
+          if ( add_point1( builder, x, y ) )
+            goto Memory_Error;
+          break;
+
+        case op_rmoveto:
+          FT_TRACE4(( " rmoveto" ));
+
+          x += top[0];
+          y += top[1];
+          break;
+
+        case op_rrcurveto:
+          FT_TRACE4(( " rcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+          add_point( builder, x, y, 0 );
+
+          x += top[2];
+          y += top[3];
+          add_point( builder, x, y, 0 );
+
+          x += top[4];
+          y += top[5];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_vhcurveto:
+          FT_TRACE4(( " vhcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          y += top[0];
+          add_point( builder, x, y, 0 );
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+          x += top[3];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_vlineto:
+          FT_TRACE4(( " vlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          y += top[0];
+          goto Add_Line;
+
+        case op_vmoveto:
+          FT_TRACE4(( " vmoveto" ));
+
+          y += top[0];
+          break;
+
+        case op_div:
+          FT_TRACE4(( " div" ));
+
+          if ( top[1] )
+          {
+            *top = top[0] / top[1];
+            ++top;
+          }
+          else
+          {
+            FT_ERROR(( "Z1_Parse_CharStrings: division by 0\n" ));
+            goto Syntax_Error;
+          }
+          break;
+
+        case op_callsubr:
+          {
+            FT_Int  index;
+
+
+            FT_TRACE4(( " callsubr" ));
+
+            index = top[0];
+            if ( index < 0 || index >= num_subrs )
+            {
+              FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = subrs_base[index];
+            zone->limit  = zone->base + subrs_len[index];
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "Z1_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+            break;
+          }
+
+        case op_pop:
+          FT_TRACE4(( " pop" ));
+
+          /* theorically, the arguments are already on the stack */
+          top++;
+          break;
+
+        case op_return:
+          FT_TRACE4(( " return" ));
+
+          if ( zone <= decoder->zones )
+          {
+            FT_ERROR(( "Z1_Parse_CharStrings: unexpected return\n" ));
+            goto Syntax_Error;
+          }
+
+          zone--;
+          ip            = zone->cursor;
+          limit         = zone->limit;
+          decoder->zone = zone;
+          break;
+
+        case op_dotsection:
+          FT_TRACE4(( " dotsection" ));
+
+          break;
+
+        case op_hstem:
+          FT_TRACE4(( " hstem" ));
+
+          break;
+
+        case op_hstem3:
+          FT_TRACE4(( " hstem3" ));
+
+          break;
+
+        case op_vstem:
+          FT_TRACE4(( " vstem" ));
+
+          break;
+
+        case op_vstem3:
+          FT_TRACE4(( " vstem3" ));
+
+          break;
+
+        case op_setcurrentpoint:
+          FT_TRACE4(( " setcurrentpoint" ));
+
+          FT_ERROR(( "Z1_Parse_CharStrings:" ));
+          FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
+          goto Syntax_Error;
+
+        default:
+          FT_ERROR(( "Z1_Parse_CharStrings: unhandled opcode %d\n", op ));
+          goto Syntax_Error;
+        }
+
+        decoder->top = top;
+
+      } /* general operator processing */
+
+    } /* while ip < limit */
+
+    FT_TRACE4(( "..end..\n\n" ));
+    return error;
+
+  Syntax_Error:
+    return T1_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return T1_Err_Stack_Underflow;
+
+  Memory_Error:
+    return builder->error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
+                                    FT_Int*  max_advance )
+  {
+    FT_Error    error;
+    Z1_Decoder  decoder;
+    FT_Int      glyph_index;
+    T1_Font*    type1 = &face->type1;
+
+
+    *max_advance = 0;
+
+    /* Initialize load decoder */
+    Z1_Init_Decoder( &decoder );
+    Z1_Init_Builder( &decoder.builder, face, 0, 0 );
+
+    decoder.blend                = face->blend;
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    /* for each glyph, parse the glyph charstring and extract */
+    /* the advance width                                      */
+    for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+    {
+      /* now get load the unscaled outline */
+      error = Z1_Parse_CharStrings( &decoder,
+                                    type1->charstrings    [glyph_index],
+                                    type1->charstrings_len[glyph_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+      /* ignore the error if one occured - skip to next glyph */
+    }
+
+    *max_advance = decoder.builder.advance.x;
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********               UNHINTED GLYPH LOADER                  *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of loading a      *********/
+  /**********    single outline.  It completely ignores hinting    *********/
+  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
+  /**********                                                      *********/
+  /**********      The Type 1 hinter is located in `t1hint.c'      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Load_Glyph( Z1_GlyphSlot  glyph,
+                           Z1_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags )
+  {
+    FT_Error    error;
+    Z1_Decoder  decoder;
+    T1_Face     face = (T1_Face)glyph->root.face;
+    FT_Bool     hinting;
+    T1_Font*    type1 = &face->type1;
+
+
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = size->root.metrics.x_scale;
+    glyph->y_scale = size->root.metrics.y_scale;
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+              ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+    glyph->root.format = ft_glyph_format_outline;
+
+    Z1_Init_Decoder( &decoder );
+    Z1_Init_Builder( &decoder.builder, face, size, glyph );
+
+    decoder.blend              = ((T1_Face)glyph->root.face)->blend;
+    decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
+
+    /* now load the unscaled outline */
+    error = Z1_Parse_CharStrings( &decoder,
+                                  type1->charstrings    [glyph_index],
+                                  type1->charstrings_len[glyph_index],
+                                  type1->num_subrs,
+                                  type1->subrs,
+                                  type1->subrs_len );
+
+    /* save new glyph tables */
+    Z1_Done_Builder( &decoder.builder );
+
+    /* now, set the metrics -- this is rather simple, as   */
+    /* the left side bearing is the xMin, and the top side */
+    /* bearing the yMax                                    */
+    if ( !error )
+    {
+      glyph->root.outline.flags &= ft_outline_owner;
+      glyph->root.outline.flags |= ft_outline_reverse_fill;
+      
+      /* for composite glyphs, return only left side bearing and */
+      /* advance width                                           */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
+      {
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
+      }
+      else
+      {
+        FT_BBox           cbox;
+        FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance = decoder.builder.advance.x;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        if ( size && size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+#if 0
+        glyph->root.outline.second_pass    = TRUE;
+        glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+        glyph->root.outline.dropout_mode   = 2;
+#endif /* 0 */
+
+        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur = decoder.builder.base;
+          FT_Vector*   vec = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_Fixed     y_scale = glyph->y_scale;
+
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+          /* Then scale the metrics */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        }
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline,
+                              &face->type1.font_matrix );
+
+        /* compute the other metrics */
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if ( hinting )
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax  = ( cbox.xMax+63 ) & -64;
+          cbox.yMax  = ( cbox.yMax+63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+      }
+    }
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1z/z1gload.h b/src/freetype/type1z/z1gload.h
new file mode 100644 (file)
index 0000000..5bb6dc0
--- /dev/null
@@ -0,0 +1,187 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1gload.h                                                              */
+/*                                                                         */
+/*    Experimental Type 1 Glyph Loader (specification).                    */
+/*                                                                         */
+/*  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 Z1GLOAD_H
+#define Z1GLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1objs.h"
+
+#else
+
+#include <type1z/z1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    Z1_Builder                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used during glyph loading to store its outline.        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory       :: The current memory object.                         */
+  /*                                                                       */
+  /*    face         :: The current face object.                           */
+  /*                                                                       */
+  /*    glyph        :: The current glyph slot.                            */
+  /*                                                                       */
+  /*    loader       :: The current glyph loader.                          */
+  /*                                                                       */
+  /*    current      :: The current glyph outline.                         */
+  /*                                                                       */
+  /*    base         :: The base glyph outline.                            */
+  /*                                                                       */
+  /*    last         :: The last point position.                           */
+  /*                                                                       */
+  /*    scale_x      :: The horizontal scale (FUnits to sub-pixels).       */
+  /*                                                                       */
+  /*    scale_y      :: The vertical scale (FUnits to sub-pixels).         */
+  /*                                                                       */
+  /*    pos_x        :: The horizontal translation (for composite glyphs). */
+  /*                                                                       */
+  /*    pos_y        :: The vertical translation (for composite glyphs).   */
+  /*                                                                       */
+  /*    left_bearing :: The left side bearing point.                       */
+  /*                                                                       */
+  /*    advance      :: The horizontal advance vector.                     */
+  /*                                                                       */
+  /*    no_recurse   ::                                                    */
+  /*                                                                       */
+  /*    bbox         :: The glyph's bounding box.                          */
+  /*                                                                       */
+  /*    path_begun   :: A flag which indicates that a new path has begun.  */
+  /*                                                                       */
+  /*    load_points  :: A flag which indicates, if not set, that no points */
+  /*                    are loaded.                                        */
+  /*                                                                       */
+  /*    error        :: The current error code.                            */
+  /*                                                                       */
+  /*    metrics_only :: A flag whether to compute metrics only.            */
+  /*                                                                       */
+  typedef struct  Z1_Builder_
+  {
+    FT_Memory        memory;
+    T1_Face          face;
+    Z1_GlyphSlot     glyph;
+    FT_GlyphLoader*  loader;
+
+    FT_Outline*      current;       /* the current glyph outline   */
+    FT_Outline*      base;          /* the composite glyph outline */
+
+    FT_Vector        last;
+
+    FT_Fixed         scale_x;
+    FT_Fixed         scale_y;
+
+    FT_Pos           pos_x;
+    FT_Pos           pos_y;
+
+    FT_Vector        left_bearing;
+    FT_Vector        advance;
+
+    FT_BBox          bbox;          /* bounding box */
+    FT_Bool          path_begun;
+    FT_Bool          load_points;
+    FT_Bool          no_recurse;
+
+    FT_Error         error;         /* only used for memory errors */
+    FT_Bool          metrics_only;
+
+  } Z1_Builder;
+
+
+  /* execution context charstring zone */
+  typedef struct  Z1_Decoder_Zone_
+  {
+    FT_Byte*  base;
+    FT_Byte*  limit;
+    FT_Byte*  cursor;
+
+  } Z1_Decoder_Zone;
+
+
+  typedef struct  Z1_Decoder_
+  {
+    Z1_Builder        builder;
+
+    FT_Int            stack[T1_MAX_CHARSTRINGS_OPERANDS];
+    FT_Int*           top;
+
+    Z1_Decoder_Zone   zones[T1_MAX_SUBRS_CALLS + 1];
+    Z1_Decoder_Zone*  zone;
+
+    FT_Int            flex_state;
+    FT_Int            num_flex_vectors;
+    FT_Vector         flex_vectors[7];
+
+    T1_Blend*         blend;  /* for multiple masters */
+
+  } Z1_Decoder;
+
+
+  LOCAL_DEF
+  void  Z1_Init_Builder( Z1_Builder*   builder,
+                         T1_Face       face,
+                         Z1_Size       size,
+                         Z1_GlyphSlot  glyph );
+
+  LOCAL_DEF
+  void  Z1_Done_Builder( Z1_Builder*  builder );
+
+  LOCAL_DEF
+  void  Z1_Init_Decoder( Z1_Decoder*  decoder );
+
+  LOCAL_DEF
+  FT_Error  Z1_Compute_Max_Advance( T1_Face  face,
+                                    FT_Int*  max_advance );
+
+  LOCAL_DEF
+  FT_Error   Z1_Parse_CharStrings( Z1_Decoder*  decoder,
+                                   FT_Byte*     charstring_base,
+                                   FT_Int       charstring_len,
+                                   FT_Int       num_subrs,
+                                   FT_Byte**    subrs_base,
+                                   FT_Int*      subrs_len );
+
+  LOCAL_DEF
+  FT_Error  Z1_Load_Glyph( Z1_GlyphSlot  glyph,
+                           Z1_Size       size,
+                           FT_Int        glyph_index,
+                           FT_Int        load_flags );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif /* Z1GLOAD_H */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1load.c b/src/freetype/type1z/z1load.c
new file mode 100644 (file)
index 0000000..46478d1
--- /dev/null
@@ -0,0 +1,1725 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1load.c                                                               */
+/*                                                                         */
+/*    Experimental Type 1 font loader (body).                              */
+/*                                                                         */
+/*  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 is the new and improved Type 1 data loader for FreeType 2.  The  */
+  /* old loader has several problems: it is slow, complex, difficult to    */
+  /* maintain, and contains incredible hacks to make it accept some        */
+  /* ill-formed Type 1 fonts without hiccup-ing.  Moreover, about 5% of    */
+  /* the Type 1 fonts on my machine still aren't loaded correctly by it.   */
+  /*                                                                       */
+  /* This version is much simpler, much faster and also easier to read and */
+  /* maintain by a great order of magnitude.  The idea behind it is to     */
+  /* _not_ try to read the Type 1 token stream with a state machine (i.e.  */
+  /* a Postscript-like interpreter) but rather to perform simple pattern   */
+  /* matching.                                                             */
+  /*                                                                       */
+  /* Indeed, nearly all data definitions follow a simple pattern like      */
+  /*                                                                       */
+  /*  ... /Field <data> ...                                                */
+  /*                                                                       */
+  /* where <data> can be a number, a boolean, a string, or an array of     */
+  /* numbers.  There are a few exceptions, namely the encoding, font name, */
+  /* charstrings, and subrs; they are handled with a special pattern       */
+  /* matching routine.                                                     */
+  /*                                                                       */
+  /* All other common cases are handled very simply.  The matching rules   */
+  /* are defined in the file `t1tokens.h' through the use of several       */
+  /* macros calls PARSE_XXX.                                               */
+  /*                                                                       */
+  /* This file is included twice here; the first time to generate parsing  */
+  /* callback functions, the second to generate a table of keywords (with  */
+  /* pointers to the associated callback).                                 */
+  /*                                                                       */
+  /* The function `parse_dict' simply scans *linearly* a given dictionary  */
+  /* (either the top-level or private one) and calls the appropriate       */
+  /* callback when it encounters an immediate keyword.                     */
+  /*                                                                       */
+  /* This is by far the fastest way one can find to parse and read all     */
+  /* data.                                                                 */
+  /*                                                                       */
+  /* This led to tremendous code size reduction.  Note that later, the     */
+  /* glyph loader will also be _greatly_ simplified, and the automatic     */
+  /* hinter will replace the clumsy `t1hinter'.                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/ftmm.h>
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1load.h"
+
+#else
+
+#include <type1z/z1load.h>
+
+#endif
+
+
+#include <string.h>     /* for strncmp(), strcmp() */
+#include <ctype.h>      /* for isalnum()           */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1load
+
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    MULTIPLE MASTERS SUPPORT                   *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static
+  FT_Error  t1_allocate_blend( T1_Face  face,
+                               FT_UInt  num_designs,
+                               FT_UInt  num_axis )
+  {
+    T1_Blend*  blend;
+    FT_Memory  memory = face->root.memory;
+    FT_Error   error  = 0;
+
+
+    blend = face->blend;
+    if ( !blend )
+    {
+      if ( ALLOC( blend, sizeof ( *blend ) ) )
+        goto Exit;
+
+      face->blend = blend;
+    }
+
+    /* allocate design data if needed */
+    if ( num_designs > 0 )
+    {
+      if ( blend->num_designs == 0 )
+      {
+        FT_UInt  nn;
+        
+
+        /* allocate the blend `private' and `font_info' dictionaries */
+        if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo )  ||
+             ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private )     ||
+             ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
+          goto Exit;
+
+        blend->default_weight_vector = blend->weight_vector + num_designs;
+
+        blend->font_infos[0] = &face->type1.font_info;
+        blend->privates  [0] = &face->type1.private_dict;
+        
+        for ( nn = 2; nn <= num_designs; nn++ )
+        {
+          blend->privates[nn]   = blend->privates  [nn - 1] + 1;
+          blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
+        }
+        
+        blend->num_designs   = num_designs;
+      }
+      else if ( blend->num_designs != num_designs )
+        goto Fail;
+    }
+
+    /* allocate axis data if needed */
+    if ( num_axis > 0 )
+    {
+      if ( blend->num_axis != 0 && blend->num_axis != num_axis )
+        goto Fail;
+
+      blend->num_axis = num_axis;
+    }
+
+    /* allocate the blend design pos table if needed */
+    num_designs = blend->num_designs;
+    num_axis    = blend->num_axis;
+    if ( num_designs && num_axis && blend->design_pos[0] == 0 )
+    {
+      FT_UInt  n;
+
+
+      if ( ALLOC_ARRAY( blend->design_pos[0],
+                        num_designs * num_axis, FT_Fixed ) )
+        goto Exit;
+
+      for ( n = 1; n < num_designs; n++ )
+        blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
+    }
+
+  Exit:
+    return error;
+
+  Fail:
+    error = -1;
+    goto Exit;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Get_Multi_Master( T1_Face           face,
+                                 FT_Multi_Master*  master )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_UInt    n;
+    FT_Error   error;
+
+
+    error = T1_Err_Invalid_Argument;
+
+    if ( blend )
+    {
+      master->num_axis    = blend->num_axis;
+      master->num_designs = blend->num_designs;
+
+      for ( n = 0; n < blend->num_axis; n++ )
+      {
+        FT_MM_Axis*    axis = master->axis + n;
+        T1_DesignMap*  map = blend->design_map + n;
+
+
+        axis->name    = blend->axis_names[n];
+        axis->minimum = map->design_points[0];
+        axis->maximum = map->design_points[map->num_points - 1];
+      }
+      error = 0;
+    }
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Set_MM_Blend( T1_Face    face,
+                             FT_UInt    num_coords,
+                             FT_Fixed*  coords )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_Error   error;
+    FT_UInt    n, m;
+
+
+    error = T1_Err_Invalid_Argument;
+
+    if ( blend && blend->num_axis == num_coords )
+    {
+      /* recompute the weight vector from the blend coordinates */
+      error = FT_Err_Ok;
+
+      for ( n = 0; n < blend->num_designs; n++ )
+      {
+        FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
+
+
+        for ( m = 0; m < blend->num_axis; m++ )
+        {
+          FT_Fixed  factor;
+
+
+          /* get current blend axis position */
+          factor = coords[m];
+          if ( factor < 0 )        factor = 0;
+          if ( factor > 0x10000L ) factor = 0x10000L;
+
+          if ( ( n & ( 1 << m ) ) == 0 )
+            factor = 0x10000L - factor;
+
+          result = FT_MulFix( result, factor );
+        }
+        blend->weight_vector[n] = result;
+      }
+
+      error = FT_Err_Ok;
+    }
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Set_MM_Design( T1_Face   face,
+                              FT_UInt   num_coords,
+                              FT_Long*  coords )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_Error   error;
+    FT_UInt    n, p;
+
+
+    error = T1_Err_Invalid_Argument;
+    if ( blend && blend->num_axis == num_coords )
+    {
+      /* compute the blend coordinates through the blend design map */
+      FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
+
+
+      for ( n = 0; n < blend->num_axis; n++ )
+      {
+        FT_Long        design  = coords[n];
+        FT_Fixed       the_blend;
+        T1_DesignMap*  map     = blend->design_map + n;
+        FT_Fixed*      designs = map->design_points;
+        FT_Fixed*      blends  = map->blend_points;
+        FT_Int         before  = -1, after = -1;
+
+        for ( p = 0; p < map->num_points; p++ )
+        {
+          FT_Fixed  p_design = designs[p];
+
+
+          /* exact match ? */
+          if ( design == p_design )
+          {
+            the_blend = blends[p];
+            goto Found;
+          }
+
+          if ( design < p_design )
+          {
+            after = p;
+            break;
+          }
+
+          before = p;
+        }
+
+        /* now, interpolate if needed */
+        if ( before < 0 )
+          the_blend = blends[0];
+
+        else if ( after < 0 )
+          the_blend = blends[map->num_points - 1];
+
+        else
+          the_blend = FT_MulDiv( design         - designs[before],
+                                 blends [after] - blends [before],
+                                 designs[after] - designs[before] );
+
+      Found:
+        final_blends[n] = the_blend;
+      }
+
+      error = Z1_Set_MM_Blend( face, num_coords, final_blends );
+    }
+
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_Done_Blend( T1_Face  face )
+  {
+    FT_Memory  memory = face->root.memory;
+    T1_Blend*  blend  = face->blend;
+
+
+    if ( blend )
+    {
+      FT_UInt  num_designs = blend->num_designs;
+      FT_UInt  num_axis    = blend->num_axis;
+      FT_UInt  n;
+
+
+      /* release design pos table */
+      FREE( blend->design_pos[0] );
+      for ( n = 1; n < num_designs; n++ )
+        blend->design_pos[n] = 0;
+
+      /* release blend `private' and `font info' dictionaries */
+      FREE( blend->privates[1] );
+      FREE( blend->font_infos[1] );
+
+      for ( n = 0; n < num_designs; n++ )
+      {
+        blend->privates  [n] = 0;
+        blend->font_infos[n] = 0;
+      }
+
+      /* release weight vectors */
+      FREE( blend->weight_vector );
+      blend->default_weight_vector = 0;
+
+      /* release axis names */
+      for ( n = 0; n < num_axis; n++ )
+        FREE( blend->axis_names[n] );
+
+      /* release design map */
+      for ( n = 0; n < num_axis; n++ )
+      {
+        T1_DesignMap*  dmap = blend->design_map + n;
+
+
+        FREE( dmap->design_points );
+        dmap->num_points = 0;
+      }
+
+      FREE( face->blend );
+    }
+  }
+
+
+  static
+  void  parse_blend_axis_types( T1_Face     face,
+                                Z1_Loader*  loader )
+  {
+    Z1_Token_Rec  axis_tokens[ T1_MAX_MM_AXIS ];
+    FT_Int        n, num_axis;
+    FT_Error      error = 0;
+    T1_Blend*     blend;
+    FT_Memory     memory;
+
+
+    /* take an array of objects */
+    Z1_ToTokenArray( &loader->parser, axis_tokens,
+                     T1_MAX_MM_AXIS, &num_axis );
+    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+    {
+      FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
+                 num_axis ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* allocate blend if necessary */
+    error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
+    if ( error )
+      goto Exit;
+
+    blend  = face->blend;
+    memory = face->root.memory;
+
+    /* each token is an immediate containing the name of the axis */
+    for ( n = 0; n < num_axis; n++ )
+    {
+      Z1_Token_Rec*  token = axis_tokens + n;
+      FT_Byte*       name;
+      FT_Int         len;
+
+      /* skip first slash, if any */
+      if (token->start[0] == '/')
+        token->start++;
+
+      len = token->limit - token->start;
+      if ( len <= 0 )
+      {
+        error = T1_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      if ( ALLOC( blend->axis_names[n], len + 1 ) )
+        goto Exit;
+
+      name = (FT_Byte*)blend->axis_names[n];
+      MEM_Copy( name, token->start, len );
+      name[len] = 0;
+    }
+
+  Exit:
+    loader->parser.error = error;
+  }
+
+
+  static
+  void  parse_blend_design_positions( T1_Face     face,
+                                      Z1_Loader*  loader )
+  {
+    Z1_Token_Rec  design_tokens[ T1_MAX_MM_DESIGNS ];
+    FT_Int        num_designs;
+    FT_Int        num_axis;
+    Z1_Parser*    parser = &loader->parser;
+
+    FT_Error      error = 0;
+    T1_Blend*     blend;
+
+
+    /* get the array of design tokens - compute number of designs */
+    Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
+    if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
+    {
+      FT_ERROR(( "parse_blend_design_positions:" ));
+      FT_ERROR(( " incorrect number of designs: %d\n",
+                 num_designs ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    {
+      FT_Byte*  old_cursor = parser->cursor;
+      FT_Byte*  old_limit  = parser->limit;
+      FT_UInt   n;
+
+
+      blend    = face->blend;
+      num_axis = 0;  /* make compiler happy */
+
+      for ( n = 0; n < (FT_UInt)num_designs; n++ )
+      {
+        Z1_Token_Rec   axis_tokens[ T1_MAX_MM_DESIGNS ];
+        Z1_Token_Rec*  token;
+        FT_Int         axis, n_axis;
+
+
+        /* read axis/coordinates tokens */
+        token = design_tokens + n;
+        parser->cursor = token->start - 1;
+        parser->limit  = token->limit + 1;
+        Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
+
+        if ( n == 0 )
+        {
+          num_axis = n_axis;
+          error = t1_allocate_blend( face, num_designs, num_axis );
+          if ( error )
+            goto Exit;
+          blend = face->blend;
+        }
+        else if ( n_axis != num_axis )
+        {
+          FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
+          error = T1_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* now, read each axis token into the design position */
+        for ( axis = 0; axis < n_axis; axis++ )
+        {
+          Z1_Token_Rec*  token2 = axis_tokens + axis;
+
+
+          parser->cursor = token2->start;
+          parser->limit  = token2->limit;
+          blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
+        }
+      }
+
+      loader->parser.cursor = old_cursor;
+      loader->parser.limit  = old_limit;
+    }
+
+  Exit:
+    loader->parser.error = error;
+  }
+
+
+  static
+  void  parse_blend_design_map( T1_Face     face,
+                                Z1_Loader*  loader )
+  {
+    FT_Error      error  = 0;
+    Z1_Parser*    parser = &loader->parser;
+    T1_Blend*     blend;
+    Z1_Token_Rec  axis_tokens[ T1_MAX_MM_AXIS ];
+    FT_Int        n, num_axis;
+    FT_Byte*      old_cursor;
+    FT_Byte*      old_limit;
+    FT_Memory     memory = face->root.memory;
+
+
+    Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
+    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+    {
+      FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
+                 num_axis ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+    old_cursor = parser->cursor;
+    old_limit  = parser->limit;
+
+    error = t1_allocate_blend( face, 0, num_axis );
+    if ( error )
+      goto Exit;
+    blend = face->blend;
+
+    /* now, read each axis design map */
+    for ( n = 0; n < num_axis; n++ )
+    {
+      T1_DesignMap*   map = blend->design_map + n;
+      Z1_Token_Rec*   token;
+      FT_Int          p, num_points;
+
+
+      token = axis_tokens + n;
+      parser->cursor = token->start;
+      parser->limit  = token->limit;
+
+      /* count the number of map points */
+      {
+        FT_Byte*  p     = token->start;
+        FT_Byte*  limit = token->limit;
+
+
+        num_points = 0;
+        for ( ; p < limit; p++ )
+          if ( p[0] == '[' )
+            num_points++;
+      }
+      if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
+      {
+        FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
+        error = T1_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      /* allocate design map data */
+      if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
+        goto Exit;
+      map->blend_points = map->design_points + num_points;
+      map->num_points   = (FT_Byte)num_points;
+
+      for ( p = 0; p < num_points; p++ )
+      {
+        map->design_points[p] = Z1_ToInt( parser );
+        map->blend_points [p] = Z1_ToFixed( parser, 0 );
+      }
+    }
+
+    parser->cursor = old_cursor;
+    parser->limit  = old_limit;
+
+  Exit:
+    parser->error = error;
+  }
+
+
+  static
+  void  parse_weight_vector( T1_Face     face,
+                             Z1_Loader*  loader )
+  {
+    FT_Error      error  = 0;
+    Z1_Parser*    parser = &loader->parser;
+    T1_Blend*     blend  = face->blend;
+    Z1_Token_Rec  master;
+    FT_UInt       n;
+    FT_Byte*      old_cursor;
+    FT_Byte*      old_limit;
+
+
+    if ( !blend || blend->num_designs == 0 )
+    {
+      FT_ERROR(( "parse_weight_vector: too early!\n" ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    Z1_ToToken( parser, &master );
+    if ( master.type != t1_token_array )
+    {
+      FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    old_cursor = parser->cursor;
+    old_limit  = parser->limit;
+
+    parser->cursor = master.start;
+    parser->limit  = master.limit;
+
+    for ( n = 0; n < blend->num_designs; n++ )
+    {
+      blend->default_weight_vector[n] =
+      blend->weight_vector[n]         = Z1_ToFixed( parser, 0 );
+    }
+
+    parser->cursor = old_cursor;
+    parser->limit  = old_limit;
+
+  Exit:
+    parser->error = error;
+  }
+
+
+  /* the keyword `/shareddict' appears in some multiple master fonts   */
+  /* with a lot of Postscript garbage behind it (that's completely out */
+  /* of spec!); we detect it and terminate the parsing                 */
+  /*                                                                   */
+  static
+  void  parse_shared_dict( T1_Face     face,
+                           Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+
+    FT_UNUSED( face );
+
+
+    parser->cursor = parser->limit;
+    parser->error  = 0;
+  }
+
+#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      TYPE 1 SYMBOL PARSING                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* First of all, define the token field static variables.  This is a set */
+  /* of Z1_Field_Rec variables used later.                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+#define Z1_NEW_STRING( _name, _field )              \
+          static                                    \
+          const Z1_Field_Rec  t1_field_ ## _field = \
+            Z1_FIELD_STRING( T1TYPE, _field );
+
+#define Z1_NEW_BOOL( _name, _field )                \
+          static                                    \
+          const Z1_Field_Rec  t1_field_ ## _field = \
+            Z1_FIELD_BOOL( T1TYPE, _field );
+
+#define Z1_NEW_NUM( _name, _field )                 \
+          static                                    \
+          const Z1_Field_Rec  t1_field_ ## _field = \
+            Z1_FIELD_NUM( T1TYPE, _field );
+
+#define Z1_NEW_FIXED( _name, _field )                 \
+          static                                      \
+          const Z1_Field_Rec  t1_field_ ## _field =   \
+            Z1_FIELD_FIXED( T1TYPE, _field, _power );
+
+#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count )         \
+          static                                                \
+          const Z1_Field_Rec  t1_field_ ## _field =             \
+            Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max );
+
+#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count )         \
+          static                                                  \
+          const Z1_Field_Rec  t1_field_ ## _field =               \
+            Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max );
+
+#define Z1_NEW_NUM_TABLE2( _name, _field, _max )         \
+          static                                         \
+          const Z1_Field_Rec  t1_field_ ## _field =      \
+            Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max );
+
+#define Z1_NEW_FIXED_TABLE2( _name, _field, _max )         \
+          static                                           \
+          const Z1_Field_Rec  t1_field_ ## _field =        \
+            Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max );
+
+
+#define Z1_FONTINFO_STRING( n, f )          Z1_NEW_STRING( n, f )
+#define Z1_FONTINFO_NUM( n, f )             Z1_NEW_NUM( n, f )
+#define Z1_FONTINFO_BOOL( n, f )            Z1_NEW_BOOL( n, f )
+#define Z1_PRIVATE_NUM( n, f )              Z1_NEW_NUM( n, f )
+#define Z1_PRIVATE_FIXED( n, f )            Z1_NEW_FIXED( n, f )
+#define Z1_PRIVATE_NUM_TABLE( n, f, m, c )  Z1_NEW_NUM_TABLE( n, f, m, c )
+#define Z1_PRIVATE_NUM_TABLE2( n, f, m )    Z1_NEW_NUM_TABLE2( n, f, m )
+#define Z1_TOPDICT_NUM( n, f )              Z1_NEW_NUM( n, f )
+#define Z1_TOPDICT_NUM_FIXED2( n, f, m )    Z1_NEW_FIXED_TABLE2( n, f, m )
+
+
+  /* including this file defines all field variables */
+#ifdef FT_FLAT_COMPILE
+
+#include "z1tokens.h"
+
+#else
+
+#include <type1z/z1tokens.h>
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Second, define the keyword variables.  This is a set of Z1_KeyWord    */
+  /* structures used to model the way each keyword is `loaded'.            */
+  /*                                                                       */
+  /*************************************************************************/
+
+  typedef void  (*Z1_Parse_Func)( T1_Face     face,
+                                  Z1_Loader*  loader );
+
+
+  typedef enum  Z1_KeyWord_Type_
+  {
+    t1_keyword_callback = 0,
+    t1_keyword_field,
+    t1_keyword_field_table
+
+  } Z1_KeyWord_Type;
+
+
+  typedef enum  Z1_KeyWord_Location_
+  {
+    t1_keyword_type1 = 0,
+    t1_keyword_font_info,
+    t1_keyword_private
+
+  } Z1_KeyWord_Location;
+
+
+  typedef struct  Z1_KeyWord_
+  {
+    const char*          name;
+    Z1_KeyWord_Type      type;
+    Z1_KeyWord_Location  location;
+    Z1_Parse_Func        parsing;
+    const Z1_Field_Rec*  field;
+
+  } Z1_KeyWord;
+
+
+#define Z1_KEYWORD_CALLBACK( name, callback )                      \
+        {                                                          \
+          name, t1_keyword_callback, t1_keyword_type1, callback, 0 \
+        }
+
+#define Z1_KEYWORD_TYPE1( name, f )                                    \
+        {                                                              \
+          name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \
+        }
+
+#define Z1_KEYWORD_FONTINFO( name, f )                                     \
+        {                                                                  \
+          name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \
+        }
+
+#define Z1_KEYWORD_PRIVATE( name, f )                                    \
+        {                                                                \
+          name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \
+        }
+
+#define Z1_KEYWORD_FONTINFO_TABLE( name, f )                     \
+        {                                                        \
+          name, t1_keyword_field_table, t1_keyword_font_info, 0, \
+          &t1_field_ ## f                                        \
+        }
+
+#define Z1_KEYWORD_PRIVATE_TABLE( name, f )                    \
+        {                                                      \
+          name, t1_keyword_field_table, t1_keyword_private, 0, \
+          &t1_field_ ## f                                      \
+        }
+
+
+#undef  Z1_FONTINFO_STRING
+#undef  Z1_FONTINFO_NUM
+#undef  Z1_FONTINFO_BOOL
+#undef  Z1_PRIVATE_NUM
+#undef  Z1_PRIVATE_FIXED
+#undef  Z1_PRIVATE_NUM_TABLE
+#undef  Z1_PRIVATE_NUM_TABLE2
+#undef  Z1_TOPDICT_NUM
+#undef  Z1_TOPDICT_NUM_FIXED2
+
+#define Z1_FONTINFO_STRING( n, f )          Z1_KEYWORD_FONTINFO( n, f ),
+#define Z1_FONTINFO_NUM( n, f )             Z1_KEYWORD_FONTINFO( n, f ),
+#define Z1_FONTINFO_BOOL( n, f )            Z1_KEYWORD_FONTINFO( n, f ),
+#define Z1_PRIVATE_NUM( n, f )              Z1_KEYWORD_PRIVATE( n, f ),
+#define Z1_PRIVATE_FIXED( n, f )            Z1_KEYWORD_PRIVATE( n, f ),
+#define Z1_PRIVATE_NUM_TABLE( n, f, m, c )  Z1_KEYWORD_PRIVATE_TABLE( n, f ),
+#define Z1_PRIVATE_NUM_TABLE2( n, f, m )    Z1_KEYWORD_PRIVATE_TABLE( n, f ),
+#define Z1_TOPDICT_NUM( n, f )              Z1_KEYWORD_TYPE1( n, f ),
+#define Z1_TOPDICT_NUM_FIXED2( n, f, m )    Z1_KEYWORD_TYPE1( n, f ),
+
+
+  static
+  FT_Error  t1_load_keyword( T1_Face      face,
+                             Z1_Loader*   loader,
+                             Z1_KeyWord*  keyword )
+  {
+    FT_Error   error;
+    void*      dummy_object;
+    void**     objects;
+    FT_UInt    max_objects;
+    T1_Blend*  blend = face->blend;
+
+
+    /* if the keyword has a dedicated callback, call it */
+    if ( keyword->type == t1_keyword_callback )
+    {
+      keyword->parsing( face, loader );
+      error = loader->parser.error;
+      goto Exit;
+    }
+
+    /* now, the keyword is either a simple field, or a table of fields; */
+    /* we are now going to take care of it                              */
+    switch ( keyword->location )
+    {
+    case t1_keyword_font_info:
+      dummy_object = &face->type1.font_info;
+      objects      = &dummy_object;
+      max_objects  = 0;
+
+      if ( blend )
+      {
+        objects     = (void**)blend->font_infos;
+        max_objects = blend->num_designs;
+      }
+      break;
+
+    case t1_keyword_private:
+      dummy_object = &face->type1.private_dict;
+      objects      = &dummy_object;
+      max_objects  = 0;
+
+      if ( blend )
+      {
+        objects     = (void**)blend->privates;
+        max_objects = blend->num_designs;
+      }
+      break;
+
+    default:
+      dummy_object = &face->type1;
+      objects      = &dummy_object;
+      max_objects  = 0;
+    }
+
+    if ( keyword->type == t1_keyword_field_table )
+      error = Z1_Load_Field_Table( &loader->parser, keyword->field,
+                                   objects, max_objects, 0 );
+    else
+      error = Z1_Load_Field( &loader->parser, keyword->field,
+                             objects, max_objects, 0 );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  int  is_space( char  c )
+  {
+    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+  }
+
+
+  static
+  int  is_alpha( char c )
+  {
+    return ( isalnum( c ) ||
+             ( c == '.' ) ||
+             ( c == '_' ) );
+  }
+
+
+  static
+  void  skip_whitespace( Z1_Parser*  parser )
+  {
+    FT_Byte*  cur = parser->cursor;
+
+
+    while ( cur < parser->limit && is_space( *cur ) )
+      cur++;
+
+    parser->cursor = cur;
+  }
+
+
+  static
+  void skip_blackspace( Z1_Parser*  parser )
+  {
+    FT_Byte*  cur = parser->cursor;
+
+    while ( cur < parser->limit && !is_space( *cur ) )
+      cur++;
+
+    parser->cursor = cur;
+  }
+
+
+  static
+  int  read_binary_data( Z1_Parser*  parser,
+                         FT_Int*     size,
+                         FT_Byte**   base )
+  {
+    FT_Byte*  cur;
+    FT_Byte*  limit = parser->limit;
+
+
+    /* the binary data has the following format */
+    /*                                          */
+    /* `size' [white*] RD white ....... ND      */
+    /*                                          */
+
+    skip_whitespace( parser );
+    cur = parser->cursor;
+
+    if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
+    {
+      *size = Z1_ToInt( parser );
+
+      skip_whitespace( parser );
+      skip_blackspace( parser );  /* `RD' or `-|' or something else */
+
+      /* there is only one whitespace char after the */
+      /* `RD' or `-|' token                          */
+      *base = parser->cursor + 1;
+
+      parser->cursor += *size+1;
+      return 1;
+    }
+
+    FT_ERROR(( "read_binary_data: invalid size field\n" ));
+    parser->error = T1_Err_Invalid_File_Format;
+    return 0;
+  }
+
+
+  /* we will now define the routines used to handle */
+  /* the `/Encoding', `/Subrs', and `/CharStrings'  */
+  /* dictionaries                                   */
+
+  static
+  void  parse_font_name( T1_Face     face,
+                         Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Error    error;
+    FT_Memory   memory = parser->memory;
+    FT_Int      len;
+    FT_Byte*    cur;
+    FT_Byte*    cur2;
+    FT_Byte*    limit;
+
+
+    skip_whitespace( parser );
+
+    cur   = parser->cursor;
+    limit = parser->limit;
+
+    if ( cur >= limit - 1 || *cur != '/' )
+      return;
+
+    cur++;
+    cur2 = cur;
+    while ( cur2 < limit && is_alpha( *cur2 ) )
+      cur2++;
+
+    len = cur2 - cur;
+    if ( len > 0 )
+    {
+      if ( ALLOC( face->type1.font_name, len + 1 ) )
+      {
+        parser->error = error;
+        return;
+      }
+
+      MEM_Copy( face->type1.font_name, cur, len );
+      face->type1.font_name[len] = '\0';
+    }
+    parser->cursor = cur2;
+  }
+
+
+  static
+  void  parse_font_bbox( T1_Face     face,
+                         Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Short    temp[4];
+    FT_BBox*    bbox   = &face->type1.font_bbox;
+
+
+    (void)Z1_ToCoordArray( parser, 4, temp );
+    bbox->xMin = temp[0];
+    bbox->yMin = temp[1];
+    bbox->xMax = temp[2];
+    bbox->yMax = temp[3];
+  }
+
+
+  static
+  void  parse_font_matrix( T1_Face     face,
+                           Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Matrix*  matrix = &face->type1.font_matrix;
+    FT_Fixed    temp[4];
+
+
+    (void)Z1_ToFixedArray( parser, 4, temp, 3 );
+    matrix->xx = temp[0];
+    matrix->yx = temp[1];
+    matrix->xy = temp[2];
+    matrix->yy = temp[3];
+  }
+
+
+  static
+  void  parse_encoding( T1_Face     face,
+                        Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    FT_Byte*    cur   = parser->cursor;
+    FT_Byte*    limit = parser->limit;
+
+
+    /* skip whitespace */
+    while ( is_space( *cur ) )
+    {
+      cur++;
+      if ( cur >= limit )
+      {
+        FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+        parser->error = T1_Err_Invalid_File_Format;
+        return;
+      }
+    }
+
+    /* if we have a number, then the encoding is an array, */
+    /* and we must load it now                             */
+    if ( (FT_Byte)( *cur - '0' ) < 10 )
+    {
+      T1_Encoding*  encode     = &face->type1.encoding;
+      FT_Int        count, n;
+      Z1_Table*     char_table = &loader->encoding_table;
+      FT_Memory     memory     = parser->memory;
+      FT_Error      error;
+
+
+      /* read the number of entries in the encoding, should be 256 */
+      count = Z1_ToInt( parser );
+      if ( parser->error )
+        return;
+
+      /* we use a Z1_Table to store our charnames */
+      encode->num_chars = count;
+      if ( ALLOC_ARRAY( encode->char_index, count, FT_Short   )       ||
+           ALLOC_ARRAY( encode->char_name,  count, FT_String* )       ||
+           ( error = Z1_New_Table( char_table, count, memory ) ) != 0 )
+      {
+        parser->error = error;
+        return;
+      }
+
+      /* Now, we will need to read a record of the form         */
+      /* ... charcode /charname ... for each entry in our table */
+      /*                                                        */
+      /* We simply look for a number followed by an immediate   */
+      /* name.  Note that this ignores correctly the sequence   */
+      /* that is often seen in type1 fonts:                     */
+      /*                                                        */
+      /*   0 1 255 { 1 index exch /.notdef put } for dup        */
+      /*                                                        */
+      /* used to clean the encoding array before anything else. */
+      /*                                                        */
+      /* We stop when we encounter a `def'.                     */
+
+      cur   = parser->cursor;
+      limit = parser->limit;
+      n     = 0;
+
+      for ( ; cur < limit; )
+      {
+        FT_Byte  c;
+
+
+        c = *cur;
+
+        /* we stop when we encounter a `def' */
+        if ( c == 'd' && cur + 3 < limit )
+        {
+          if ( cur[1] == 'e' &&
+               cur[2] == 'f' &&
+               is_space(cur[-1]) &&
+               is_space(cur[3]) )
+          {
+            FT_TRACE6(( "encoding end\n" ));
+            break;
+          }
+        }
+
+        /* otherwise, we must find a number before anything else */
+        if ( (FT_Byte)( c - '0' ) < 10 )
+        {
+          FT_Int  charcode;
+
+
+          parser->cursor = cur;
+          charcode = Z1_ToInt( parser );
+          cur = parser->cursor;
+
+          /* skip whitespace */
+          while ( cur < limit && is_space( *cur ) )
+            cur++;
+
+          if ( cur < limit && *cur == '/' )
+          {
+            /* bingo, we have an immediate name -- it must be a */
+            /* character name                                   */
+            FT_Byte*  cur2 = cur + 1;
+            FT_Int    len;
+
+
+            while ( cur2 < limit && is_alpha( *cur2 ) )
+              cur2++;
+
+            len = cur2 - cur - 1;
+
+            parser->error = Z1_Add_Table( char_table, charcode,
+                                          cur + 1, len + 1 );
+            char_table->elements[charcode][len] = '\0';
+            if ( parser->error )
+              return;
+
+            cur = cur2;
+          }
+        }
+        else
+          cur++;
+      }
+
+      face->type1.encoding_type = t1_encoding_array;
+      parser->cursor            = cur;
+    }
+    /* Otherwise, we should have either `StandardEncoding' or */
+    /* `ExpertEncoding'                                       */
+    else
+    {
+      if ( cur + 17 < limit &&
+           strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+        face->type1.encoding_type = t1_encoding_standard;
+
+      else if ( cur + 15 < limit &&
+                strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+        face->type1.encoding_type = t1_encoding_expert;
+
+      else
+      {
+        FT_ERROR(( "parse_encoding: invalid token!\n" ));
+        parser->error = T1_Err_Invalid_File_Format;
+      }
+    }
+  }
+
+
+  static
+  void  parse_subrs( T1_Face     face,
+                     Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+    Z1_Table*   table  = &loader->subrs;
+    FT_Memory   memory = parser->memory;
+    FT_Error    error;
+    FT_Int      n;
+
+
+    loader->num_subrs = Z1_ToInt( parser );
+    if ( parser->error )
+      return;
+
+    /* position the parser right before the `dup' of the first subr */
+    skip_whitespace( parser );
+    skip_blackspace( parser );      /* `array' */
+    skip_whitespace( parser );
+
+    /* initialize subrs array */
+    error = Z1_New_Table( table, loader->num_subrs, memory );
+    if ( error )
+      goto Fail;
+
+    /* the format is simple:                                 */
+    /*                                                       */
+    /*   `index' + binary data                               */
+    /*                                                       */
+
+    for ( n = 0; n < loader->num_subrs; n++ )
+    {
+      FT_Int    index, size;
+      FT_Byte*  base;
+
+
+      /* If the next token isn't `dup', we are also done.  This */
+      /* happens when there are `holes' in the Subrs array.     */
+      if ( strncmp( (char*)parser->cursor, "dup", 3 ) != 0 )
+        break;
+
+      index = Z1_ToInt( parser );
+      
+      if ( !read_binary_data( parser, &size, &base ) )
+        return;
+
+      /* The binary string is followed by one token, e.g. `NP' */
+      /* (bound to `noaccess put') or by two separate tokens:  */
+      /* `noaccess' & `put'.  We position the parser right     */
+      /* before the next `dup', if any.                        */
+      skip_whitespace( parser );
+      skip_blackspace( parser );    /* `NP' or `I' or `noaccess' */
+      skip_whitespace( parser );
+
+      if ( strncmp( (char*)parser->cursor, "put", 3 ) == 0 )
+      {
+        skip_blackspace( parser );  /* skip `put' */
+        skip_whitespace( parser );
+      }
+
+      /* some fonts use a value of -1 for lenIV to indicate that */
+      /* the charstrings are unencoded                           */
+      /*                                                         */
+      /* thanks to Tom Kacvinsky for pointing this out           */
+      /*                                                         */
+      if ( face->type1.private_dict.lenIV >= 0 )
+      {
+        Z1_Decrypt( base, size, 4330 );
+        size -= face->type1.private_dict.lenIV;
+        base += face->type1.private_dict.lenIV;
+      }
+
+      error = Z1_Add_Table( table, index, base, size );
+      if ( error )
+        goto Fail;
+    }
+    return;
+
+  Fail:
+    parser->error = error;
+  }
+
+
+  static
+  void  parse_charstrings( T1_Face     face,
+                           Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser     = &loader->parser;
+    Z1_Table*   code_table = &loader->charstrings;
+    Z1_Table*   name_table = &loader->glyph_names;
+    FT_Memory   memory     = parser->memory;
+    FT_Error    error;
+
+    FT_Byte*    cur;
+    FT_Byte*    limit = parser->limit;
+    FT_Int      n;
+
+
+    loader->num_glyphs = Z1_ToInt( parser );
+    if ( parser->error )
+      return;
+
+    /* initialize tables */
+    error = Z1_New_Table( code_table, loader->num_glyphs, memory ) ||
+            Z1_New_Table( name_table, loader->num_glyphs, memory );
+    if ( error )
+      goto Fail;
+
+    n = 0;
+    for (;;)
+    {
+      FT_Int    size;
+      FT_Byte*  base;
+
+
+      /* the format is simple:                    */
+      /*   `/glyphname' + binary data             */
+      /*                                          */
+      /* note that we stop when we find a `def'   */
+      /*                                          */
+      skip_whitespace( parser );
+
+      cur = parser->cursor;
+      if ( cur >= limit )
+        break;
+
+      /* we stop when we find a `def' or `end' keyword */
+      if ( *cur   == 'd'   &&
+           cur + 3 < limit &&
+           cur[1] == 'e'   &&
+           cur[2] == 'f'   )
+        break;
+
+      if ( *cur   == 'e'   &&
+           cur + 3 < limit &&
+           cur[1] == 'n'   &&
+           cur[2] == 'd'   )
+        break;
+
+      if ( *cur != '/' )
+        skip_blackspace( parser );
+      else
+      {
+        FT_Byte*  cur2 = cur + 1;
+        FT_Int    len;
+
+
+        while ( cur2 < limit && is_alpha( *cur2 ) )
+          cur2++;
+        len = cur2 - cur - 1;
+
+        error = Z1_Add_Table( name_table, n, cur + 1, len + 1 );
+        if ( error )
+          goto Fail;
+
+        /* add a trailing zero to the name table */
+        name_table->elements[n][len] = '\0';
+
+        parser->cursor = cur2;
+        if ( !read_binary_data( parser, &size, &base ) )
+          return;
+
+        if ( face->type1.private_dict.lenIV >= 0 )
+        {
+          Z1_Decrypt( base, size, 4330 );
+          size -= face->type1.private_dict.lenIV;
+          base += face->type1.private_dict.lenIV;
+        }
+
+        error = Z1_Add_Table( code_table, n, base, size );
+        if ( error )
+          goto Fail;
+
+        n++;
+        if ( n >= loader->num_glyphs )
+          break;
+      }
+    }
+    loader->num_glyphs = n;
+    return;
+
+  Fail:
+    parser->error = error;
+  }
+
+
+  static
+  const Z1_KeyWord  t1_keywords[] =
+  {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1tokens.h"
+
+#else
+
+#include <type1z/z1tokens.h>
+
+#endif
+
+    /* now add the special functions... */
+    Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ),
+    Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ),
+    Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ),
+    Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ),
+    Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ),
+    Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ),
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+    Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ),
+    Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ),
+    Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ),
+    Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ),
+    Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ),
+#endif
+
+    Z1_KEYWORD_CALLBACK( 0, 0 )
+  };
+
+
+  static
+  FT_Error  parse_dict( T1_Face     face,
+                        Z1_Loader*  loader,
+                        FT_Byte*    base,
+                        FT_Long     size )
+  {
+    Z1_Parser*  parser = &loader->parser;
+
+
+    parser->cursor = base;
+    parser->limit  = base + size;
+    parser->error  = 0;
+
+    {
+      FT_Byte*  cur   = base;
+      FT_Byte*  limit = cur + size;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        /* look for `FontDirectory', which causes problems on some fonts */
+        if ( *cur == 'F' && cur + 25 < limit                 &&
+             strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+        {
+          FT_Byte*  cur2;
+
+
+          /* skip the `FontDirectory' keyword */
+          cur += 13;
+          cur2 = cur;
+
+          /* lookup the `known' keyword */
+          while ( cur < limit && *cur != 'k'        &&
+                  strncmp( (char*)cur, "known", 5 ) )
+            cur++;
+
+          if ( cur < limit )
+          {
+            Z1_Token_Rec  token;
+
+
+            /* skip the `known' keyword and the token following it */
+            cur += 5;
+            loader->parser.cursor = cur;
+            Z1_ToToken( &loader->parser, &token );
+
+            /* if the last token was an array, skip it! */
+            if ( token.type == t1_token_array )
+              cur2 = parser->cursor;
+          }
+          cur = cur2;
+        }
+        /* look for immediates */
+        else if ( *cur == '/' && cur + 2 < limit )
+        {
+          FT_Byte*  cur2;
+          FT_Int    len;
+
+
+          cur++;
+          cur2 = cur;
+          while ( cur2 < limit && is_alpha( *cur2 ) )
+            cur2++;
+
+          len  = cur2 - cur;
+          if ( len > 0 && len < 22 )
+          {
+            if ( !loader->fontdata )
+            {
+              if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
+                loader->fontdata = 1;
+            }
+            else
+            {
+              /* now, compare the immediate name to the keyword table */
+              Z1_KeyWord*  keyword = (Z1_KeyWord*)t1_keywords;
+
+
+              for (;;)
+              {
+                FT_Byte*  name;
+
+
+                name = (FT_Byte*)keyword->name;
+                if ( !name )
+                  break;
+
+                if ( cur[0] == name[0]                          &&
+                     len == (FT_Int)strlen( (const char*)name ) )
+                {
+                  FT_Int  n;
+
+
+                  for ( n = 1; n < len; n++ )
+                    if ( cur[n] != name[n] )
+                      break;
+
+                  if ( n >= len )
+                  {
+                    /* we found it -- run the parsing callback! */
+                    parser->cursor = cur2;
+                    skip_whitespace( parser );
+                    parser->error = t1_load_keyword( face, loader, keyword );
+                    if ( parser->error )
+                      return parser->error;
+
+                    cur = parser->cursor;
+                    break;
+                  }
+                }
+                keyword++;
+              }
+            }
+          }
+        }
+      }
+    }
+    return parser->error;
+  }
+
+
+  static
+  void  t1_init_loader( Z1_Loader*  loader,
+                        T1_Face     face )
+  {
+    FT_UNUSED( face );
+
+    MEM_Set( loader, 0, sizeof ( *loader ) );
+    loader->num_glyphs = 0;
+    loader->num_chars  = 0;
+
+    /* initialize the tables -- simply set their `init' field to 0 */
+    loader->encoding_table.init = 0;
+    loader->charstrings.init    = 0;
+    loader->glyph_names.init    = 0;
+    loader->subrs.init          = 0;
+    loader->fontdata            = 0;
+  }
+
+
+  static
+  void  t1_done_loader( Z1_Loader*  loader )
+  {
+    Z1_Parser*  parser = &loader->parser;
+
+
+    /* finalize tables */
+    Z1_Release_Table( &loader->encoding_table );
+    Z1_Release_Table( &loader->charstrings );
+    Z1_Release_Table( &loader->glyph_names );
+    Z1_Release_Table( &loader->subrs );
+
+    /* finalize parser */
+    Z1_Done_Parser( parser );
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Open_Face( T1_Face  face )
+  {
+    Z1_Loader   loader;
+    Z1_Parser*  parser;
+    T1_Font*    type1 = &face->type1;
+    FT_Error    error;
+
+
+    t1_init_loader( &loader, face );
+
+    /* default lenIV */
+    type1->private_dict.lenIV = 4;
+
+    parser = &loader.parser;
+    error = Z1_New_Parser( parser, face->root.stream, face->root.memory );
+    if ( error )
+      goto Exit;
+
+    error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
+    if ( error )
+      goto Exit;
+
+    error = Z1_Get_Private_Dict( parser );
+    if ( error )
+      goto Exit;
+
+    error = parse_dict( face, &loader, parser->private_dict,
+                        parser->private_len );
+    if ( error )
+      goto Exit;
+
+    /* now, propagate the subrs, charstrings, and glyphnames tables */
+    /* to the Type1 data                                            */
+    type1->num_glyphs = loader.num_glyphs;
+
+    if ( !loader.subrs.init )
+    {
+      FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" ));
+      error = T1_Err_Invalid_File_Format;
+    }
+
+    if ( !loader.charstrings.init )
+    {
+      FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" ));
+      error = T1_Err_Invalid_File_Format;
+    }
+
+    loader.subrs.init  = 0;
+    type1->num_subrs   = loader.num_subrs;
+    type1->subrs_block = loader.subrs.block;
+    type1->subrs       = loader.subrs.elements;
+    type1->subrs_len   = loader.subrs.lengths;
+
+    loader.charstrings.init  = 0;
+    type1->charstrings_block = loader.charstrings.block;
+    type1->charstrings       = loader.charstrings.elements;
+    type1->charstrings_len   = loader.charstrings.lengths;
+
+    /* we copy the glyph names `block' and `elements' fields; */
+    /* the `lengths' field must be released later             */
+    type1->glyph_names_block    = loader.glyph_names.block;
+    type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
+    loader.glyph_names.block    = 0;
+    loader.glyph_names.elements = 0;
+
+    /* we must now build type1.encoding when we have a custom */
+    /* array..                                                */
+    if ( type1->encoding_type == t1_encoding_array )
+    {
+      FT_Int    charcode, index, min_char, max_char;
+      FT_Byte*  char_name;
+      FT_Byte*  glyph_name;
+
+
+      /* OK, we do the following: for each element in the encoding  */
+      /* table, look up the index of the glyph having the same name */
+      /* the index is then stored in type1.encoding.char_index, and */
+      /* a the name to type1.encoding.char_name                     */
+
+      min_char = +32000;
+      max_char = -32000;
+
+      charcode = 0;
+      for ( ; charcode < loader.encoding_table.num_elems; charcode++ )
+      {
+        type1->encoding.char_index[charcode] = 0;
+        type1->encoding.char_name [charcode] = ".notdef";
+
+        char_name = loader.encoding_table.elements[charcode];
+        if ( char_name )
+          for ( index = 0; index < type1->num_glyphs; index++ )
+          {
+            glyph_name = (FT_Byte*)type1->glyph_names[index];
+            if ( strcmp( (const char*)char_name,
+                         (const char*)glyph_name ) == 0 )
+            {
+              type1->encoding.char_index[charcode] = index;
+              type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+              if (charcode < min_char) min_char = charcode;
+              if (charcode > max_char) max_char = charcode;
+              break;
+            }
+          }
+      }
+      type1->encoding.code_first = min_char;
+      type1->encoding.code_last  = max_char;
+      type1->encoding.num_chars  = loader.num_chars;
+   }
+
+  Exit:
+    t1_done_loader( &loader );
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1z/z1load.h b/src/freetype/type1z/z1load.h
new file mode 100644 (file)
index 0000000..672b553
--- /dev/null
@@ -0,0 +1,93 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1load.h                                                               */
+/*                                                                         */
+/*    Experimental Type 1 font loader (specification).                     */
+/*                                                                         */
+/*  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 Z1LOAD_H
+#define Z1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+#include <freetype/ftmm.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.h"
+
+#else
+
+#include <type1z/z1parse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  typedef struct  Z1_Loader_
+  {
+    Z1_Parser  parser;          /* parser used to read the stream */
+
+    FT_Int     num_chars;       /* number of characters in encoding */
+    Z1_Table   encoding_table;  /* Z1_Table used to store the       */
+                                /* encoding character names         */
+
+    FT_Int     num_glyphs;
+    Z1_Table   glyph_names;
+    Z1_Table   charstrings;
+
+    FT_Int     num_subrs;
+    Z1_Table   subrs;
+    FT_Bool    fontdata;
+
+  } Z1_Loader;
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Open_Face( T1_Face  face );
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+
+  LOCAL_DEF
+  FT_Error  Z1_Get_Multi_Master( T1_Face           face,
+                                 FT_Multi_Master*  master );
+
+  LOCAL_DEF
+  FT_Error  Z1_Set_MM_Blend( T1_Face    face,
+                             FT_UInt    num_coords,
+                             FT_Fixed*  coords );
+
+  LOCAL_DEF
+  FT_Error  Z1_Set_MM_Design( T1_Face   face,
+                              FT_UInt   num_coords,
+                              FT_Long*  coords );
+
+  LOCAL_DEF
+  void  Z1_Done_Blend( T1_Face  face );
+
+#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* Z1LOAD_H */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1objs.c b/src/freetype/type1z/z1objs.c
new file mode 100644 (file)
index 0000000..e452bb5
--- /dev/null
@@ -0,0 +1,398 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1objs.c                                                               */
+/*                                                                         */
+/*    Experimental Type 1 objects manager (body).                          */
+/*                                                                         */
+/*  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 <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1gload.h"
+#include "z1load.h"
+#include "z1afm.h"
+
+#else
+
+#include <type1z/z1gload.h>
+#include <type1z/z1load.h>
+#include <type1z/z1afm.h>
+
+#endif
+
+
+#include <freetype/internal/psnames.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1objs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                            FACE  FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object destructor.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A typeless pointer to the face object to destroy.          */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  Z1_Done_Face( T1_Face  face )
+  {
+    FT_Memory  memory;
+    T1_Font*   type1 = &face->type1;
+
+
+    if ( face )
+    {
+      memory = face->root.memory;
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+      /* release multiple masters information */
+      Z1_Done_Blend( face );
+      face->blend = 0;
+#endif
+
+      /* release font info strings */
+      {
+        T1_FontInfo*  info = &type1->font_info;
+
+
+        FREE( info->version );
+        FREE( info->notice );
+        FREE( info->full_name );
+        FREE( info->family_name );
+        FREE( info->weight );
+      }
+
+      /* release top dictionary */
+      FREE( type1->charstrings_len );
+      FREE( type1->charstrings );
+      FREE( type1->glyph_names );
+
+      FREE( type1->subrs );
+      FREE( type1->subrs_len );
+
+      FREE( type1->subrs_block );
+      FREE( type1->charstrings_block );
+      FREE( type1->glyph_names_block );
+
+      FREE( type1->encoding.char_index );
+      FREE( type1->font_name );
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+      /* release afm data if present */
+      if ( face->afm_data )
+        Z1_Done_AFM( memory, (Z1_AFM*)face->afm_data );
+#endif
+
+      /* release unicode map, if any */
+      FREE( face->unicode_map.maps );
+      face->unicode_map.num_maps = 0;
+
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object constructor.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     ::  input stream where to load font data.               */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The face record to build.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Z1_Init_Face( FT_Stream      stream,
+                          T1_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params )
+  {
+    FT_Error            error;
+    PSNames_Interface*  psnames;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+    FT_UNUSED( stream );
+
+
+    face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+    {
+      psnames = (PSNames_Interface*)
+                FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
+
+      face->psnames = psnames;
+    }
+
+    /* open the tokenizer, this will also check the font format */
+    error = Z1_Open_Face( face );
+    if ( error )
+      goto Exit;
+
+    /* if we just wanted to check the format, leave successfully now */
+    if ( face_index < 0 )
+      goto Exit;
+
+    /* check the face index */
+    if ( face_index != 0 )
+    {
+      FT_ERROR(( "Z1_Init_Face: invalid face index\n" ));
+      error = T1_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* Now, load the font program into the face object */
+
+    /* Init the face object fields */
+    /* Now set up root face fields */
+    {
+      FT_Face  root = (FT_Face)&face->root;
+
+
+      root->num_glyphs   = face->type1.num_glyphs;
+      root->num_charmaps = 1;
+
+      root->face_index = face_index;
+      root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+      root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+      root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+
+      if ( face->type1.font_info.is_fixed_pitch )
+        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      if ( face->blend )
+        root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+
+      /* XXX: TODO -- add kerning with .afm support */
+
+      /* get style name -- be careful, some broken fonts only */
+      /* have a `/FontName' dictionary entry!                 */
+      root->family_name = face->type1.font_info.family_name;
+      if ( root->family_name )
+      {
+        char*  full   = face->type1.font_info.full_name;
+        char*  family = root->family_name;
+
+
+        while ( *family && *full == *family )
+        {
+          family++;
+          full++;
+        }
+
+        root->style_name = ( *full == ' ' ? full + 1
+                                          : (char *)"Regular" );
+      }
+      else
+      {
+        /* do we have a `/FontName'? */
+        if ( face->type1.font_name )
+        {
+          root->family_name = face->type1.font_name;
+          root->style_name  = "Regular";
+        }
+      }
+
+      /* no embedded bitmap support */
+      root->num_fixed_sizes = 0;
+      root->available_sizes = 0;
+
+      root->bbox         = face->type1.font_bbox;
+      root->units_per_EM = 1000;
+      root->ascender     =  (FT_Short)face->type1.font_bbox.yMax;
+      root->descender    = -(FT_Short)face->type1.font_bbox.yMin;
+      root->height       = ( ( root->ascender + root->descender ) * 12 ) / 10;
+
+      /* now compute the maximum advance width */
+
+      root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+      /* compute max advance width for proportional fonts */
+      if ( !face->type1.font_info.is_fixed_pitch )
+      {
+        FT_Int  max_advance;
+
+
+        error = Z1_Compute_Max_Advance( face, &max_advance );
+
+        /* in case of error, keep the standard width */
+        if ( !error )
+          root->max_advance_width = max_advance;
+        else
+          error = 0;   /* clear error */
+      }
+
+      root->max_advance_height = root->height;
+
+      root->underline_position  = face->type1.font_info.underline_position;
+      root->underline_thickness = face->type1.font_info.underline_thickness;
+
+      root->max_points   = 0;
+      root->max_contours = 0;
+    }
+
+    /* charmap support -- synthetize unicode charmap if possible */
+    {
+      FT_Face     root    = &face->root;
+      FT_CharMap  charmap = face->charmaprecs;
+
+
+      /* synthesize a Unicode charmap if there is support in the `PSNames' */
+      /* module                                                            */
+      if ( face->psnames )
+      {
+        PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+
+        if ( psnames->unicode_value )
+        {
+          error = psnames->build_unicodes(
+                    root->memory,
+                    face->type1.num_glyphs,
+                    (const char**)face->type1.glyph_names,
+                    &face->unicode_map );
+          if ( !error )
+          {
+            root->charmap        = charmap;
+            charmap->face        = (FT_Face)face;
+            charmap->encoding    = ft_encoding_unicode;
+            charmap->platform_id = 3;
+            charmap->encoding_id = 1;
+            charmap++;
+          }
+
+          /* simply clear the error in case of failure (which really) */
+          /* means that out of memory or no unicode glyph names       */
+          error = FT_Err_Ok;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encoding */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
+
+      switch ( face->type1.encoding_type )
+      {
+      case t1_encoding_standard:
+        charmap->encoding    = ft_encoding_adobe_standard;
+        charmap->encoding_id = 0;
+        break;
+
+      case t1_encoding_expert:
+        charmap->encoding    = ft_encoding_adobe_expert;
+        charmap->encoding_id = 1;
+        break;
+
+      default:
+        charmap->encoding    = ft_encoding_adobe_custom;
+        charmap->encoding_id = 2;
+        break;
+      }
+
+      root->charmaps     = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0]  = &face->charmaprecs[0];
+      face->charmaps[1]  = &face->charmaprecs[1];
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Init_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given Type 1 driver object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Z1_Init_Driver( Z1_Driver  driver )
+  {
+    FT_UNUSED( driver );
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Done_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given Type 1 driver.                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver  :: A handle to the target Type 1 driver.                   */
+  /*                                                                       */
+  LOCAL_DEF
+  void  Z1_Done_Driver( Z1_Driver  driver )
+  {
+    FT_UNUSED( driver );
+  }
+
+
+/* END */
diff --git a/src/freetype/type1z/z1objs.h b/src/freetype/type1z/z1objs.h
new file mode 100644 (file)
index 0000000..c655a67
--- /dev/null
@@ -0,0 +1,161 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1objs.h                                                               */
+/*                                                                         */
+/*    Experimental Type 1 objects manager (specification).                 */
+/*                                                                         */
+/*  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 Z1OBJS_H
+#define Z1OBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  /* The following structures must be defined by the hinter */
+  typedef struct Z1_Size_Hints_   Z1_Size_Hints;
+  typedef struct Z1_Glyph_Hints_  Z1_Glyph_Hints;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 driver object.                                */
+  /*                                                                       */
+  typedef struct Z1_DriverRec_   *Z1_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 size object.                                  */
+  /*                                                                       */
+  typedef struct Z1_SizeRec_*  Z1_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 glyph slot object.                            */
+  /*                                                                       */
+  typedef struct Z1_GlyphSlotRec_*  Z1_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_CharMap                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 character mapping object.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The Type 1 format doesn't use a charmap but an encoding table.     */
+  /*    The driver is responsible for making up charmap objects            */
+  /*    corresponding to these tables.                                     */
+  /*                                                                       */
+  typedef struct Z1_CharMapRec_*   Z1_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  HERE BEGINS THE TYPE1 SPECIFIC STUFF                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_SizeRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 size record.                                                */
+  /*                                                                       */
+  typedef struct  Z1_SizeRec_
+  {
+    FT_SizeRec      root;
+    FT_Bool         valid;
+    Z1_Size_Hints*  hints;  /* defined in the hinter. This allows */
+                            /* us to experiment with different    */
+                            /* hinting schemes without having to  */
+                            /* change `z1objs' each time.         */
+  } Z1_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    Z1_GlyphSlotRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 glyph slot record.                                          */
+  /*                                                                       */
+  typedef struct  Z1_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Int           max_points;
+    FT_Int           max_contours;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+    Z1_Glyph_Hints*  hints;  /* defined in the hinter */
+
+  } Z1_GlyphSlotRec;
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Init_Face( FT_Stream      stream,
+                          T1_Face        face,
+                          FT_Int         face_index,
+                          FT_Int         num_params,
+                          FT_Parameter*  params );
+
+  LOCAL_DEF
+  void  Z1_Done_Face( T1_Face  face );
+
+  LOCAL_DEF
+  FT_Error  Z1_Init_Driver( Z1_Driver  driver );
+
+  LOCAL_DEF
+  void  Z1_Done_Driver( Z1_Driver  driver );
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* Z1OBJS_H */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1parse.c b/src/freetype/type1z/z1parse.c
new file mode 100644 (file)
index 0000000..9bc2913
--- /dev/null
@@ -0,0 +1,1398 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1parse.c                                                              */
+/*                                                                         */
+/*    Experimental Type 1 parser (body).                                   */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The Type 1 parser is in charge of the following:                      */
+  /*                                                                       */
+  /*  - provide an implementation of a growing sequence of objects called  */
+  /*    a `Z1_Table' (used to build various tables needed by the loader).  */
+  /*                                                                       */
+  /*  - opening .pfb and .pfa files to extract their top-level and private */
+  /*    dictionaries.                                                      */
+  /*                                                                       */
+  /*  - read numbers, arrays & strings from any dictionary.                */
+  /*                                                                       */
+  /* See `z1load.c' to see how data is loaded from the font file.          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "z1parse.h"
+
+#else
+
+#include <type1z/z1parse.h>
+
+#endif
+
+
+#include <string.h>     /* for strncmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_z1parse
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****              IMPLEMENTATION OF Z1_TABLE OBJECT                *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_New_Table                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initialises a Z1_Table.                                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The address of the target table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    count  :: The table size = the maximum number of elements.         */
+  /*                                                                       */
+  /*    memory :: The memory object to use for all subsequent              */
+  /*              reallocations.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Z1_New_Table( Z1_Table*  table,
+                          FT_Int     count,
+                          FT_Memory  memory )
+  {
+    FT_Error  error;
+
+
+    table->memory = memory;
+    if ( ALLOC_ARRAY( table->elements, count, FT_Byte*  ) ||
+         ALLOC_ARRAY( table->lengths, count, FT_Byte* )   )
+      goto Exit;
+
+    table->max_elems = count;
+    table->init      = 0xdeadbeef;
+    table->num_elems = 0;
+    table->block     = 0;
+    table->capacity  = 0;
+    table->cursor    = 0;
+
+  Exit:
+    if ( error )
+      FREE( table->elements );
+
+    return error;
+  }
+
+
+  static
+  void  shift_elements( Z1_Table*  table,
+                        FT_Byte*   old_base )
+  {
+    FT_Long    delta  = table->block - old_base;
+    FT_Byte**  offset = table->elements;
+    FT_Byte**  limit  = offset + table->max_elems;
+
+
+    if ( delta )
+      for ( ; offset < limit; offset++ )
+      {
+        if ( offset[0] )
+          offset[0] += delta;
+      }
+  }
+
+
+  static
+  FT_Error  reallocate_t1_table( Z1_Table*  table,
+                                 FT_Int     new_size )
+  {
+    FT_Memory  memory   = table->memory;
+    FT_Byte*   old_base = table->block;
+    FT_Error   error;
+
+
+    /* reallocate the base block */
+    if ( REALLOC( table->block, table->capacity, new_size ) )
+      return error;
+
+    table->capacity = new_size;
+
+    /* shift all offsets if necessary */
+    if ( old_base )
+      shift_elements( table, old_base );
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Add_Table                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds an object to a Z1_Table, possibly growing its memory block.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The target table.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    index  :: The index of the object in the table.                    */
+  /*                                                                       */
+  /*    object :: The address of the object to copy in memory.             */
+  /*                                                                       */
+  /*    length :: The length in bytes of the source object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  An error is returned if a  */
+  /*    reallocation fails.                                                */
+  /*                                                                       */
+  LOCAL_FUNC
+  FT_Error  Z1_Add_Table( Z1_Table*  table,
+                          FT_Int     index,
+                          void*      object,
+                          FT_Int     length )
+  {
+    if ( index < 0 || index > table->max_elems )
+    {
+      FT_ERROR(( "Z1_Add_Table: invalid index\n" ));
+      return T1_Err_Syntax_Error;
+    }
+
+    /* grow the base block if needed */
+    if ( table->cursor + length > table->capacity )
+    {
+      FT_Error  error;
+      FT_Int    new_size = table->capacity;
+
+
+      while ( new_size < table->cursor + length )
+        new_size += 1024;
+
+      error = reallocate_t1_table( table, new_size );
+      if ( error )
+        return error;
+    }
+
+    /* add the object to the base block and adjust offset */
+    table->elements[index] = table->block + table->cursor;
+    table->lengths [index] = length;
+    MEM_Copy( table->block + table->cursor, object, length );
+
+    table->cursor += length;
+    return T1_Err_Ok;
+  }
+
+
+#if 0
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Z1_Done_Table                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a Z1_Table (i.e., reallocate it to its current cursor).  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table :: The target table.                                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT release the heap's memory block.  It is up  */
+  /*    to the caller to clean it, or reference it in its own structures.  */
+  /*                                                                       */
+  LOCAL_FUNC
+  void  Z1_Done_Table( Z1_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+    FT_Error   error;
+    FT_Byte*   old_base;
+
+
+    /* should never fail, as rec.cursor <= rec.size */
+    old_base = table->block;
+    if ( !old_base )
+      return;
+
+    (void)REALLOC( table->block, table->capacity, table->cursor );
+    table->capacity = table->cursor;
+
+    if ( old_base != table->block )
+      shift_elements( table, old_base );
+  }
+
+#endif /* 0 */
+
+
+  LOCAL_FUNC
+  void  Z1_Release_Table( Z1_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+
+
+    if ( table->init == (FT_Long)0xDEADBEEF )
+    {
+      FREE( table->block );
+      FREE( table->elements );
+      FREE( table->lengths );
+      table->init = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   INPUT STREAM PARSER                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define IS_Z1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
+#define IS_Z1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
+
+#define IS_Z1_SPACE( c )  ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) )
+
+
+  LOCAL_FUNC
+  void  Z1_Skip_Spaces( Z1_Parser*  parser )
+  {
+    FT_Byte* cur   = parser->cursor;
+    FT_Byte* limit = parser->limit;
+
+
+    while ( cur < limit )
+    {
+      FT_Byte  c = *cur;
+
+
+      if ( !IS_Z1_SPACE( c ) )
+        break;
+      cur++;
+    }
+    parser->cursor = cur;
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_ToToken( Z1_Parser*     parser,
+                    Z1_Token_Rec*  token )
+  {
+    FT_Byte*  cur;
+    FT_Byte*  limit;
+    FT_Byte   starter, ender;
+    FT_Int    embed;
+
+
+    token->type  = t1_token_none;
+    token->start = 0;
+    token->limit = 0;
+
+    /* first of all, skip space */
+    Z1_Skip_Spaces( parser );
+
+    cur   = parser->cursor;
+    limit = parser->limit;
+
+    if ( cur < limit )
+    {
+      switch ( *cur )
+      {
+        /************* check for strings ***********************/
+      case '(':
+        token->type = t1_token_string;
+        ender = ')';
+        goto Lookup_Ender;
+
+        /************* check for programs/array ****************/
+      case '{':
+        token->type = t1_token_array;
+        ender = '}';
+        goto Lookup_Ender;
+
+        /************* check for table/array ******************/
+      case '[':
+        token->type = t1_token_array;
+        ender = ']';
+
+      Lookup_Ender:
+        embed   = 1;
+        starter = *cur++;
+        token->start = cur;
+        while ( cur < limit )
+        {
+          if ( *cur == starter )
+            embed++;
+          else if ( *cur == ender )
+          {
+            embed--;
+            if ( embed <= 0 )
+            {
+              token->limit = cur++;
+              break;
+            }
+          }
+          cur++;
+        }
+        break;
+
+        /* **************** otherwise, it's any token **********/
+      default:
+        token->start = cur++;
+        token->type  = t1_token_any;
+        while ( cur < limit && !IS_Z1_SPACE( *cur ) )
+          cur++;
+
+        token->limit = cur;
+      }
+
+      if ( !token->limit )
+      {
+        token->start = 0;
+        token->type  = t1_token_none;
+      }
+
+      parser->cursor = cur;
+    }
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_ToTokenArray( Z1_Parser*     parser,
+                         Z1_Token_Rec*  tokens,
+                         FT_UInt        max_tokens,
+                         FT_Int*        pnum_tokens )
+  {
+    Z1_Token_Rec  master;
+
+
+    *pnum_tokens = -1;
+
+    Z1_ToToken( parser, &master );
+    if ( master.type == t1_token_array )
+    {
+      FT_Byte*       old_cursor = parser->cursor;
+      FT_Byte*       old_limit  = parser->limit;
+      Z1_Token_Rec*  cur        = tokens;
+      Z1_Token_Rec*  limit      = cur + max_tokens;
+
+
+      parser->cursor = master.start;
+      parser->limit  = master.limit;
+
+      while ( parser->cursor < parser->limit )
+      {
+        Z1_Token_Rec  token;
+
+
+        Z1_ToToken( parser, &token );
+        if ( !token.type )
+          break;
+
+        if ( cur < limit )
+          *cur = token;
+
+        cur++;
+      }
+
+      *pnum_tokens = cur - tokens;
+
+      parser->cursor = old_cursor;
+      parser->limit  = old_limit;
+    }
+  }
+
+
+  static
+  FT_Long  t1_toint( FT_Byte**  cursor,
+                     FT_Byte*   limit )
+  {
+    FT_Long   result = 0;
+    FT_Byte*  cur    = *cursor;
+    FT_Byte   c, d;
+
+
+    for ( ; cur < limit; cur++ )
+    {
+      c = *cur;
+      d = (FT_Byte)( c - '0' );
+      if ( d < 10 )
+        break;
+
+      if ( c == '-' )
+      {
+        cur++;
+        break;
+      }
+    }
+
+    if ( cur < limit )
+    {
+      do
+      {
+        d = (FT_Byte)( cur[0] - '0' );
+        if ( d >= 10 )
+          break;
+
+        result = result * 10 + d;
+        cur++;
+
+      } while ( cur < limit );
+
+      if ( c == '-' )
+        result = -result;
+    }
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  FT_Long  t1_tofixed( FT_Byte**  cursor,
+                       FT_Byte*   limit,
+                       FT_Long    power_ten )
+  {
+    FT_Byte* cur  = *cursor;
+    FT_Long  num, divider, result;
+    FT_Int   sign = 0;
+    FT_Byte  d;
+
+
+    if ( cur >= limit )
+      return 0;
+
+    /* first of all, read the integer part */
+    result  = t1_toint( &cur, limit ) << 16;
+    num     = 0;
+    divider = 1;
+
+    if ( result < 0 )
+    {
+      sign   = 1;
+      result = -result;
+    }
+
+    if ( cur >= limit )
+      goto Exit;
+
+    /* read decimal part, if any */
+    if ( *cur == '.' && cur + 1 < limit )
+    {
+      cur++;
+
+      for (;;)
+      {
+        d = (FT_Byte)( *cur - '0' );
+        if ( d >= 10 )
+          break;
+
+        if ( divider < 10000000L )
+        {
+          num      = num * 10 + d;
+          divider *= 10;
+        }
+
+        cur++;
+        if ( cur >= limit )
+          break;
+      }
+    }
+
+    /* read exponent, if any */
+    if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
+    {
+      cur++;
+      power_ten += t1_toint( &cur, limit );
+    }
+
+  Exit:
+    /* raise to power of ten if needed */
+    while ( power_ten > 0 )
+    {
+      result = result * 10;
+      num    = num * 10;
+      power_ten--;
+    }
+
+    while ( power_ten < 0 )
+    {
+      result  = result / 10;
+      divider = divider * 10;
+      power_ten++;
+    }
+
+    if ( num )
+      result += FT_DivFix( num, divider );
+
+    if ( sign )
+      result = -result;
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  static
+  FT_Int  t1_tocoordarray( FT_Byte**  cursor,
+                           FT_Byte*   limit,
+                           FT_Int     max_coords,
+                           FT_Short*  coords )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+
+    if ( cur >= limit )
+      goto Exit;
+
+    /* check for the beginning of an array. If not, only one number will */
+    /* be read                                                           */
+    c     = *cur;
+    ender = 0;
+
+    if ( c == '[' )
+      ender = ']';
+
+    if ( c == '{' )
+      ender = '}';
+
+    if ( ender )
+      cur++;
+
+    /* now, read the coordinates */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' )
+          break;
+
+        cur++;
+        if ( cur >= limit )
+          goto Exit;
+      }
+
+      if ( count >= max_coords || c == ender )
+        break;
+
+      coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
+      count++;
+
+      if ( !ender )
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+  static
+  FT_Int  t1_tofixedarray( FT_Byte**  cursor,
+                           FT_Byte*   limit,
+                           FT_Int     max_values,
+                           FT_Fixed*  values,
+                           FT_Int     power_ten )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+
+    if ( cur >= limit ) goto Exit;
+
+    /* check for the beginning of an array. If not, only one number will */
+    /* be read                                                           */
+    c     = *cur;
+    ender = 0;
+
+    if ( c == '[' )
+      ender = ']';
+
+    if ( c == '{' )
+      ender = '}';
+
+    if ( ender )
+      cur++;
+
+    /* now, read the values */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' )
+          break;
+
+        cur++;
+        if ( cur >= limit )
+          goto Exit;
+      }
+
+      if ( count >= max_values || c == ender )
+        break;
+
+      values[count] = t1_tofixed( &cur, limit, power_ten );
+      count++;
+
+      if ( !ender )
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+#if 0
+
+  static
+  FT_String*  t1_tostring( FT_Byte**  cursor,
+                           FT_Byte*   limit,
+                           FT_Memory  memory )
+  {
+    FT_Byte*    cur = *cursor;
+    FT_Int      len = 0;
+    FT_Int      count;
+    FT_String*  result;
+    FT_Error    error;
+
+
+    /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
+    /*      that simply doesn't begin with an opening parenthesis, even */
+    /*      though they have a closing one!  E.g. "amuncial.pfb"        */
+    /*                                                                  */
+    /*      We must deal with these ill-fated cases there.  Note that   */
+    /*      these fonts didn't work with the old Type 1 driver as the   */
+    /*      notice/copyright was not recognized as a valid string token */
+    /*      and made the old token parser commit errors.                */
+
+    while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
+      cur++;
+    if ( cur + 1 >= limit )
+      return 0;
+
+    if ( *cur == '(' )
+      cur++;  /* skip the opening parenthesis, if there is one */
+
+    *cursor = cur;
+    count   = 0;
+
+    /* then, count its length */
+    for ( ; cur < limit; cur++ )
+    {
+      if ( *cur == '(' )
+        count++;
+
+      else if ( *cur == ')' )
+      {
+        count--;
+        if ( count < 0 )
+          break;
+      }
+    }
+
+    len = cur - *cursor;
+    if ( cur >= limit || ALLOC( result, len + 1 ) )
+      return 0;
+
+    /* now copy the string */
+    MEM_Copy( result, *cursor, len );
+    result[len] = '\0';
+    *cursor = cur;
+    return result;
+  }
+
+#endif /* 0 */
+
+
+  static
+  int  t1_tobool( FT_Byte**  cursor,
+                  FT_Byte*   limit )
+  {
+    FT_Byte*  cur    = *cursor;
+    FT_Bool   result = 0;
+
+
+    /* return 1 if we find `true', 0 otherwise */
+    if ( cur + 3 < limit &&
+         cur[0] == 't' &&
+         cur[1] == 'r' &&
+         cur[2] == 'u' &&
+         cur[3] == 'e' )
+    {
+      result = 1;
+      cur   += 5;
+    }
+    else if ( cur + 4 < limit &&
+              cur[0] == 'f' &&
+              cur[1] == 'a' &&
+              cur[2] == 'l' &&
+              cur[3] == 's' &&
+              cur[4] == 'e' )
+    {
+      result = 0;
+      cur   += 6;
+    }
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  /* Load a simple field (i.e. non-table) into the current list of objects */
+  LOCAL_FUNC
+  FT_Error  Z1_Load_Field( Z1_Parser*           parser,
+                           const Z1_Field_Rec*  field,
+                           void**               objects,
+                           FT_UInt              max_objects,
+                           FT_ULong*            pflags )
+  {
+    Z1_Token_Rec  token;
+    FT_Byte*      cur;
+    FT_Byte*      limit;
+    FT_UInt       count;
+    FT_UInt       index;
+    FT_Error      error;
+
+
+    Z1_ToToken( parser, &token );
+    if ( !token.type )
+      goto Fail;
+
+    count = 1;
+    index = 0;
+    cur   = token.start;
+    limit = token.limit;
+
+    if ( token.type == t1_token_array )
+    {
+      /* if this is an array, and we have no blend, an error occurs */
+      if ( max_objects == 0 )
+        goto Fail;
+
+      count = max_objects;
+      index = 1;
+    }
+
+    for ( ; count > 0; count--, index++ )
+    {
+      FT_Byte*    q = (FT_Byte*)objects[index] + field->offset;
+      FT_Long     val;
+      FT_String*  string;
+
+      switch ( field->type )
+      {
+      case t1_field_bool:
+        val = t1_tobool( &cur, limit );
+        goto Store_Integer;
+
+      case t1_field_fixed:
+        val = t1_tofixed( &cur, limit, 3 );
+        goto Store_Integer;
+
+      case t1_field_integer:
+        val = t1_toint( &cur, limit );
+
+      Store_Integer:
+        switch ( field->size )
+        {
+        case 1:
+          *(FT_Byte*)q = (FT_Byte)val;
+          break;
+
+        case 2:
+          *(FT_UShort*)q = (FT_UShort)val;
+          break;
+
+        case 4:
+          *(FT_UInt32*)q = (FT_UInt32)val;
+          break;
+
+        default:  /* for 64-bit systems */
+          *(FT_Long*)q = val;
+        }
+        break;
+
+      case t1_field_string:
+        {
+          FT_Memory  memory = parser->memory;
+          FT_UInt    len    = limit-cur;
+
+          if ( ALLOC( string, len + 1 ) )
+            goto Exit;
+
+          MEM_Copy( string, cur, len );
+          string[len] = 0;
+
+          *(FT_String**)q = string;
+        }
+        break;
+
+      default:
+        /* an error occured */
+        goto Fail;
+      }
+    }
+
+    if ( pflags )
+      *pflags |= 1L << field->flag_bit;
+
+    error = FT_Err_Ok;
+
+  Exit:
+    return error;
+
+  Fail:
+    error = T1_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+#define T1_MAX_TABLE_ELEMENTS  32
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Load_Field_Table( Z1_Parser*           parser,
+                                 const Z1_Field_Rec*  field,
+                                 void**               objects,
+                                 FT_UInt              max_objects,
+                                 FT_ULong*            pflags )
+  {
+    Z1_Token_Rec   elements[T1_MAX_TABLE_ELEMENTS];
+    Z1_Token_Rec*  token;
+    FT_Int         num_elements;
+    FT_Error       error = 0;
+    FT_Byte*       old_cursor;
+    FT_Byte*       old_limit;
+    Z1_Field_Rec   fieldrec = *(Z1_Field_Rec*)field;
+
+
+    Z1_ToTokenArray( parser, elements, 32, &num_elements );
+    if ( num_elements < 0 )
+      goto Fail;
+
+    if ( num_elements > T1_MAX_TABLE_ELEMENTS )
+      num_elements = T1_MAX_TABLE_ELEMENTS;
+
+    old_cursor = parser->cursor;
+    old_limit  = parser->limit;
+
+    /* we store the elements count */
+    *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) = num_elements;
+
+    /* we now load each element, adjusting the field.offset on each one */
+    token = elements;
+    for ( ; num_elements > 0; num_elements--, token++ )
+    {
+      parser->cursor = token->start;
+      parser->limit  = token->limit;
+      Z1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
+      fieldrec.offset += fieldrec.size;
+    }
+
+    if ( pflags )
+      *pflags |= 1L << field->flag_bit;
+
+    parser->cursor = old_cursor;
+    parser->limit  = old_limit;
+
+  Exit:
+    return error;
+
+  Fail:
+    error = T1_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+  LOCAL_FUNC
+  FT_Long  Z1_ToInt  ( Z1_Parser*  parser )
+  {
+    return t1_toint( &parser->cursor, parser->limit );
+  }
+
+
+  LOCAL_FUNC
+  FT_Long  Z1_ToFixed( Z1_Parser*  parser,
+                       FT_Int      power_ten )
+  {
+    return t1_tofixed( &parser->cursor, parser->limit, power_ten );
+  }
+
+
+  LOCAL_FUNC
+  FT_Int  Z1_ToCoordArray( Z1_Parser*  parser,
+                           FT_Int      max_coords,
+                           FT_Short*   coords )
+  {
+    return t1_tocoordarray( &parser->cursor, parser->limit,
+                            max_coords, coords );
+  }
+
+
+  LOCAL_FUNC
+  FT_Int  Z1_ToFixedArray( Z1_Parser*  parser,
+                           FT_Int      max_values,
+                           FT_Fixed*   values,
+                           FT_Int      power_ten )
+  {
+    return t1_tofixedarray( &parser->cursor, parser->limit,
+                            max_values, values, power_ten );
+  }
+
+
+#if 0
+
+  LOCAL_FUNC
+  FT_String*  Z1_ToString( Z1_Parser*  parser )
+  {
+    return t1_tostring( &parser->cursor, parser->limit, parser->memory );
+  }
+
+
+  LOCAL_FUNC
+  FT_Bool  Z1_ToBool( Z1_Parser*  parser )
+  {
+    return t1_tobool( &parser->cursor, parser->limit );
+  }
+
+#endif /* 0 */
+
+
+  static
+  FT_Error  read_pfb_tag( FT_Stream   stream,
+                          FT_UShort*  tag,
+                          FT_Long*    size )
+  {
+    FT_Error  error;
+
+
+    if ( READ_UShort( *tag ) )
+      goto Exit;
+
+    if ( *tag == 0x8001 || *tag == 0x8002 )
+    {
+      FT_Long  asize;
+
+
+      if ( READ_ULong( asize ) )
+        goto Exit;
+
+      /* swap between big and little endianness */
+      *size  = ( ( asize & 0xFF000000L ) >> 24 ) |
+               ( ( asize & 0x00FF0000L ) >> 8  ) |
+               ( ( asize & 0x0000FF00L ) << 8  ) |
+               ( ( asize & 0x000000FFL ) << 24 );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_New_Parser( Z1_Parser*  parser,
+                           FT_Stream   stream,
+                           FT_Memory   memory )
+  {
+    FT_Error  error;
+    FT_UShort tag;
+    FT_Long   size;
+
+
+    parser->stream       = stream;
+    parser->memory       = memory;
+    parser->base_len     = 0;
+    parser->base_dict    = 0;
+    parser->private_len  = 0;
+    parser->private_dict = 0;
+    parser->in_pfb       = 0;
+    parser->in_memory    = 0;
+    parser->single_block = 0;
+
+    parser->cursor       = 0;
+    parser->limit        = 0;
+
+    /******************************************************************/
+    /*                                                                */
+    /* Here a short summary of what is going on:                      */
+    /*                                                                */
+    /*   When creating a new Type 1 parser, we try to locate and load */
+    /*   the base dictionary if this is possible (i.e. for PFB        */
+    /*   files).  Otherwise, we load the whole font into memory.      */
+    /*                                                                */
+    /*   When `loading' the base dictionary, we only setup pointers   */
+    /*   in the case of a memory-based stream.  Otherwise, we         */
+    /*   allocate and load the base dictionary in it.                 */
+    /*                                                                */
+    /*   parser->in_pfb is set if we are in a binary (".pfb") font.   */
+    /*   parser->in_memory is set if we have a memory stream.         */
+    /*                                                                */
+
+    /* try to compute the size of the base dictionary;   */
+    /* look for a Postscript binary file tag, i.e 0x8001 */
+    if ( FILE_Seek( 0L ) )
+      goto Exit;
+
+    error = read_pfb_tag( stream, &tag, &size );
+    if ( error )
+      goto Exit;
+
+    if ( tag != 0x8001 )
+    {
+      /* assume that this is a PFA file for now; an error will */
+      /* be produced later when more things are checked        */
+      (void)FILE_Seek( 0L );
+      size = stream->size;
+    }
+    else
+      parser->in_pfb = 1;
+
+    /* now, try to load `size' bytes of the `base' dictionary we */
+    /* found previously                                          */
+
+    /* if it is a memory-based resource, set up pointers */
+    if ( !stream->read )
+    {
+      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+      parser->base_len  = size;
+      parser->in_memory = 1;
+
+      /* check that the `size' field is valid */
+      if ( FILE_Skip( size ) )
+        goto Exit;
+    }
+    else
+    {
+      /* read segment in memory */
+      if ( ALLOC( parser->base_dict, size )     ||
+           FILE_Read( parser->base_dict, size ) )
+        goto Exit;
+      parser->base_len = size;
+    }
+
+    /* Now check font format; we must see `%!PS-AdobeFont-1' */
+    /* or `%!FontType'                                       */
+    {
+      if ( size <= 16                                    ||
+           ( strncmp( (const char*)parser->base_dict,
+                      "%!PS-AdobeFont-1", 16 )        &&
+             strncmp( (const char*)parser->base_dict,
+                      "%!FontType", 10 )              )  )
+      {
+        FT_TRACE2(( "[not a Type1 font]\n" ));
+        error = FT_Err_Unknown_File_Format;
+      }
+      else
+      {
+        parser->cursor = parser->base_dict;
+        parser->limit  = parser->cursor + parser->base_len;
+      }
+    }
+
+  Exit:
+    if ( error && !parser->in_memory )
+      FREE( parser->base_dict );
+
+    return error;
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_Done_Parser( Z1_Parser*  parser )
+  {
+    FT_Memory   memory = parser->memory;
+
+
+    /* always free the private dictionary */
+    FREE( parser->private_dict );
+
+    /* free the base dictionary only when we have a disk stream */
+    if ( !parser->in_memory )
+      FREE( parser->base_dict );
+  }
+
+
+  /* return the value of an hexadecimal digit */
+  static
+  int  hexa_value( char  c )
+  {
+   unsigned int  d;
+
+
+    d = (unsigned int)( c - '0' );
+    if ( d <= 9 )
+      return (int)d;
+
+    d = (unsigned int)( c - 'a' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    d = (unsigned int)( c - 'A' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    return -1;
+  }
+
+
+  LOCAL_FUNC
+  void  Z1_Decrypt( FT_Byte*   buffer,
+                    FT_Int     length,
+                    FT_UShort  seed )
+  {
+    while ( length > 0 )
+    {
+      FT_Byte  plain;
+
+
+      plain     = ( *buffer ^ ( seed >> 8 ) );
+      seed      = ( *buffer + seed ) * 52845 + 22719;
+      *buffer++ = plain;
+      length--;
+    }
+  }
+
+
+  LOCAL_FUNC
+  FT_Error  Z1_Get_Private_Dict( Z1_Parser*  parser )
+  {
+    FT_Stream  stream = parser->stream;
+    FT_Memory  memory = parser->memory;
+    FT_Error   error  = 0;
+    FT_Long    size;
+
+
+    if ( parser->in_pfb )
+    {
+      /* in the case of the PFB format, the private dictionary can be  */
+      /* made of several segments.  We thus first read the number of   */
+      /* segments to compute the total size of the private dictionary  */
+      /* then re-read them into memory.                                */
+      FT_Long    start_pos = FILE_Pos();
+      FT_UShort  tag;
+      FT_Long    size;
+
+
+      parser->private_len = 0;
+      for (;;)
+      {
+        error = read_pfb_tag( stream, &tag, &size );
+        if ( error )
+          goto Fail;
+
+        if ( tag != 0x8002 )
+          break;
+
+        parser->private_len += size;
+
+        if ( FILE_Skip( size ) )
+          goto Fail;
+      }
+
+      /* Check that we have a private dictionary there */
+      /* and allocate private dictionary buffer        */
+      if ( parser->private_len == 0 )
+      {
+        FT_ERROR(( "Z1_Get_Private_Dict:" ));
+        FT_ERROR(( " invalid private dictionary section\n" ));
+        error = T1_Err_Invalid_File_Format;
+        goto Fail;
+      }
+
+      if ( FILE_Seek( start_pos )                             ||
+           ALLOC( parser->private_dict, parser->private_len ) )
+        goto Fail;
+
+      parser->private_len = 0;
+      for (;;)
+      {
+        error = read_pfb_tag( stream, &tag, &size );
+        if ( error || tag != 0x8002 )
+        {
+          error = FT_Err_Ok;
+          break;
+        }
+
+        if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
+          goto Fail;
+
+        parser->private_len += size;
+      }
+    }
+    else
+    {
+      /* we have already `loaded' the whole PFA font file into memory; */
+      /* if this is a memory resource, allocate a new block to hold    */
+      /* the private dict. Otherwise, simply overwrite into the base   */
+      /* dictionary block in the heap.                                 */
+
+      /* first of all, look at the `eexec' keyword */
+      FT_Byte*  cur   = parser->base_dict;
+      FT_Byte*  limit = cur + parser->base_len;
+      FT_Byte   c;
+
+
+      for (;;)
+      {
+        c = cur[0];
+        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
+                                            /* newline + 4 chars           */
+        {
+          if ( cur[1] == 'e' && cur[2] == 'x' &&
+               cur[3] == 'e' && cur[4] == 'c' )
+          {
+            cur += 6; /* we skip the newling after the `eexec' */
+
+            /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
+            /*      skip the extra \n if we find it                     */
+            if ( cur[0] == '\n' )
+              cur++;
+
+            break;
+          }
+        }
+        cur++;
+        if ( cur >= limit )
+        {
+          FT_ERROR(( "Z1_Get_Private_Dict:" ));
+          FT_ERROR(( " could not find `eexec' keyword\n" ));
+          error = T1_Err_Invalid_File_Format;
+          goto Exit;
+        }
+      }
+
+      /* now determine where to write the _encrypted_ binary private  */
+      /* dictionary.  We overwrite the base dictionary for disk-based */
+      /* resources and allocate a new block otherwise                 */
+
+      size = parser->base_len - ( cur - parser->base_dict);
+
+      if ( parser->in_memory )
+      {
+        /* note that we allocate one more byte to put a terminating `0' */
+        if ( ALLOC( parser->private_dict, size + 1 ) )
+          goto Fail;
+        parser->private_len = size;
+      }
+      else
+      {
+        parser->single_block = 1;
+        parser->private_dict = parser->base_dict;
+        parser->private_len  = size;
+        parser->base_dict    = 0;
+        parser->base_len     = 0;
+      }
+
+      /* now determine whether the private dictionary is encoded in binary */
+      /* or hexadecimal ASCII format -- decode it accordingly              */
+
+      /* we need to access the next 4 bytes (after the final \r following */
+      /* the `eexec' keyword); if they all are hexadecimal digits, then   */
+      /* we have a case of ASCII storage                                  */
+
+      if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
+             hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
+
+        /* binary encoding -- `simply' copy the private dict */
+        MEM_Copy( parser->private_dict, cur, size );
+
+      else
+      {
+        /* ASCII hexadecimal encoding */
+
+        FT_Byte*  write;
+        FT_Int    count;
+
+
+        write = parser->private_dict;
+        count = 0;
+
+        for ( ;cur < limit; cur++ )
+        {
+          int  hex1;
+
+
+          /* check for newline */
+          if ( cur[0] == '\r' || cur[0] == '\n' )
+            continue;
+
+          /* exit if we have a non-hexadecimal digit that isn't a newline */
+          hex1 = hexa_value( cur[0] );
+          if ( hex1 < 0 || cur + 1 >= limit )
+            break;
+
+          /* otherwise, store byte */
+          *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
+          count++;
+          cur++;
+        }
+
+        /* put a safeguard */
+        parser->private_len = write - parser->private_dict;
+        *write++ = 0;
+      }
+    }
+
+    /* we now decrypt the encoded binary private dictionary */
+    Z1_Decrypt( parser->private_dict, parser->private_len, 55665 );
+    parser->cursor = parser->private_dict;
+    parser->limit  = parser->cursor + parser->private_len;
+
+  Fail:
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/src/freetype/type1z/z1parse.h b/src/freetype/type1z/z1parse.h
new file mode 100644 (file)
index 0000000..d0b6a65
--- /dev/null
@@ -0,0 +1,363 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1parse.h                                                              */
+/*                                                                         */
+/*    Experimental Type 1 parser (specification).                          */
+/*                                                                         */
+/*  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 Z1PARSE_H
+#define Z1PARSE_H
+
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+  /* simple enumeration type used to identify token types */
+  typedef enum  Z1_Token_Type_
+  {
+    t1_token_none = 0,
+    t1_token_any,
+    t1_token_string,
+    t1_token_array,
+
+    /* do not remove */
+    t1_token_max
+
+  } Z1_Token_Type;
+
+
+  /* a simple structure used to identify tokens */
+  typedef struct  Z1_Token_Rec_
+  {
+    FT_Byte*       start;   /* first character of token in input stream */
+    FT_Byte*       limit;   /* first character after the token          */
+    Z1_Token_Type  type;    /* type of token..                          */
+
+  } Z1_Token_Rec;
+
+
+  /* enumeration type used to identify object fields */
+  typedef enum  Z1_Field_Type_
+  {
+    t1_field_none = 0,
+    t1_field_bool,
+    t1_field_integer,
+    t1_field_fixed,
+    t1_field_string,
+    t1_field_integer_array,
+    t1_field_fixed_array,
+
+    /* do not remove */
+    t1_field_max
+
+  } Z1_Field_Type;
+
+
+  /* structure type used to model object fields */
+  typedef struct  Z1_Field_Rec_
+  {
+    Z1_Field_Type  type;          /* type of field                        */
+    FT_UInt        offset;        /* offset of field in object            */
+    FT_UInt        size;          /* size of field in bytes               */
+    FT_UInt        array_max;     /* maximum number of elements for array */
+    FT_UInt        count_offset;  /* offset of element count for arrays   */
+    FT_Int         flag_bit;      /* bit number for field flag            */
+
+  } Z1_Field_Rec;
+
+
+#define Z1_FIELD_REF( s, f )  ( ((s*)0)->f )
+
+#define Z1_FIELD_BOOL( _ftype, _fname )                      \
+          {                                                  \
+            t1_field_bool,                                   \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname ) ),       \
+            0, 0, 0                                          \
+          }
+
+#define Z1_FIELD_NUM( _ftype, _fname )                       \
+          {                                                  \
+            t1_field_integer,                                \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname ) ),       \
+            0, 0, 0                                          \
+          }
+
+#define Z1_FIELD_FIXED( _ftype, _fname, _power )             \
+          {                                                  \
+            t1_field_fixed,                                  \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname ) ),       \
+            0, 0, 0                                          \
+          }
+
+#define Z1_FIELD_STRING( _ftype, _fname )                    \
+          {                                                  \
+            t1_field_string,                                 \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname ) ),       \
+            0, 0, 0                                          \
+          }
+
+#define Z1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax )  \
+          {                                                   \
+            t1_field_integer,                                 \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ),  \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ),     \
+            _fmax,                                            \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \
+            0                                                 \
+          }
+
+#define Z1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \
+          {                                                    \
+            t1_field_fixed,                                    \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ),   \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ),      \
+            _fmax,                                             \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ),  \
+            0                                                  \
+          }
+
+#define Z1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax )         \
+          {                                                  \
+            t1_field_integer,                                \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ),    \
+            _fmax,                                           \
+            0, 0                                             \
+          }
+
+#define Z1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax )       \
+          {                                                  \
+            t1_field_fixed,                                  \
+            (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \
+            sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ),    \
+            _fmax,                                           \
+            0, 0                                             \
+          }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    Z1_Table                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A Z1_Table is a simple object used to store an array of objects in */
+  /*    a single memory block.                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    block     :: The address in memory of the growheap's block.  This  */
+  /*                 can change between two object adds, due to the use of */
+  /*                 reallocation.                                         */
+  /*                                                                       */
+  /*    cursor    :: The current top of the grow heap within its block.    */
+  /*                                                                       */
+  /*    capacity  :: The current size of the heap block.  Increments in    */
+  /*                 1kByte blocks.                                        */
+  /*                                                                       */
+  /*    init      :: A boolean.  Set when the table has been initialized   */
+  /*                 (the table user should set this field).               */
+  /*                                                                       */
+  /*    max_elems :: The maximum number of elements in the table.          */
+  /*                                                                       */
+  /*    num_elems :: The current number of elements in the table.          */
+  /*                                                                       */
+  /*    elements  :: A table of element addresses within the block.        */
+  /*                                                                       */
+  /*    lengths   :: A table of element sizes within the block.            */
+  /*                                                                       */
+  /*    memory    :: The memory object used for memory operations          */
+  /*                 (allocation/reallocation).                            */
+  /*                                                                       */
+  typedef struct  Z1_Table_
+  {
+    FT_Byte*   block;          /* current memory block           */
+    FT_Int     cursor;         /* current cursor in memory block */
+    FT_Int     capacity;       /* current size of memory block   */
+    FT_Long    init;
+
+    FT_Int     max_elems;
+    FT_Int     num_elems;
+    FT_Byte**  elements;       /* addresses of table elements */
+    FT_Int*    lengths;        /* lengths of table elements   */
+
+    FT_Memory  memory;
+
+  } Z1_Table;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    Z1_Parser                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A Z1_Parser is an object used to parse a Type 1 fonts very         */
+  /*    quickly.                                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    stream       :: The current input stream.                          */
+  /*                                                                       */
+  /*    memory       :: The current memory object.                         */
+  /*                                                                       */
+  /*    base_dict    :: A pointer to the top-level dictionary.             */
+  /*                                                                       */
+  /*    base_len     :: The length in bytes of the top dictionary.         */
+  /*                                                                       */
+  /*    private_dict :: A pointer to the private dictionary.               */
+  /*                                                                       */
+  /*    private_len  :: The length in bytes of the private dictionary.     */
+  /*                                                                       */
+  /*    in_pfb       :: A boolean.  Indicates that we are handling a PFB   */
+  /*                    file.                                              */
+  /*                                                                       */
+  /*    in_memory    :: A boolean.  Indicates a memory-based stream.       */
+  /*                                                                       */
+  /*    single_block :: A boolean.  Indicates that the private dictionary  */
+  /*                    is stored in lieu of the base dictionary.          */
+  /*                                                                       */
+  /*    cursor       :: The current parser cursor.                         */
+  /*                                                                       */
+  /*    limit        :: The current parser limit (first byte after the     */
+  /*                    current dictionary).                               */
+  /*                                                                       */
+  /*    error        :: The current parsing error.                         */
+  /*                                                                       */
+  typedef struct  Z1_Parser_
+  {
+    FT_Stream  stream;
+    FT_Memory  memory;
+
+    FT_Byte*   base_dict;
+    FT_Int     base_len;
+
+    FT_Byte*   private_dict;
+    FT_Int     private_len;
+
+    FT_Byte    in_pfb;
+    FT_Byte    in_memory;
+    FT_Byte    single_block;
+
+    FT_Byte*   cursor;
+    FT_Byte*   limit;
+    FT_Error   error;
+
+  } Z1_Parser;
+
+
+  LOCAL_DEF
+  FT_Error  Z1_New_Table( Z1_Table*  table,
+                          FT_Int     count,
+                          FT_Memory  memory );
+
+
+  LOCAL_DEF
+  FT_Error  Z1_Add_Table( Z1_Table*  table,
+                          FT_Int     index,
+                          void*      object,
+                          FT_Int     length );
+
+#if 0
+  LOCAL_DEF
+  void  Z1_Done_Table( Z1_Table*  table );
+#endif
+
+  LOCAL_DEF
+  void  Z1_Release_Table( Z1_Table*  table );
+
+  LOCAL_DEF
+  FT_Long  Z1_ToInt( Z1_Parser*  parser );
+
+  LOCAL_DEF
+  FT_Long  Z1_ToFixed( Z1_Parser*  parser,
+                       FT_Int      power_ten );
+
+  LOCAL_DEF
+  FT_Int  Z1_ToCoordArray( Z1_Parser*  parser,
+                           FT_Int      max_coords,
+                           FT_Short*   coords );
+
+  LOCAL_DEF
+  FT_Int  Z1_ToFixedArray( Z1_Parser*  parser,
+                           FT_Int      max_values,
+                           FT_Fixed*   values,
+                           FT_Int      power_ten );
+
+#if 0
+  LOCAL_DEF
+  FT_String*  Z1_ToString( Z1_Parser*  parser );
+
+  LOCAL_DEF
+  FT_Bool  Z1_ToBool( Z1_Parser*  parser );
+#endif
+
+
+  LOCAL_DEF
+  void  Z1_Skip_Spaces( Z1_Parser*  parser );
+
+  LOCAL_DEF
+  void  Z1_ToToken( Z1_Parser*     parser,
+                    Z1_Token_Rec*  token );
+
+  LOCAL_FUNC
+  void  Z1_ToTokenArray( Z1_Parser*     parser,
+                         Z1_Token_Rec*  tokens,
+                         FT_UInt        max_tokens,
+                         FT_Int*        pnum_tokens );
+
+  LOCAL_DEF
+  FT_Error  Z1_Load_Field( Z1_Parser*           parser,
+                           const Z1_Field_Rec*  field,
+                           void**               objects,
+                           FT_UInt              max_objects,
+                           FT_ULong*            pflags );
+
+  LOCAL_DEF
+  FT_Error  Z1_Load_Field_Table( Z1_Parser*           parser,
+                                 const Z1_Field_Rec*  field,
+                                 void**               objects,
+                                 FT_UInt              max_objects,
+                                 FT_ULong*            pflags );
+
+
+  LOCAL_DEF
+  FT_Error  Z1_New_Parser( Z1_Parser*  parser,
+                           FT_Stream   stream,
+                           FT_Memory   memory );
+
+  LOCAL_DEF
+  FT_Error  Z1_Get_Private_Dict( Z1_Parser*  parser );
+
+  LOCAL_DEF
+  void  Z1_Decrypt( FT_Byte*   buffer,
+                    FT_Int     length,
+                    FT_UShort  seed );
+
+  LOCAL_DEF
+  void  Z1_Done_Parser( Z1_Parser*  parser );
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* Z1PARSE_H */
+
+
+/* END */
diff --git a/src/freetype/type1z/z1tokens.h b/src/freetype/type1z/z1tokens.h
new file mode 100644 (file)
index 0000000..73c0228
--- /dev/null
@@ -0,0 +1,132 @@
+/***************************************************************************/
+/*                                                                         */
+/*  z1tokens.h                                                             */
+/*                                                                         */
+/*    Experimental Type 1 tokenizer (specification).                       */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#undef  T1TYPE
+#define T1TYPE  T1_FontInfo
+
+  Z1_FONTINFO_STRING( "version", version )
+  Z1_FONTINFO_STRING( "Notice", notice )
+  Z1_FONTINFO_STRING( "FullName", full_name )
+  Z1_FONTINFO_STRING( "FamilyName", family_name )
+  Z1_FONTINFO_STRING( "Weight", weight )
+
+  Z1_FONTINFO_NUM   ( "ItalicAngle", italic_angle )
+  Z1_FONTINFO_BOOL  ( "isFixedPitch", is_fixed_pitch )
+  Z1_FONTINFO_NUM   ( "UnderlinePosition", underline_position )
+  Z1_FONTINFO_NUM   ( "UnderlineThickness", underline_thickness )
+
+
+#undef  T1TYPE
+#define T1TYPE  T1_Private
+
+  Z1_PRIVATE_NUM       ( "UniqueID", unique_id )
+  Z1_PRIVATE_NUM       ( "lenIV", lenIV )
+  Z1_PRIVATE_NUM       ( "LanguageGroup", language_group )
+  Z1_PRIVATE_NUM       ( "password", password )
+
+  Z1_PRIVATE_FIXED     ( "BlueScale", blue_scale )
+  Z1_PRIVATE_NUM       ( "BlueShift", blue_shift )
+  Z1_PRIVATE_NUM       ( "BlueFuzz",  blue_fuzz )
+
+  Z1_PRIVATE_NUM_TABLE ( "BlueValues", blue_values, 14, num_blue_values )
+  Z1_PRIVATE_NUM_TABLE ( "OtherBlues", other_blues, 10, num_other_blues )
+  Z1_PRIVATE_NUM_TABLE ( "FamilyBlues", family_blues, 14, num_family_blues )
+  Z1_PRIVATE_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, \
+                                             num_family_other_blues )
+
+  Z1_PRIVATE_NUM_TABLE2( "StdHW", standard_width,  1 )
+  Z1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 )
+  Z1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+  Z1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths )
+  Z1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights )
+
+
+#undef  T1TYPE
+#define T1TYPE  T1_Font
+
+  Z1_TOPDICT_NUM( "PaintType", paint_type )
+  Z1_TOPDICT_NUM( "FontType", font_type )
+  Z1_TOPDICT_NUM( "StrokeWidth", stroke_width )
+
+
+#if 0
+
+ /* define the font info dictionary parsing callbacks */
+#undef  FACE
+#define FACE  (face->type1.font_info)
+
+  PARSE_STRING( "version", version )
+  PARSE_STRING( "Notice", notice )
+  PARSE_STRING( "FullName", full_name )
+  PARSE_STRING( "FamilyName", family_name )
+  PARSE_STRING( "Weight", weight )
+
+  PARSE_INT   ( "ItalicAngle", italic_angle )
+  PARSE_BOOL  ( "isFixedPitch", is_fixed_pitch )
+  PARSE_NUM   ( "UnderlinePosition", underline_position, FT_Short )
+  PARSE_NUM   ( "UnderlineThickness", underline_thickness, FT_UShort )
+
+
+  /* define the private dict parsing callbacks */
+#undef  FACE
+#define FACE  (face->type1.private_dict)
+
+  PARSE_INT    ("UniqueID", unique_id )
+  PARSE_INT    ("lenIV", lenIV )
+
+  PARSE_COORDS ( "BlueValues", num_blues, 14, blue_values)
+  PARSE_COORDS ( "OtherBlues", num_other_blues, 10, other_blues)
+
+  PARSE_COORDS ( "FamilyBlues", num_family_blues, 14, family_blues )
+  PARSE_COORDS ( "FamilyOtherBlues", num_family_other_blues, 10,
+                                     family_other_blues )
+
+  PARSE_FIXED  ( "BlueScale", blue_scale )
+  PARSE_INT    ( "BlueShift", blue_shift )
+
+  PARSE_INT    ( "BlueFuzz", blue_fuzz )
+
+  PARSE_COORDS2( "StdHW", 1, standard_width )
+  PARSE_COORDS2( "StdVW", 1, standard_height )
+
+  PARSE_COORDS ( "StemSnapH", num_snap_widths, 12, stem_snap_widths )
+  PARSE_COORDS ( "StemSnapV", num_snap_heights, 12, stem_snap_heights )
+
+  PARSE_INT    ( "LanguageGroup", language_group )
+  PARSE_INT    ( "password", password )
+  PARSE_COORDS2( "MinFeature", 2, min_feature )
+
+
+  /* define the top-level dictionary parsing callbacks */
+#undef  FACE
+#define FACE  (face->type1)
+
+/*PARSE_STRING ( "FontName", font_name ) -- handled by special routine */
+  PARSE_NUM    ( "PaintType", paint_type, FT_Byte )
+  PARSE_NUM    ( "FontType", font_type, FT_Byte )
+  PARSE_FIXEDS2( "FontMatrix", 4, font_matrix )
+/*PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special routine */
+  PARSE_INT    ( "StrokeWidth", stroke_width )
+
+#undef FACE
+
+#endif /* 0 */
+
+
+/* END */
diff --git a/src/freetype/unix/ftsystem.c b/src/freetype/unix/ftsystem.c
new file mode 100644 (file)
index 0000000..9ecd95c
--- /dev/null
@@ -0,0 +1,306 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsystem.c                                                             */
+/*                                                                         */
+/*    Unix-specific FreeType low-level system interface (body).            */
+/*                                                                         */
+/*  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 <ftconfig.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftsystem.h>
+#include <freetype/fterrors.h>
+#include <freetype/fttypes.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+  /* memory-mapping includes and definitions                            */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sys/mman.h>
+#ifndef MAP_FILE
+#define MAP_FILE  0x00
+#endif
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The prototype for munmap() is not provided on SunOS.  This needs to   */
+  /* have a check added later to see if the GNU C library is being used.   */
+  /* If so, then this prototype is not needed.                             */
+  /*                                                                       */
+#if defined( __sun__ ) && !defined( SVR4 ) && !defined( __SVR4 )
+  extern int  munmap( caddr_t  addr,
+                      int      len );
+#endif
+
+#include <sys/stat.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       MEMORY MANAGEMENT INTERFACE                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_alloc                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory allocation function.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A pointer to the memory object.                          */
+  /*    size   :: The requested size in bytes.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    block  :: The address of newly allocated block.                    */
+  /*                                                                       */
+  static
+  void*  ft_alloc( FT_Memory  memory,
+                   long       size )
+  {
+    FT_UNUSED( memory );
+
+    return malloc( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_realloc                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory reallocation function.                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory   :: A pointer to the memory object.                        */
+  /*                                                                       */
+  /*    cur_size :: The current size of the allocated memory block.        */
+  /*                                                                       */
+  /*    new_size :: The newly requested size in bytes.                     */
+  /*                                                                       */
+  /*    block    :: The current address of the block in memory.            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the reallocated memory block.                       */
+  /*                                                                       */
+  static
+  void*  ft_realloc( FT_Memory  memory,
+                     long       cur_size,
+                     long       new_size,
+                     void*      block )
+  {
+    FT_UNUSED( memory );
+    FT_UNUSED( cur_size );
+
+    return realloc( block, new_size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_free                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory release function.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory  :: A pointer to the memory object.                         */
+  /*                                                                       */
+  /*    block   :: The address of block in memory to be freed.             */
+  /*                                                                       */
+  static
+  void  ft_free( FT_Memory  memory,
+                 void*      block )
+  {
+    FT_UNUSED( memory );
+
+    free( block );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     RESOURCE MANAGEMENT INTERFACE                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_io
+
+  /* We use the macro STREAM_FILE for convenience to extract the       */
+  /* system-specific stream handle from a given FreeType stream object */
+#define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_close_stream                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The function to close a stream.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A pointer to the stream object.                          */
+  /*                                                                       */
+  static
+  void  ft_close_stream( FT_Stream  stream )
+  {
+    munmap ( stream->descriptor.pointer, stream->size );
+        
+    stream->descriptor.pointer = NULL;
+    stream->size               = 0;
+    stream->base               = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Stream                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new stream object.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    filepathname :: The name of the stream (usually a file) to be      */
+  /*                    opened.                                            */
+  /*                                                                       */
+  /*    stream       :: A pointer to the stream object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Error )  FT_New_Stream( const char*  filepathname,
+                                             FT_Stream    stream )
+  {
+    int          file;
+    struct stat  stat_buf;
+
+
+    if ( !stream )
+      return FT_Err_Invalid_Stream_Handle;
+
+    /* open the file */
+    file = open( filepathname, O_RDONLY );
+    if ( file < 0 )
+    {
+      FT_ERROR(( "FT_New_Stream:" ));
+      FT_ERROR(( " could not open `%s'\n", filepathname ));
+      return FT_Err_Cannot_Open_Resource;
+    }
+
+    if ( fstat( file, &stat_buf ) < 0 )
+    {
+      FT_ERROR(( "FT_New_Stream:" ));
+      FT_ERROR(( " could not `fstat' file `%s'\n", filepathname ));
+      goto Fail_Map;
+    }
+      
+    stream->size = stat_buf.st_size;
+    stream->pos  = 0;
+    stream->base = mmap( NULL,
+                         stream->size,
+                         PROT_READ,
+                         MAP_FILE | MAP_PRIVATE,
+                         file,
+                         0 );
+
+    if ( (long)stream->base == -1 )
+    {
+      FT_ERROR(( "FT_New_Stream:" ));
+      FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
+      goto Fail_Map;
+    }
+
+    close( file );
+
+    stream->descriptor.pointer = stream->base;
+    stream->pathname.pointer   = (char*)filepathname;
+    
+    stream->close = ft_close_stream;
+    stream->read  = 0;
+    
+    FT_TRACE1(( "FT_New_Stream:" ));
+    FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
+                filepathname, stream->size ));
+
+    return FT_Err_Ok;
+    
+  Fail_Map:
+    close( file );
+
+    stream->base = NULL;
+    stream->size = 0;
+    stream->pos  = 0;
+    
+    return FT_Err_Cannot_Open_Stream;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Memory                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new memory object.                                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A pointer to the new memory object.  0 in case of error.           */
+  /*                                                                       */
+  FT_EXPORT_FUNC( FT_Memory )  FT_New_Memory( void )
+  {
+    FT_Memory  memory;
+    
+
+    memory = (FT_Memory)malloc( sizeof ( *memory ) );
+    if ( memory )
+    {
+      memory->user    = 0;
+      memory->alloc   = ft_alloc;
+      memory->realloc = ft_realloc;
+      memory->free    = ft_free;
+    }
+
+    return memory;
+  }
+
+
+/* END */
diff --git a/src/freetype/winfonts/module.mk b/src/freetype/winfonts/module.mk
new file mode 100644 (file)
index 0000000..5c12eb6
--- /dev/null
@@ -0,0 +1,6 @@
+make_module_list: add_windows_driver
+
+add_windows_driver:
+       $(OPEN_DRIVER)winfnt_driver_class$(CLOSE_DRIVER)
+       $(ECHO_DRIVER)winfnt    $(ECHO_DRIVER_DESC)Windows bitmap fonts with extension *.fnt or *.fon$(ECHO_DRIVER_DONE)
+
diff --git a/src/freetype/winfonts/rules.mk b/src/freetype/winfonts/rules.mk
new file mode 100644 (file)
index 0000000..8396894
--- /dev/null
@@ -0,0 +1,64 @@
+#
+# FreeType 2 Windows FNT/FON driver configuration rules
+#
+
+
+# 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.
+
+
+# Windows driver directory
+#
+FNT_DIR  := $(SRC_)winfonts
+FNT_DIR_ := $(FNT_DIR)$(SEP)
+
+
+FNT_COMPILE := $(FT_COMPILE)
+
+
+# Windows driver sources (i.e., C files)
+#
+FNT_DRV_SRC := $(FNT_DIR_)winfnt.c
+
+# Windows driver headers
+#
+FNT_DRV_H := $(FNT_DRV_SRC:%.c=%.h)
+
+
+# Windows driver object(s)
+#
+#   FNT_DRV_OBJ_M is used during `multi' builds
+#   FNT_DRV_OBJ_S is used during `single' builds
+#
+FNT_DRV_OBJ_M := $(FNT_DRV_SRC:$(FNT_DIR_)%.c=$(OBJ_)%.$O)
+FNT_DRV_OBJ_S := $(OBJ_)winfnt.$O
+
+# Windows driver source file for single build
+#
+FNT_DRV_SRC_S := $(FNT_DIR_)winfnt.c
+
+
+# Windows driver - single object
+#
+$(FNT_DRV_OBJ_S): $(FNT_DRV_SRC_S) $(FNT_DRV_SRC) $(FREETYPE_H) $(FNT_DRV_H)
+       $(FNT_COMPILE) $T$@ $(FNT_DRV_SRC_S)
+
+
+# Windows driver - multiple objects
+#
+$(OBJ_)%.$O: $(FNT_DIR_)%.c $(FREETYPE_H) $(FNT_DRV_H)
+       $(FNT_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(FNT_DRV_OBJ_S)
+DRV_OBJS_M += $(FNT_DRV_OBJ_M)
+
+# EOF
diff --git a/src/freetype/winfonts/winfnt.c b/src/freetype/winfonts/winfnt.c
new file mode 100644 (file)
index 0000000..470440a
--- /dev/null
@@ -0,0 +1,623 @@
+/***************************************************************************/
+/*                                                                         */
+/*  winfnt.c                                                               */
+/*                                                                         */
+/*    FreeType font driver for Windows FNT/FON files                       */
+/*                                                                         */
+/*  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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "winfnt.h"
+
+#else
+
+#include <winfonts/winfnt.h>
+
+#endif
+
+
+#include <freetype/fterrors.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_winfnt
+
+
+  static
+  const FT_Frame_Field  winmz_header_fields[] =
+  {
+    FT_FRAME_START( 64 ),
+    FT_FRAME_USHORT_LE ( WinMZ_Header, magic ),
+    FT_FRAME_SKIP_BYTES( 29 * 2 ),
+    FT_FRAME_ULONG_LE  ( WinMZ_Header, lfanew ),
+    FT_FRAME_END
+  };
+
+  static
+  const FT_Frame_Field  winne_header_fields[] =
+  {
+    FT_FRAME_START( 40 ),
+    FT_FRAME_USHORT_LE ( WinNE_Header, magic ),
+    FT_FRAME_SKIP_BYTES( 34 ),
+    FT_FRAME_USHORT_LE ( WinNE_Header, resource_tab_offset ),
+    FT_FRAME_USHORT_LE ( WinNE_Header, rname_tab_offset ),
+    FT_FRAME_END
+  };
+
+  static
+  const FT_Frame_Field  winfnt_header_fields[] =
+  {
+    FT_FRAME_START( 134 ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, version ),
+    FT_FRAME_ULONG_LE ( WinFNT_Header, file_size ),
+    FT_FRAME_BYTES    ( WinFNT_Header, copyright, 60 ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, file_type ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, nominal_point_size ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, vertical_resolution ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, horizontal_resolution ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, ascent ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, internal_leading ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, external_leading ),
+    FT_FRAME_BYTE     ( WinFNT_Header, italic ),
+    FT_FRAME_BYTE     ( WinFNT_Header, underline ),
+    FT_FRAME_BYTE     ( WinFNT_Header, strike_out ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, weight ),
+    FT_FRAME_BYTE     ( WinFNT_Header, charset ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, pixel_width ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, pixel_height ),
+    FT_FRAME_BYTE     ( WinFNT_Header, pitch_and_family ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, avg_width ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, max_width ),
+    FT_FRAME_BYTE     ( WinFNT_Header, first_char ),
+    FT_FRAME_BYTE     ( WinFNT_Header, last_char ),
+    FT_FRAME_BYTE     ( WinFNT_Header, default_char ),
+    FT_FRAME_BYTE     ( WinFNT_Header, break_char ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, bytes_per_row ),
+    FT_FRAME_ULONG_LE ( WinFNT_Header, device_offset ),
+    FT_FRAME_ULONG_LE ( WinFNT_Header, face_name_offset ),
+    FT_FRAME_ULONG_LE ( WinFNT_Header, bits_pointer ),
+    FT_FRAME_ULONG_LE ( WinFNT_Header, bits_offset ),
+    FT_FRAME_BYTE     ( WinFNT_Header, reserved ),
+    FT_FRAME_ULONG_LE ( WinFNT_Header, flags ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, A_space ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, B_space ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, C_space ),
+    FT_FRAME_USHORT_LE( WinFNT_Header, color_table_offset ),
+    FT_FRAME_BYTES    ( WinFNT_Header, reserved, 4 ),
+    FT_FRAME_END
+  };
+
+
+  static
+  void  fnt_done_font( FT_Stream  stream,
+                       FNT_Font*  font )
+  {
+    if ( font->fnt_frame )
+      RELEASE_Frame( font->fnt_frame );
+
+    font->fnt_size  = 0;
+    font->fnt_frame = 0;
+  }
+
+
+  static
+  FT_Error  fnt_load_font( FT_Stream  stream,
+                           FNT_Font*  font )
+  {
+    FT_Error        error;
+    WinFNT_Header*  header = &font->header;
+
+
+    /* first of all, read the FNT header */
+    if ( FILE_Seek( font->offset )                   ||
+         READ_Fields( winfnt_header_fields, header ) )
+      goto Exit;
+
+    /* check header */
+    if ( header->version != 0x200 &&
+         header->version != 0x300 )
+    {
+      FT_TRACE2(( "[not a valid FNT file]\n" ));
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    if ( header->file_type & 1 )
+    {
+      FT_TRACE2(( "can't handle vector FNT fonts\n" ));
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* small fixup -- some fonts have the `pixel_width' field set to 0 */
+    if ( header->pixel_width == 0 )
+      header->pixel_width = header->pixel_height;
+
+    /* this is a FNT file/table, we now extract its frame */
+    if ( FILE_Seek( font->offset )                           ||
+         EXTRACT_Frame( header->file_size, font->fnt_frame ) )
+      goto Exit;
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  fnt_done_fonts( FNT_Face  face )
+  {
+    FT_Memory  memory = FT_FACE(face)->memory;
+    FT_Stream  stream = FT_FACE(face)->stream;
+    FNT_Font*  cur    = face->fonts;
+    FNT_Font*  limit  = cur + face->num_fonts;
+
+
+    for ( ; cur < limit; cur++ )
+      fnt_done_font( stream, cur );
+
+    FREE( face->fonts );
+    face->num_fonts = 0;
+  }
+
+  static
+  FT_Error  fnt_get_dll_fonts( FNT_Face  face )
+  {
+    FT_Error      error;
+    FT_Stream     stream = FT_FACE(face)->stream;
+    FT_Memory     memory = FT_FACE(face)->memory;
+    WinMZ_Header  mz_header;
+
+
+    face->fonts     = 0;
+    face->num_fonts = 0;
+
+    /* does it begin with a MZ header? */
+    if ( FILE_Seek( 0 )                                 ||
+         READ_Fields( winmz_header_fields, &mz_header ) )
+      goto Exit;
+
+    error = FT_Err_Unknown_File_Format;
+    if ( mz_header.magic == WINFNT_MZ_MAGIC )
+    {
+      /* yes, now look for a NE header in the file */
+      WinNE_Header  ne_header;
+
+
+      if ( FILE_Seek( mz_header.lfanew )                  ||
+           READ_Fields( winne_header_fields, &ne_header ) )
+        goto Exit;
+
+      error = FT_Err_Unknown_File_Format;
+      if ( ne_header.magic == WINFNT_NE_MAGIC )
+      {
+        /* good, now look in the resource table for each FNT resource */
+        FT_ULong   res_offset = mz_header.lfanew +
+                                ne_header.resource_tab_offset;
+
+        FT_UShort  size_shift;
+        FT_UShort  font_count  = 0;
+        FT_ULong   font_offset = 0;
+
+
+        if ( FILE_Seek( res_offset ) ||
+             ACCESS_Frame( ne_header.rname_tab_offset -
+                           ne_header.resource_tab_offset ) )
+          goto Exit;
+
+        size_shift = GET_UShortLE();
+
+        for (;;)
+        {
+          FT_UShort  type_id, count;
+
+
+          type_id = GET_UShortLE();
+          if ( !type_id )
+            break;
+
+          count = GET_UShortLE();
+
+          if ( type_id == 0x8008 )
+          {
+            font_count  = count;
+            font_offset = FILE_Pos() + 4 + ( stream->cursor - stream->limit );
+            break;
+          }
+
+          stream->cursor += 4 + count * 12;
+        }
+        FORGET_Frame();
+
+        if ( !font_count || !font_offset )
+        {
+          FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
+          error = FT_Err_Unknown_File_Format;
+          goto Exit;
+        }
+
+        if ( FILE_Seek( font_offset )                         ||
+             ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) )
+          goto Exit;
+
+        face->num_fonts = font_count;
+
+        if ( ACCESS_Frame( (FT_Long)font_count * 12 ) )
+          goto Exit;
+
+        /* now read the offset and position of each FNT font */
+        {
+          FNT_Font*  cur   = face->fonts;
+          FNT_Font*  limit = cur + font_count;
+
+
+          for ( ; cur < limit; cur++ )
+          {
+            cur->offset     = (FT_ULong)GET_UShortLE() << size_shift;
+            cur->fnt_size   = (FT_ULong)GET_UShortLE() << size_shift;
+            cur->size_shift = size_shift;
+            stream->cursor += 8;
+          }
+        }
+        FORGET_Frame();
+
+        /* finally, try to load each font there */
+        {
+          FNT_Font*  cur   = face->fonts;
+          FNT_Font*  limit = cur + font_count;
+
+
+          for ( ; cur < limit; cur++ )
+          {
+            error = fnt_load_font( stream, cur );
+            if ( error )
+              goto Fail;
+          }
+        }
+      }
+    }
+
+  Fail:
+    if ( error )
+      fnt_done_fonts( face );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  FNT_Done_Face( FNT_Face  face )
+  {
+    FT_Memory  memory = FT_FACE_MEMORY( face );
+
+
+    fnt_done_fonts( face );
+
+    FREE( face->root.available_sizes );
+    face->root.num_fixed_sizes = 0;
+  }
+
+
+  static
+  FT_Error  FNT_Init_Face( FT_Stream      stream,
+                           FNT_Face       face,
+                           FT_Int         face_index,
+                           FT_Int         num_params,
+                           FT_Parameter*  params )
+  {
+    FT_Error   error;
+    FT_Memory  memory = FT_FACE_MEMORY( face );
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+
+
+    /* try to load several fonts from a DLL */
+    error = fnt_get_dll_fonts( face );
+    if ( error )
+    {
+      /* this didn't work, now try to load a single FNT font */
+      FT_Memory  memory = FT_FACE_MEMORY( face );
+      FNT_Font*  font;
+
+      if ( ALLOC( face->fonts, sizeof ( *face->fonts ) ) )
+        goto Exit;
+
+      face->num_fonts = 1;
+      font            = face->fonts;
+
+      font->offset   = 0;
+      font->fnt_size = stream->size;
+
+      error = fnt_load_font( stream, font );
+      if ( error )
+        goto Fail;
+    }
+
+    /* all right, one or more fonts were loaded; we now need to */
+    /* fill the root FT_Face fields with relevant information   */
+    {
+      FT_Face    root  = FT_FACE( face );
+      FNT_Font*  fonts = face->fonts;
+      FNT_Font*  limit = fonts + face->num_fonts;
+      FNT_Font*  cur;
+
+
+      root->num_faces  = 1;
+      root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
+                         FT_FACE_FLAG_HORIZONTAL;
+
+      if ( fonts->header.avg_width == fonts->header.max_width )
+        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      if ( fonts->header.italic )
+        root->style_flags |= FT_STYLE_FLAG_ITALIC;
+
+      if ( fonts->header.weight >= 800 )
+        root->style_flags |= FT_STYLE_FLAG_BOLD;
+
+      /* Setup the `fixed_sizes' array */
+      if ( ALLOC_ARRAY( root->available_sizes, face->num_fonts,
+                        FT_Bitmap_Size ) )
+        goto Fail;
+
+      root->num_fixed_sizes = face->num_fonts;
+
+      {
+        FT_Bitmap_Size*  size = root->available_sizes;
+
+
+        for ( cur = fonts; cur < limit; cur++, size++ )
+        {
+          size->width  = cur->header.pixel_width;
+          size->height = cur->header.pixel_height;
+        }
+      }
+
+      /* Setup the `charmaps' array */
+      root->charmaps     = &face->charmap_handle;
+      root->num_charmaps = 1;
+
+      face->charmap.encoding    = ft_encoding_unicode;
+      face->charmap.platform_id = 3;
+      face->charmap.encoding_id = 1;
+      face->charmap.face        = root;
+
+      face->charmap_handle = &face->charmap;
+
+      root->charmap = face->charmap_handle;
+
+      /* setup remaining flags */
+      root->num_glyphs = fonts->header.last_char -
+                         fonts->header.first_char + 1;
+
+      root->family_name = (FT_String*)fonts->fnt_frame +
+                          fonts->header.face_name_offset;
+      root->style_name  = "Regular";
+
+      if ( root->style_flags & FT_STYLE_FLAG_BOLD )
+      {
+        if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+          root->style_name = "Bold Italic";
+        else
+          root->style_name = "Bold";
+      }
+      else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+        root->style_name = "Italic";
+    }
+
+  Fail:
+    if ( error )
+      FNT_Done_Face( face );
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  FT_Error  FNT_Set_Pixel_Size( FNT_Size  size )
+  {
+    /* look up a font corresponding to the current pixel size */
+    FNT_Face   face  = (FNT_Face)FT_SIZE_FACE( size );
+    FNT_Font*  cur   = face->fonts;
+    FNT_Font*  limit = cur + face->num_fonts;
+
+
+    size->font = 0;
+    for ( ; cur < limit; cur++ )
+    {
+      /* we only compare the character height, as fonts used some strange */
+      /* values                                                           */
+      if ( cur->header.pixel_height == size->root.metrics.y_ppem )
+      {
+        size->font = cur;
+        
+        size->root.metrics.ascender  = cur->header.ascent * 64;
+        size->root.metrics.descender = ( cur->header.pixel_height -
+                                           cur->header.ascent ) * 64;
+        size->root.metrics.height    = cur->header.pixel_height * 64;
+        break;
+      }
+    }
+
+    return ( size->font ? FT_Err_Ok : FT_Err_Invalid_Argument );
+  }
+
+
+  static
+  FT_UInt  FNT_Get_Char_Index( FT_CharMap  charmap,
+                               FT_ULong    char_code )
+  {
+    FT_UInt  result = char_code;
+
+
+    if ( charmap )
+    {
+      FNT_Font*  font  = ((FNT_Face)charmap->face)->fonts;
+      FT_UInt    first = font->header.first_char;
+      FT_UInt    count = font->header.last_char - first + 1;
+
+
+      char_code -= first;
+      if ( char_code < count )
+        result = char_code + 1;
+      else
+        result = 0;
+    }
+
+    return result;
+  }
+
+
+  static
+  FT_Error  FNT_Load_Glyph( FT_GlyphSlot  slot,
+                            FNT_Size      size,
+                            FT_UInt       glyph_index,
+                            FT_Int        load_flags )
+  {
+    FNT_Font*   font  = size->font;
+    FT_Error    error = 0;
+    FT_Byte*    p;
+    FT_Int      len;
+    FT_Bitmap*  bitmap = &slot->bitmap;
+    FT_ULong    offset;
+    FT_Bool     new_format;
+
+    FT_UNUSED( slot );
+    FT_UNUSED( load_flags );
+
+
+    if ( !font )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    if ( glyph_index > 0 )
+      glyph_index--;
+    else
+      glyph_index = font->header.default_char - font->header.first_char;
+      
+    new_format = font->header.version == 0x300;
+    len        = new_format ? 6 : 4;
+
+    /* jump to glyph entry */
+    p = font->fnt_frame + 118 + len * glyph_index;
+
+    bitmap->width = NEXT_ShortLE(p);
+
+    if ( new_format )
+      offset = NEXT_ULongLE(p);
+    else
+      offset = NEXT_UShortLE(p);
+
+    /* jump to glyph data */
+    p = font->fnt_frame + /* font->header.bits_offset */ + offset;
+
+    /* allocate and build bitmap */
+    {
+      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
+      FT_Int     pitch  = ( bitmap->width + 7 ) >> 3;
+      FT_Byte*   column;
+      FT_Byte*   write;
+
+
+      bitmap->pitch      = pitch;
+      bitmap->rows       = font->header.pixel_height;
+      bitmap->pixel_mode = ft_pixel_mode_mono;
+
+      if ( ALLOC( bitmap->buffer, pitch * bitmap->rows ) )
+        goto Exit;
+
+      column = (FT_Byte*)bitmap->buffer;
+
+      for ( ; pitch > 0; pitch--, column++ )
+      {
+        FT_Byte*  limit = p + bitmap->rows;
+
+
+        for ( write = column; p < limit; p++, write += bitmap->pitch )
+          write[0] = p[0];
+      }
+    }
+
+    slot->flags       = ft_glyph_own_bitmap;
+    slot->bitmap_left = 0;
+    slot->bitmap_top  = font->header.ascent;
+    slot->format      = ft_glyph_format_bitmap;
+
+    /* now set up metrics */
+    slot->metrics.horiAdvance  = bitmap->width << 6;
+    slot->metrics.horiBearingX = 0;
+    slot->metrics.horiBearingY = slot->bitmap_top << 6;
+
+    slot->linearHoriAdvance    = (FT_Fixed)bitmap->width << 16;
+
+  Exit:
+    return error;
+  }
+
+
+  const FT_Driver_Class  winfnt_driver_class =
+  {
+    {
+      ft_module_font_driver,
+      sizeof ( FT_DriverRec ),
+
+      "winfonts",
+      0x10000L,
+      0x20000L,
+
+      0,
+
+      (FT_Module_Constructor)0,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    sizeof( FNT_FaceRec ),
+    sizeof( FNT_SizeRec ),
+    sizeof( FT_GlyphSlotRec ),
+
+    (FTDriver_initFace)     FNT_Init_Face,
+    (FTDriver_doneFace)     FNT_Done_Face,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) FNT_Set_Pixel_Size,
+    (FTDriver_setPixelSizes)FNT_Set_Pixel_Size,
+
+    (FTDriver_loadGlyph)    FNT_Load_Glyph,
+    (FTDriver_getCharIndex) FNT_Get_Char_Index,
+
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+    (FTDriver_getAdvances)  0
+  };
+
+
+/* END */
diff --git a/src/freetype/winfonts/winfnt.h b/src/freetype/winfonts/winfnt.h
new file mode 100644 (file)
index 0000000..eaf308b
--- /dev/null
@@ -0,0 +1,150 @@
+/***************************************************************************/
+/*                                                                         */
+/*  winfnt.h                                                               */
+/*                                                                         */
+/*    FreeType font driver for Windows FNT/FON files                       */
+/*                                                                         */
+/*  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 WINFNT_H
+#define WINFNT_H
+
+#include <freetype/internal/ftdriver.h>
+
+
+  typedef struct  WinMZ_Header_
+  {
+    FT_UShort  magic;
+    /* skipped content */
+    FT_UShort  lfanew;
+
+  } WinMZ_Header;
+
+
+  typedef struct  WinNE_Header_
+  {
+    FT_UShort  magic;
+    /* skipped content */
+    FT_UShort  resource_tab_offset;
+    FT_UShort  rname_tab_offset;
+
+  } WinNE_Header;
+
+
+  typedef struct  WinNameInfo_
+  {
+    FT_UShort  offset;
+    FT_UShort  length;
+    FT_UShort  flags;
+    FT_UShort  id;
+    FT_UShort  handle;
+    FT_UShort  usage;
+
+  } WinNameInfo;
+
+
+  typedef struct  WinResourceInfo_
+  {
+    FT_UShort  type_id;
+    FT_UShort  count;
+
+  } WinResourceInfo;
+
+
+#define  WINFNT_MZ_MAGIC  0x5A4D
+#define  WINFNT_NE_MAGIC  0x454E
+
+
+  typedef struct  WinFNT_Header_
+  {
+    FT_UShort  version;
+    FT_ULong   file_size;
+    FT_Byte    copyright[60];
+    FT_UShort  file_type;
+    FT_UShort  nominal_point_size;
+    FT_UShort  vertical_resolution;
+    FT_UShort  horizontal_resolution;
+    FT_UShort  ascent;
+    FT_UShort  internal_leading;
+    FT_UShort  external_leading;
+    FT_Byte    italic;
+    FT_Byte    underline;
+    FT_Byte    strike_out;
+    FT_UShort  weight;
+    FT_Byte    charset;
+    FT_UShort  pixel_width;
+    FT_UShort  pixel_height;
+    FT_Byte    pitch_and_family;
+    FT_UShort  avg_width;
+    FT_UShort  max_width;
+    FT_Byte    first_char;
+    FT_Byte    last_char;
+    FT_Byte    default_char;
+    FT_Byte    break_char;
+    FT_UShort  bytes_per_row;
+    FT_ULong   device_offset;
+    FT_ULong   face_name_offset;
+    FT_ULong   bits_pointer;
+    FT_ULong   bits_offset;
+    FT_Byte    reserved;
+    FT_ULong   flags;
+    FT_UShort  A_space;
+    FT_UShort  B_space;
+    FT_UShort  C_space;
+    FT_UShort  color_table_offset;
+    FT_Byte    reserved2[4];
+
+  } WinFNT_Header;
+
+
+  typedef struct  FNT_Font_
+  {
+    FT_ULong       offset;
+    FT_Int         size_shift;
+
+    WinFNT_Header  header;
+
+    FT_Byte*       fnt_frame;
+    FT_ULong       fnt_size;
+
+  } FNT_Font;
+
+
+  typedef struct  FNT_SizeRec_
+  {
+    FT_SizeRec  root;
+    FNT_Font*   font;
+
+  } FNT_SizeRec, *FNT_Size;
+
+
+  typedef struct  FNT_FaceRec_
+  {
+    FT_FaceRec     root;
+
+    FT_UInt        num_fonts;
+    FNT_Font*      fonts;
+
+    FT_CharMap     charmap_handle;
+    FT_CharMapRec  charmap;  /* a single charmap per face */
+
+  } FNT_FaceRec, *FNT_Face;
+
+
+  FT_EXPORT_VAR( const FT_Driver_Class )  winfnt_driver_class;
+
+
+#endif /* WINFNT_H */
+
+
+/* END */