Commits

Anonymous committed 57e6107

Upgrade to latest Harfbuzz library and add CleanSpec.mk.

The Harfbuzz version includes:
1. More bug fixings.
2. Memory reduction - 50 % less.
3. Shapping for Greek.

Note: The following files include the bug fixings from Chrome:
a. contrib/harfbuzz-unicode.c
b. src/harfbuzz-shaper.cpp

Change-Id: I9f5fc16b01c85fb54bbd66c6f9f5526e68e7d01a

  • Participants
  • Parent commits bc50321

Comments (0)

Files changed (31)

         src/harfbuzz-arabic.c \
         src/harfbuzz-hangul.c \
         src/harfbuzz-myanmar.c \
-        src/harfbuzz-thai.c
+        src/harfbuzz-thai.c \
+        src/harfbuzz-greek.c
 
 LOCAL_SHARED_LIBRARIES := \
         libcutils \

File CleanSpec.mk

+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libharfbuzz_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libharfbuzz_intermediates)
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************

File contrib/harfbuzz-unicode.c

 }
 
 void *
-HB_Library_Resolve(const char *library, const char *symbol) {
+HB_Library_Resolve(const char *library, int version, const char *symbol) {
   abort();
   return NULL;
 }
-
-void *
-HB_TextCodecForMib(int mib) {
-  abort();
-  return NULL;
-}
-
-char *
-HB_TextCodec_ConvertFromUnicode(void *codec, const HB_UChar16 *unicode, hb_uint32 length, hb_uint32 *outputLength) {
-  abort();
-  return NULL;
-}
-
-void
-HB_TextCodec_FreeResult(char *v) {
-  abort();
-}

File src/Makefile.am

 	harfbuzz-impl.c \
 	harfbuzz-open.c \
 	harfbuzz-shaper.cpp \
-	harfbuzz-tibetan.c \
+        harfbuzz-greek.c \
+        harfbuzz-tibetan.c \
 	harfbuzz-khmer.c \
 	harfbuzz-indic.cpp \
 	harfbuzz-hebrew.c \

File src/harfbuzz-arabic.c

     assert(item->item.script == HB_Script_Arabic || item->item.script == HB_Script_Syriac
            || item->item.script == HB_Script_Nko);
 
-    item->shaperFlags |= HB_ShaperFlag_ForceMarksToZeroWidth;
 #ifndef NO_OPENTYPE
 
     if (HB_SelectScript(item, item->item.script == HB_Script_Arabic ? arabic_features : syriac_features)) {

File src/harfbuzz-buffer.h

 
 HB_BEGIN_HEADER
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(push, 1)
+#endif
+
 typedef struct HB_GlyphItemRec_ {
   HB_UInt     gindex;
   HB_UInt     properties;
   HB_Fixed   y_advance;
   HB_UShort  back;            /* number of glyphs to go back
 				 for drawing current glyph   */
+  HB_Short  cursive_chain;   /* character to which this connects,
+				 may be positive or negative; used
+				 only internally                     */
   HB_Bool    new_advance;     /* if set, the advance width values are
 				 absolute, i.e., they won't be
 				 added to the original glyph's value
 				 but rather replace them.            */
-  HB_Short  cursive_chain;   /* character to which this connects,
-				 may be positive or negative; used
-				 only internally                     */
 } HB_PositionRec, *HB_Position;
 
 
   HB_UInt    in_pos;
   HB_UInt    out_pos;
   
-  HB_Bool       separate_out;
   HB_GlyphItem  in_string;
   HB_GlyphItem  out_string;
   HB_GlyphItem  alt_string;
   HB_Position   positions;
   HB_UShort      max_ligID;
+  HB_Bool       separate_out;
 } HB_BufferRec, *HB_Buffer;
 
 HB_Error
 		      HB_UInt    properties,
 		      HB_UInt    cluster );
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(pop)
+#endif
+
 HB_END_HEADER
 
 #endif /* HARFBUZZ_BUFFER_H */

File src/harfbuzz-dump.c

   if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE)
     DUMP_FINT (ValueRecord, XAdvance);
   if (value_format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE)
-    RECURSE (Device, Device, &ValueRecord->XPlacementDevice);
+    RECURSE (Device, Device, &*ValueRecord->DeviceTables[VR_X_PLACEMENT_DEVICE]);
   if (value_format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE)
-    RECURSE (Device, Device, &ValueRecord->YPlacementDevice);
+    RECURSE (Device, Device, &*ValueRecord->DeviceTables[VR_Y_PLACEMENT_DEVICE]);
   if (value_format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE)
-    RECURSE (Device, Device, &ValueRecord->XAdvanceDevice);
+    RECURSE (Device, Device, &*ValueRecord->DeviceTables[VR_X_ADVANCE_DEVICE]);
   if (value_format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE)
-    RECURSE (Device, Device, &ValueRecord->YAdvanceDevice);
+    RECURSE (Device, Device, &*ValueRecord->DeviceTables[VR_Y_ADVANCE_DEVICE]);
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   if (value_format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT)
     DUMP_FUINT (ValueRecord, XIdPlacement);
   if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT)
     DUMP_FUINT (ValueRecord, XIdAdvance);
   if (value_format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE)
     DUMP_FUINT (ValueRecord, XIdAdvance);
+#endif
 }
 
 static void

File src/harfbuzz-external.h

 int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch);
 HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch);
 
-void *HB_Library_Resolve(const char *library, const char *symbol);
-
-void *HB_TextCodecForMib(int mib);
-char *HB_TextCodec_ConvertFromUnicode(void *codec, const HB_UChar16 *unicode, hb_uint32 length, hb_uint32 *outputLength);
-void HB_TextCodec_FreeResult(char *);
+void *HB_Library_Resolve(const char *library, int version, const char *symbol);
 
 HB_END_HEADER
 

File src/harfbuzz-gdef-private.h

 HB_BEGIN_HEADER
 
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(push, 1)
+#endif
+
 /* Attachment related structures */
 
 struct  HB_AttachPoint_
 {
-  HB_UShort   PointCount;             /* size of the PointIndex array */
   HB_UShort*  PointIndex;             /* array of contour points      */
+  HB_UShort   PointCount;             /* size of the PointIndex array */
 };
 
 /* Ligature Caret related structures */
 
 struct  HB_CaretValueFormat3_
 {
+  HB_Device*  Device;                 /* Device table for x or y value  */
   HB_Short    Coordinate;             /* x or y value (in design units) */
-  HB_Device  Device;                 /* Device table for x or y value  */
 };
 
 typedef struct HB_CaretValueFormat3_  HB_CaretValueFormat3;
 
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
 struct  HB_CaretValueFormat4_
 {
   HB_UShort  IdCaretValue;            /* metric ID */
 };
 
 typedef struct HB_CaretValueFormat4_  HB_CaretValueFormat4;
+#endif
 
 
 struct  HB_CaretValue_
 {
-  HB_UShort  CaretValueFormat;        /* 1, 2, 3, or 4 */
-
   union
   {
     HB_CaretValueFormat1  cvf1;
     HB_CaretValueFormat2  cvf2;
     HB_CaretValueFormat3  cvf3;
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     HB_CaretValueFormat4  cvf4;
+#endif
   } cvf;
+
+  HB_Byte  CaretValueFormat;          /* 1, 2, 3, or 4 */
 };
 
 typedef struct HB_CaretValue_  HB_CaretValue;
 
 struct  HB_LigGlyph_
 {
-  HB_Bool          loaded;
-
-  HB_UShort        CaretCount;        /* number of caret values */
   HB_CaretValue*  CaretValue;        /* array of caret values  */
+  HB_UShort        CaretCount;        /* number of caret values */
+  HB_Bool          loaded;
 };
 
 
 						  HB_Lookup*     lo,
 						  HB_UShort      num_lookups );
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(pop)
+#endif
+
 HB_END_HEADER
 
 #endif /* HARFBUZZ_GDEF_PRIVATE_H */

File src/harfbuzz-gdef.c

     if ( ACCESS_Frame( 2L ) )
       return error;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     cv->cvf.cvf4.IdCaretValue = GET_UShort();
+#else
+    (void) GET_UShort();
+#endif
 
     FORGET_Frame();
     break;
 static void  Free_CaretValue( HB_CaretValue*  cv)
 {
   if ( cv->CaretValueFormat == 3 )
-    _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device );
+    _HB_OPEN_Free_Device( cv->cvf.cvf3.Device );
 }
 
 

File src/harfbuzz-gdef.h

 
 HB_BEGIN_HEADER
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(push, 1)
+#endif
+
 /* GDEF glyph properties.  Note that HB_GDEF_COMPONENT has no corresponding
  * flag in the LookupFlag field.     */
 #define HB_GDEF_BASE_GLYPH  0x0002
 
 struct  HB_AttachList_
 {
-  HB_Bool           loaded;
-
+  HB_AttachPoint*   AttachPoint;      /* array of AttachPoint tables */
   HB_Coverage       Coverage;         /* Coverage table              */
   HB_UShort         GlyphCount;       /* number of glyphs with
 					 attachments                 */
-  HB_AttachPoint*   AttachPoint;      /* array of AttachPoint tables */
+  HB_Bool           loaded;
 };
 
 typedef struct HB_AttachList_  HB_AttachList;
 
 struct  HB_LigCaretList_
 {
-  HB_Bool        loaded;
-
+  HB_LigGlyph*   LigGlyph;            /* array of LigGlyph tables  */
   HB_Coverage    Coverage;            /* Coverage table            */
   HB_UShort      LigGlyphCount;       /* number of ligature glyphs */
-  HB_LigGlyph*   LigGlyph;            /* array of LigGlyph tables  */
+  HB_Bool        loaded;
 };
 
 typedef struct HB_LigCaretList_  HB_LigCaretList;
 
 struct  HB_GDEFHeader_
 {
+  HB_UShort**          NewGlyphClasses;
   HB_UInt             offset;
+  HB_UInt             MarkAttachClassDef_offset;
 
   HB_16Dot16             Version;
 
   HB_ClassDefinition   GlyphClassDef;
   HB_AttachList        AttachList;
   HB_LigCaretList      LigCaretList;
-  HB_UInt             MarkAttachClassDef_offset;
   HB_ClassDefinition   MarkAttachClassDef;        /* new in OT 1.2 */
 
   HB_UShort            LastGlyph;
-  HB_UShort**          NewGlyphClasses;
 };
 
 typedef struct HB_GDEFHeader_   HB_GDEFHeader;
 					 HB_UShort*       glyph_array,
 					 HB_UShort*       class_array );
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(pop)
+#endif
 
 HB_END_HEADER
 

File src/harfbuzz-global.h

 #define HB_END_HEADER  /* nothing */
 #endif
 
+#if defined(__GNUC__) || defined(_MSC_VER)
+#define HB_USE_PACKED_STRUCTS
+#endif
+
 HB_BEGIN_HEADER
 
 #ifndef FALSE

File src/harfbuzz-gpos-private.h

 
 HB_BEGIN_HEADER
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(push, 1)
+#endif
 
 /* shared tables */
 
+#define VR_X_PLACEMENT_DEVICE 0
+#define VR_Y_PLACEMENT_DEVICE 1
+#define VR_X_ADVANCE_DEVICE   2
+#define VR_Y_ADVANCE_DEVICE   3
+
 struct  HB_ValueRecord_
 {
   HB_Short    XPlacement;             /* horizontal adjustment for
 					 advance                        */
   HB_Short    YAdvance;               /* vertical adjustment for
 					 advance                        */
-  HB_Device  XPlacementDevice;       /* device table for horizontal
-					 placement                      */
-  HB_Device  YPlacementDevice;       /* device table for vertical
-					 placement                      */
-  HB_Device  XAdvanceDevice;         /* device table for horizontal
-					 advance                        */
-  HB_Device  YAdvanceDevice;         /* device table for vertical
-					 advance                        */
+
+  HB_Device** DeviceTables;           /* device tables for placement
+					 and advance                    */
+
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   HB_UShort   XIdPlacement;           /* horizontal placement metric ID */
   HB_UShort   YIdPlacement;           /* vertical placement metric ID   */
   HB_UShort   XIdAdvance;             /* horizontal advance metric ID   */
   HB_UShort   YIdAdvance;             /* vertical advance metric ID     */
+#endif
 };
 
 typedef struct HB_ValueRecord_  HB_ValueRecord;
 /* Mask values to scan the value format of the ValueRecord structure.
  We always expand compressed ValueRecords of the font.              */
 
+#define HB_GPOS_FORMAT_HAVE_DEVICE_TABLES       0x00F0
+
 #define HB_GPOS_FORMAT_HAVE_X_PLACEMENT         0x0001
 #define HB_GPOS_FORMAT_HAVE_Y_PLACEMENT         0x0002
 #define HB_GPOS_FORMAT_HAVE_X_ADVANCE           0x0004
 
 typedef struct HB_AnchorFormat2_  HB_AnchorFormat2;
 
+#define AF3_X_DEVICE_TABLE 0
+#define AF3_Y_DEVICE_TABLE 1
 
 struct  HB_AnchorFormat3_
 {
   HB_Short    XCoordinate;            /* horizontal value              */
   HB_Short    YCoordinate;            /* vertical value                */
-  HB_Device  XDeviceTable;           /* device table for X coordinate */
-  HB_Device  YDeviceTable;           /* device table for Y coordinate */
+  HB_Device** DeviceTables;           /* device tables for coordinates */
 };
 
 typedef struct HB_AnchorFormat3_  HB_AnchorFormat3;
 
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
 struct  HB_AnchorFormat4_
 {
   HB_UShort  XIdAnchor;               /* horizontal metric ID */
 };
 
 typedef struct HB_AnchorFormat4_  HB_AnchorFormat4;
+#endif
 
 
 struct  HB_Anchor_
 {
-  HB_UShort  PosFormat;               /* 1, 2, 3, or 4 -- 0 indicates
+  HB_Byte  PosFormat;                 /* 1, 2, 3, or 4 -- 0 indicates
 					 that there is no Anchor table */
 
   union
     HB_AnchorFormat1  af1;
     HB_AnchorFormat2  af2;
     HB_AnchorFormat3  af3;
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     HB_AnchorFormat4  af4;
+#endif
   } af;
 };
 
 
 struct  HB_SinglePos_
 {
-  HB_UShort     PosFormat;            /* 1 or 2         */
+  HB_Byte       PosFormat;            /* 1 or 2         */
   HB_Coverage  Coverage;             /* Coverage table */
 
   HB_UShort     ValueFormat;          /* format of ValueRecord table */
 
 struct  HB_PairPos_
 {
-  HB_UShort     PosFormat;            /* 1 or 2         */
+  HB_Byte       PosFormat;            /* 1 or 2         */
   HB_Coverage  Coverage;             /* Coverage table */
   HB_UShort     ValueFormat1;         /* format of ValueRecord table
 					 for first glyph             */
 
 struct  HB_ContextPos_
 {
-  HB_UShort  PosFormat;               /* 1, 2, or 3     */
+  HB_Byte  PosFormat;                 /* 1, 2, or 3     */
 
   union
   {
 
 struct  HB_ChainPosRule_
 {
+  HB_UShort*            Backtrack;    /* array of backtrack glyph IDs     */
+  HB_UShort*            Input;        /* array of input glyph IDs         */
+  HB_UShort*            Lookahead;    /* array of lookahead glyph IDs     */
+  HB_PosLookupRecord*  PosLookupRecord;
+				      /* array of PosLookupRecords       */
   HB_UShort             BacktrackGlyphCount;
 				      /* total number of backtrack glyphs */
-  HB_UShort*            Backtrack;    /* array of backtrack glyph IDs     */
   HB_UShort             InputGlyphCount;
 				      /* total number of input glyphs     */
-  HB_UShort*            Input;        /* array of input glyph IDs         */
   HB_UShort             LookaheadGlyphCount;
 				      /* total number of lookahead glyphs */
-  HB_UShort*            Lookahead;    /* array of lookahead glyph IDs     */
   HB_UShort             PosCount;     /* number of PosLookupRecords       */
-  HB_PosLookupRecord*  PosLookupRecord;
-				      /* array of PosLookupRecords       */
 };
 
 typedef struct HB_ChainPosRule_  HB_ChainPosRule;
 
 struct  HB_ChainPosClassRule_
 {
+  HB_UShort*            Backtrack;    /* array of backtrack classes      */
+  HB_UShort*            Input;        /* array of context classes        */
+  HB_UShort*            Lookahead;    /* array of lookahead classes      */
+  HB_PosLookupRecord*  PosLookupRecord;
+				      /* array of substitution lookups   */
   HB_UShort             BacktrackGlyphCount;
 				      /* total number of backtrack
 					 classes                         */
-  HB_UShort*            Backtrack;    /* array of backtrack classes      */
   HB_UShort             InputGlyphCount;
 				      /* total number of context classes */
-  HB_UShort*            Input;        /* array of context classes        */
   HB_UShort             LookaheadGlyphCount;
 				      /* total number of lookahead
 					 classes                         */
-  HB_UShort*            Lookahead;    /* array of lookahead classes      */
   HB_UShort             PosCount;     /* number of PosLookupRecords      */
-  HB_PosLookupRecord*  PosLookupRecord;
-				      /* array of substitution lookups   */
 };
 
 typedef struct HB_ChainPosClassRule_  HB_ChainPosClassRule;
 
 struct  HB_ChainContextPos_
 {
-  HB_UShort  PosFormat;             /* 1, 2, or 3 */
+  HB_Byte  PosFormat;               /* 1, 2, or 3 */
 
   union
   {
 _HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
 			      HB_UShort     lookup_type );
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(pop)
+#endif
+
 HB_END_HEADER
 
 #endif /* HARFBUZZ_GPOS_PRIVATE_H */

File src/harfbuzz-gpos.c

 
 
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
 /* the client application must replace this with something more
    meaningful if multiple master fonts are to be supported.     */
 
   HB_UNUSED(data);
   return ERR(HB_Err_Not_Covered); /* ERR() call intended */
 }
+#endif
 
 
 
   if ( ALLOC ( gpos, sizeof( *gpos ) ) )
     return error;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   gpos->mmfunc = default_mmfunc;
+#endif
 
   /* skip version */
 
   else
     vr->YAdvance = 0;
 
+  if ( format & HB_GPOS_FORMAT_HAVE_DEVICE_TABLES )
+  {
+    if ( ALLOC_ARRAY( vr->DeviceTables, 4, HB_Device ) )
+      return error;
+    vr->DeviceTables[VR_X_ADVANCE_DEVICE] = 0;
+    vr->DeviceTables[VR_Y_ADVANCE_DEVICE] = 0;
+    vr->DeviceTables[VR_X_PLACEMENT_DEVICE] = 0;
+    vr->DeviceTables[VR_Y_PLACEMENT_DEVICE] = 0;
+  }
+  else
+  {
+    vr->DeviceTables = 0;
+  }
+
   if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
   {
     if ( ACCESS_Frame( 2L ) )
-      return error;
+      goto Fail4;
 
     new_offset = GET_UShort();
 
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-	   ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice,
+	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_X_PLACEMENT_DEVICE],
 				  stream ) ) != HB_Err_Ok )
-	return error;
+       goto Fail4;
       (void)FILE_Seek( cur_offset );
     }
-    else
-      goto empty1;
-  }
-  else
-  {
-  empty1:
-    vr->XPlacementDevice.StartSize  = 0;
-    vr->XPlacementDevice.EndSize    = 0;
-    vr->XPlacementDevice.DeltaValue = NULL;
   }
 
   if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-	   ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice,
+	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_Y_PLACEMENT_DEVICE],
 				  stream ) ) != HB_Err_Ok )
 	goto Fail3;
       (void)FILE_Seek( cur_offset );
     }
-    else
-      goto empty2;
-  }
-  else
-  {
-  empty2:
-    vr->YPlacementDevice.StartSize  = 0;
-    vr->YPlacementDevice.EndSize    = 0;
-    vr->YPlacementDevice.DeltaValue = NULL;
   }
 
   if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-	   ( error = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,
+	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_X_ADVANCE_DEVICE],
 				  stream ) ) != HB_Err_Ok )
 	goto Fail2;
       (void)FILE_Seek( cur_offset );
     }
-    else
-      goto empty3;
-  }
-  else
-  {
-  empty3:
-    vr->XAdvanceDevice.StartSize  = 0;
-    vr->XAdvanceDevice.EndSize    = 0;
-    vr->XAdvanceDevice.DeltaValue = NULL;
   }
 
   if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-	   ( error = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,
+	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_Y_ADVANCE_DEVICE],
 				  stream ) ) != HB_Err_Ok )
 	goto Fail1;
       (void)FILE_Seek( cur_offset );
     }
-    else
-      goto empty4;
-  }
-  else
-  {
-  empty4:
-    vr->YAdvanceDevice.StartSize  = 0;
-    vr->YAdvanceDevice.EndSize    = 0;
-    vr->YAdvanceDevice.DeltaValue = NULL;
   }
 
   if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
     if ( ACCESS_Frame( 2L ) )
       goto Fail1;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     vr->XIdPlacement = GET_UShort();
+#else
+    (void) GET_UShort();
+#endif
 
     FORGET_Frame();
   }
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   else
     vr->XIdPlacement = 0;
+#endif
 
   if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
   {
     if ( ACCESS_Frame( 2L ) )
       goto Fail1;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     vr->YIdPlacement = GET_UShort();
+#else
+    (void) GET_UShort();
+#endif
 
     FORGET_Frame();
   }
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   else
     vr->YIdPlacement = 0;
+#endif
 
   if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
   {
     if ( ACCESS_Frame( 2L ) )
       goto Fail1;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     vr->XIdAdvance = GET_UShort();
+#else
+    (void) GET_UShort();
+#endif
 
     FORGET_Frame();
   }
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   else
     vr->XIdAdvance = 0;
+#endif
 
   if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
   {
     if ( ACCESS_Frame( 2L ) )
       goto Fail1;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     vr->YIdAdvance = GET_UShort();
+#else
+    (void) GET_UShort();
+#endif
 
     FORGET_Frame();
   }
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   else
     vr->YIdAdvance = 0;
+#endif
 
   return HB_Err_Ok;
 
 Fail1:
-  _HB_OPEN_Free_Device( &vr->YAdvanceDevice );
+  if ( vr->DeviceTables )
+    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_ADVANCE_DEVICE] );
 
 Fail2:
-  _HB_OPEN_Free_Device( &vr->XAdvanceDevice );
+  if ( vr->DeviceTables )
+    _HB_OPEN_Free_Device( vr->DeviceTables[VR_X_ADVANCE_DEVICE] );
 
 Fail3:
-  _HB_OPEN_Free_Device( &vr->YPlacementDevice );
+  if ( vr->DeviceTables )
+    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_PLACEMENT_DEVICE] );
+
+Fail4:
+  FREE( vr->DeviceTables );
   return error;
 }
 
 			       HB_UShort         format )
 {
   if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
-    _HB_OPEN_Free_Device( &vr->YAdvanceDevice );
+    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_ADVANCE_DEVICE] );
   if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
-    _HB_OPEN_Free_Device( &vr->XAdvanceDevice );
+    _HB_OPEN_Free_Device( vr->DeviceTables[VR_X_ADVANCE_DEVICE] );
   if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
-    _HB_OPEN_Free_Device( &vr->YPlacementDevice );
+    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_PLACEMENT_DEVICE] );
   if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
-    _HB_OPEN_Free_Device( &vr->XPlacementDevice );
+    _HB_OPEN_Free_Device( vr->DeviceTables[VR_X_PLACEMENT_DEVICE] );
+  FREE( vr->DeviceTables );
 }
 
 
 				  HB_UShort         format,
 				  HB_Position      gd )
 {
-  HB_Fixed           value;
   HB_Short         pixel_value;
   HB_Error         error = HB_Err_Ok;
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   HB_GPOSHeader*  gpos = gpi->gpos;
+  HB_Fixed           value;
+#endif
 
   HB_UShort  x_ppem, y_ppem;
   HB_16Dot16   x_scale, y_scale;
 
     if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
     {
-      _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );
+      _HB_OPEN_Get_Device( vr->DeviceTables[VR_X_PLACEMENT_DEVICE], x_ppem, &pixel_value );
       gd->x_pos += pixel_value << 6;
     }
     if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
     {
-      _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );
+      _HB_OPEN_Get_Device( vr->DeviceTables[VR_Y_PLACEMENT_DEVICE], y_ppem, &pixel_value );
       gd->y_pos += pixel_value << 6;
     }
     if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
     {
-      _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );
+      _HB_OPEN_Get_Device( vr->DeviceTables[VR_X_ADVANCE_DEVICE], x_ppem, &pixel_value );
       gd->x_advance += pixel_value << 6;
     }
     if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
     {
-      _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );
+      _HB_OPEN_Get_Device( vr->DeviceTables[VR_Y_ADVANCE_DEVICE], y_ppem, &pixel_value );
       gd->y_advance += pixel_value << 6;
     }
   }
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   /* values returned from mmfunc() are already in fractional pixels */
 
   if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
       return error;
     gd->y_advance += value;
   }
+#endif
 
   return error;
 }
 
     if ( new_offset )
     {
+      if ( ALLOC_ARRAY( an->af.af3.DeviceTables, 2, HB_Device ) )
+        return error;
+
+      an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] = 0;
+      an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE] = 0;
+
       new_offset += base_offset;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-	   ( error = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable,
+	   ( error = _HB_OPEN_Load_Device( &an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE],
 				  stream ) ) != HB_Err_Ok )
-	return error;
+	goto Fail2;
       (void)FILE_Seek( cur_offset );
     }
-    else
-    {
-      an->af.af3.XDeviceTable.StartSize  = 0;
-      an->af.af3.XDeviceTable.EndSize    = 0;
-      an->af.af3.XDeviceTable.DeltaValue = NULL;
-    }
 
     if ( ACCESS_Frame( 2L ) )
       goto Fail;
 
     if ( new_offset )
     {
+      if ( !an->af.af3.DeviceTables )
+      {
+        if ( ALLOC_ARRAY( an->af.af3.DeviceTables, 2, HB_Device ) )
+          return error;
+
+        an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] = 0;
+        an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE] = 0;
+      }
+
       new_offset += base_offset;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-	   ( error = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable,
+	   ( error = _HB_OPEN_Load_Device( &an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE],
 				  stream ) ) != HB_Err_Ok )
 	goto Fail;
       (void)FILE_Seek( cur_offset );
     }
-    else
-    {
-      an->af.af3.YDeviceTable.StartSize  = 0;
-      an->af.af3.YDeviceTable.EndSize    = 0;
-      an->af.af3.YDeviceTable.DeltaValue = NULL;
-    }
     break;
 
   case 4:
     if ( ACCESS_Frame( 4L ) )
       return error;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     an->af.af4.XIdAnchor = GET_UShort();
     an->af.af4.YIdAnchor = GET_UShort();
+#else
+    (void) GET_UShort();
+    (void) GET_UShort();
+#endif
 
     FORGET_Frame();
     break;
   return HB_Err_Ok;
 
 Fail:
-  _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );
+  if ( an->af.af3.DeviceTables )
+    _HB_OPEN_Free_Device( an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] );
+
+Fail2:
+  FREE( an->af.af3.DeviceTables );
   return error;
 }
 
 
 static void  Free_Anchor( HB_Anchor*  an)
 {
-  if ( an->PosFormat == 3 )
+  if ( an->PosFormat == 3 && an->af.af3.DeviceTables )
   {
-    _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable );
-    _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );
+    _HB_OPEN_Free_Device( an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] );
+    _HB_OPEN_Free_Device( an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE] );
+    FREE( an->af.af3.DeviceTables );
   }
 }
 
 {
   HB_Error  error = HB_Err_Ok;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   HB_GPOSHeader*  gpos = gpi->gpos;
+#endif
   HB_UShort        ap;
 
   HB_Short         pixel_value;
   case 3:
     if ( !gpi->dvi )
     {
-      _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );
+      _HB_OPEN_Get_Device( an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE], x_ppem, &pixel_value );
       *x_value = pixel_value << 6;
-      _HB_OPEN_Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value );
+      _HB_OPEN_Get_Device( an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE], y_ppem, &pixel_value );
       *y_value = pixel_value << 6;
     }
     else
     break;
 
   case 4:
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
     error = (gpos->mmfunc)( gpi->font, an->af.af4.XIdAnchor,
 			    x_value, gpos->data );
     if ( error )
     if ( error )
       return error;
     break;
+#else
+    return ERR(HB_Err_Not_Covered);
+#endif
   }
 
   return error;
   return HB_Err_Ok;
 }
 
-
-
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
 HB_Error  HB_GPOS_Register_MM_Function( HB_GPOSHeader*  gpos,
 					HB_MMFunction   mmfunc,
 					void*            data )
 
   return HB_Err_Ok;
 }
+#endif
 
 /* If `dvi' is TRUE, glyph contour points for anchor points and device
    tables are ignored -- you will get device independent values.         */

File src/harfbuzz-gpos.h

 #define HB_GPOS_LOOKUP_CHAIN      8
 #define HB_GPOS_LOOKUP_EXTENSION  9
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
 /* A pointer to a function which accesses the PostScript interpreter.
    Multiple Master fonts need this interface to convert a metric ID
    (as stored in an OpenType font version 1.2 or higher) `metric_id'
 				    HB_UShort    metric_id,
 				    HB_Fixed*      metric_value,
 				    void*        data );
+#endif
 
 
 struct  HB_GPOSHeader_
 
   HB_GDEFHeader*    gdef;
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
   /* this is OpenType 1.2 -- Multiple Master fonts need this
      callback function to get various metric values from the
      PostScript interpreter.                                 */
 
   HB_MMFunction     mmfunc;
   void*              data;
+#endif
 };
 
 typedef struct HB_GPOSHeader_  HB_GPOSHeader;
 HB_Error  HB_GPOS_Clear_Features( HB_GPOSHeader*  gpos );
 
 
+#ifdef HB_SUPPORT_MULTIPLE_MASTER
 HB_Error  HB_GPOS_Register_MM_Function( HB_GPOSHeader*  gpos,
 					HB_MMFunction   mmfunc,
 					void*            data );
+#endif
 
 /* If `dvi' is TRUE, glyph contour points for anchor points and device
    tables are ignored -- you will get device independent values.         */

File src/harfbuzz-greek.c

+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This is part of HarfBuzz, an OpenType Layout engine library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "harfbuzz-shaper.h"
+#include "harfbuzz-shaper-private.h"
+#include <assert.h>
+
+#ifndef NO_OPENTYPE
+static const HB_OpenTypeFeature greek_features[] = {
+    { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
+    { HB_MAKE_TAG('l', 'i', 'g', 'a'), CcmpProperty },
+    { HB_MAKE_TAG('c', 'l', 'i', 'g'), CcmpProperty },
+    {0, 0}
+};
+#endif
+
+/*
+  Greek decompositions
+*/
+
+
+typedef struct _hb_greek_decomposition {
+    HB_UChar16 composed;
+    HB_UChar16 base;
+} hb_greek_decomposition;
+
+static const hb_greek_decomposition decompose_0x300[] = {
+    { 0x1FBA, 0x0391 },
+    { 0x1FC8, 0x0395 },
+    { 0x1FCA, 0x0397 },
+    { 0x1FDA, 0x0399 },
+    { 0x1FF8, 0x039F },
+    { 0x1FEA, 0x03A5 },
+    { 0x1FFA, 0x03A9 },
+    { 0x1F70, 0x03B1 },
+    { 0x1F72, 0x03B5 },
+    { 0x1F74, 0x03B7 },
+    { 0x1F76, 0x03B9 },
+    { 0x1F78, 0x03BF },
+    { 0x1F7A, 0x03C5 },
+    { 0x1F7C, 0x03C9 },
+    { 0x1FD2, 0x03CA },
+    { 0x1FE2, 0x03CB },
+    { 0x1F02, 0x1F00 },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x300(HB_UChar16 base)
+{
+    if ((base ^ 0x1f00) < 0x100) {
+        if (base <= 0x1f69 && !(base & 0x6))
+            return base + 2;
+        if (base == 0x1fbf)
+            return 0x1fcd;
+        if (base == 0x1ffe)
+            return 0x1fdd;
+        return 0;
+    }
+    {
+        const hb_greek_decomposition *d = decompose_0x300;
+        while (d->base && d->base != base)
+            ++d;
+        return d->composed;
+    }
+}
+
+static const hb_greek_decomposition decompose_0x301[] = {
+    { 0x0386, 0x0391 },
+    { 0x0388, 0x0395 },
+    { 0x0389, 0x0397 },
+    { 0x038A, 0x0399 },
+    { 0x038C, 0x039F },
+    { 0x038E, 0x03A5 },
+    { 0x038F, 0x03A9 },
+    { 0x03AC, 0x03B1 },
+    { 0x03AD, 0x03B5 },
+    { 0x03AE, 0x03B7 },
+    { 0x03AF, 0x03B9 },
+    { 0x03CC, 0x03BF },
+    { 0x03CD, 0x03C5 },
+    { 0x03CE, 0x03C9 },
+    { 0x0390, 0x03CA },
+    { 0x03B0, 0x03CB },
+    { 0x03D3, 0x03D2 },
+    { 0, 0 }
+};
+
+
+static HB_UChar16 compose_0x301(HB_UChar16 base)
+{
+    if ((base ^ 0x1f00) < 0x100) {
+        if (base <= 0x1f69 && !(base & 0x6))
+            return base + 4;
+        if (base == 0x1fbf)
+            return 0x1fce;
+        if (base == 0x1ffe)
+            return 0x1fde;
+    }
+    {
+        const hb_greek_decomposition *d = decompose_0x301;
+        while (d->base && d->base != base)
+            ++d;
+        return d->composed;
+    }
+}
+
+static const hb_greek_decomposition decompose_0x304[] = {
+    { 0x1FB9, 0x0391 },
+    { 0x1FD9, 0x0399 },
+    { 0x1FE9, 0x03A5 },
+    { 0x1FB1, 0x03B1 },
+    { 0x1FD1, 0x03B9 },
+    { 0x1FE1, 0x03C5 },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x304(HB_UChar16 base)
+{
+    const hb_greek_decomposition *d = decompose_0x304;
+    while (d->base && d->base != base)
+        ++d;
+    return d->composed;
+}
+
+static const hb_greek_decomposition decompose_0x306[] = {
+    { 0x1FB8, 0x0391 },
+    { 0x1FD8, 0x0399 },
+    { 0x1FE8, 0x03A5 },
+    { 0x1FB0, 0x03B1 },
+    { 0x1FD0, 0x03B9 },
+    { 0x1FE0, 0x03C5 },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x306(HB_UChar16 base)
+{
+    const hb_greek_decomposition *d = decompose_0x306;
+    while (d->base && d->base != base)
+        ++d;
+    return d->composed;
+}
+
+static const hb_greek_decomposition decompose_0x308[] = {
+    { 0x03AA, 0x0399  },
+    { 0x03AB, 0x03A5  },
+    { 0x03CA, 0x03B9  },
+    { 0x03CB, 0x03C5  },
+    { 0x03D4, 0x03D2  },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x308(HB_UChar16 base)
+{
+    const hb_greek_decomposition *d = decompose_0x308;
+    while (d->base && d->base != base)
+        ++d;
+    return d->composed;
+}
+
+
+static const hb_greek_decomposition decompose_0x313[] = {
+    { 0x1F08, 0x0391 },
+    { 0x1F18, 0x0395 },
+    { 0x1F28, 0x0397 },
+    { 0x1F38, 0x0399 },
+    { 0x1F48, 0x039F },
+    { 0x1F68, 0x03A9 },
+    { 0x1F00, 0x03B1 },
+    { 0x1F10, 0x03B5 },
+    { 0x1F20, 0x03B7 },
+    { 0x1F30, 0x03B9 },
+    { 0x1F40, 0x03BF },
+    { 0x1FE4, 0x03C1 },
+    { 0x1F50, 0x03C5 },
+    { 0x1F60, 0x03C9 },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x313(HB_UChar16 base)
+{
+    const hb_greek_decomposition *d = decompose_0x313;
+    while (d->base && d->base != base)
+        ++d;
+    return d->composed;
+}
+
+static const hb_greek_decomposition decompose_0x314[] = {
+    { 0x1F09, 0x0391 },
+    { 0x1F19, 0x0395 },
+    { 0x1F29, 0x0397 },
+    { 0x1F39, 0x0399 },
+    { 0x1F49, 0x039F },
+    { 0x1FEC, 0x03A1 },
+    { 0x1F59, 0x03A5 },
+    { 0x1F69, 0x03A9 },
+    { 0x1F01, 0x03B1 },
+    { 0x1F11, 0x03B5 },
+    { 0x1F21, 0x03B7 },
+    { 0x1F31, 0x03B9 },
+    { 0x1F41, 0x03BF },
+    { 0x1FE5, 0x03C1 },
+    { 0x1F51, 0x03C5 },
+    { 0x1F61, 0x03C9 },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x314(HB_UChar16 base)
+{
+    const hb_greek_decomposition *d = decompose_0x314;
+    while (d->base && d->base != base)
+        ++d;
+    return d->composed;
+}
+
+static const hb_greek_decomposition decompose_0x342[] = {
+    { 0x1FB6, 0x03B1 },
+    { 0x1FC6, 0x03B7 },
+    { 0x1FD6, 0x03B9 },
+    { 0x1FE6, 0x03C5 },
+    { 0x1FF6, 0x03C9 },
+    { 0x1FD7, 0x03CA },
+    { 0x1FE7, 0x03CB },
+    { 0x1F06, 0x1F00 },
+    { 0x1F07, 0x1F01 },
+    { 0x1F0E, 0x1F08 },
+    { 0x1F0F, 0x1F09 },
+    { 0x1F26, 0x1F20 },
+    { 0x1F27, 0x1F21 },
+    { 0x1F2E, 0x1F28 },
+    { 0x1F2F, 0x1F29 },
+    { 0x1F36, 0x1F30 },
+    { 0x1F37, 0x1F31 },
+    { 0x1F3E, 0x1F38 },
+    { 0x1F3F, 0x1F39 },
+    { 0x1F56, 0x1F50 },
+    { 0x1F57, 0x1F51 },
+    { 0x1F5F, 0x1F59 },
+    { 0x1F66, 0x1F60 },
+    { 0x1F67, 0x1F61 },
+    { 0x1F6E, 0x1F68 },
+    { 0x1F6F, 0x1F69 },
+    { 0x1FCF, 0x1FBF },
+    { 0x1FDF, 0x1FFE },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x342(HB_UChar16 base)
+{
+    const hb_greek_decomposition *d = decompose_0x342;
+    while (d->base && d->base != base)
+        ++d;
+    return d->composed;
+}
+
+static const hb_greek_decomposition decompose_0x345[] = {
+    { 0x1FBC, 0x0391 },
+    { 0x1FCC, 0x0397 },
+    { 0x1FFC, 0x03A9 },
+    { 0x1FB4, 0x03AC },
+    { 0x1FC4, 0x03AE },
+    { 0x1FB3, 0x03B1 },
+    { 0x1FC3, 0x03B7 },
+    { 0x1FF3, 0x03C9 },
+    { 0x1FF4, 0x03CE },
+    { 0x1F80, 0x1F00 },
+    { 0x1F81, 0x1F01 },
+    { 0x1F82, 0x1F02 },
+    { 0x1F83, 0x1F03 },
+    { 0x1F84, 0x1F04 },
+    { 0x1F85, 0x1F05 },
+    { 0x1F86, 0x1F06 },
+    { 0x1F87, 0x1F07 },
+    { 0x1F88, 0x1F08 },
+    { 0x1F89, 0x1F09 },
+    { 0x1F8A, 0x1F0A },
+    { 0x1F8B, 0x1F0B },
+    { 0x1F8C, 0x1F0C },
+    { 0x1F8D, 0x1F0D },
+    { 0x1F8E, 0x1F0E },
+    { 0x1F8F, 0x1F0F },
+    { 0x1F90, 0x1F20 },
+    { 0x1F91, 0x1F21 },
+    { 0x1F92, 0x1F22 },
+    { 0x1F93, 0x1F23 },
+    { 0x1F94, 0x1F24 },
+    { 0x1F95, 0x1F25 },
+    { 0x1F96, 0x1F26 },
+    { 0x1F97, 0x1F27 },
+    { 0x1F98, 0x1F28 },
+    { 0x1F99, 0x1F29 },
+    { 0x1F9A, 0x1F2A },
+    { 0x1F9B, 0x1F2B },
+    { 0x1F9C, 0x1F2C },
+    { 0x1F9D, 0x1F2D },
+    { 0x1F9E, 0x1F2E },
+    { 0x1F9F, 0x1F2F },
+    { 0x1FA0, 0x1F60 },
+    { 0x1FA1, 0x1F61 },
+    { 0x1FA2, 0x1F62 },
+    { 0x1FA3, 0x1F63 },
+    { 0x1FA4, 0x1F64 },
+    { 0x1FA5, 0x1F65 },
+    { 0x1FA6, 0x1F66 },
+    { 0x1FA7, 0x1F67 },
+    { 0x1FA8, 0x1F68 },
+    { 0x1FA9, 0x1F69 },
+    { 0x1FAA, 0x1F6A },
+    { 0x1FAB, 0x1F6B },
+    { 0x1FAC, 0x1F6C },
+    { 0x1FAD, 0x1F6D },
+    { 0x1FAE, 0x1F6E },
+    { 0x1FAF, 0x1F6F },
+    { 0x1FB2, 0x1F70 },
+    { 0x1FC2, 0x1F74 },
+    { 0x1FF2, 0x1F7C },
+    { 0x1FB7, 0x1FB6 },
+    { 0x1FC7, 0x1FC6 },
+    { 0x1FF7, 0x1FF6 },
+    { 0, 0 }
+};
+
+static HB_UChar16 compose_0x345(HB_UChar16 base)
+{
+    const hb_greek_decomposition *d = decompose_0x345;
+    while (d->base && d->base != base)
+        ++d;
+    return d->composed;
+}
+
+/*
+  Greek shaping. Heuristic positioning can't render polytonic greek correctly. We're a lot
+  better off mapping greek chars with diacritics to the characters in the extended greek
+  region in Unicode if possible.
+*/
+HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item)
+{
+    const int availableGlyphs = shaper_item->num_glyphs;
+    const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos;
+    unsigned short *logClusters = shaper_item->log_clusters;
+    HB_GlyphAttributes *attributes = shaper_item->attributes;
+
+    HB_Bool haveGlyphs;
+    int slen = 1;
+    int cluster_start = 0;
+    hb_uint32 i;
+
+    HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length);
+
+    assert(shaper_item->item.script == HB_Script_Greek);
+
+    *shapedChars = *uc;
+    logClusters[0] = 0;
+
+    for (i = 1; i < shaper_item->item.length; ++i) {
+        hb_uint16 base = shapedChars[slen-1];
+        hb_uint16 shaped = 0;
+        if (uc[i] == 0x300)
+            shaped = compose_0x300(base);
+        else if (uc[i] == 0x301)
+            shaped = compose_0x301(base);
+        else if (uc[i] == 0x304)
+            shaped = compose_0x304(base);
+        else if (uc[i] == 0x306)
+            shaped = compose_0x306(base);
+        else if (uc[i] == 0x308)
+            shaped = compose_0x308(base);
+        else if (uc[i] == 0x313)
+            shaped = compose_0x313(base);
+        else if (uc[i] == 0x314)
+            shaped = compose_0x314(base);
+        else if (uc[i] == 0x342)
+            shaped = compose_0x342(base);
+        else if (uc[i] == 0x345)
+            shaped = compose_0x345(base);
+
+        if (shaped) {
+            if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) {
+                shapedChars[slen-1] = shaped;
+            } else {
+                shaped = 0;
+            }
+        }
+
+        if (!shaped) {
+            HB_CharCategory category;
+            int cmb;
+            shapedChars[slen] = uc[i];
+            HB_GetUnicodeCharProperties(uc[i], &category, &cmb);
+            if (category != HB_Mark_NonSpacing) {
+                attributes[slen].clusterStart = TRUE;
+                attributes[slen].mark = FALSE;
+                attributes[slen].combiningClass = 0;
+                attributes[slen].dontPrint = HB_IsControlChar(uc[i]);
+                cluster_start = slen;
+            } else {
+                attributes[slen].clusterStart = FALSE;
+                attributes[slen].mark = TRUE;
+                attributes[slen].combiningClass = cmb;
+            }
+            ++slen;
+        }
+        logClusters[i] = cluster_start;
+    }
+
+    haveGlyphs = shaper_item->font->klass
+        ->convertStringToGlyphIndices(shaper_item->font,
+                                      shapedChars, slen,
+                                      shaper_item->glyphs, &shaper_item->num_glyphs,
+                                      shaper_item->item.bidiLevel % 2);
+
+    HB_FREE_STACKARRAY(shapedChars);
+
+    if (!haveGlyphs)
+        return FALSE;
+
+#ifndef NO_OPENTYPE
+    if (HB_SelectScript(shaper_item, greek_features)) {
+        HB_OpenTypeShape(shaper_item, /*properties*/0);
+        return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE);
+    }
+#endif
+    HB_HeuristicPosition(shaper_item);
+
+    return TRUE;
+}
+

File src/harfbuzz-gsub-private.h

 
 HB_BEGIN_HEADER
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(push, 1)
+#endif
 
 typedef union HB_GSUB_SubTable_  HB_GSUB_SubTable;
 
 
 struct  HB_SingleSubstFormat2_
 {
+  HB_UShort*  Substitute;             /* array of substitute glyph IDs */
   HB_UShort   GlyphCount;             /* number of glyph IDs in
 					 Substitute array              */
-  HB_UShort*  Substitute;             /* array of substitute glyph IDs */
 };
 
 typedef struct HB_SingleSubstFormat2_  HB_SingleSubstFormat2;
 
 struct  HB_SingleSubst_
 {
-  HB_UShort     SubstFormat;          /* 1 or 2         */
-  HB_Coverage  Coverage;             /* Coverage table */
-
   union
   {
     HB_SingleSubstFormat1  ssf1;
     HB_SingleSubstFormat2  ssf2;
   } ssf;
+
+  HB_Coverage  Coverage;             /* Coverage table */
+  HB_Byte     SubstFormat;            /* 1 or 2         */
 };
 
 typedef struct HB_SingleSubst_  HB_SingleSubst;
 
 struct  HB_Sequence_
 {
-  HB_UShort   GlyphCount;             /* number of glyph IDs in the
-					 Substitute array           */
   HB_UShort*  Substitute;             /* string of glyph IDs to
 					 substitute                 */
+  HB_UShort   GlyphCount;             /* number of glyph IDs in the
+					 Substitute array           */
 };
 
 typedef struct HB_Sequence_  HB_Sequence;
 
 struct  HB_MultipleSubst_
 {
-  HB_UShort      SubstFormat;         /* always 1                  */
+  HB_Sequence*  Sequence;            /* array of Sequence tables  */
   HB_Coverage   Coverage;            /* Coverage table            */
+  HB_UShort      SubstFormat;         /* always 1                  */
   HB_UShort      SequenceCount;       /* number of Sequence tables */
-  HB_Sequence*  Sequence;            /* array of Sequence tables  */
 };
 
 typedef struct HB_MultipleSubst_  HB_MultipleSubst;
 
 struct  HB_AlternateSet_
 {
+  HB_UShort*  Alternate;              /* array of alternate glyph IDs */
   HB_UShort   GlyphCount;             /* number of glyph IDs in the
 					 Alternate array              */
-  HB_UShort*  Alternate;              /* array of alternate glyph IDs */
 };
 
 typedef struct HB_AlternateSet_  HB_AlternateSet;
 
 struct  HB_AlternateSubst_
 {
-  HB_UShort          SubstFormat;     /* always 1                      */
+  HB_AlternateSet*  AlternateSet;    /* array of AlternateSet tables  */
   HB_Coverage       Coverage;        /* Coverage table                */
+  HB_UShort          SubstFormat;     /* always 1                      */
   HB_UShort          AlternateSetCount;
 				      /* number of AlternateSet tables */
-  HB_AlternateSet*  AlternateSet;    /* array of AlternateSet tables  */
 };
 
 typedef struct HB_AlternateSubst_  HB_AlternateSubst;
 
 struct  HB_Ligature_
 {
+  HB_UShort*  Component;              /* array of component glyph IDs     */
   HB_UShort   LigGlyph;               /* glyphID of ligature
 					 to substitute                    */
   HB_UShort   ComponentCount;         /* number of components in ligature */
-  HB_UShort*  Component;              /* array of component glyph IDs     */
 };
 
 typedef struct HB_Ligature_  HB_Ligature;
 
 struct  HB_LigatureSet_
 {
-  HB_UShort      LigatureCount;       /* number of Ligature tables */
   HB_Ligature*  Ligature;            /* array of Ligature tables  */
+  HB_UShort      LigatureCount;       /* number of Ligature tables */
 };
 
 typedef struct HB_LigatureSet_  HB_LigatureSet;
 
 struct  HB_LigatureSubst_
 {
-  HB_UShort         SubstFormat;      /* always 1                     */
+  HB_LigatureSet*  LigatureSet;      /* array of LigatureSet tables  */
   HB_Coverage      Coverage;         /* Coverage table               */
+  HB_UShort         SubstFormat;      /* always 1                     */
   HB_UShort         LigatureSetCount; /* number of LigatureSet tables */
-  HB_LigatureSet*  LigatureSet;      /* array of LigatureSet tables  */
 };
 
 typedef struct HB_LigatureSubst_  HB_LigatureSubst;
 
 struct  HB_SubRule_
 {
-  HB_UShort               GlyphCount; /* total number of input glyphs */
-  HB_UShort               SubstCount; /* number of SubstLookupRecord
-					 tables                       */
   HB_UShort*              Input;      /* array of input glyph IDs     */
   HB_SubstLookupRecord*  SubstLookupRecord;
 				      /* array of SubstLookupRecord
 					 tables                       */
+  HB_UShort               GlyphCount; /* total number of input glyphs */
+  HB_UShort               SubstCount; /* number of SubstLookupRecord
+					 tables                       */
 };
 
 typedef struct HB_SubRule_  HB_SubRule;
 
 struct  HB_SubRuleSet_
 {
-  HB_UShort     SubRuleCount;         /* number of SubRule tables */
   HB_SubRule*  SubRule;              /* array of SubRule tables  */
+  HB_UShort     SubRuleCount;         /* number of SubRule tables */
 };
 
 typedef struct HB_SubRuleSet_  HB_SubRuleSet;
 
 struct  HB_ContextSubstFormat1_
 {
+  HB_SubRuleSet*  SubRuleSet;        /* array of SubRuleSet tables  */
   HB_Coverage     Coverage;          /* Coverage table              */
   HB_UShort        SubRuleSetCount;   /* number of SubRuleSet tables */
-  HB_SubRuleSet*  SubRuleSet;        /* array of SubRuleSet tables  */
 };
 
 typedef struct HB_ContextSubstFormat1_  HB_ContextSubstFormat1;
 
 struct  HB_SubClassRule_
 {
-  HB_UShort               GlyphCount; /* total number of context classes */
-  HB_UShort               SubstCount; /* number of SubstLookupRecord
-					 tables                          */
   HB_UShort*              Class;      /* array of classes                */
   HB_SubstLookupRecord*  SubstLookupRecord;
 				      /* array of SubstLookupRecord
 					 tables                          */
+  HB_UShort               GlyphCount; /* total number of context classes */
+  HB_UShort               SubstCount; /* number of SubstLookupRecord
+					 tables                          */
 };
 
 typedef struct HB_SubClassRule_  HB_SubClassRule;
 
 struct  HB_SubClassSet_
 {
+  HB_SubClassRule*  SubClassRule;    /* array of SubClassRule tables  */
   HB_UShort          SubClassRuleCount;
 				      /* number of SubClassRule tables */
-  HB_SubClassRule*  SubClassRule;    /* array of SubClassRule tables  */
 };
 
 typedef struct HB_SubClassSet_  HB_SubClassSet;
 
 struct  HB_ContextSubstFormat2_
 {
-  HB_UShort            MaxContextLength;
-				      /* maximal context length       */
+  HB_SubClassSet*     SubClassSet;   /* array of SubClassSet tables  */
   HB_Coverage         Coverage;      /* Coverage table               */
   HB_ClassDefinition  ClassDef;      /* ClassDef table               */
   HB_UShort            SubClassSetCount;
 				      /* number of SubClassSet tables */
-  HB_SubClassSet*     SubClassSet;   /* array of SubClassSet tables  */
+  HB_UShort            MaxContextLength;
+				      /* maximal context length       */
 };
 
 typedef struct HB_ContextSubstFormat2_  HB_ContextSubstFormat2;
 
 struct  HB_ContextSubstFormat3_
 {
-  HB_UShort               GlyphCount; /* number of input glyphs        */
-  HB_UShort               SubstCount; /* number of SubstLookupRecords  */
   HB_Coverage*           Coverage;   /* array of Coverage tables      */
   HB_SubstLookupRecord*  SubstLookupRecord;
 				      /* array of substitution lookups */
+  HB_UShort               GlyphCount; /* number of input glyphs        */
+  HB_UShort               SubstCount; /* number of SubstLookupRecords  */
 };
 
 typedef struct HB_ContextSubstFormat3_  HB_ContextSubstFormat3;
 
 struct  HB_ContextSubst_
 {
-  HB_UShort  SubstFormat;             /* 1, 2, or 3 */
-
   union
   {
     HB_ContextSubstFormat1  csf1;
     HB_ContextSubstFormat2  csf2;
     HB_ContextSubstFormat3  csf3;
   } csf;
+
+  HB_Byte  SubstFormat;               /* 1, 2, or 3 */
 };
 
 typedef struct HB_ContextSubst_  HB_ContextSubst;
 
 struct  HB_ChainSubRule_
 {
+  HB_UShort*              Backtrack;  /* array of backtrack glyph IDs     */
+  HB_UShort*              Input;      /* array of input glyph IDs         */
+  HB_UShort*              Lookahead;  /* array of lookahead glyph IDs     */
+  HB_SubstLookupRecord*  SubstLookupRecord;
+				      /* array of SubstLookupRecords      */
   HB_UShort               BacktrackGlyphCount;
 				      /* total number of backtrack glyphs */
-  HB_UShort*              Backtrack;  /* array of backtrack glyph IDs     */
   HB_UShort               InputGlyphCount;
 				      /* total number of input glyphs     */
-  HB_UShort*              Input;      /* array of input glyph IDs         */
   HB_UShort               LookaheadGlyphCount;
 				      /* total number of lookahead glyphs */
-  HB_UShort*              Lookahead;  /* array of lookahead glyph IDs     */
   HB_UShort               SubstCount; /* number of SubstLookupRecords     */
-  HB_SubstLookupRecord*  SubstLookupRecord;
-				      /* array of SubstLookupRecords      */
 };
 
 typedef struct HB_ChainSubRule_  HB_ChainSubRule;
 
 struct  HB_ChainSubRuleSet_
 {
+  HB_ChainSubRule*  ChainSubRule;    /* array of ChainSubRule tables  */
   HB_UShort          ChainSubRuleCount;
 				      /* number of ChainSubRule tables */
-  HB_ChainSubRule*  ChainSubRule;    /* array of ChainSubRule tables  */
 };
 
 typedef struct HB_ChainSubRuleSet_  HB_ChainSubRuleSet;
 
 struct  HB_ChainContextSubstFormat1_
 {
+  HB_ChainSubRuleSet*  ChainSubRuleSet;
+				      /* array of ChainSubRuleSet tables  */
   HB_Coverage          Coverage;     /* Coverage table                   */
   HB_UShort             ChainSubRuleSetCount;
 				      /* number of ChainSubRuleSet tables */
-  HB_ChainSubRuleSet*  ChainSubRuleSet;
-				      /* array of ChainSubRuleSet tables  */
 };
 
 typedef struct HB_ChainContextSubstFormat1_  HB_ChainContextSubstFormat1;
 
 struct  HB_ChainSubClassRule_
 {
+  HB_UShort*              Backtrack;  /* array of backtrack classes      */
+  HB_UShort*              Input;      /* array of context classes        */
+  HB_UShort*              Lookahead;  /* array of lookahead classes      */
+  HB_SubstLookupRecord*  SubstLookupRecord;
+				      /* array of substitution lookups   */
   HB_UShort               BacktrackGlyphCount;
 				      /* total number of backtrack
 					 classes                         */
-  HB_UShort*              Backtrack;  /* array of backtrack classes      */
   HB_UShort               InputGlyphCount;
 				      /* total number of context classes */
-  HB_UShort*              Input;      /* array of context classes        */
   HB_UShort               LookaheadGlyphCount;
 				      /* total number of lookahead
 					 classes                         */
-  HB_UShort*              Lookahead;  /* array of lookahead classes      */
   HB_UShort               SubstCount; /* number of SubstLookupRecords    */
-  HB_SubstLookupRecord*  SubstLookupRecord;
-				      /* array of substitution lookups   */
 };
 
 typedef struct HB_ChainSubClassRule_  HB_ChainSubClassRule;
 
 struct  HB_ChainSubClassSet_
 {
-  HB_UShort               ChainSubClassRuleCount;
-				      /* number of ChainSubClassRule
-					 tables                      */
   HB_ChainSubClassRule*  ChainSubClassRule;
 				      /* array of ChainSubClassRule
 					 tables                      */
+  HB_UShort               ChainSubClassRuleCount;
+				      /* number of ChainSubClassRule
+					 tables                      */
 };
 
 typedef struct HB_ChainSubClassSet_  HB_ChainSubClassSet;
 
 struct  HB_ChainContextSubstFormat2_
 {
+  HB_ChainSubClassSet*  ChainSubClassSet;
+				      /* array of ChainSubClassSet
+					 tables                     */
   HB_Coverage           Coverage;    /* Coverage table             */
 
-  HB_UShort              MaxBacktrackLength;
-				      /* maximal backtrack length   */
   HB_ClassDefinition    BacktrackClassDef;
 				      /* BacktrackClassDef table    */
-  HB_UShort              MaxInputLength;
-				      /* maximal input length       */
   HB_ClassDefinition    InputClassDef;
 				      /* InputClassDef table        */
-  HB_UShort              MaxLookaheadLength;
-				      /* maximal lookahead length   */
   HB_ClassDefinition    LookaheadClassDef;
 				      /* LookaheadClassDef table    */
 
   HB_UShort              ChainSubClassSetCount;
 				      /* number of ChainSubClassSet
 					 tables                     */
-  HB_ChainSubClassSet*  ChainSubClassSet;
-				      /* array of ChainSubClassSet
-					 tables                     */
+  HB_UShort              MaxBacktrackLength;
+				      /* maximal backtrack length   */
+  HB_UShort              MaxLookaheadLength;
+				      /* maximal lookahead length   */
+  HB_UShort              MaxInputLength;
+				      /* maximal input length       */
 };
 
 typedef struct HB_ChainContextSubstFormat2_  HB_ChainContextSubstFormat2;
 
 struct  HB_ChainContextSubstFormat3_
 {
-  HB_UShort               BacktrackGlyphCount;
-				      /* number of backtrack glyphs    */
   HB_Coverage*           BacktrackCoverage;
 				      /* array of backtrack Coverage
 					 tables                        */
-  HB_UShort               InputGlyphCount;
-				      /* number of input glyphs        */
   HB_Coverage*           InputCoverage;
 				      /* array of input coverage
 					 tables                        */
-  HB_UShort               LookaheadGlyphCount;
-				      /* number of lookahead glyphs    */
   HB_Coverage*           LookaheadCoverage;
 				      /* array of lookahead coverage
 					 tables                        */
-  HB_UShort               SubstCount; /* number of SubstLookupRecords  */
   HB_SubstLookupRecord*  SubstLookupRecord;
 				      /* array of substitution lookups */
+  HB_UShort               BacktrackGlyphCount;
+				      /* number of backtrack glyphs    */
+  HB_UShort               InputGlyphCount;
+				      /* number of input glyphs        */
+  HB_UShort               LookaheadGlyphCount;
+				      /* number of lookahead glyphs    */
+  HB_UShort               SubstCount; /* number of SubstLookupRecords  */
 };
 
 typedef struct HB_ChainContextSubstFormat3_  HB_ChainContextSubstFormat3;
 
 struct  HB_ChainContextSubst_
 {
-  HB_UShort  SubstFormat;             /* 1, 2, or 3 */
-
   union
   {
     HB_ChainContextSubstFormat1  ccsf1;
     HB_ChainContextSubstFormat2  ccsf2;
     HB_ChainContextSubstFormat3  ccsf3;
   } ccsf;
+
+  HB_Byte  SubstFormat;               /* 1, 2, or 3 */
 };
 
 typedef struct HB_ChainContextSubst_  HB_ChainContextSubst;
 /* LookupType 7 */
 struct HB_ExtensionSubst_
 {
+  HB_GSUB_SubTable *subtable;         /* referenced subtable */
   HB_UShort      SubstFormat;         /* always 1 */
   HB_UShort      LookuptType;         /* lookup-type of referenced subtable */
-  HB_GSUB_SubTable *subtable;         /* referenced subtable */
 };
 
 typedef struct HB_ExtensionSubst_  HB_ExtensionSubst;
 /* LookupType 8 */
 struct HB_ReverseChainContextSubst_
 {
-  HB_UShort      SubstFormat;         /* always 1 */
-  HB_Coverage   Coverage;	        /* coverage table for input glyphs */
-  HB_UShort      BacktrackGlyphCount; /* number of backtrack glyphs      */
+  HB_Coverage*  LookaheadCoverage;   /* array of lookahead Coverage
+					 tables                          */
+  HB_UShort*     Substitute;          /* array of substitute Glyph ID    */
   HB_Coverage*  BacktrackCoverage;   /* array of backtrack Coverage
 					 tables                          */
+  HB_Coverage   Coverage;	        /* coverage table for input glyphs */
+  HB_UShort      SubstFormat;         /* always 1 */
+  HB_UShort      BacktrackGlyphCount; /* number of backtrack glyphs      */
   HB_UShort      LookaheadGlyphCount; /* number of lookahead glyphs      */
-  HB_Coverage*  LookaheadCoverage;   /* array of lookahead Coverage
-					 tables                          */
   HB_UShort      GlyphCount;          /* number of Glyph IDs             */
-  HB_UShort*     Substitute;          /* array of substitute Glyph ID    */
 };
 
 typedef struct HB_ReverseChainContextSubst_  HB_ReverseChainContextSubst;
 _HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
 			      HB_UShort     lookup_type );
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(pop)
+#endif
+
 HB_END_HEADER
 
 #endif /* HARFBUZZ_GSUB_PRIVATE_H */

File src/harfbuzz-gsub.h

 HB_BEGIN_HEADER
 
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(push, 1)
+#endif
+
 /* Lookup types for glyph substitution */
 
 #define HB_GSUB_LOOKUP_SINGLE        1
 
 struct  HB_GSUBHeader_
 {
+  HB_GDEFHeader*  gdef;
+
+  /* the next two fields are used for an alternate substitution callback
+     function to select the proper alternate glyph.                      */
+
+  void*            data;
+  HB_AltFunction  altfunc;
+
   HB_UInt         offset;
 
   HB_16Dot16         Version;
   HB_ScriptList   ScriptList;
   HB_FeatureList  FeatureList;
   HB_LookupList   LookupList;
-
-  HB_GDEFHeader*  gdef;
-
-  /* the next two fields are used for an alternate substitution callback
-     function to select the proper alternate glyph.                      */
-
-  HB_AltFunction  altfunc;
-  void*            data;
 };
 
 typedef struct HB_GSUBHeader_   HB_GSUBHeader;
 HB_Error  HB_GSUB_Apply_String( HB_GSUBHeader*   gsub,
 				HB_Buffer        buffer );
 
+#ifdef HB_USE_PACKED_STRUCTS
+#pragma pack(pop)
+#endif
 
 HB_END_HEADER