Module Name:    xsrc
Committed By:   maya
Date:           Wed May  9 07:21:08 UTC 2018

Modified Files:
        xsrc/external/mit/freetype/dist/builds/unix: freetype-config.in
        xsrc/external/mit/freetype/dist/src/cff: cffload.c
        xsrc/external/mit/freetype/dist/src/gzip: ftgzip.c
        xsrc/external/mit/freetype/dist/src/lzw: ftzopen.c
        xsrc/external/mit/freetype/dist/src/sfnt: ttcmap.c
        xsrc/external/mit/freetype/dist/src/smooth: ftsmooth.c
Removed Files:
        xsrc/external/mit/freetype/dist/builds: newline
        xsrc/external/mit/freetype/dist/docs: VERSION.DLL
        xsrc/external/mit/freetype/dist/src/cff: cf2arrst.c cf2arrst.h
            cf2blues.c cf2blues.h cf2error.c cf2error.h cf2fixed.h cf2font.c
            cf2font.h cf2ft.c cf2ft.h cf2glue.h cf2hints.c cf2hints.h
            cf2intrp.c cf2intrp.h cf2read.c cf2read.h cf2stack.c cf2stack.h
            cf2types.h cfftypes.h
        xsrc/external/mit/freetype/dist/src/gzip: zconf.h

Log Message:
Merge freetype 2.9.1


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.1 -r0 xsrc/external/mit/freetype/dist/builds/newline
cvs rdiff -u -r1.8 -r1.9 \
    xsrc/external/mit/freetype/dist/builds/unix/freetype-config.in
cvs rdiff -u -r1.1.1.10 -r0 xsrc/external/mit/freetype/dist/docs/VERSION.DLL
cvs rdiff -u -r1.1.1.4 -r0 xsrc/external/mit/freetype/dist/src/cff/cf2arrst.c \
    xsrc/external/mit/freetype/dist/src/cff/cf2font.h
cvs rdiff -u -r1.1.1.2 -r0 xsrc/external/mit/freetype/dist/src/cff/cf2arrst.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2blues.c \
    xsrc/external/mit/freetype/dist/src/cff/cf2blues.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2error.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2glue.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2intrp.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2read.c \
    xsrc/external/mit/freetype/dist/src/cff/cf2read.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2stack.c \
    xsrc/external/mit/freetype/dist/src/cff/cf2stack.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2types.h
cvs rdiff -u -r1.1.1.1 -r0 xsrc/external/mit/freetype/dist/src/cff/cf2error.c
cvs rdiff -u -r1.1.1.3 -r0 xsrc/external/mit/freetype/dist/src/cff/cf2fixed.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2font.c \
    xsrc/external/mit/freetype/dist/src/cff/cf2ft.h \
    xsrc/external/mit/freetype/dist/src/cff/cf2hints.h
cvs rdiff -u -r1.1.1.5 -r0 xsrc/external/mit/freetype/dist/src/cff/cf2ft.c \
    xsrc/external/mit/freetype/dist/src/cff/cf2hints.c \
    xsrc/external/mit/freetype/dist/src/cff/cf2intrp.c
cvs rdiff -u -r1.8 -r1.9 xsrc/external/mit/freetype/dist/src/cff/cffload.c
cvs rdiff -u -r1.1.1.6 -r0 xsrc/external/mit/freetype/dist/src/cff/cfftypes.h
cvs rdiff -u -r1.10 -r1.11 xsrc/external/mit/freetype/dist/src/gzip/ftgzip.c
cvs rdiff -u -r1.1.1.2 -r0 xsrc/external/mit/freetype/dist/src/gzip/zconf.h
cvs rdiff -u -r1.7 -r1.8 xsrc/external/mit/freetype/dist/src/lzw/ftzopen.c
cvs rdiff -u -r1.8 -r1.9 xsrc/external/mit/freetype/dist/src/sfnt/ttcmap.c
cvs rdiff -u -r1.9 -r1.10 \
    xsrc/external/mit/freetype/dist/src/smooth/ftsmooth.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/external/mit/freetype/dist/builds/unix/freetype-config.in
diff -u xsrc/external/mit/freetype/dist/builds/unix/freetype-config.in:1.8 xsrc/external/mit/freetype/dist/builds/unix/freetype-config.in:1.9
--- xsrc/external/mit/freetype/dist/builds/unix/freetype-config.in:1.8	Mon May 16 22:18:38 2016
+++ xsrc/external/mit/freetype/dist/builds/unix/freetype-config.in	Wed May  9 07:21:07 2018
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# Copyright 2000-2016 by
+# Copyright 2000-2018 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -12,13 +12,53 @@
 LC_ALL=C
 export LC_ALL
 
-prefix="%prefix%"
-exec_prefix="%exec_prefix%"
-exec_prefix_set="no"
-includedir="%includedir%"
-libdir="%libdir%"
-enable_shared="%build_libtool_libs%"
-hardcode_libdir_flag_spec=%hardcode_libdir_flag_spec%
+# if `pkg-config' is available, use values from `freetype2.pc'
+%PKG_CONFIG% --atleast-pkgconfig-version 0.24 >/dev/null 2>&1
+if test $? -eq 0 ; then
+  # note that option `--variable' is not affected by the
+  # PKG_CONFIG_SYSROOT_DIR environment variable
+  if test "x$SYSROOT" != "x" ; then
+    PKG_CONFIG_SYSROOT_DIR="$SYSROOT"
+    export PKG_CONFIG_SYSROOT_DIR
+  fi
+
+  prefix=`%PKG_CONFIG% --variable prefix freetype2`
+  exec_prefix=`%PKG_CONFIG% --variable exec_prefix freetype2`
+
+  includedir=`%PKG_CONFIG% --variable includedir freetype2`
+  libdir=`%PKG_CONFIG% --variable libdir freetype2`
+
+  version=`%PKG_CONFIG% --modversion freetype2`
+
+  cflags=`%PKG_CONFIG% --cflags freetype2`
+  dynamic_libs=`%PKG_CONFIG% --libs freetype2`
+  static_libs=`%PKG_CONFIG% --static --libs freetype2`
+else
+  prefix="%prefix%"
+  exec_prefix="%exec_prefix%"
+
+  includedir="%includedir%"
+  libdir="%libdir%"
+
+  version=%ft_version%
+
+  cflags="-I${SYSROOT}$includedir/freetype2"
+  dynamic_libs="-lfreetype"
+  static_libs="%LIBSSTATIC_CONFIG%"
+  if test "${SYSROOT}$libdir" != "/usr/lib"   &&
+     test "${SYSROOT}$libdir" != "/usr/lib64" ; then
+    libs_L="-L${SYSROOT}$libdir"
+  fi
+fi
+
+orig_prefix=$prefix
+orig_exec_prefix=$exec_prefix
+
+orig_includedir=$includedir
+orig_libdir=$libdir
+
+include_suffix=`echo $includedir | sed "s|$prefix||"`
+lib_suffix=`echo $libdir | sed "s|$exec_prefix||"`
 
 usage()
 {
@@ -41,14 +81,17 @@ Options:
                          library
   --static               make command line options display flags
                          for static linking
+  --help                 display this help and exit
 EOF
   exit $1
 }
 
+
 if test $# -eq 0 ; then
   usage 1 1>&2
 fi
 
+
 while test $# -gt 0 ; do
   case "$1" in
   -*=*)
@@ -76,8 +119,8 @@ while test $# -gt 0 ; do
     echo_exec_prefix=yes
     ;;
   --version)
-    echo %ft_version%
-    exit 0
+    echo_version=yes
+    break
     ;;
   --ftversion)
     echo_ft_version=yes
@@ -94,6 +137,9 @@ while test $# -gt 0 ; do
   --static)
     show_static=yes
     ;;
+  --help)
+    usage 0
+    ;;
   *)
     usage 1 1>&2
     ;;
@@ -101,12 +147,27 @@ while test $# -gt 0 ; do
   shift
 done
 
+
 if test "$local_prefix" = "yes" ; then
   if test "$exec_prefix_set" != "yes" ; then
     exec_prefix=$prefix
   fi
 fi
 
+if test "$local_prefix" = "yes" ; then
+  includedir=${prefix}${include_suffix}
+  if test "$exec_prefix_set" = "yes" ; then
+    libdir=${exec_prefix}${lib_suffix}
+  else
+    libdir=${prefix}${lib_suffix}
+  fi
+fi
+
+
+if test "$echo_version" = "yes" ; then
+  echo $version
+fi
+
 if test "$echo_prefix" = "yes" ; then
   echo ${SYSROOT}$prefix
 fi
@@ -115,15 +176,6 @@ if test "$echo_exec_prefix" = "yes" ; th
   echo ${SYSROOT}$exec_prefix
 fi
 
-if test "$exec_prefix_set" = "yes" ; then
-  libdir=$exec_prefix/lib
-else
-  if test "$local_prefix" = "yes" ; then
-    includedir=$prefix/include
-    libdir=$prefix/lib
-  fi
-fi
-
 if test "$echo_ft_version" = "yes" ; then
   major=`grep define ${SYSROOT}$includedir/freetype2/freetype/freetype.h \
          | grep FREETYPE_MAJOR \
@@ -138,30 +190,20 @@ if test "$echo_ft_version" = "yes" ; the
 fi
 
 if test "$echo_cflags" = "yes" ; then
-  echo -I${SYSROOT}$includedir/freetype2
+  echo $cflags | sed "s|$orig_includedir/freetype2|$includedir/freetype2|"
 fi
 
 if test "$echo_libs" = "yes" ; then
-  rpath=
-  if test "$enable_shared" = "yes" ; then
-    eval "rpath=\"$hardcode_libdir_flag_spec\""
-  fi
-  libs="-lfreetype"
-  staticlibs="%LIBSSTATIC_CONFIG%"
   if test "$show_static" = "yes" ; then
-    libs="$staticlibs"
-  fi
-  if test "${SYSROOT}$libdir" != "/usr/lib"  &&
-     test "${SYSROOT}$libdir" != "/usr/lib64"; then
-    echo -L${SYSROOT}$libdir $libs $rpath
+    libs="$libs_L $static_libs"
   else
-    echo $libs $rpath
+    libs="$libs_L $dynamic_libs"
   fi
+  echo $libs | sed "s|$orig_libdir|$libdir|"
 fi
 
 if test "$echo_libtool" = "yes" ; then
-  convlib="libfreetype.la"
-  echo ${SYSROOT}$libdir/$convlib
+  echo ${SYSROOT}$libdir/libfreetype.la
 fi
 
 # EOF

Index: xsrc/external/mit/freetype/dist/src/cff/cffload.c
diff -u xsrc/external/mit/freetype/dist/src/cff/cffload.c:1.8 xsrc/external/mit/freetype/dist/src/cff/cffload.c:1.9
--- xsrc/external/mit/freetype/dist/src/cff/cffload.c:1.8	Mon May 16 22:18:39 2016
+++ xsrc/external/mit/freetype/dist/src/cff/cffload.c	Wed May  9 07:21:07 2018
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType and CFF data/program tables loader (body).                  */
 /*                                                                         */
-/*  Copyright 1996-2016 by                                                 */
+/*  Copyright 1996-2018 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,6 +22,12 @@
 #include FT_INTERNAL_STREAM_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_MULTIPLE_MASTERS_H
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#endif
 
 #include "cffload.h"
 #include "cffparse.h"
@@ -29,6 +35,9 @@
 #include "cfferrs.h"
 
 
+#define FT_FIXED_ONE  ( (FT_Fixed)0x10000 )
+
+
 #if 1
 
   static const FT_UShort  cff_isoadobe_charset[229] =
@@ -225,19 +234,33 @@
   static FT_Error
   cff_index_init( CFF_Index  idx,
                   FT_Stream  stream,
-                  FT_Bool    load )
+                  FT_Bool    load,
+                  FT_Bool    cff2 )
   {
     FT_Error   error;
     FT_Memory  memory = stream->memory;
-    FT_UShort  count;
+    FT_UInt    count;
 
 
-    FT_MEM_ZERO( idx, sizeof ( *idx ) );
+    FT_ZERO( idx );
 
     idx->stream = stream;
     idx->start  = FT_STREAM_POS();
-    if ( !FT_READ_USHORT( count ) &&
-         count > 0                )
+
+    if ( cff2 )
+    {
+      if ( FT_READ_ULONG( count ) )
+        goto Exit;
+      idx->hdr_size = 5;
+    }
+    else
+    {
+      if ( FT_READ_USHORT( count ) )
+        goto Exit;
+      idx->hdr_size = 3;
+    }
+
+    if ( count > 0 )
     {
       FT_Byte   offsize;
       FT_ULong  size;
@@ -258,7 +281,7 @@
       idx->off_size = offsize;
       size          = (FT_ULong)( count + 1 ) * offsize;
 
-      idx->data_offset = idx->start + 3 + size;
+      idx->data_offset = idx->start + idx->hdr_size + size;
 
       if ( FT_STREAM_SKIP( size - offsize ) )
         goto Exit;
@@ -310,7 +333,7 @@
         FT_FRAME_RELEASE( idx->bytes );
 
       FT_FREE( idx->offsets );
-      FT_MEM_ZERO( idx, sizeof ( *idx ) );
+      FT_ZERO( idx );
     }
   }
 
@@ -323,7 +346,7 @@
     FT_Memory  memory = stream->memory;
 
 
-    if ( idx->count > 0 && idx->offsets == NULL )
+    if ( idx->count > 0 && !idx->offsets )
     {
       FT_Byte    offsize = idx->off_size;
       FT_ULong   data_size;
@@ -335,7 +358,7 @@
       data_size = (FT_ULong)( idx->count + 1 ) * offsize;
 
       if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
-           FT_STREAM_SEEK( idx->start + 3 )             ||
+           FT_STREAM_SEEK( idx->start + idx->hdr_size ) ||
            FT_FRAME_ENTER( data_size )                  )
         goto Exit;
 
@@ -382,28 +405,31 @@
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
                           FT_Byte***  table,
-                          FT_Byte**   pool )
+                          FT_Byte**   pool,
+                          FT_ULong*   pool_size )
   {
     FT_Error   error     = FT_Err_Ok;
     FT_Memory  memory    = idx->stream->memory;
 
     FT_Byte**  t         = NULL;
     FT_Byte*   new_bytes = NULL;
+    FT_ULong   new_size;
 
 
     *table = NULL;
 
-    if ( idx->offsets == NULL )
+    if ( !idx->offsets )
     {
       error = cff_index_load_offsets( idx );
       if ( error )
         goto Exit;
     }
 
-    if ( idx->count > 0                                        &&
-         !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
-         ( !pool || !FT_ALLOC( new_bytes,
-                               idx->data_size + idx->count ) ) )
+    new_size = idx->data_size + idx->count;
+
+    if ( idx->count > 0                                &&
+         !FT_NEW_ARRAY( t, idx->count + 1 )            &&
+         ( !pool || !FT_ALLOC( new_bytes, new_size ) ) )
     {
       FT_ULong  n, cur_offset;
       FT_ULong  extra = 0;
@@ -459,6 +485,8 @@
 
       if ( pool )
         *pool = new_bytes;
+      if ( pool_size )
+        *pool_size = new_size;
     }
 
   Exit:
@@ -488,7 +516,7 @@
         FT_ULong  pos = element * idx->off_size;
 
 
-        if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
+        if ( FT_STREAM_SEEK( idx->start + idx->hdr_size + pos ) )
           goto Exit;
 
         off1 = cff_index_read_offset( idx, &error );
@@ -584,20 +612,26 @@
                       FT_UInt   element )
   {
     CFF_Index   idx = &font->name_index;
-    FT_Memory   memory = idx->stream->memory;
+    FT_Memory   memory;
     FT_Byte*    bytes;
     FT_ULong    byte_len;
     FT_Error    error;
     FT_String*  name = 0;
 
 
+    if ( !idx->stream )  /* CFF2 does not include a name index */
+      goto Exit;
+
+    memory = idx->stream->memory;
+
     error = cff_index_access_element( idx, element, &bytes, &byte_len );
     if ( error )
       goto Exit;
 
     if ( !FT_ALLOC( name, byte_len + 1 ) )
     {
-      FT_MEM_COPY( name, bytes, byte_len );
+      if ( byte_len )
+        FT_MEM_COPY( name, bytes, byte_len );
       name[byte_len] = 0;
     }
     cff_index_forget_element( idx, &bytes );
@@ -719,6 +753,11 @@
     FT_Byte  fd = 0;
 
 
+    /* if there is no FDSelect, return zero               */
+    /* Note: CFF2 with just one Font Dict has no FDSelect */
+    if ( !fdselect->data )
+      goto Exit;
+
     switch ( fdselect->format )
     {
     case 0:
@@ -771,6 +810,7 @@
       ;
     }
 
+  Exit:
     return fd;
   }
 
@@ -809,7 +849,7 @@
     /* When multiple GIDs map to the same CID, we choose the lowest */
     /* GID.  This is not described in any spec, but it matches the  */
     /* behaviour of recent Acroread versions.                       */
-    for ( j = (FT_Long)num_glyphs - 1; j >= 0 ; j-- )
+    for ( j = (FT_Long)num_glyphs - 1; j >= 0; j-- )
       charset->cids[charset->sids[j]] = (FT_UShort)j;
 
     charset->max_cid    = max_cid;
@@ -871,8 +911,8 @@
     FT_UShort  glyph_sid;
 
 
-    /* If the the offset is greater than 2, we have to parse the */
-    /* charset table.                                            */
+    /* If the offset is greater than 2, we have to parse the charset */
+    /* table.                                                        */
     if ( offset > 2 )
     {
       FT_UInt  j;
@@ -1049,6 +1089,523 @@
 
 
   static void
+  cff_vstore_done( CFF_VStoreRec*  vstore,
+                   FT_Memory       memory )
+  {
+    FT_UInt  i;
+
+
+    /* free regionList and axisLists */
+    if ( vstore->varRegionList )
+    {
+      for ( i = 0; i < vstore->regionCount; i++ )
+        FT_FREE( vstore->varRegionList[i].axisList );
+    }
+    FT_FREE( vstore->varRegionList );
+
+    /* free varData and indices */
+    if ( vstore->varData )
+    {
+      for ( i = 0; i < vstore->dataCount; i++ )
+        FT_FREE( vstore->varData[i].regionIndices );
+    }
+    FT_FREE( vstore->varData );
+  }
+
+
+  /* convert 2.14 to Fixed */
+  #define FT_fdot14ToFixed( x )  ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
+
+
+  static FT_Error
+  cff_vstore_load( CFF_VStoreRec*  vstore,
+                   FT_Stream       stream,
+                   FT_ULong        base_offset,
+                   FT_ULong        offset )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error  = FT_ERR( Invalid_File_Format );
+
+    FT_ULong*  dataOffsetArray = NULL;
+    FT_UInt    i, j;
+
+
+    /* no offset means no vstore to parse */
+    if ( offset )
+    {
+      FT_UInt   vsOffset;
+      FT_UInt   format;
+      FT_ULong  regionListOffset;
+
+
+      /* we need to parse the table to determine its size; */
+      /* skip table length                                 */
+      if ( FT_STREAM_SEEK( base_offset + offset ) ||
+           FT_STREAM_SKIP( 2 )                    )
+        goto Exit;
+
+      /* actual variation store begins after the length */
+      vsOffset = FT_STREAM_POS();
+
+      /* check the header */
+      if ( FT_READ_USHORT( format ) )
+        goto Exit;
+      if ( format != 1 )
+      {
+        error = FT_THROW( Invalid_File_Format );
+        goto Exit;
+      }
+
+      /* read top level fields */
+      if ( FT_READ_ULONG( regionListOffset )   ||
+           FT_READ_USHORT( vstore->dataCount ) )
+        goto Exit;
+
+      /* make temporary copy of item variation data offsets; */
+      /* we'll parse region list first, then come back       */
+      if ( FT_NEW_ARRAY( dataOffsetArray, vstore->dataCount ) )
+        goto Exit;
+
+      for ( i = 0; i < vstore->dataCount; i++ )
+      {
+        if ( FT_READ_ULONG( dataOffsetArray[i] ) )
+          goto Exit;
+      }
+
+      /* parse regionList and axisLists */
+      if ( FT_STREAM_SEEK( vsOffset + regionListOffset ) ||
+           FT_READ_USHORT( vstore->axisCount )           ||
+           FT_READ_USHORT( vstore->regionCount )         )
+        goto Exit;
+
+      if ( FT_NEW_ARRAY( vstore->varRegionList, vstore->regionCount ) )
+        goto Exit;
+
+      for ( i = 0; i < vstore->regionCount; i++ )
+      {
+        CFF_VarRegion*  region = &vstore->varRegionList[i];
+
+
+        if ( FT_NEW_ARRAY( region->axisList, vstore->axisCount ) )
+          goto Exit;
+
+        for ( j = 0; j < vstore->axisCount; j++ )
+        {
+          CFF_AxisCoords*  axis = &region->axisList[j];
+
+          FT_Int16  start14, peak14, end14;
+
+
+          if ( FT_READ_SHORT( start14 ) ||
+               FT_READ_SHORT( peak14 )  ||
+               FT_READ_SHORT( end14 )   )
+            goto Exit;
+
+          axis->startCoord = FT_fdot14ToFixed( start14 );
+          axis->peakCoord  = FT_fdot14ToFixed( peak14 );
+          axis->endCoord   = FT_fdot14ToFixed( end14 );
+        }
+      }
+
+      /* use dataOffsetArray now to parse varData items */
+      if ( FT_NEW_ARRAY( vstore->varData, vstore->dataCount ) )
+        goto Exit;
+
+      for ( i = 0; i < vstore->dataCount; i++ )
+      {
+        CFF_VarData*  data = &vstore->varData[i];
+
+
+        if ( FT_STREAM_SEEK( vsOffset + dataOffsetArray[i] ) )
+          goto Exit;
+
+        /* ignore `itemCount' and `shortDeltaCount' */
+        /* because CFF2 has no delta sets           */
+        if ( FT_STREAM_SKIP( 4 ) )
+          goto Exit;
+
+        /* Note: just record values; consistency is checked later    */
+        /*       by cff_blend_build_vector when it consumes `vstore' */
+
+        if ( FT_READ_USHORT( data->regionIdxCount ) )
+          goto Exit;
+
+        if ( FT_NEW_ARRAY( data->regionIndices, data->regionIdxCount ) )
+          goto Exit;
+
+        for ( j = 0; j < data->regionIdxCount; j++ )
+        {
+          if ( FT_READ_USHORT( data->regionIndices[j] ) )
+            goto Exit;
+        }
+      }
+    }
+
+    error = FT_Err_Ok;
+
+  Exit:
+    FT_FREE( dataOffsetArray );
+    if ( error )
+      cff_vstore_done( vstore, memory );
+
+    return error;
+  }
+
+
+  /* Clear blend stack (after blend values are consumed). */
+  /*                                                      */
+  /* TODO: Should do this in cff_run_parse, but subFont   */
+  /*       ref is not available there.                    */
+  /*                                                      */
+  /* Allocation is not changed when stack is cleared.     */
+  FT_LOCAL_DEF( void )
+  cff_blend_clear( CFF_SubFont  subFont )
+  {
+    subFont->blend_top  = subFont->blend_stack;
+    subFont->blend_used = 0;
+  }
+
+
+  /* Blend numOperands on the stack,                       */
+  /* store results into the first numBlends values,        */
+  /* then pop remaining arguments.                         */
+  /*                                                       */
+  /* This is comparable to `cf2_doBlend' but               */
+  /* the cffparse stack is different and can't be written. */
+  /* Blended values are written to a different buffer,     */
+  /* using reserved operator 255.                          */
+  /*                                                       */
+  /* Blend calculation is done in 16.16 fixed point.       */
+  FT_LOCAL_DEF( FT_Error )
+  cff_blend_doBlend( CFF_SubFont  subFont,
+                     CFF_Parser   parser,
+                     FT_UInt      numBlends )
+  {
+    FT_UInt  delta;
+    FT_UInt  base;
+    FT_UInt  i, j;
+    FT_UInt  size;
+
+    CFF_Blend  blend = &subFont->blend;
+
+    FT_Memory  memory = subFont->blend.font->memory; /* for FT_REALLOC */
+    FT_Error   error  = FT_Err_Ok;                   /* for FT_REALLOC */
+
+    /* compute expected number of operands for this blend */
+    FT_UInt  numOperands = (FT_UInt)( numBlends * blend->lenBV );
+    FT_UInt  count       = (FT_UInt)( parser->top - 1 - parser->stack );
+
+
+    if ( numOperands > count )
+    {
+      FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d argument%s\n",
+                  count,
+                  count == 1 ? "" : "s" ));
+
+      error = FT_THROW( Stack_Underflow );
+      goto Exit;
+    }
+
+    /* check whether we have room for `numBlends' values at `blend_top' */
+    size = 5 * numBlends;           /* add 5 bytes per entry    */
+    if ( subFont->blend_used + size > subFont->blend_alloc )
+    {
+      FT_Byte*  blend_stack_old = subFont->blend_stack;
+      FT_Byte*  blend_top_old   = subFont->blend_top;
+
+
+      /* increase or allocate `blend_stack' and reset `blend_top'; */
+      /* prepare to append `numBlends' values to the buffer        */
+      if ( FT_REALLOC( subFont->blend_stack,
+                       subFont->blend_alloc,
+                       subFont->blend_alloc + size ) )
+        goto Exit;
+
+      subFont->blend_top    = subFont->blend_stack + subFont->blend_used;
+      subFont->blend_alloc += size;
+
+      /* iterate over the parser stack and adjust pointers */
+      /* if the reallocated buffer has a different address */
+      if ( blend_stack_old                         &&
+           subFont->blend_stack != blend_stack_old )
+      {
+        FT_PtrDist  offset = subFont->blend_stack - blend_stack_old;
+        FT_Byte**   p;
+
+
+        for ( p = parser->stack; p < parser->top; p++ )
+        {
+          if ( *p >= blend_stack_old && *p < blend_top_old )
+            *p += offset;
+        }
+      }
+    }
+    subFont->blend_used += size;
+
+    base  = count - numOperands;     /* index of first blend arg */
+    delta = base + numBlends;        /* index of first delta arg */
+
+    for ( i = 0; i < numBlends; i++ )
+    {
+      const FT_Int32*  weight = &blend->BV[1];
+      FT_UInt32        sum;
+
+
+      /* convert inputs to 16.16 fixed point */
+      sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000;
+
+      for ( j = 1; j < blend->lenBV; j++ )
+        sum += cff_parse_num( parser, &parser->stack[delta++] ) * *weight++;
+
+      /* point parser stack to new value on blend_stack */
+      parser->stack[i + base] = subFont->blend_top;
+
+      /* Push blended result as Type 2 5-byte fixed point number.  This */
+      /* will not conflict with actual DICTs because 255 is a reserved  */
+      /* opcode in both CFF and CFF2 DICTs.  See `cff_parse_num' for    */
+      /* decode of this, which rounds to an integer.                    */
+      *subFont->blend_top++ = 255;
+      *subFont->blend_top++ = (FT_Byte)( sum >> 24 );
+      *subFont->blend_top++ = (FT_Byte)( sum >> 16 );
+      *subFont->blend_top++ = (FT_Byte)( sum >>  8 );
+      *subFont->blend_top++ = (FT_Byte)sum;
+    }
+
+    /* leave only numBlends results on parser stack */
+    parser->top = &parser->stack[base + numBlends];
+
+  Exit:
+    return error;
+  }
+
+
+  /* Compute a blend vector from variation store index and normalized  */
+  /* vector based on pseudo-code in OpenType Font Variations Overview. */
+  /*                                                                   */
+  /* Note: lenNDV == 0 produces a default blend vector, (1,0,0,...).   */
+  FT_LOCAL_DEF( FT_Error )
+  cff_blend_build_vector( CFF_Blend  blend,
+                          FT_UInt    vsindex,
+                          FT_UInt    lenNDV,
+                          FT_Fixed*  NDV )
+  {
+    FT_Error   error  = FT_Err_Ok;            /* for FT_REALLOC */
+    FT_Memory  memory = blend->font->memory;  /* for FT_REALLOC */
+
+    FT_UInt       len;
+    CFF_VStore    vs;
+    CFF_VarData*  varData;
+    FT_UInt       master;
+
+
+    FT_ASSERT( lenNDV == 0 || NDV );
+
+    blend->builtBV = FALSE;
+
+    vs = &blend->font->vstore;
+
+    /* VStore and fvar must be consistent */
+    if ( lenNDV != 0 && lenNDV != vs->axisCount )
+    {
+      FT_TRACE4(( " cff_blend_build_vector: Axis count mismatch\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    if ( vsindex >= vs->dataCount )
+    {
+      FT_TRACE4(( " cff_blend_build_vector: vsindex out of range\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    /* select the item variation data structure */
+    varData = &vs->varData[vsindex];
+
+    /* prepare buffer for the blend vector */
+    len = varData->regionIdxCount + 1;    /* add 1 for default component */
+    if ( FT_REALLOC( blend->BV,
+                     blend->lenBV * sizeof( *blend->BV ),
+                     len * sizeof( *blend->BV ) ) )
+      goto Exit;
+
+    blend->lenBV = len;
+
+    /* outer loop steps through master designs to be blended */
+    for ( master = 0; master < len; master++ )
+    {
+      FT_UInt         j;
+      FT_UInt         idx;
+      CFF_VarRegion*  varRegion;
+
+
+      /* default factor is always one */
+      if ( master == 0 )
+      {
+        blend->BV[master] = FT_FIXED_ONE;
+        FT_TRACE4(( "   build blend vector len %d\n"
+                    "   [ %f ",
+                    len,
+                    blend->BV[master] / 65536.0 ));
+        continue;
+      }
+
+      /* VStore array does not include default master, so subtract one */
+      idx       = varData->regionIndices[master - 1];
+      varRegion = &vs->varRegionList[idx];
+
+      if ( idx >= vs->regionCount )
+      {
+        FT_TRACE4(( " cff_blend_build_vector:"
+                    " region index out of range\n" ));
+        error = FT_THROW( Invalid_File_Format );
+        goto Exit;
+      }
+
+      /* Note: `lenNDV' could be zero.                              */
+      /*       In that case, build default blend vector (1,0,0...). */
+      if ( !lenNDV )
+      {
+        blend->BV[master] = 0;
+        continue;
+      }
+
+      /* In the normal case, initialize each component to 1 */
+      /* before inner loop.                                 */
+      blend->BV[master] = FT_FIXED_ONE; /* default */
+
+      /* inner loop steps through axes in this region */
+      for ( j = 0; j < lenNDV; j++ )
+      {
+        CFF_AxisCoords*  axis = &varRegion->axisList[j];
+        FT_Fixed         axisScalar;
+
+
+        /* compute the scalar contribution of this axis; */
+        /* ignore invalid ranges                         */
+        if ( axis->startCoord > axis->peakCoord ||
+             axis->peakCoord > axis->endCoord   )
+          axisScalar = FT_FIXED_ONE;
+
+        else if ( axis->startCoord < 0 &&
+                  axis->endCoord > 0   &&
+                  axis->peakCoord != 0 )
+          axisScalar = FT_FIXED_ONE;
+
+        /* peak of 0 means ignore this axis */
+        else if ( axis->peakCoord == 0 )
+          axisScalar = FT_FIXED_ONE;
+
+        /* ignore this region if coords are out of range */
+        else if ( NDV[j] < axis->startCoord ||
+                  NDV[j] > axis->endCoord   )
+          axisScalar = 0;
+
+        /* calculate a proportional factor */
+        else
+        {
+          if ( NDV[j] == axis->peakCoord )
+            axisScalar = FT_FIXED_ONE;
+          else if ( NDV[j] < axis->peakCoord )
+            axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
+                                    axis->peakCoord - axis->startCoord );
+          else
+            axisScalar = FT_DivFix( axis->endCoord - NDV[j],
+                                    axis->endCoord - axis->peakCoord );
+        }
+
+        /* take product of all the axis scalars */
+        blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
+      }
+
+      FT_TRACE4(( ", %f ",
+                  blend->BV[master] / 65536.0 ));
+    }
+
+    FT_TRACE4(( "]\n" ));
+
+    /* record the parameters used to build the blend vector */
+    blend->lastVsindex = vsindex;
+
+    if ( lenNDV != 0 )
+    {
+      /* user has set a normalized vector */
+      if ( FT_REALLOC( blend->lastNDV,
+                       blend->lenNDV * sizeof ( *NDV ),
+                       lenNDV * sizeof ( *NDV ) ) )
+        goto Exit;
+
+      FT_MEM_COPY( blend->lastNDV,
+                   NDV,
+                   lenNDV * sizeof ( *NDV ) );
+    }
+
+    blend->lenNDV  = lenNDV;
+    blend->builtBV = TRUE;
+
+  Exit:
+    return error;
+  }
+
+
+  /* `lenNDV' is zero for default vector;           */
+  /* return TRUE if blend vector needs to be built. */
+  FT_LOCAL_DEF( FT_Bool )
+  cff_blend_check_vector( CFF_Blend  blend,
+                          FT_UInt    vsindex,
+                          FT_UInt    lenNDV,
+                          FT_Fixed*  NDV )
+  {
+    if ( !blend->builtBV                                ||
+         blend->lastVsindex != vsindex                  ||
+         blend->lenNDV != lenNDV                        ||
+         ( lenNDV                                     &&
+           ft_memcmp( NDV,
+                      blend->lastNDV,
+                      lenNDV * sizeof ( *NDV ) ) != 0 ) )
+    {
+      /* need to build blend vector */
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+  FT_LOCAL_DEF( FT_Error )
+  cff_get_var_blend( CFF_Face     face,
+                     FT_UInt     *num_coords,
+                     FT_Fixed*   *coords,
+                     FT_Fixed*   *normalizedcoords,
+                     FT_MM_Var*  *mm_var )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->get_var_blend( FT_FACE( face ),
+                              num_coords,
+                              coords,
+                              normalizedcoords,
+                              mm_var );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cff_done_blend( CFF_Face  face )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    if (mm)
+      mm->done_blend( FT_FACE( face ) );
+  }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
+  static void
   cff_encoding_done( CFF_Encoding  encoding )
   {
     encoding->format = 0;
@@ -1300,26 +1857,156 @@
   }
 
 
+  /* Parse private dictionary; first call is always from `cff_face_init', */
+  /* so NDV has not been set for CFF2 variation.                          */
+  /*                                                                      */
+  /* `cff_slot_load' must call this function each time NDV changes.       */
+  FT_LOCAL_DEF( FT_Error )
+  cff_load_private_dict( CFF_Font     font,
+                         CFF_SubFont  subfont,
+                         FT_UInt      lenNDV,
+                         FT_Fixed*    NDV )
+  {
+    FT_Error         error  = FT_Err_Ok;
+    CFF_ParserRec    parser;
+    CFF_FontRecDict  top    = &subfont->font_dict;
+    CFF_Private      priv   = &subfont->private_dict;
+    FT_Stream        stream = font->stream;
+    FT_UInt          stackSize;
+
+
+    /* store handle needed to access memory, vstore for blend;    */
+    /* we need this for clean-up even if there is no private DICT */
+    subfont->blend.font   = font;
+    subfont->blend.usedBV = FALSE;  /* clear state */
+
+    if ( !top->private_offset || !top->private_size )
+      goto Exit2;       /* no private DICT, do nothing */
+
+    /* set defaults */
+    FT_ZERO( 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 * 1000 );
+
+    /* provide inputs for blend calculations */
+    priv->subfont   = subfont;
+    subfont->lenNDV = lenNDV;
+    subfont->NDV    = NDV;
+
+    /* add 1 for the operator */
+    stackSize = font->cff2 ? font->top_font.font_dict.maxstack + 1
+                           : CFF_MAX_STACK_DEPTH + 1;
+
+    if ( cff_parser_init( &parser,
+                          font->cff2 ? CFF2_CODE_PRIVATE : CFF_CODE_PRIVATE,
+                          priv,
+                          font->library,
+                          stackSize,
+                          top->num_designs,
+                          top->num_axes ) )
+      goto Exit;
+
+    if ( FT_STREAM_SEEK( font->base_offset + top->private_offset ) ||
+         FT_FRAME_ENTER( top->private_size )                       )
+      goto Exit;
+
+    FT_TRACE4(( " private dictionary:\n" ));
+    error = cff_parser_run( &parser,
+                            (FT_Byte*)stream->cursor,
+                            (FT_Byte*)stream->limit );
+    FT_FRAME_EXIT();
+
+    if ( error )
+      goto Exit;
+
+    /* ensure that `num_blue_values' is even */
+    priv->num_blue_values &= ~1;
+
+    /* sanitize `initialRandomSeed' to be a positive value, if necessary;  */
+    /* this is not mandated by the specification but by our implementation */
+    if ( priv->initial_random_seed < 0 )
+      priv->initial_random_seed = -priv->initial_random_seed;
+    else if ( priv->initial_random_seed == 0 )
+      priv->initial_random_seed = 987654321;
+
+    /* some sanitizing to avoid overflows later on; */
+    /* the upper limits are ad-hoc values           */
+    if ( priv->blue_shift > 1000 || priv->blue_shift < 0 )
+    {
+      FT_TRACE2(( "cff_load_private_dict:"
+                  " setting unlikely BlueShift value %d to default (7)\n",
+                  priv->blue_shift ));
+      priv->blue_shift = 7;
+    }
+
+    if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 )
+    {
+      FT_TRACE2(( "cff_load_private_dict:"
+                  " setting unlikely BlueFuzz value %d to default (1)\n",
+                  priv->blue_fuzz ));
+      priv->blue_fuzz = 1;
+    }
+
+  Exit:
+    /* clean up */
+    cff_blend_clear( subfont ); /* clear blend stack */
+    cff_parser_done( &parser ); /* free parser stack */
+
+  Exit2:
+    /* no clean up (parser not initialized) */
+    return error;
+  }
+
+
+  /* There are 3 ways to call this function, distinguished by code.  */
+  /*                                                                 */
+  /* . CFF_CODE_TOPDICT for either a CFF Top DICT or a CFF Font DICT */
+  /* . CFF2_CODE_TOPDICT for CFF2 Top DICT                           */
+  /* . CFF2_CODE_FONTDICT for CFF2 Font DICT                         */
+
   static FT_Error
-  cff_subfont_load( CFF_SubFont  font,
+  cff_subfont_load( CFF_SubFont  subfont,
                     CFF_Index    idx,
                     FT_UInt      font_index,
                     FT_Stream    stream,
                     FT_ULong     base_offset,
-                    FT_Library   library )
+                    FT_UInt      code,
+                    CFF_Font     font,
+                    CFF_Face     face )
   {
     FT_Error         error;
     CFF_ParserRec    parser;
     FT_Byte*         dict = NULL;
     FT_ULong         dict_len;
-    CFF_FontRecDict  top  = &font->font_dict;
-    CFF_Private      priv = &font->private_dict;
+    CFF_FontRecDict  top  = &subfont->font_dict;
+    CFF_Private      priv = &subfont->private_dict;
 
+    PSAux_Service  psaux = (PSAux_Service)face->psaux;
 
-    cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
+    FT_Bool  cff2      = FT_BOOL( code == CFF2_CODE_TOPDICT  ||
+                                  code == CFF2_CODE_FONTDICT );
+    FT_UInt  stackSize = cff2 ? CFF2_DEFAULT_STACK
+                              : CFF_MAX_STACK_DEPTH;
+
+
+    /* Note: We use default stack size for CFF2 Font DICT because        */
+    /*       Top and Font DICTs are not allowed to have blend operators. */
+    error = cff_parser_init( &parser,
+                             code,
+                             &subfont->font_dict,
+                             font->library,
+                             stackSize,
+                             0,
+                             0 );
+    if ( error )
+      goto Exit;
 
     /* set defaults */
-    FT_MEM_ZERO( top, sizeof ( *top ) );
+    FT_ZERO( top );
 
     top->underline_position  = -( 100L << 16 );
     top->underline_thickness = 50L << 16;
@@ -1342,14 +2029,35 @@
     top->cid_ordering        = 0xFFFFU;
     top->cid_font_name       = 0xFFFFU;
 
-    error = cff_index_access_element( idx, font_index, &dict, &dict_len );
+    /* set default stack size */
+    top->maxstack            = cff2 ? CFF2_DEFAULT_STACK : 48;
+
+    if ( idx->count )   /* count is nonzero for a real index */
+      error = cff_index_access_element( idx, font_index, &dict, &dict_len );
+    else
+    {
+      /* CFF2 has a fake top dict index;     */
+      /* simulate `cff_index_access_element' */
+
+      /* Note: macros implicitly use `stream' and set `error' */
+      if ( FT_STREAM_SEEK( idx->data_offset )       ||
+           FT_FRAME_EXTRACT( idx->data_size, dict ) )
+        goto Exit;
+
+      dict_len = idx->data_size;
+    }
+
     if ( !error )
     {
       FT_TRACE4(( " top dictionary:\n" ));
       error = cff_parser_run( &parser, dict, dict + dict_len );
     }
 
-    cff_index_forget_element( idx, &dict );
+    /* clean up regardless of error */
+    if ( idx->count )
+      cff_index_forget_element( idx, &dict );
+    else
+      FT_FRAME_RELEASE( dict );
 
     if ( error )
       goto Exit;
@@ -1358,34 +2066,63 @@
     if ( top->cid_registry != 0xFFFFU )
       goto Exit;
 
-    /* parse the private dictionary, if any */
-    if ( top->private_offset && top->private_size )
+    /* Parse the private dictionary, if any.                   */
+    /*                                                         */
+    /* CFF2 does not have a private dictionary in the Top DICT */
+    /* but may have one in a Font DICT.  We need to parse      */
+    /* the latter here in order to load any local subrs.       */
+    error = cff_load_private_dict( font, subfont, 0, 0 );
+    if ( error )
+      goto Exit;
+
+    if ( !cff2 )
     {
-      /* set defaults */
-      FT_MEM_ZERO( priv, sizeof ( *priv ) );
+      /*
+       * Initialize the random number generator.
+       *
+       * . If we have a face-specific seed, use it.
+       *   If non-zero, update it to a positive value.
+       *
+       * . Otherwise, use the seed from the CFF driver.
+       *   If non-zero, update it to a positive value.
+       *
+       * . If the random value is zero, use the seed given by the subfont's
+       *   `initialRandomSeed' value.
+       *
+       */
+      if ( face->root.internal->random_seed == -1 )
+      {
+        PS_Driver  driver = (PS_Driver)FT_FACE_DRIVER( face );
 
-      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 * 1000 );
 
-      cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
+        subfont->random = (FT_UInt32)driver->random_seed;
+        if ( driver->random_seed )
+        {
+          do
+          {
+            driver->random_seed =
+              (FT_Int32)psaux->cff_random( (FT_UInt32)driver->random_seed );
 
-      if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
-           FT_FRAME_ENTER( font->font_dict.private_size )                 )
-        goto Exit;
+          } while ( driver->random_seed < 0 );
+        }
+      }
+      else
+      {
+        subfont->random = (FT_UInt32)face->root.internal->random_seed;
+        if ( face->root.internal->random_seed )
+        {
+          do
+          {
+            face->root.internal->random_seed =
+              (FT_Int32)psaux->cff_random(
+                (FT_UInt32)face->root.internal->random_seed );
 
-      FT_TRACE4(( " private dictionary:\n" ));
-      error = cff_parser_run( &parser,
-                              (FT_Byte*)stream->cursor,
-                              (FT_Byte*)stream->limit );
-      FT_FRAME_EXIT();
-      if ( error )
-        goto Exit;
+          } while ( face->root.internal->random_seed < 0 );
+        }
+      }
 
-      /* ensure that `num_blue_values' is even */
-      priv->num_blue_values &= ~1;
+      if ( !subfont->random )
+        subfont->random = (FT_UInt32)priv->initial_random_seed;
     }
 
     /* read the local subrs, if any */
@@ -1395,17 +2132,19 @@
                            priv->local_subrs_offset ) )
         goto Exit;
 
-      error = cff_index_init( &font->local_subrs_index, stream, 1 );
+      error = cff_index_init( &subfont->local_subrs_index, stream, 1, cff2 );
       if ( error )
         goto Exit;
 
-      error = cff_index_get_pointers( &font->local_subrs_index,
-                                      &font->local_subrs, NULL );
+      error = cff_index_get_pointers( &subfont->local_subrs_index,
+                                      &subfont->local_subrs, NULL, NULL );
       if ( error )
         goto Exit;
     }
 
   Exit:
+    cff_parser_done( &parser ); /* free parser stack */
+
     return error;
   }
 
@@ -1418,6 +2157,10 @@
     {
       cff_index_done( &subfont->local_subrs_index );
       FT_FREE( subfont->local_subrs );
+
+      FT_FREE( subfont->blend.lastNDV );
+      FT_FREE( subfont->blend.BV );
+      FT_FREE( subfont->blend_stack );
     }
   }
 
@@ -1427,18 +2170,19 @@
                  FT_Stream  stream,
                  FT_Int     face_index,
                  CFF_Font   font,
-                 FT_Bool    pure_cff )
+                 CFF_Face   face,
+                 FT_Bool    pure_cff,
+                 FT_Bool    cff2 )
   {
     static const FT_Frame_Field  cff_header_fields[] =
     {
 #undef  FT_STRUCTURE
 #define FT_STRUCTURE  CFF_FontRec
 
-      FT_FRAME_START( 4 ),
+      FT_FRAME_START( 3 ),
         FT_FRAME_BYTE( version_major ),
         FT_FRAME_BYTE( version_minor ),
         FT_FRAME_BYTE( header_size ),
-        FT_FRAME_BYTE( absolute_offsize ),
       FT_FRAME_END
     };
 
@@ -1453,42 +2197,133 @@
     FT_ZERO( font );
     FT_ZERO( &string_index );
 
-    font->stream = stream;
-    font->memory = memory;
-    dict         = &font->top_font.font_dict;
-    base_offset  = FT_STREAM_POS();
+    dict        = &font->top_font.font_dict;
+    base_offset = FT_STREAM_POS();
+
+    font->library     = library;
+    font->stream      = stream;
+    font->memory      = memory;
+    font->cff2        = cff2;
+    font->base_offset = base_offset;
 
     /* read CFF font header */
     if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
       goto Exit;
 
-    /* check format */
-    if ( font->version_major   != 1 ||
-         font->header_size      < 4 ||
-         font->absolute_offsize > 4 )
+    if ( cff2 )
     {
-      FT_TRACE2(( "  not a CFF font header\n" ));
-      error = FT_THROW( Unknown_File_Format );
-      goto Exit;
+      if ( font->version_major != 2 ||
+           font->header_size < 5    )
+      {
+        FT_TRACE2(( "  not a CFF2 font header\n" ));
+        error = FT_THROW( Unknown_File_Format );
+        goto Exit;
+      }
+
+      if ( FT_READ_USHORT( font->top_dict_length ) )
+        goto Exit;
+    }
+    else
+    {
+      FT_Byte  absolute_offset;
+
+
+      if ( FT_READ_BYTE( absolute_offset ) )
+        goto Exit;
+
+      if ( font->version_major != 1 ||
+           font->header_size < 4    ||
+           absolute_offset > 4      )
+      {
+        FT_TRACE2(( "  not a CFF font header\n" ));
+        error = FT_THROW( Unknown_File_Format );
+        goto Exit;
+      }
     }
 
     /* skip the rest of the header */
-    if ( FT_STREAM_SKIP( font->header_size - 4 ) )
+    if ( FT_STREAM_SEEK( base_offset + font->header_size ) )
+    {
+      /* For pure CFFs we have read only four bytes so far.  Contrary to */
+      /* other formats like SFNT those bytes doesn't define a signature; */
+      /* it is thus possible that the font isn't a CFF at all.           */
+      if ( pure_cff )
+      {
+        FT_TRACE2(( "  not a CFF file\n" ));
+        error = FT_THROW( Unknown_File_Format );
+      }
       goto Exit;
+    }
 
-    /* read the name, top dict, string and global subrs index */
-    if ( FT_SET_ERROR( cff_index_init( &font->name_index,
-                                       stream, 0 ) )                  ||
-         FT_SET_ERROR( cff_index_init( &font->font_dict_index,
-                                       stream, 0 ) )                  ||
-         FT_SET_ERROR( cff_index_init( &string_index,
-                                       stream, 1 ) )                  ||
-         FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
-                                       stream, 1 ) )                  ||
-         FT_SET_ERROR( cff_index_get_pointers( &string_index,
-                                               &font->strings,
-                                               &font->string_pool ) ) )
-      goto Exit;
+    if ( cff2 )
+    {
+      /* For CFF2, the top dict data immediately follow the header    */
+      /* and the length is stored in the header `offSize' field;      */
+      /* there is no index for it.                                    */
+      /*                                                              */
+      /* Use the `font_dict_index' to save the current position       */
+      /* and length of data, but leave count at zero as an indicator. */
+      FT_ZERO( &font->font_dict_index );
+
+      font->font_dict_index.data_offset = FT_STREAM_POS();
+      font->font_dict_index.data_size   = font->top_dict_length;
+
+      /* skip the top dict data for now, we will parse it later */
+      if ( FT_STREAM_SKIP( font->top_dict_length ) )
+        goto Exit;
+
+      /* next, read the global subrs index */
+      if ( FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
+                                         stream, 1, cff2 ) ) )
+        goto Exit;
+    }
+    else
+    {
+      /* for CFF, read the name, top dict, string and global subrs index */
+      if ( FT_SET_ERROR( cff_index_init( &font->name_index,
+                                         stream, 0, cff2 ) ) )
+      {
+        if ( pure_cff )
+        {
+          FT_TRACE2(( "  not a CFF file\n" ));
+          error = FT_THROW( Unknown_File_Format );
+        }
+        goto Exit;
+      }
+
+      /* if we have an empty font name,      */
+      /* it must be the only font in the CFF */
+      if ( font->name_index.count > 1                          &&
+           font->name_index.data_size < font->name_index.count )
+      {
+        /* for pure CFFs, we still haven't checked enough bytes */
+        /* to be sure that it is a CFF at all                   */
+        error = pure_cff ? FT_THROW( Unknown_File_Format )
+                         : FT_THROW( Invalid_File_Format );
+        goto Exit;
+      }
+
+      if ( FT_SET_ERROR( cff_index_init( &font->font_dict_index,
+                                         stream, 0, cff2 ) )                 ||
+           FT_SET_ERROR( cff_index_init( &string_index,
+                                         stream, 1, cff2 ) )                 ||
+           FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
+                                         stream, 1, cff2 ) )                 ||
+           FT_SET_ERROR( cff_index_get_pointers( &string_index,
+                                                 &font->strings,
+                                                 &font->string_pool,
+                                                 &font->string_pool_size ) ) )
+        goto Exit;
+
+      /* there must be a Top DICT index entry for each name index entry */
+      if ( font->name_index.count > font->font_dict_index.count )
+      {
+        FT_ERROR(( "cff_font_load:"
+                   " not enough entries in Top DICT index\n" ));
+        error = FT_THROW( Invalid_File_Format );
+        goto Exit;
+      }
+    }
 
     font->num_strings = string_index.count;
 
@@ -1534,34 +2369,48 @@
                               subfont_index,
                               stream,
                               base_offset,
-                              library );
+                              cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT,
+                              font,
+                              face );
     if ( error )
       goto Exit;
 
     if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
       goto Exit;
 
-    error = cff_index_init( &font->charstrings_index, stream, 0 );
+    error = cff_index_init( &font->charstrings_index, stream, 0, cff2 );
     if ( error )
       goto Exit;
 
-    /* now, check for a CID font */
-    if ( dict->cid_registry != 0xFFFFU )
+    /* now, check for a CID or CFF2 font */
+    if ( dict->cid_registry != 0xFFFFU ||
+         cff2                          )
     {
       CFF_IndexRec  fd_index;
       CFF_SubFont   sub = NULL;
       FT_UInt       idx;
 
 
+      /* for CFF2, read the Variation Store if available;                 */
+      /* this must follow the Top DICT parse and precede any Private DICT */
+      error = cff_vstore_load( &font->vstore,
+                               stream,
+                               base_offset,
+                               dict->vstore_offset );
+      if ( error )
+        goto Exit;
+
       /* this is a CID-keyed font, we must now allocate a table of */
       /* sub-fonts, then load each of them separately              */
       if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
         goto Exit;
 
-      error = cff_index_init( &fd_index, stream, 0 );
+      error = cff_index_init( &fd_index, stream, 0, cff2 );
       if ( error )
         goto Exit;
 
+      /* Font Dicts are not limited to 256 for CFF2. */
+      /* TODO: support this for CFF2                 */
       if ( fd_index.count > CFF_MAX_CID_FONTS )
       {
         FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
@@ -1582,17 +2431,26 @@
       {
         sub = font->subfonts[idx];
         FT_TRACE4(( "parsing subfont %u\n", idx ));
-        error = cff_subfont_load( sub, &fd_index, idx,
-                                  stream, base_offset, library );
+        error = cff_subfont_load( sub,
+                                  &fd_index,
+                                  idx,
+                                  stream,
+                                  base_offset,
+                                  cff2 ? CFF2_CODE_FONTDICT
+                                       : CFF_CODE_TOPDICT,
+                                  font,
+                                  face );
         if ( error )
           goto Fail_CID;
       }
 
-      /* now load the FD Select array */
-      error = CFF_Load_FD_Select( &font->fd_select,
-                                  font->charstrings_index.count,
-                                  stream,
-                                  base_offset + dict->cid_fd_select_offset );
+      /* now load the FD Select array;               */
+      /* CFF2 omits FDSelect if there is only one FD */
+      if ( !cff2 || fd_index.count > 1 )
+        error = CFF_Load_FD_Select( &font->fd_select,
+                                    font->charstrings_index.count,
+                                    stream,
+                                    base_offset + dict->cid_fd_select_offset );
 
     Fail_CID:
       cff_index_done( &fd_index );
@@ -1614,13 +2472,13 @@
     font->num_glyphs = font->charstrings_index.count;
 
     error = cff_index_get_pointers( &font->global_subrs_index,
-                                    &font->global_subrs, NULL );
+                                    &font->global_subrs, NULL, NULL );
 
     if ( error )
       goto Exit;
 
     /* read the Charset and Encoding tables if available */
-    if ( font->num_glyphs > 0 )
+    if ( !cff2 && font->num_glyphs > 0 )
     {
       FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
 
@@ -1668,7 +2526,7 @@
     cff_index_done( &font->charstrings_index );
 
     /* release font dictionaries, but only if working with */
-    /* a CID keyed CFF font                                */
+    /* a CID keyed CFF font or a CFF2 font                 */
     if ( font->num_subfonts > 0 )
     {
       for ( idx = 0; idx < font->num_subfonts; idx++ )
@@ -1680,6 +2538,7 @@
 
     cff_encoding_done( &font->encoding );
     cff_charset_done( &font->charset, font->stream );
+    cff_vstore_done( &font->vstore, memory );
 
     cff_subfont_done( memory, &font->top_font );
 
@@ -1697,6 +2556,8 @@
       font->cf2_instance.finalizer( font->cf2_instance.data );
       FT_FREE( font->cf2_instance.data );
     }
+
+    FT_FREE( font->font_extra );
   }
 
 

Index: xsrc/external/mit/freetype/dist/src/gzip/ftgzip.c
diff -u xsrc/external/mit/freetype/dist/src/gzip/ftgzip.c:1.10 xsrc/external/mit/freetype/dist/src/gzip/ftgzip.c:1.11
--- xsrc/external/mit/freetype/dist/src/gzip/ftgzip.c:1.10	Mon May 16 22:18:39 2016
+++ xsrc/external/mit/freetype/dist/src/gzip/ftgzip.c	Wed May  9 07:21:07 2018
@@ -8,7 +8,7 @@
 /*  parse compressed PCF fonts, as found with many X11 server              */
 /*  distributions.                                                         */
 /*                                                                         */
-/*  Copyright 2002-2016 by                                                 */
+/*  Copyright 2002-2018 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -51,17 +51,29 @@
 
 #else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
 
- /* In this case, we include our own modified sources of the ZLib    */
- /* within the "ftgzip" component.  The modifications were necessary */
- /* to #include all files without conflicts, as well as preventing   */
- /* the definition of "extern" functions that may cause linking      */
- /* conflicts when a program is linked with both FreeType and the    */
- /* original ZLib.                                                   */
+  /* In this case, we include our own modified sources of the ZLib  */
+  /* within the `gzip' component.  The modifications were necessary */
+  /* to #include all files without conflicts, as well as preventing */
+  /* the definition of `extern' functions that may cause linking    */
+  /* conflicts when a program is linked with both FreeType and the  */
+  /* original ZLib.                                                 */
 
 #ifndef USE_ZLIB_ZCALLOC
-#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutils.c */
+#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutil.c */
 #endif
 
+  /* Note that our `zlib.h' includes `ftzconf.h' instead of `zconf.h'; */
+  /* the main reason is that even a global `zlib.h' includes `zconf.h' */
+  /* with                                                              */
+  /*                                                                   */
+  /*   #include "zconf.h"                                              */
+  /*                                                                   */
+  /* instead of the expected                                           */
+  /*                                                                   */
+  /*   #include <zconf.h>                                              */
+  /*                                                                   */
+  /* so that configuration with `FT_CONFIG_OPTION_SYSTEM_ZLIB' might   */
+  /* include the wrong `zconf.h' file, leading to errors.              */
 #include "zlib.h"
 
 #undef  SLOW
@@ -305,7 +317,7 @@
     zstream->next_in  = zip->buffer;
 
     if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
-         zstream->next_in == NULL                     )
+         !zstream->next_in                           )
       error = FT_THROW( Invalid_File_Format );
 
   Exit:

Index: xsrc/external/mit/freetype/dist/src/lzw/ftzopen.c
diff -u xsrc/external/mit/freetype/dist/src/lzw/ftzopen.c:1.7 xsrc/external/mit/freetype/dist/src/lzw/ftzopen.c:1.8
--- xsrc/external/mit/freetype/dist/src/lzw/ftzopen.c:1.7	Mon May 16 22:18:39 2016
+++ xsrc/external/mit/freetype/dist/src/lzw/ftzopen.c	Wed May  9 07:21:08 2018
@@ -8,7 +8,7 @@
 /*  be used to parse compressed PCF fonts, as found with many X11 server   */
 /*  distributions.                                                         */
 /*                                                                         */
-/*  Copyright 2005-2016 by                                                 */
+/*  Copyright 2005-2018 by                                                 */
 /*  David Turner.                                                          */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -42,7 +42,12 @@
     state->buf_total += count;
     state->in_eof     = FT_BOOL( count < state->num_bits );
     state->buf_offset = 0;
-    state->buf_size   = ( state->buf_size << 3 ) - ( state->num_bits - 1 );
+
+    state->buf_size <<= 3;
+    if ( state->buf_size > state->num_bits )
+      state->buf_size -= state->num_bits - 1;
+    else
+      return -1; /* not enough data */
 
     if ( count == 0 )  /* end of file */
       return -1;
@@ -66,7 +71,10 @@
     {
       if ( state->free_ent >= state->free_bits )
       {
-        state->num_bits  = ++num_bits;
+        state->num_bits = ++num_bits;
+        if ( num_bits > LZW_MAX_BITS )
+          return -1;
+
         state->free_bits = state->num_bits < state->max_bits
                            ? (FT_UInt)( ( 1UL << num_bits ) - 256 )
                            : state->max_free + 1;
@@ -353,7 +361,7 @@
       {
         while ( state->stack_top > 0 )
         {
-          --state->stack_top;
+          state->stack_top--;
 
           if ( buffer )
             buffer[result] = state->stack[state->stack_top];

Index: xsrc/external/mit/freetype/dist/src/sfnt/ttcmap.c
diff -u xsrc/external/mit/freetype/dist/src/sfnt/ttcmap.c:1.8 xsrc/external/mit/freetype/dist/src/sfnt/ttcmap.c:1.9
--- xsrc/external/mit/freetype/dist/src/sfnt/ttcmap.c:1.8	Mon May 16 22:18:39 2016
+++ xsrc/external/mit/freetype/dist/src/sfnt/ttcmap.c	Wed May  9 07:21:08 2018
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType character mapping table (cmap) support (body).              */
 /*                                                                         */
-/*  Copyright 2002-2016 by                                                 */
+/*  Copyright 2002-2018 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,8 +23,10 @@
 
 #include FT_INTERNAL_VALIDATE_H
 #include FT_INTERNAL_STREAM_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
 #include "ttload.h"
 #include "ttcmap.h"
+#include "ttpost.h"
 #include "sfntpic.h"
 
 
@@ -180,22 +182,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap0_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap0_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap0_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     0,
-    (TT_CMap_ValidateFunc)tt_cmap0_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap0_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap0_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap0_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
 
@@ -218,10 +222,10 @@
   /***** The following charmap lookup and iteration functions all      *****/
   /***** assume that the value `charcode' fulfills the following.      *****/
   /*****                                                               *****/
-  /*****   - For one byte characters, `charcode' is simply the         *****/
+  /*****   - For one-byte characters, `charcode' is simply the         *****/
   /*****     character code.                                           *****/
   /*****                                                               *****/
-  /*****   - For two byte characters, `charcode' is the 2-byte         *****/
+  /*****   - For two-byte characters, `charcode' is the 2-byte         *****/
   /*****     character code in big endian format.  More precisely:     *****/
   /*****                                                               *****/
   /*****       (charcode >> 8)    is the first byte value              *****/
@@ -248,11 +252,11 @@
   /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
   /*   glyph_ids   518+NSUB*8     USHORT[]        glyph ID array           */
   /*                                                                       */
-  /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
+  /* The `keys' table is used to map charcode high bytes to sub-headers.   */
   /* The value of `NSUBS' is the number of sub-headers defined in the      */
   /* table and is computed by finding the maximum of the `keys' table.     */
   /*                                                                       */
-  /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
+  /* Note that for any `n', `keys[n]' is a byte offset within the `subs'   */
   /* table, i.e., it is the corresponding sub-header index multiplied      */
   /* by 8.                                                                 */
   /*                                                                       */
@@ -265,8 +269,8 @@
   /*   delta       4           SHORT           see below                   */
   /*   offset      6           USHORT          see below                   */
   /*                                                                       */
-  /* A sub-header defines, for each high-byte, the range of valid          */
-  /* low-bytes within the charmap.  Note that the range defined by `first' */
+  /* A sub-header defines, for each high byte, the range of valid          */
+  /* low bytes within the charmap.  Note that the range defined by `first' */
   /* and `count' must be completely included in the interval [0..255]      */
   /* according to the specification.                                       */
   /*                                                                       */
@@ -356,7 +360,7 @@
       /* check range within 0..255 */
       if ( valid->level >= FT_VALIDATE_PARANOID )
       {
-        if ( first_code >= 256 || first_code + code_count > 256 )
+        if ( first_code >= 256 || code_count > 256 - first_code )
           FT_INVALID_DATA;
       }
 
@@ -408,7 +412,7 @@
     {
       FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
       FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
-      FT_Byte*  p       = table + 6;    /* keys table */
+      FT_Byte*  p       = table + 6;    /* keys table       */
       FT_Byte*  subs    = table + 518;  /* subheaders table */
       FT_Byte*  sub;
 
@@ -421,8 +425,8 @@
         sub = subs;  /* jump to first sub-header */
 
         /* check that the sub-header for this byte is 0, which */
-        /* indicates that it is really a valid one-byte value  */
-        /* Otherwise, return 0                                 */
+        /* indicates that it is really a valid one-byte value; */
+        /* otherwise, return 0                                 */
         /*                                                     */
         p += char_lo * 2;
         if ( TT_PEEK_USHORT( p ) != 0 )
@@ -441,6 +445,7 @@
         if ( sub == subs )
           goto Exit;
       }
+
       result = sub;
     }
 
@@ -513,8 +518,19 @@
         FT_UInt   pos, idx;
 
 
+        if ( char_lo >= start + count && charcode <= 0xFF )
+        {
+          /* this happens only for a malformed cmap */
+          charcode = 0x100;
+          continue;
+        }
+
         if ( offset == 0 )
+        {
+          if ( charcode == 0x100 )
+            goto Exit; /* this happens only for a malformed cmap */
           goto Next_SubHeader;
+        }
 
         if ( char_lo < start )
         {
@@ -541,11 +557,20 @@
             }
           }
         }
+
+        /* if unsuccessful, avoid `charcode' leaving */
+        /* the current 256-character block           */
+        if ( count )
+          charcode--;
       }
 
-      /* jump to next sub-header, i.e. higher byte value */
+      /* If `charcode' is <= 0xFF, retry with `charcode + 1'.      */
+      /* Otherwise jump to the next 256-character block and retry. */
     Next_SubHeader:
-      charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
+      if ( charcode <= 0xFF )
+        charcode++;
+      else
+        charcode = FT_PAD_FLOOR( charcode, 0x100 ) + 0x100;
     }
 
   Exit:
@@ -571,22 +596,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap2_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap2_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap2_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap2_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     2,
-    (TT_CMap_ValidateFunc)tt_cmap2_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap2_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap2_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap2_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
 
@@ -763,6 +790,9 @@
   static void
   tt_cmap4_next( TT_CMap4  cmap )
   {
+    TT_Face   face  = (TT_Face)cmap->cmap.cmap.charmap.face;
+    FT_Byte*  limit = face->cmap_table + face->cmap_size;
+
     FT_UInt  charcode;
 
 
@@ -788,15 +818,19 @@
           FT_Byte*  p = values + 2 * ( charcode - cmap->cur_start );
 
 
+          /* if p > limit, the whole segment is invalid */
+          if ( p > limit )
+            goto Next_Segment;
+
           do
           {
             FT_UInt  gindex = FT_NEXT_USHORT( p );
 
 
-            if ( gindex != 0 )
+            if ( gindex )
             {
               gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
-              if ( gindex != 0 )
+              if ( gindex )
               {
                 cmap->cur_charcode = charcode;
                 cmap->cur_gindex   = gindex;
@@ -812,7 +846,26 @@
             FT_UInt  gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
 
 
-            if ( gindex != 0 )
+            if ( gindex >= (FT_UInt)face->root.num_glyphs )
+            {
+              /* we have an invalid glyph index; if there is an overflow, */
+              /* we can adjust `charcode', otherwise the whole segment is */
+              /* invalid                                                  */
+              gindex = 0;
+
+              if ( (FT_Int)charcode + delta < 0 &&
+                   (FT_Int)end + delta >= 0     )
+                charcode = (FT_UInt)( -delta );
+
+              else if ( (FT_Int)charcode + delta < 0x10000L &&
+                        (FT_Int)end + delta >= 0x10000L     )
+                charcode = (FT_UInt)( 0x10000L - delta );
+
+              else
+                goto Next_Segment;
+            }
+
+            if ( gindex )
             {
               cmap->cur_charcode = charcode;
               cmap->cur_gindex   = gindex;
@@ -822,6 +875,7 @@
         }
       }
 
+    Next_Segment:
       /* we need to find another range */
       if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
         break;
@@ -1170,6 +1224,9 @@
                             FT_UInt32*  pcharcode,
                             FT_Bool     next )
   {
+    TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
+    FT_Byte*  limit = face->cmap_table + face->cmap_size;
+
     FT_UInt   num_segs2, start, end, offset;
     FT_Int    delta;
     FT_UInt   max, min, mid, num_segs;
@@ -1221,10 +1278,6 @@
         if ( mid >= num_segs - 1                &&
              start == 0xFFFFU && end == 0xFFFFU )
         {
-          TT_Face   face  = (TT_Face)cmap->cmap.charmap.face;
-          FT_Byte*  limit = face->cmap_table + face->cmap_size;
-
-
           if ( offset && p + offset + 2 > limit )
           {
             delta  = 1;
@@ -1245,7 +1298,7 @@
             mid = max + 1;
 
           /* search in segments before the current segment */
-          for ( i = max ; i > 0; i-- )
+          for ( i = max; i > 0; i-- )
           {
             FT_UInt   prev_end;
             FT_Byte*  old_p;
@@ -1347,13 +1400,40 @@
         if ( offset )
         {
           p += offset + ( charcode - start ) * 2;
+
+          /* if p > limit, the whole segment is invalid */
+          if ( next && p > limit )
+            break;
+
           gindex = TT_PEEK_USHORT( p );
-          if ( gindex != 0 )
+          if ( gindex )
+          {
             gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
+            if ( gindex >= (FT_UInt)face->root.num_glyphs )
+              gindex = 0;
+          }
         }
         else
+        {
           gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
 
+          if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
+          {
+            /* we have an invalid glyph index; if there is an overflow, */
+            /* we can adjust `charcode', otherwise the whole segment is */
+            /* invalid                                                  */
+            gindex = 0;
+
+            if ( (FT_Int)charcode + delta < 0 &&
+                 (FT_Int)end + delta >= 0     )
+              charcode = (FT_UInt)( -delta );
+
+            else if ( (FT_Int)charcode + delta < 0x10000L &&
+                      (FT_Int)end + delta >= 0x10000L     )
+              charcode = (FT_UInt)( 0x10000L - delta );
+          }
+        }
+
         break;
       }
     }
@@ -1463,21 +1543,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap4_class_rec,
-    sizeof ( TT_CMap4Rec ),
-    (FT_CMap_InitFunc)     tt_cmap4_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap4_char_next,
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      sizeof ( TT_CMap4Rec ),
+
+      (FT_CMap_InitFunc)     tt_cmap4_init,        /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap4_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap4_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     4,
-    (TT_CMap_ValidateFunc)tt_cmap4_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap4_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap4_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap4_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
 
@@ -1630,22 +1713,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap6_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap6_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap6_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap6_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     6,
-    (TT_CMap_ValidateFunc)tt_cmap6_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap6_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap6_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap6_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
 
@@ -1922,22 +2007,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap8_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap8_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap8_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap8_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     8,
-    (TT_CMap_ValidateFunc)tt_cmap8_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap8_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap8_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
 
@@ -2092,22 +2179,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap10_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap10_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,          /* init       */
+      (FT_CMap_DoneFunc)     NULL,                  /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap10_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap10_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     10,
-    (TT_CMap_ValidateFunc)tt_cmap10_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap10_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap10_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
 
@@ -2446,22 +2535,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap12_class_rec,
-    sizeof ( TT_CMap12Rec ),
 
-    (FT_CMap_InitFunc)     tt_cmap12_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap12_char_next,
+      sizeof ( TT_CMap12Rec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap12_init,        /* init       */
+      (FT_CMap_DoneFunc)     NULL,                  /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap12_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap12_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     12,
-    (TT_CMap_ValidateFunc)tt_cmap12_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap12_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap12_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
 
@@ -2770,22 +2861,24 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap13_class_rec,
-    sizeof ( TT_CMap13Rec ),
 
-    (FT_CMap_InitFunc)     tt_cmap13_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap13_char_next,
+      sizeof ( TT_CMap13Rec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap13_init,        /* init       */
+      (FT_CMap_DoneFunc)     NULL,                  /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap13_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap13_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     13,
-    (TT_CMap_ValidateFunc)tt_cmap13_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap13_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap13_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
 
@@ -2876,7 +2969,7 @@
 
 
     cmap->max_results = 0;
-    if ( memory != NULL && cmap->results != NULL )
+    if ( memory && cmap->results )
       FT_FREE( cmap->results );
   }
 
@@ -2983,7 +3076,7 @@
           if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
             FT_INVALID_TOO_SHORT;
 
-          for ( i = 0; i < numRanges; ++i )
+          for ( i = 0; i < numRanges; i++ )
           {
             FT_ULong  base = TT_NEXT_UINT24( defp );
             FT_ULong  cnt  = FT_NEXT_BYTE( defp );
@@ -3016,7 +3109,7 @@
           if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
             FT_INVALID_TOO_SHORT;
 
-          for ( i = 0; i < numMappings; ++i )
+          for ( i = 0; i < numMappings; i++ )
           {
             FT_ULong  uni = TT_NEXT_UINT24( ndp );
             FT_ULong  gid = TT_NEXT_USHORT( ndp );
@@ -3104,7 +3197,7 @@
 
       if ( char_code < start )
         max = mid;
-      else if ( char_code > start+cnt )
+      else if ( char_code > start + cnt )
         min = mid + 1;
       else
         return TRUE;
@@ -3257,7 +3350,7 @@
       return NULL;
 
     result = cmap14->results;
-    for ( i = 0; i < count; ++i )
+    for ( i = 0; i < count; i++ )
     {
       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
       p        += 8;
@@ -3282,7 +3375,7 @@
     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
       return NULL;
 
-    for ( q = cmap14->results; count > 0; --count )
+    for ( q = cmap14->results; count > 0; count-- )
     {
       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
       FT_ULong   defOff    = TT_NEXT_ULONG( p );
@@ -3341,7 +3434,7 @@
     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
       return NULL;
 
-    for ( q = cmap14->results; numRanges > 0; --numRanges )
+    for ( q = cmap14->results; numRanges > 0; numRanges-- )
     {
       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
 
@@ -3378,7 +3471,7 @@
       return NULL;
 
     ret = cmap14->results;
-    for ( i = 0; i < numMappings; ++i )
+    for ( i = 0; i < numMappings; i++ )
     {
       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
       p += 2;
@@ -3462,10 +3555,10 @@
       {
         if ( nuni > duni + dcnt )
         {
-          for ( k = 0; k <= dcnt; ++k )
+          for ( k = 0; k <= dcnt; k++ )
             ret[i++] = duni + k;
 
-          ++di;
+          di++;
 
           if ( di > numRanges )
             break;
@@ -3479,7 +3572,7 @@
             ret[i++] = nuni;
           /* If it is within the default range then ignore it -- */
           /* that should not have happened                       */
-          ++ni;
+          ni++;
           if ( ni > numMappings )
             break;
 
@@ -3498,7 +3591,7 @@
         {
           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
           p += 2;
-          ++ni;
+          ni++;
         }
       }
       else if ( di <= numRanges )
@@ -3506,7 +3599,7 @@
         /* If we get here then we have run out of all non-default     */
         /* mappings.  We have read one default range which we haven't */
         /* stored and there may be others that need to be read.       */
-        for ( k = 0; k <= dcnt; ++k )
+        for ( k = 0; k <= dcnt; k++ )
           ret[i++] = duni + k;
 
         while ( di < numRanges )
@@ -3514,9 +3607,9 @@
           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
           dcnt = FT_NEXT_BYTE( dp );
 
-          for ( k = 0; k <= dcnt; ++k )
+          for ( k = 0; k <= dcnt; k++ )
             ret[i++] = duni + k;
-          ++di;
+          di++;
         }
       }
 
@@ -3529,27 +3622,133 @@
 
   FT_DEFINE_TT_CMAP(
     tt_cmap14_class_rec,
-    sizeof ( TT_CMap14Rec ),
 
-    (FT_CMap_InitFunc)     tt_cmap14_init,
-    (FT_CMap_DoneFunc)     tt_cmap14_done,
-    (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap14_char_next,
-
-    /* Format 14 extension functions */
-    (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
-    (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
-    (FT_CMap_VariantListFunc)     tt_cmap14_variants,
-    (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
-    (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
+      sizeof ( TT_CMap14Rec ),
+
+      (FT_CMap_InitFunc)     tt_cmap14_init,        /* init       */
+      (FT_CMap_DoneFunc)     tt_cmap14_done,        /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap14_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap14_char_next,   /* char_next  */
+
+      /* Format 14 extension functions */
+      (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
+      (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
+      (FT_CMap_VariantListFunc)     tt_cmap14_variants,
+      (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
+      (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
 
     14,
-    (TT_CMap_ValidateFunc)tt_cmap14_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap14_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap14_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
 
 
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                       SYNTHETIC UNICODE                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*        This charmap is generated using postscript glyph names.        */
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+  FT_CALLBACK_DEF( const char * )
+  tt_get_glyph_name( TT_Face  face,
+                     FT_UInt  idx )
+  {
+    FT_String*  PSname;
+
+
+    tt_face_get_ps_name( face, idx, &PSname );
+
+    return PSname;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  tt_cmap_unicode_init( PS_Unicodes  unicodes,
+                        FT_Pointer   pointer )
+  {
+    TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
+    FT_Memory           memory  = FT_FACE_MEMORY( face );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
+
+    FT_UNUSED( pointer );
+
+
+    return psnames->unicodes_init( memory,
+                                   unicodes,
+                                   face->root.num_glyphs,
+                                   (PS_GetGlyphNameFunc)&tt_get_glyph_name,
+                                   (PS_FreeGlyphNameFunc)NULL,
+                                   (FT_Pointer)face );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  tt_cmap_unicode_done( PS_Unicodes  unicodes )
+  {
+    FT_Face    face   = FT_CMAP_FACE( unicodes );
+    FT_Memory  memory = FT_FACE_MEMORY( face );
+
+
+    FT_FREE( unicodes->maps );
+    unicodes->num_maps = 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt )
+  tt_cmap_unicode_char_index( PS_Unicodes  unicodes,
+                              FT_UInt32    char_code )
+  {
+    TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+    return psnames->unicodes_char_index( unicodes, char_code );
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt32 )
+  tt_cmap_unicode_char_next( PS_Unicodes  unicodes,
+                             FT_UInt32   *pchar_code )
+  {
+    TT_Face             face    = (TT_Face)FT_CMAP_FACE( unicodes );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
+
+
+    return psnames->unicodes_char_next( unicodes, pchar_code );
+  }
+
+
+  FT_DEFINE_TT_CMAP(
+    tt_cmap_unicode_class_rec,
+
+      sizeof ( PS_UnicodesRec ),
+
+      (FT_CMap_InitFunc)     tt_cmap_unicode_init,        /* init       */
+      (FT_CMap_DoneFunc)     tt_cmap_unicode_done,        /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
+
+    ~0U,
+    (TT_CMap_ValidateFunc)NULL,  /* validate      */
+    (TT_CMap_Info_GetFunc)NULL   /* get_cmap_info */
+  )
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
 #ifndef FT_CONFIG_OPTION_PIC
 
   static const TT_CMap_Class  tt_cmap_classes[] =
@@ -3684,7 +3883,7 @@
               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
             }
 
-            if ( valid.validator.error == 0 )
+            if ( !valid.validator.error )
             {
               FT_CMap  ttcmap;
 
@@ -3710,7 +3909,7 @@
           }
         }
 
-        if ( *pclazz == NULL )
+        if ( !*pclazz )
         {
           FT_TRACE0(( "tt_face_build_cmaps:"
                       " unsupported cmap sub-table ignored\n" ));
@@ -3729,8 +3928,10 @@
     FT_CMap        cmap  = (FT_CMap)charmap;
     TT_CMap_Class  clazz = (TT_CMap_Class)cmap->clazz;
 
-
-    return clazz->get_cmap_info( charmap, cmap_info );
+    if ( clazz->get_cmap_info )
+      return clazz->get_cmap_info( charmap, cmap_info );
+    else
+      return FT_THROW( Invalid_CharMap_Format );
   }
 
 

Index: xsrc/external/mit/freetype/dist/src/smooth/ftsmooth.c
diff -u xsrc/external/mit/freetype/dist/src/smooth/ftsmooth.c:1.9 xsrc/external/mit/freetype/dist/src/smooth/ftsmooth.c:1.10
--- xsrc/external/mit/freetype/dist/src/smooth/ftsmooth.c:1.9	Mon May 16 22:18:39 2016
+++ xsrc/external/mit/freetype/dist/src/smooth/ftsmooth.c	Wed May  9 07:21:08 2018
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Anti-aliasing renderer interface (body).                             */
 /*                                                                         */
-/*  Copyright 2000-2016 by                                                 */
+/*  Copyright 2000-2018 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -31,12 +31,7 @@
   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 );
+    render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
 
     return 0;
   }
@@ -87,7 +82,7 @@
                       FT_GlyphSlot  slot,
                       FT_BBox*      cbox )
   {
-    FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
+    FT_ZERO( cbox );
 
     if ( slot->format == render->glyph_format )
       FT_Outline_Get_CBox( &slot->outline, cbox );
@@ -102,26 +97,17 @@
                             const FT_Vector*  origin,
                             FT_Render_Mode    required_mode )
   {
-    FT_Error     error;
+    FT_Error     error   = FT_Err_Ok;
     FT_Outline*  outline = &slot->outline;
     FT_Bitmap*   bitmap  = &slot->bitmap;
     FT_Memory    memory  = render->root.memory;
-    FT_BBox      cbox;
     FT_Pos       x_shift = 0;
     FT_Pos       y_shift = 0;
-    FT_Pos       x_left, y_top;
-    FT_Pos       width, height, pitch;
-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-    FT_Pos       height_org, width_org;
-#endif
-    FT_Int       hmul    = mode == FT_RENDER_MODE_LCD;
-    FT_Int       vmul    = mode == FT_RENDER_MODE_LCD_V;
+    FT_Int       hmul    = ( mode == FT_RENDER_MODE_LCD );
+    FT_Int       vmul    = ( mode == FT_RENDER_MODE_LCD_V );
 
     FT_Raster_Params  params;
 
-    FT_Bool  have_outline_shifted = FALSE;
-    FT_Bool  have_buffer          = FALSE;
-
 
     /* check glyph image format */
     if ( slot->format != render->glyph_format )
@@ -137,91 +123,6 @@
       goto Exit;
     }
 
-    if ( origin )
-    {
-      x_shift = origin->x;
-      y_shift = origin->y;
-    }
-
-    /* compute the control box, and grid fit it */
-    /* taking into account the origin shift     */
-    FT_Outline_Get_CBox( outline, &cbox );
-
-    cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
-    cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
-    cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
-    cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift );
-
-    x_shift -= cbox.xMin;
-    y_shift -= cbox.yMin;
-
-    x_left  = cbox.xMin >> 6;
-    y_top   = cbox.yMax >> 6;
-
-    width  = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
-    height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
-
-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-    width_org  = width;
-    height_org = height;
-#endif
-
-    pitch = width;
-    if ( hmul )
-    {
-      width *= 3;
-      pitch  = FT_PAD_CEIL( width, 4 );
-    }
-
-    if ( vmul )
-      height *= 3;
-
-#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-
-    if ( slot->library->lcd_filter_func )
-    {
-      FT_Int  extra = slot->library->lcd_extra;
-
-
-      if ( hmul )
-      {
-        x_shift += 64 * ( extra >> 1 );
-        x_left  -= extra >> 1;
-        width   += 3 * extra;
-        pitch    = FT_PAD_CEIL( width, 4 );
-      }
-
-      if ( vmul )
-      {
-        y_shift += 64 * ( extra >> 1 );
-        y_top   += extra >> 1;
-        height  += 3 * extra;
-      }
-    }
-
-#endif
-
-    /*
-     * XXX: on 16bit system, we return an error for huge bitmap
-     * to prevent an overflow.
-     */
-    if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ||
-         x_left < FT_INT_MIN || y_top < FT_INT_MIN )
-    {
-      error = FT_THROW( Invalid_Pixel_Size );
-      goto Exit;
-    }
-
-    /* Required check is (pitch * height < FT_ULONG_MAX),        */
-    /* but we care realistic cases only.  Always pitch <= width. */
-    if ( width > 0x7FFF || height > 0x7FFF )
-    {
-      FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
-                 width, height ));
-      error = FT_THROW( Raster_Overflow );
-      goto Exit;
-    }
-
     /* release old bitmap buffer */
     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
     {
@@ -229,30 +130,30 @@
       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
     }
 
+    ft_glyphslot_preset_bitmap( slot, mode, origin );
+
     /* allocate new one */
-    if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
+    if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
       goto Exit;
-    else
-      have_buffer = TRUE;
 
     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
-    slot->format      = FT_GLYPH_FORMAT_BITMAP;
-    slot->bitmap_left = (FT_Int)x_left;
-    slot->bitmap_top  = (FT_Int)y_top;
-
-    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
-    bitmap->num_grays  = 256;
-    bitmap->width      = (unsigned int)width;
-    bitmap->rows       = (unsigned int)height;
-    bitmap->pitch      = pitch;
+    x_shift = 64 * -slot->bitmap_left;
+    y_shift = 64 * -slot->bitmap_top;
+    if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
+      y_shift += 64 * (FT_Int)bitmap->rows / 3;
+    else
+      y_shift += 64 * (FT_Int)bitmap->rows;
+
+    if ( origin )
+    {
+      x_shift += origin->x;
+      y_shift += origin->y;
+    }
 
     /* translate outline to render it into the bitmap */
     if ( x_shift || y_shift )
-    {
       FT_Outline_Translate( outline, x_shift, y_shift );
-      have_outline_shifted = TRUE;
-    }
 
     /* set up parameters */
     params.target = bitmap;
@@ -299,80 +200,143 @@
     if ( error )
       goto Exit;
 
-    if ( slot->library->lcd_filter_func )
-      slot->library->lcd_filter_func( bitmap, mode, slot->library );
+    /* finally apply filtering */
+    if ( hmul || vmul )
+    {
+      FT_Byte*                 lcd_weights;
+      FT_Bitmap_LcdFilterFunc  lcd_filter_func;
 
-#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-    /* render outline into bitmap */
-    error = render->raster_render( render->raster, &params );
-    if ( error )
-      goto Exit;
+      /* Per-face LCD filtering takes priority if set up. */
+      if ( slot->face && slot->face->internal->lcd_filter_func )
+      {
+        lcd_weights     = slot->face->internal->lcd_weights;
+        lcd_filter_func = slot->face->internal->lcd_filter_func;
+      }
+      else
+      {
+        lcd_weights     = slot->library->lcd_weights;
+        lcd_filter_func = slot->library->lcd_filter_func;
+      }
 
-    /* expand it horizontally */
-    if ( hmul )
+      if ( lcd_filter_func )
+        lcd_filter_func( bitmap, mode, lcd_weights );
+    }
+
+#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+    if ( hmul )  /* lcd */
     {
-      FT_Byte*  line = bitmap->buffer;
-      FT_UInt   hh;
+      FT_Byte*  line;
+      FT_Byte*  temp = NULL;
+      FT_UInt   i, j;
 
+      unsigned int  height = bitmap->rows;
+      unsigned int  width  = bitmap->width;
+      int           pitch  = bitmap->pitch;
 
-      for ( hh = height_org; hh > 0; hh--, line += pitch )
-      {
-        FT_UInt   xx;
-        FT_Byte*  end = line + width;
 
+      /* Render 3 separate monochrome bitmaps, shifting the outline  */
+      /* by 1/3 pixel.                                               */
+      width /= 3;
 
-        for ( xx = width_org; xx > 0; xx-- )
-        {
-          FT_UInt  pixel = line[xx-1];
+      bitmap->buffer += width;
 
+      error = render->raster_render( render->raster, &params );
+      if ( error )
+        goto Exit;
 
-          end[-3] = (FT_Byte)pixel;
-          end[-2] = (FT_Byte)pixel;
-          end[-1] = (FT_Byte)pixel;
-          end    -= 3;
+      FT_Outline_Translate( outline, -21, 0 );
+      x_shift        -= 21;
+      bitmap->buffer += width;
+
+      error = render->raster_render( render->raster, &params );
+      if ( error )
+        goto Exit;
+
+      FT_Outline_Translate( outline,  42, 0 );
+      x_shift        += 42;
+      bitmap->buffer -= 2 * width;
+
+      error = render->raster_render( render->raster, &params );
+      if ( error )
+        goto Exit;
+
+      /* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD.    */
+      /* XXX: It is more efficient to render every third byte above. */
+
+      if ( FT_ALLOC( temp, (FT_ULong)pitch ) )
+        goto Exit;
+
+      for ( i = 0; i < height; i++ )
+      {
+        line = bitmap->buffer + i * (FT_ULong)pitch;
+        for ( j = 0; j < width; j++ )
+        {
+          temp[3 * j    ] = line[j];
+          temp[3 * j + 1] = line[j + width];
+          temp[3 * j + 2] = line[j + width + width];
         }
+        FT_MEM_COPY( line, temp, pitch );
       }
-    }
 
-    /* expand it vertically */
-    if ( vmul )
+      FT_FREE( temp );
+    }
+    else if ( vmul )  /* lcd_v */
     {
-      FT_Byte*  read  = bitmap->buffer + ( height - height_org ) * pitch;
-      FT_Byte*  write = bitmap->buffer;
-      FT_UInt   hh;
+      int  pitch  = bitmap->pitch;
 
 
-      for ( hh = height_org; hh > 0; hh-- )
-      {
-        ft_memcpy( write, read, pitch );
-        write += pitch;
+      /* Render 3 separate monochrome bitmaps, shifting the outline  */
+      /* by 1/3 pixel. Triple the pitch to render on each third row. */
+      bitmap->pitch *= 3;
+      bitmap->rows  /= 3;
 
-        ft_memcpy( write, read, pitch );
-        write += pitch;
+      bitmap->buffer += pitch;
 
-        ft_memcpy( write, read, pitch );
-        write += pitch;
-        read  += pitch;
-      }
-    }
+      error = render->raster_render( render->raster, &params );
+      if ( error )
+        goto Exit;
 
-#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+      FT_Outline_Translate( outline, 0,  21 );
+      y_shift        += 21;
+      bitmap->buffer += pitch;
+
+      error = render->raster_render( render->raster, &params );
+      if ( error )
+        goto Exit;
+
+      FT_Outline_Translate( outline, 0, -42 );
+      y_shift        -= 42;
+      bitmap->buffer -= 2 * pitch;
 
-    /* everything is fine; don't deallocate buffer */
-    have_buffer = FALSE;
+      error = render->raster_render( render->raster, &params );
+      if ( error )
+        goto Exit;
 
-    error = FT_Err_Ok;
+      bitmap->pitch /= 3;
+      bitmap->rows  *= 3;
+    }
+    else  /* grayscale */
+      error = render->raster_render( render->raster, &params );
+
+#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
   Exit:
-    if ( have_outline_shifted )
-      FT_Outline_Translate( outline, -x_shift, -y_shift );
-    if ( have_buffer )
+    if ( !error )
+    {
+      /* everything is fine; the glyph is now officially a bitmap */
+      slot->format = FT_GLYPH_FORMAT_BITMAP;
+    }
+    else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
     {
       FT_FREE( bitmap->buffer );
       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
     }
 
+    if ( x_shift || y_shift )
+      FT_Outline_Translate( outline, -x_shift, -y_shift );
+
     return error;
   }
 
@@ -399,14 +363,8 @@
                         FT_Render_Mode    mode,
                         const FT_Vector*  origin )
   {
-    FT_Error  error;
-
-    error = ft_smooth_render_generic( render, slot, mode, origin,
-                                      FT_RENDER_MODE_LCD );
-    if ( !error )
-      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
-
-    return error;
+    return ft_smooth_render_generic( render, slot, mode, origin,
+                                     FT_RENDER_MODE_LCD );
   }
 
 
@@ -417,18 +375,13 @@
                           FT_Render_Mode    mode,
                           const FT_Vector*  origin )
   {
-    FT_Error  error;
-
-    error = ft_smooth_render_generic( render, slot, mode, origin,
-                                      FT_RENDER_MODE_LCD_V );
-    if ( !error )
-      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
-
-    return error;
+    return ft_smooth_render_generic( render, slot, mode, origin,
+                                     FT_RENDER_MODE_LCD_V );
   }
 
 
-  FT_DEFINE_RENDERER( ft_smooth_renderer_class,
+  FT_DEFINE_RENDERER(
+    ft_smooth_renderer_class,
 
       FT_MODULE_RENDERER,
       sizeof ( FT_RendererRec ),
@@ -437,25 +390,25 @@
       0x10000L,
       0x20000L,
 
-      0,    /* module specific interface */
+      NULL,    /* module specific interface */
 
-      (FT_Module_Constructor)ft_smooth_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
+      (FT_Module_Constructor)ft_smooth_init,  /* module_init   */
+      (FT_Module_Destructor) NULL,            /* module_done   */
+      (FT_Module_Requester)  NULL,            /* get_interface */
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Renderer_RenderFunc)   ft_smooth_render,
-    (FT_Renderer_TransformFunc)ft_smooth_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
+    (FT_Renderer_RenderFunc)   ft_smooth_render,     /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_smooth_transform,  /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,   /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,   /* set_mode        */
 
-    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
+    (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET           /* raster_class    */
   )
 
 
-  FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class,
+  FT_DEFINE_RENDERER(
+    ft_smooth_lcd_renderer_class,
 
       FT_MODULE_RENDERER,
       sizeof ( FT_RendererRec ),
@@ -464,24 +417,25 @@
       0x10000L,
       0x20000L,
 
-      0,    /* module specific interface */
+      NULL,    /* module specific interface */
 
-      (FT_Module_Constructor)ft_smooth_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
+      (FT_Module_Constructor)ft_smooth_init,  /* module_init   */
+      (FT_Module_Destructor) NULL,            /* module_done   */
+      (FT_Module_Requester)  NULL,            /* get_interface */
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,
-    (FT_Renderer_TransformFunc)ft_smooth_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
+    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,  /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_smooth_transform,   /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,    /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,    /* set_mode        */
 
-    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
+    (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET            /* raster_class    */
   )
 
-  FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class,
+
+  FT_DEFINE_RENDERER(
+    ft_smooth_lcdv_renderer_class,
 
       FT_MODULE_RENDERER,
       sizeof ( FT_RendererRec ),
@@ -490,21 +444,20 @@
       0x10000L,
       0x20000L,
 
-      0,    /* module specific interface */
+      NULL,    /* module specific interface */
 
-      (FT_Module_Constructor)ft_smooth_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
+      (FT_Module_Constructor)ft_smooth_init,  /* module_init   */
+      (FT_Module_Destructor) NULL,            /* module_done   */
+      (FT_Module_Requester)  NULL,            /* get_interface */
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,
-    (FT_Renderer_TransformFunc)ft_smooth_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
+    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,  /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_smooth_transform,     /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,      /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,      /* set_mode        */
 
-    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
+    (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET              /* raster_class    */
   )
 
 

Reply via email to