shithub: freetype+ttf2subf

Download patch

ref: d76fe5a1af5fb9a08b38d4d426688ee9cd34996b
parent: b66178851a4ea0a2bd15fd548d8f35f140913ca8
author: Werner Lemberg <[email protected]>
date: Wed Aug 8 02:38:06 EDT 2007

* src/otvalid/otvbase.c, src/otvalid/otvcommn.c,
src/otvalid/otvgdef.c, src/otvalid/otvgpos.c, src/otvalid/otvgsub.c,
src/otvalid/otvjstf.c: s/FT_INVALID_DATA/FT_INVALID_FORMAT/ where
appropriate.  Reported by George.

* include/freetype/internal/fttrace.h: Define `trace_otvmath'.

* src/otvalid/rules.mk (OTV_DRV_SRC): Add otvmath.c.

* docs/CHANGES: Updated.


Add `MATH' validating support to otvalid module.

* include/freetype/tttags.h (TTAG_MATH): New macro.
* include/freetype/ftotval.h (FT_VALIDATE_MATH): New macro.
(FT_VALIDATE_OT): Updated.

* src/otvalid/otmath.c: New file.

* src/otvalid/otvalid.c: Include otvmath.c.
* src/otvalid/otvmod.c (otv_validate): Handle `MATH' table.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2007-08-08  Werner Lemberg  <[email protected]>
+
+	* src/otvalid/otvbase.c, src/otvalid/otvcommn.c,
+	src/otvalid/otvgdef.c, src/otvalid/otvgpos.c, src/otvalid/otvgsub.c,
+	src/otvalid/otvjstf.c: s/FT_INVALID_DATA/FT_INVALID_FORMAT/ where
+	appropriate.  Reported by George.
+
+	* include/freetype/internal/fttrace.h: Define `trace_otvmath'.
+
+	* src/otvalid/rules.mk (OTV_DRV_SRC): Add otvmath.c.
+
+	* docs/CHANGES: Updated.
+
+2007-08-08  George Williams  <[email protected]>
+
+	Add `MATH' validating support to otvalid module.
+
+	* include/freetype/tttags.h (TTAG_MATH): New macro.
+	* include/freetype/ftotval.h (FT_VALIDATE_MATH): New macro.
+	(FT_VALIDATE_OT): Updated.
+
+	* src/otvalid/otmath.c: New file.
+
+	* src/otvalid/otvalid.c: Include otvmath.c.
+	* src/otvalid/otvmod.c (otv_validate): Handle `MATH' table.
+
 2007-08-04  Werner Lemberg  <[email protected]>
 
 	* builds/unix/configure.raw: Add call to AC_LIBTOOL_WIN32_DLL. 
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -7,6 +7,9 @@
       access to  those fields in a CID-keyed font.  The code  has been
       contributed by Derek Clegg.
 
+    - George Williams  contributed  code  to validate  the new  `MATH'
+      OpenType  table (within  the `otvalid'  module).  The  `ftvalid'
+      demo program has been extended accordingly.
 
 ======================================================================
 
--- a/include/freetype/ftotval.h
+++ b/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for validating OpenType tables (specification).         */
 /*                                                                         */
-/*  Copyright 2004, 2005, 2006 by                                          */
+/*  Copyright 2004, 2005, 2006, 2007 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -86,8 +86,11 @@
   *    FT_VALIDATE_JSTF ::
   *      Validate JSTF table.
   *
+  *    FT_VALIDATE_MATH ::
+  *      Validate MATH table.
+  *
   *    FT_VALIDATE_OT ::
-  *      Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF).
+  *      Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).
   *
   */
 #define FT_VALIDATE_BASE  0x0100
@@ -95,12 +98,14 @@
 #define FT_VALIDATE_GPOS  0x0400
 #define FT_VALIDATE_GSUB  0x0800
 #define FT_VALIDATE_JSTF  0x1000
+#define FT_VALIDATE_MATH  0x2000
 
 #define FT_VALIDATE_OT  FT_VALIDATE_BASE | \
                         FT_VALIDATE_GDEF | \
                         FT_VALIDATE_GPOS | \
                         FT_VALIDATE_GSUB | \
-                        FT_VALIDATE_JSTF
+                        FT_VALIDATE_JSTF | \
+                        FT_VALIDATE_MATH
 
   /* */
 
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tracing handling (specification only).                               */
 /*                                                                         */
-/*  Copyright 2002, 2004, 2005, 2006 by                                    */
+/*  Copyright 2002, 2004, 2005, 2006, 2007 by                              */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -114,6 +114,7 @@
 FT_TRACE_DEF( otvgpos )
 FT_TRACE_DEF( otvgsub )
 FT_TRACE_DEF( otvjstf )
+FT_TRACE_DEF( otvmath )
 
   /* TrueTypeGX/AAT validation components */
 FT_TRACE_DEF( gxvmodule )
--- a/include/freetype/tttags.h
+++ b/include/freetype/tttags.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tags for TrueType and OpenType tables (specification only).          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2004, 2005 by                                     */
+/*  Copyright 1996-2001, 2004, 2005, 2007 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -67,6 +67,7 @@
 #define TTAG_lcar  FT_MAKE_TAG( 'l', 'c', 'a', 'r' )
 #define TTAG_loca  FT_MAKE_TAG( 'l', 'o', 'c', 'a' )
 #define TTAG_LTSH  FT_MAKE_TAG( 'L', 'T', 'S', 'H' )
+#define TTAG_MATH  FT_MAKE_TAG( 'M', 'A', 'T', 'H' )
 #define TTAG_maxp  FT_MAKE_TAG( 'm', 'a', 'x', 'p' )
 #define TTAG_META  FT_MAKE_TAG( 'M', 'E', 'T', 'A' )
 #define TTAG_MMFX  FT_MAKE_TAG( 'M', 'M', 'F', 'X' )
--- a/src/otvalid/otvalid.c
+++ b/src/otvalid/otvalid.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType validator for OpenType tables (body only).                  */
 /*                                                                         */
-/*  Copyright 2004 by                                                      */
+/*  Copyright 2004, 2007 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,6 +25,7 @@
 #include "otvgpos.c"
 #include "otvgsub.c"
 #include "otvjstf.c"
+#include "otvmath.c"
 #include "otvmod.c"
 
 /* END */
--- a/src/otvalid/otvbase.c
+++ b/src/otvalid/otvbase.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType BASE table validation (body).                               */
 /*                                                                         */
-/*  Copyright 2004 by                                                      */
+/*  Copyright 2004, 2007 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -62,7 +62,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -297,7 +297,7 @@
     OTV_LIMIT_CHECK( 6 );
 
     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
 
     table_size = 6;
 
--- a/src/otvalid/otvcommn.c
+++ b/src/otvalid/otvcommn.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType common tables validation (body).                            */
 /*                                                                         */
-/*  Copyright 2004, 2005, 2006 by                                          */
+/*  Copyright 2004, 2005, 2006, 2007 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -291,7 +291,10 @@
     EndSize     = FT_NEXT_USHORT( p );
     DeltaFormat = FT_NEXT_USHORT( p );
 
-    if ( DeltaFormat < 1 || DeltaFormat > 3 || EndSize < StartSize )
+    if ( DeltaFormat < 1 || DeltaFormat > 3 )
+      FT_INVALID_FORMAT;
+
+    if ( EndSize < StartSize )
       FT_INVALID_DATA;
 
     count = EndSize - StartSize + 1;
--- a/src/otvalid/otvgdef.c
+++ b/src/otvalid/otvgdef.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType GDEF table validation (body).                               */
 /*                                                                         */
-/*  Copyright 2004, 2005 by                                                */
+/*  Copyright 2004, 2005, 2007 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -126,7 +126,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
--- a/src/otvalid/otvgpos.c
+++ b/src/otvalid/otvgpos.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType GPOS table validation (body).                               */
 /*                                                                         */
-/*  Copyright 2002, 2004, 2005, 2006 by                                    */
+/*  Copyright 2002, 2004, 2005, 2006, 2007 by                              */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -191,7 +191,7 @@
 #endif
 
     if ( format >= 0x100 )
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
 
     for ( count = 4; count > 0; count-- )
     {
@@ -294,7 +294,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -409,7 +409,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -558,7 +558,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -629,7 +629,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -670,7 +670,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -711,7 +711,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -752,7 +752,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -811,7 +811,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -872,7 +872,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -925,7 +925,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -989,7 +989,7 @@
     OTV_LIMIT_CHECK( 10 );
 
     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
 
     ScriptList  = FT_NEXT_USHORT( p );
     FeatureList = FT_NEXT_USHORT( p );
--- a/src/otvalid/otvgsub.c
+++ b/src/otvalid/otvgsub.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType GSUB table validation (body).                               */
 /*                                                                         */
-/*  Copyright 2004, 2005 by                                                */
+/*  Copyright 2004, 2005, 2007 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -103,7 +103,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -144,7 +144,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -185,7 +185,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -259,7 +259,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -318,7 +318,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -379,7 +379,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -434,7 +434,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -509,7 +509,7 @@
       break;
 
     default:
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
     }
 
     OTV_EXIT;
@@ -560,7 +560,7 @@
     OTV_LIMIT_CHECK( 10 );
 
     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
 
     ScriptList  = FT_NEXT_USHORT( p );
     FeatureList = FT_NEXT_USHORT( p );
--- a/src/otvalid/otvjstf.c
+++ b/src/otvalid/otvjstf.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType JSTF table validation (body).                               */
 /*                                                                         */
-/*  Copyright 2004 by                                                      */
+/*  Copyright 2004, 2007 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -222,7 +222,7 @@
     OTV_LIMIT_CHECK( 6 );
 
     if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
-      FT_INVALID_DATA;
+      FT_INVALID_FORMAT;
 
     JstfScriptCount = FT_NEXT_USHORT( p );
 
--- /dev/null
+++ b/src/otvalid/otvmath.c
@@ -1,0 +1,426 @@
+/***************************************************************************/
+/*                                                                         */
+/*  otvmath.c                                                              */
+/*                                                                         */
+/*    OpenType MATH table validation (body).                               */
+/*                                                                         */
+/*  Copyright 2007 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  Written by George Williams.                                            */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "otvalid.h"
+#include "otvcommn.h"
+#include "otvgpos.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_otvmath
+
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                  MATH TYPOGRAPHIC CONSTANTS                   *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  otv_MathConstants_validate( FT_Bytes       table,
+                              OTV_Validator  valid )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   i;
+    FT_UInt   table_size;
+
+    OTV_OPTIONAL_TABLE( DeviceTableOffset );
+
+
+    OTV_NAME_ENTER( "MathConstants" );
+
+    /* 57 constants, 52 have device tables */
+    OTV_LIMIT_CHECK( 2 * ( 57 + 52 ) );
+    table_size = 2 * ( 57 + 52 );
+
+    p += 4 * 2;                 /* First 4 constants have no device tables */
+    for ( i = 0; i < 52; ++i )
+    {
+      p += 2;                                            /* skip the value */
+      OTV_OPTIONAL_OFFSET( DeviceTableOffset );
+      OTV_SIZE_CHECK( DeviceTableOffset );
+      if ( DeviceTableOffset )
+        otv_Device_validate( table + DeviceTableOffset, valid );
+    }
+
+    OTV_EXIT;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   MATH ITALICS CORRECTION                     *****/
+  /*****                 MATH TOP ACCENT ATTACHMENT                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  otv_MathItalicsCorrectionInfo_validate( FT_Bytes       table,
+                                          OTV_Validator  valid,
+                                          FT_Int         isItalic )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   i, cnt, table_size ;
+
+    OTV_OPTIONAL_TABLE( Coverage );
+    OTV_OPTIONAL_TABLE( DeviceTableOffset );
+
+
+    OTV_NAME_ENTER( isItalic ? "MathItalicsCorrectionInfo"
+                             : "MathTopAccentAttachment" );
+
+    OTV_LIMIT_CHECK( 4 );
+
+    OTV_OPTIONAL_OFFSET( Coverage );
+    cnt = FT_NEXT_USHORT( p );
+
+    OTV_LIMIT_CHECK( 4 * cnt );
+    table_size = 4 + 4 * cnt;
+
+    OTV_SIZE_CHECK( Coverage );
+    otv_Coverage_validate( table + Coverage, valid );
+
+    for ( i = 0; i < cnt; ++i )
+    {
+      p += 2;                                            /* Skip the value */
+      OTV_OPTIONAL_OFFSET( DeviceTableOffset );
+      OTV_SIZE_CHECK( DeviceTableOffset );
+      if ( DeviceTableOffset )
+        otv_Device_validate( table + DeviceTableOffset, valid );
+    }
+
+    OTV_EXIT;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                           MATH KERNING                        *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  otv_MathKern_validate( FT_Bytes       table,
+                         OTV_Validator  valid )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   i, cnt, table_size;
+
+    OTV_OPTIONAL_TABLE( DeviceTableOffset );
+
+
+    /* OTV_NAME_ENTER( "MathKern" );*/
+
+    OTV_LIMIT_CHECK( 2 );
+
+    cnt = FT_NEXT_USHORT( p );
+
+    OTV_LIMIT_CHECK( 4 * cnt + 2 );
+    table_size = 4 + 4 * cnt;
+
+    /* Heights */
+    for ( i = 0; i < cnt; ++i )
+    {
+      p += 2;                                            /* Skip the value */
+      OTV_OPTIONAL_OFFSET( DeviceTableOffset );
+      OTV_SIZE_CHECK( DeviceTableOffset );
+      if ( DeviceTableOffset )
+        otv_Device_validate( table + DeviceTableOffset, valid );
+    }
+
+    /* One more Kerning value */
+    for ( i = 0; i < cnt + 1; ++i )
+    {
+      p += 2;                                            /* Skip the value */
+      OTV_OPTIONAL_OFFSET( DeviceTableOffset );
+      OTV_SIZE_CHECK( DeviceTableOffset );
+      if ( DeviceTableOffset )
+        otv_Device_validate( table + DeviceTableOffset, valid );
+    }
+
+    OTV_EXIT;
+  }
+
+
+  static void
+  otv_MathKernInfo_validate( FT_Bytes       table,
+                             OTV_Validator  valid )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   i, j, cnt, table_size;
+
+    OTV_OPTIONAL_TABLE( Coverage );
+    OTV_OPTIONAL_TABLE( MKRecordOffset );
+
+
+    OTV_NAME_ENTER( "MathKernInfo" );
+
+    OTV_LIMIT_CHECK( 4 );
+
+    OTV_OPTIONAL_OFFSET( Coverage );
+    cnt = FT_NEXT_USHORT( p );
+
+    OTV_LIMIT_CHECK( 8 * cnt );
+    table_size = 4 + 8 * cnt;
+
+    OTV_SIZE_CHECK( Coverage );
+    otv_Coverage_validate( table + Coverage, valid );
+
+    for ( i = 0; i < cnt; ++i )
+    {
+      for ( j = 0; j < 4; ++j )
+      {
+        OTV_OPTIONAL_OFFSET( MKRecordOffset );
+        OTV_SIZE_CHECK( MKRecordOffset );
+        if ( MKRecordOffset )
+          otv_MathKern_validate( table + MKRecordOffset, valid );
+      }
+    }
+
+    OTV_EXIT;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                         MATH GLYPH INFO                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  otv_MathGlyphInfo_validate( FT_Bytes       table,
+                              OTV_Validator  valid )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   MathItalicsCorrectionInfo, MathTopAccentAttachment;
+    FT_UInt   ExtendedShapeCoverage, MathKernInfo;
+
+
+    OTV_NAME_ENTER( "MathGlyphInfo" );
+
+    OTV_LIMIT_CHECK( 8 );
+
+    MathItalicsCorrectionInfo = FT_NEXT_USHORT( p );
+    MathTopAccentAttachment   = FT_NEXT_USHORT( p );
+    ExtendedShapeCoverage     = FT_NEXT_USHORT( p );
+    MathKernInfo              = FT_NEXT_USHORT( p );
+
+    if ( MathItalicsCorrectionInfo )
+      otv_MathItalicsCorrectionInfo_validate(
+        table + MathItalicsCorrectionInfo, valid, TRUE );
+
+    /* Italic correction and Top Accent Attachment have the same format */
+    if ( MathTopAccentAttachment )
+      otv_MathItalicsCorrectionInfo_validate(
+        table + MathTopAccentAttachment, valid, FALSE );
+
+    if ( ExtendedShapeCoverage ) {
+      OTV_NAME_ENTER( "ExtendedShapeCoverage" );
+      otv_Coverage_validate( table + ExtendedShapeCoverage, valid );
+      OTV_EXIT;
+    }
+
+    if ( MathKernInfo )
+      otv_MathKernInfo_validate( table + MathKernInfo, valid );
+
+    OTV_EXIT;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    MATH GLYPH CONSTRUCTION                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  otv_GlyphAssembly_validate( FT_Bytes       table,
+                              OTV_Validator  valid )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   pcnt, table_size;
+
+    OTV_OPTIONAL_TABLE( DeviceTableOffset );
+
+
+    /* OTV_NAME_ENTER( "GlyphAssembly" ); */
+
+    OTV_LIMIT_CHECK( 6 );
+
+    p += 2;                           /* Skip the Italics Correction value */
+    OTV_OPTIONAL_OFFSET( DeviceTableOffset );
+    pcnt = FT_NEXT_USHORT( p );
+
+    OTV_LIMIT_CHECK( 8 * pcnt );
+    table_size = 6 + 8 * pcnt;
+
+    OTV_SIZE_CHECK( DeviceTableOffset );
+    if ( DeviceTableOffset )
+      otv_Device_validate( table + DeviceTableOffset, valid );
+
+    /* OTV_EXIT; */
+  }
+
+
+  static void
+  otv_MathGlyphConstruction_validate( FT_Bytes       table,
+                                      OTV_Validator  valid )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   vcnt, table_size;
+
+    OTV_OPTIONAL_TABLE( GlyphAssembly );
+
+
+    /* OTV_NAME_ENTER( "MathGlyphConstruction" ); */
+
+    OTV_LIMIT_CHECK( 4 );
+
+    OTV_OPTIONAL_OFFSET( GlyphAssembly );
+    vcnt = FT_NEXT_USHORT( p );
+
+    OTV_LIMIT_CHECK( 4 * vcnt );
+    table_size = 4 + 4 * vcnt;
+
+    OTV_SIZE_CHECK( GlyphAssembly );
+    if ( GlyphAssembly )
+      otv_GlyphAssembly_validate( table+GlyphAssembly, valid );
+
+    /* OTV_EXIT; */
+  }
+
+
+  static void
+  otv_MathVariants_validate( FT_Bytes       table,
+                             OTV_Validator  valid )
+  {
+    FT_Bytes  p = table;
+    FT_UInt   vcnt, hcnt, i, table_size;
+
+    OTV_OPTIONAL_TABLE( VCoverage );
+    OTV_OPTIONAL_TABLE( HCoverage );
+    OTV_OPTIONAL_TABLE( Offset );
+
+
+    OTV_NAME_ENTER( "MathVariants" );
+
+    OTV_LIMIT_CHECK( 10 );
+
+    p += 2;                       /* Skip the MinConnectorOverlap constant */
+    OTV_OPTIONAL_OFFSET( VCoverage );
+    OTV_OPTIONAL_OFFSET( HCoverage );
+    vcnt = FT_NEXT_USHORT( p );
+    hcnt = FT_NEXT_USHORT( p );
+
+    OTV_LIMIT_CHECK( 2 * vcnt + 2 * hcnt );
+    table_size = 10 + 2 * vcnt + 2 * hcnt;
+
+    OTV_SIZE_CHECK( VCoverage );
+    if ( VCoverage )
+      otv_Coverage_validate( table + VCoverage, valid );
+
+    OTV_SIZE_CHECK( HCoverage );
+    if ( HCoverage )
+      otv_Coverage_validate( table + HCoverage, valid );
+
+    for ( i = 0; i < vcnt; ++i )
+    {
+      OTV_OPTIONAL_OFFSET( Offset );
+      OTV_SIZE_CHECK( Offset );
+      otv_MathGlyphConstruction_validate( table + Offset, valid );
+    }
+
+    for ( i = 0; i < hcnt; ++i )
+    {
+      OTV_OPTIONAL_OFFSET( Offset );
+      OTV_SIZE_CHECK( Offset );
+      otv_MathGlyphConstruction_validate( table + Offset, valid );
+    }
+
+    OTV_EXIT;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                          MATH TABLE                           *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* sets valid->glyph_count */
+
+  FT_LOCAL_DEF( void )
+  otv_MATH_validate( FT_Bytes      table,
+                     FT_UInt       glyph_count,
+                     FT_Validator  ftvalid )
+  {
+    OTV_ValidatorRec  validrec;
+    OTV_Validator     valid = &validrec;
+    FT_Bytes          p     = table;
+    FT_UInt           MathConstants, MathGlyphInfo, MathVariants;
+
+
+    valid->root = ftvalid;
+
+    FT_TRACE3(( "validating MATH table\n" ));
+    OTV_INIT;
+
+    OTV_LIMIT_CHECK( 10 );
+
+    if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
+      FT_INVALID_FORMAT;
+
+    MathConstants = FT_NEXT_USHORT( p );
+    MathGlyphInfo = FT_NEXT_USHORT( p );
+    MathVariants  = FT_NEXT_USHORT( p );
+
+    valid->glyph_count = glyph_count;
+
+    otv_MathConstants_validate( table + MathConstants,
+                                valid );
+    otv_MathGlyphInfo_validate( table + MathGlyphInfo,
+                                valid );
+    otv_MathVariants_validate ( table + MathVariants,
+                                valid );
+
+    FT_TRACE4(( "\n" ));
+  }
+
+
+/* END */
--- a/src/otvalid/otvmod.c
+++ b/src/otvalid/otvmod.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType's OpenType validation module implementation (body).         */
 /*                                                                         */
-/*  Copyright 2004, 2005, 2006 by                                          */
+/*  Copyright 2004, 2005, 2006, 2007 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -79,12 +79,14 @@
     FT_Byte* volatile         gpos;
     FT_Byte* volatile         gsub;
     FT_Byte* volatile         jstf;
+    FT_Byte* volatile         math;
     FT_ULong                  len_base, len_gdef, len_gpos, len_gsub, len_jstf;
+    FT_ULong                  len_math;
     FT_ValidatorRec volatile  valid;
 
 
-    base     = gdef     = gpos     = gsub     = jstf     = NULL;
-    len_base = len_gdef = len_gpos = len_gsub = len_jstf = 0;
+    base     = gdef     = gpos     = gsub     = jstf     = math     = NULL;
+    len_base = len_gdef = len_gpos = len_gsub = len_jstf = len_math = 0;
 
     /* load tables */
 
@@ -123,6 +125,13 @@
         goto Exit;
     }
 
+    if ( ot_flags & FT_VALIDATE_MATH )
+    {
+      error = otv_load_table( face, TTAG_MATH, &math, &len_math );
+      if ( error )
+        goto Exit;
+    }
+
     /* validate tables */
 
     if ( base )
@@ -175,6 +184,16 @@
         goto Exit;
     }
 
+    if ( math )
+    {
+      ft_validator_init( &valid, math, math + len_math, FT_VALIDATE_DEFAULT );
+      if ( ft_setjmp( valid.jump_buffer ) == 0 )
+        otv_MATH_validate( math, face->num_glyphs, &valid );
+      error = valid.error;
+      if ( error )
+        goto Exit;
+    }
+
     *ot_base = (FT_Bytes)base;
     *ot_gdef = (FT_Bytes)gdef;
     *ot_gpos = (FT_Bytes)gpos;
@@ -191,6 +210,12 @@
       FT_FREE( gpos );
       FT_FREE( gsub );
       FT_FREE( jstf );
+    }
+    {
+      FT_Memory  memory = FT_FACE_MEMORY( face );
+
+
+      FT_FREE( math );                 /* Can't return this as API is frozen */
     }
 
     return error;
--- a/src/otvalid/rules.mk
+++ b/src/otvalid/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright 2004 by
+# Copyright 2004, 2007 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -31,14 +31,15 @@
                $(OTV_DIR)/otvgpos.c  \
                $(OTV_DIR)/otvgsub.c  \
                $(OTV_DIR)/otvjstf.c  \
+               $(OTV_DIR)/otvmath.c  \
                $(OTV_DIR)/otvmod.c
 
 # OTV driver headers
 #
-OTV_DRV_H := $(OTV_DIR)/otvalid.h \
-             $(OTV_DIR)/otverror.h  \
+OTV_DRV_H := $(OTV_DIR)/otvalid.h  \
              $(OTV_DIR)/otvcommn.h \
-             $(OTV_DIR)/otvgpos.h \
+             $(OTV_DIR)/otverror.h \
+             $(OTV_DIR)/otvgpos.h  \
              $(OTV_DIR)/otvmod.h