[icu-le] Start adding a icu-layout-engine backend
authorBehdad Esfahbod <behdad@behdad.org>
Fri, 24 Aug 2012 01:23:41 +0000 (21:23 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Fri, 24 Aug 2012 04:00:29 +0000 (00:00 -0400)
Import PortableFontInstance and add shaper stub.

14 files changed:
configure.ac
src/Makefile.am
src/hb-icu-le.cc [new file with mode: 0644]
src/hb-icu-le/FontTableCache.cpp [new file with mode: 0644]
src/hb-icu-le/FontTableCache.h [new file with mode: 0644]
src/hb-icu-le/Makefile.am [new file with mode: 0644]
src/hb-icu-le/PortableFontInstance.cpp [new file with mode: 0644]
src/hb-icu-le/PortableFontInstance.h [new file with mode: 0644]
src/hb-icu-le/README [new file with mode: 0644]
src/hb-icu-le/cmaps.cpp [new file with mode: 0644]
src/hb-icu-le/cmaps.h [new file with mode: 0644]
src/hb-icu-le/letest.h [new file with mode: 0644]
src/hb-icu-le/license.html [new file with mode: 0644]
src/hb-icu-le/sfnt.h [new file with mode: 0644]

index 916a5d4..de3c55c 100644 (file)
@@ -160,6 +160,14 @@ AM_CONDITIONAL(HAVE_ICU, $have_icu)
 
 dnl ==========================================================================
 
+PKG_CHECK_MODULES(ICU_LE, icu-le, have_icu_le=true, have_icu_le=false)
+if $have_icu_le; then
+       AC_DEFINE(HAVE_ICU_LE, 1, [Have ICU Layout Engine library])
+fi
+AM_CONDITIONAL(HAVE_ICU_LE, $have_icu_le)
+
+dnl ==========================================================================
+
 PKG_CHECK_MODULES(GRAPHITE2, graphite2, have_graphite=true, have_graphite=false)
 if $have_graphite; then
     AC_DEFINE(HAVE_GRAPHITE2, 1, [Have Graphite library])
@@ -229,6 +237,7 @@ harfbuzz.pc
 src/Makefile
 src/hb-version.h
 src/hb-old/Makefile
+src/hb-icu-le/Makefile
 util/Makefile
 test/Makefile
 test/api/Makefile
index 5894b20..166ba79 100644 (file)
@@ -163,6 +163,14 @@ HBSOURCES += hb-old.cc
 endif
 DIST_SUBDIRS += hb-old
 
+if HAVE_ICU_LE
+SUBDIRS += hb-icu-le
+HBCFLAGS += -I$(srcdir)/hb-icu-le
+HBLIBS   += hb-icu-le/libhb-icu-le.la
+HBSOURCES += hb-icu-le.cc
+endif
+DIST_SUBDIRS += hb-icu-le
+
 
 
 # Put the library together
diff --git a/src/hb-icu-le.cc b/src/hb-icu-le.cc
new file mode 100644 (file)
index 0000000..9629534
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping 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.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#define HB_SHAPER icu_le
+#include "hb-shaper-impl-private.hh"
+
+#include "hb-icu-le/PortableFontInstance.h"
+
+#include "layout/loengine.h"
+
+#include <harfbuzz.h>
+
+
+#ifndef HB_DEBUG_ICU_LE
+#define HB_DEBUG_ICU_LE (HB_DEBUG+0)
+#endif
+
+
+/*
+ * shaper face data
+ */
+
+struct hb_icu_le_shaper_face_data_t {};
+
+hb_icu_le_shaper_face_data_t *
+_hb_icu_le_shaper_face_data_create (hb_face_t *face)
+{
+  return (hb_icu_le_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_icu_le_shaper_face_data_destroy (hb_icu_le_shaper_face_data_t *data)
+{
+}
+
+
+/*
+ * shaper font data
+ */
+
+struct hb_icu_le_shaper_font_data_t {};
+
+hb_icu_le_shaper_font_data_t *
+_hb_icu_le_shaper_font_data_create (hb_font_t *font)
+{
+  return (hb_icu_le_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t *data)
+{
+  free (data);
+}
+
+
+/*
+ * shaper shape_plan data
+ */
+
+struct hb_icu_le_shaper_shape_plan_data_t {};
+
+hb_icu_le_shaper_shape_plan_data_t *
+_hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
+                                      const hb_feature_t *user_features,
+                                      unsigned int        num_user_features)
+{
+  return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+}
+
+void
+_hb_icu_le_shaper_shape_plan_data_destroy (hb_icu_le_shaper_shape_plan_data_t *data)
+{
+}
+
+
+/*
+ * shaper
+ */
+
+hb_bool_t
+_hb_icu_le_shape (hb_shape_plan_t    *shape_plan,
+                 hb_font_t          *font,
+                 hb_buffer_t        *buffer,
+                 const hb_feature_t *features,
+                 unsigned int        num_features)
+{
+  return false;
+}
diff --git a/src/hb-icu-le/FontTableCache.cpp b/src/hb-icu-le/FontTableCache.cpp
new file mode 100644 (file)
index 0000000..84d5507
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ **********************************************************************
+ *   Copyright (C) 2003-2008, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ **********************************************************************
+ */
+
+#include "layout/LETypes.h"
+
+#include "letest.h"
+#include "FontTableCache.h"
+
+#define TABLE_CACHE_INIT 5
+#define TABLE_CACHE_GROW 5
+
+struct FontTableCacheEntry
+{
+    LETag tag;
+    const void *table;
+};
+
+FontTableCache::FontTableCache()
+    : fTableCacheCurr(0), fTableCacheSize(TABLE_CACHE_INIT)
+{
+    fTableCache = NEW_ARRAY(FontTableCacheEntry, fTableCacheSize);
+
+    if (fTableCache == NULL) {
+        fTableCacheSize = 0;
+        return;
+    }
+
+    for (int i = 0; i < fTableCacheSize; i += 1) {
+        fTableCache[i].tag   = 0;
+        fTableCache[i].table = NULL;
+    }
+}
+
+FontTableCache::~FontTableCache()
+{
+    for (int i = fTableCacheCurr - 1; i >= 0; i -= 1) {
+        DELETE_ARRAY(fTableCache[i].table);
+
+        fTableCache[i].tag   = 0;
+        fTableCache[i].table = NULL;
+    }
+
+    fTableCacheCurr = 0;
+
+    DELETE_ARRAY(fTableCache);
+}
+
+void FontTableCache::freeFontTable(const void *table) const
+{
+    DELETE_ARRAY(table);
+}
+
+const void *FontTableCache::find(LETag tableTag) const
+{
+    for (int i = 0; i < fTableCacheCurr; i += 1) {
+        if (fTableCache[i].tag == tableTag) {
+            return fTableCache[i].table;
+        }
+    }
+
+    const void *table = readFontTable(tableTag);
+
+    ((FontTableCache *) this)->add(tableTag, table);
+
+    return table;
+}
+
+void FontTableCache::add(LETag tableTag, const void *table)
+{
+    if (fTableCacheCurr >= fTableCacheSize) {
+        le_int32 newSize = fTableCacheSize + TABLE_CACHE_GROW;
+
+        fTableCache = (FontTableCacheEntry *) GROW_ARRAY(fTableCache, newSize);
+
+        for (le_int32 i = fTableCacheSize; i < newSize; i += 1) {
+            fTableCache[i].tag   = 0;
+            fTableCache[i].table = NULL;
+        }
+
+        fTableCacheSize = newSize;
+    }
+
+    fTableCache[fTableCacheCurr].tag   = tableTag;
+    fTableCache[fTableCacheCurr].table = table;
+
+    fTableCacheCurr += 1;
+}
diff --git a/src/hb-icu-le/FontTableCache.h b/src/hb-icu-le/FontTableCache.h
new file mode 100644 (file)
index 0000000..36971e4
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ **********************************************************************
+ *   Copyright (C) 2003-2008, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ **********************************************************************
+ */
+
+#ifndef __FONTTABLECACHE_H
+
+#define __FONTTABLECACHE_H
+
+#include "layout/LETypes.h"
+
+U_NAMESPACE_USE
+
+struct FontTableCacheEntry;
+
+class FontTableCache
+{
+public:
+    FontTableCache();
+
+    virtual ~FontTableCache();
+
+    const void *find(LETag tableTag) const;
+
+protected:
+    virtual const void *readFontTable(LETag tableTag) const = 0;
+    virtual void freeFontTable(const void *table) const;
+
+private:
+
+    void add(LETag tableTag, const void *table);
+
+    FontTableCacheEntry *fTableCache;
+    le_int32 fTableCacheCurr;
+    le_int32 fTableCacheSize;
+};
+
+#endif
+
diff --git a/src/hb-icu-le/Makefile.am b/src/hb-icu-le/Makefile.am
new file mode 100644 (file)
index 0000000..dd99dc1
--- /dev/null
@@ -0,0 +1,25 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_LTLIBRARIES = libhb-icu-le.la
+
+
+libhb_icu_le_la_SOURCES = \
+       FontTableCache.cpp \
+       FontTableCache.h \
+       PortableFontInstance.cpp \
+       PortableFontInstance.h \
+       cmaps.cpp \
+       cmaps.h \
+       letest.h \
+       sfnt.h
+libhb_icu_le_la_CPPFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/src \
+       -I$(top_builddir)/src \
+       $(ICU_LE_CFLAGS)
+libhb_icu_le_la_LIBADD = \
+       $(ICU_LE_LIBS)
+
+EXTRA_DIST = README license.html
+
+-include $(top_srcdir)/git.mk
diff --git a/src/hb-icu-le/PortableFontInstance.cpp b/src/hb-icu-le/PortableFontInstance.cpp
new file mode 100644 (file)
index 0000000..14e3f52
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2008, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ *   file name:  PortableFontInstance.cpp
+ *
+ *   created on: 11/22/1999
+ *   created by: Eric R. Mader
+ */
+
+#include <stdio.h>
+
+#include "layout/LETypes.h"
+#include "layout/LEFontInstance.h"
+#include "layout/LESwaps.h"
+
+#include "PortableFontInstance.h"
+
+#include "letest.h"
+#include "sfnt.h"
+
+#include <string.h>
+
+//
+// Finds the high bit by binary searching
+// through the bits in n.
+//
+le_int8 PortableFontInstance::highBit(le_int32 value)
+{
+    if (value <= 0) {
+        return -32;
+    }
+
+    le_uint8 bit = 0;
+
+    if (value >= 1 << 16) {
+        value >>= 16;
+        bit += 16;
+    }
+
+    if (value >= 1 << 8) {
+        value >>= 8;
+        bit += 8;
+    }
+
+    if (value >= 1 << 4) {
+        value >>= 4;
+        bit += 4;
+    }
+
+    if (value >= 1 << 2) {
+        value >>= 2;
+        bit += 2;
+    }
+
+    if (value >= 1 << 1) {
+        value >>= 1;
+        bit += 1;
+    }
+
+    return bit;
+}
+
+PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize, LEErrorCode &status)
+    : fFile(NULL), fPointSize(pointSize), fUnitsPerEM(0), fFontChecksum(0), fAscent(0), fDescent(0), fLeading(0),
+      fDirectory(NULL), fNAMETable(NULL), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0)
+{
+    if (LE_FAILURE(status)) {
+        return;
+    }
+
+    // open the font file
+    fFile = fopen(fileName, "rb");
+
+    if (fFile == NULL) {
+        status = LE_FONT_FILE_NOT_FOUND_ERROR;
+        return;
+    }
+
+    // read in the directory
+    SFNTDirectory tempDir;
+
+    fread(&tempDir, sizeof tempDir, 1, fFile);
+
+    le_int32 dirSize = sizeof tempDir + ((SWAPW(tempDir.numTables) - ANY_NUMBER) * sizeof(DirectoryEntry));
+    const LETag headTag = LE_HEAD_TABLE_TAG;
+    const LETag hheaTag = LE_HHEA_TABLE_TAG;
+    const HEADTable *headTable = NULL;
+    const HHEATable *hheaTable = NULL;
+//  const NAMETable *nameTable = NULL;
+    le_uint16 numTables = 0;
+
+    fDirectory = (const SFNTDirectory *) NEW_ARRAY(char, dirSize);
+
+    if (fDirectory == NULL) {
+        status = LE_MEMORY_ALLOCATION_ERROR;
+        goto error_exit;
+    }
+
+    fseek(fFile, 0L, SEEK_SET);
+    fread((void *) fDirectory, sizeof(char), dirSize, fFile);
+
+    //
+    // We calculate these numbers 'cause some fonts
+    // have bogus values for them in the directory header.
+    //
+    numTables = SWAPW(fDirectory->numTables);
+    fDirPower = 1 << highBit(numTables);
+    fDirExtra = numTables - fDirPower;
+
+    // read unitsPerEm from 'head' table
+    headTable = (const HEADTable *) readFontTable(headTag);
+
+    if (headTable == NULL) {
+        status = LE_MISSING_FONT_TABLE_ERROR;
+        goto error_exit;
+    }
+
+    fUnitsPerEM   = SWAPW(headTable->unitsPerEm);
+    fFontChecksum = SWAPL(headTable->checksumAdjustment);
+    freeFontTable(headTable);
+
+    //nameTable = (NAMETable *) readFontTable(nameTag);
+
+    //if (nameTable == NULL) {
+    //    status = LE_MISSING_FONT_TABLE_ERROR;
+    //    goto error_exit;
+    //}
+
+    //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
+
+    //if (fFontVersionString == NULL) {
+    //    status = LE_MISSING_FONT_TABLE_ERROR;
+    //    goto error_exit;
+    //}
+
+    //freeFontTable(nameTable);
+
+    hheaTable = (HHEATable *) readFontTable(hheaTag);
+
+    if (hheaTable == NULL) {
+        status = LE_MISSING_FONT_TABLE_ERROR;
+        goto error_exit;
+    }
+
+    fAscent  = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent));
+    fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent));
+    fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap));
+
+    fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
+
+    freeFontTable((void *) hheaTable);
+
+    fCMAPMapper = findUnicodeMapper();
+
+    if (fCMAPMapper == NULL) {
+        status = LE_MISSING_FONT_TABLE_ERROR;
+        goto error_exit;
+    }
+
+    return;
+
+error_exit:
+    fclose(fFile);
+    fFile = NULL;
+    return;
+}
+
+PortableFontInstance::~PortableFontInstance()
+{
+    if (fFile != NULL) {
+        fclose(fFile);
+
+        freeFontTable(fHMTXTable);
+        freeFontTable(fNAMETable);
+
+        delete fCMAPMapper;
+
+        DELETE_ARRAY(fDirectory);
+    }
+}
+
+const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const
+{
+    if (fDirectory != NULL) {
+        le_uint16 table = 0;
+        le_uint16 probe = fDirPower;
+
+        if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) {
+            table = fDirExtra;
+        }
+
+        while (probe > (1 << 0)) {
+            probe >>= 1;
+
+            if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) {
+                table += probe;
+            }
+        }
+
+        if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) {
+            return &fDirectory->tableDirectory[table];
+        }
+    }
+
+    return NULL;
+}
+
+const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const
+{
+    const DirectoryEntry *entry = findTable(tag);
+
+    if (entry == NULL) {
+        *length = 0;
+        return NULL;
+    }
+
+    *length = SWAPL(entry->length);
+
+    void *table = NEW_ARRAY(char, *length);
+
+    if (table != NULL) {
+        fseek(fFile, SWAPL(entry->offset), SEEK_SET);
+        fread(table, sizeof(char), *length, fFile);
+    }
+
+    return table;
+}
+
+const void *PortableFontInstance::getFontTable(LETag tableTag) const
+{
+    return FontTableCache::find(tableTag);
+}
+
+const void *PortableFontInstance::readFontTable(LETag tableTag) const
+{
+    le_uint32 len;
+
+    return readTable(tableTag, &len);
+}
+
+CMAPMapper *PortableFontInstance::findUnicodeMapper()
+{
+    LETag cmapTag = LE_CMAP_TABLE_TAG;
+    const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag);
+
+    if (cmap == NULL) {
+        return NULL;
+    }
+
+    return CMAPMapper::createUnicodeMapper(cmap);
+}
+
+const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
+{
+    if (fNAMETable == NULL) {
+        LETag nameTag = LE_NAME_TABLE_TAG;
+        PortableFontInstance *realThis = (PortableFontInstance *) this;
+
+        realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
+
+        if (realThis->fNAMETable != NULL) {
+            realThis->fNameCount        = SWAPW(realThis->fNAMETable->count);
+            realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
+        }
+    }
+
+    for(le_int32 i = 0; i < fNameCount; i += 1) {
+        const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
+        
+        if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
+            SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
+            char *name = ((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset);
+            le_uint16 length = SWAPW(nameRecord->length);
+            char *result = NEW_ARRAY(char, length + 2);
+
+            ARRAY_COPY(result, name, length);
+            result[length] = result[length + 1] = 0;
+
+            return result;
+        }
+    }
+
+    return NULL;
+}
+
+const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
+{
+    if (fNAMETable == NULL) {
+        LETag nameTag = LE_NAME_TABLE_TAG;
+        PortableFontInstance *realThis = (PortableFontInstance *) this;
+
+        realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
+
+        if (realThis->fNAMETable != NULL) {
+            realThis->fNameCount        = SWAPW(realThis->fNAMETable->count);
+            realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
+        }
+    }
+
+    for(le_int32 i = 0; i < fNameCount; i += 1) {
+        const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
+        
+        if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
+            SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
+            LEUnicode16 *name = (LEUnicode16 *) (((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset));
+            le_uint16 length = SWAPW(nameRecord->length) / 2;
+            LEUnicode16 *result = NEW_ARRAY(LEUnicode16, length + 2);
+
+            for (le_int32 c = 0; c < length; c += 1) {
+                result[c] = SWAPW(name[c]);
+            }
+
+            result[length] = 0;
+
+            return result;
+        }
+    }
+
+    return NULL;
+}
+
+void PortableFontInstance::deleteNameString(const char *name) const
+{
+    DELETE_ARRAY(name);
+}
+
+void PortableFontInstance::deleteNameString(const LEUnicode16 *name) const
+{
+    DELETE_ARRAY(name);
+}
+
+void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
+{
+    TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
+
+    if (fHMTXTable == NULL) {
+        LETag maxpTag = LE_MAXP_TABLE_TAG;
+        LETag hmtxTag = LE_HMTX_TABLE_TAG;
+        const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag);
+        PortableFontInstance *realThis = (PortableFontInstance *) this;
+
+        if (maxpTable != NULL) {
+            realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
+            freeFontTable(maxpTable);
+        }
+
+        realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag);
+    }
+
+    le_uint16 index = ttGlyph;
+
+    if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) {
+        advance.fX = advance.fY = 0;
+        return;
+    }
+
+    if (ttGlyph >= fNumLongHorMetrics) {
+        index = fNumLongHorMetrics - 1;
+    }
+
+    advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth));
+    advance.fY = 0;
+}
+
+le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*pointNumber*/, LEPoint &/*point*/) const
+{
+    return FALSE;
+}
+
+le_int32 PortableFontInstance::getUnitsPerEM() const
+{
+    return fUnitsPerEM;
+}
+
+le_uint32 PortableFontInstance::getFontChecksum() const
+{
+    return fFontChecksum;
+}
+
+le_int32 PortableFontInstance::getAscent() const
+{
+    return fAscent;
+}
+
+le_int32 PortableFontInstance::getDescent() const
+{
+    return fDescent;
+}
+
+le_int32 PortableFontInstance::getLeading() const
+{
+    return fLeading;
+}
+
+// We really want to inherit this method from the superclass, but some compilers
+// issue a warning if we don't implement it...
+LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const
+{
+    return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth);
+}
+
+// We really want to inherit this method from the superclass, but some compilers
+// issue a warning if we don't implement it...
+LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
+{
+    return LEFontInstance::mapCharToGlyph(ch, mapper);
+}
+
+LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const
+{
+    return fCMAPMapper->unicodeToGlyph(ch);
+}
+
+float PortableFontInstance::getXPixelsPerEm() const
+{
+    return fPointSize;
+}
+
+float PortableFontInstance::getYPixelsPerEm() const
+{
+    return fPointSize;
+}
+
+float PortableFontInstance::getScaleFactorX() const
+{
+    return 1.0;
+}
+
+float PortableFontInstance::getScaleFactorY() const
+{
+    return 1.0;
+}
diff --git a/src/hb-icu-le/PortableFontInstance.h b/src/hb-icu-le/PortableFontInstance.h
new file mode 100644 (file)
index 0000000..3e86112
--- /dev/null
@@ -0,0 +1,117 @@
+
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2008, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ *   file name:  PortableFontInstance.h
+ *
+ *   created on: 11/12/1999
+ *   created by: Eric R. Mader
+ */
+
+#ifndef __PORTABLEFONTINSTANCE_H
+#define __PORTABLEFONTINSTANCE_H
+
+#include <stdio.h>
+
+#include "layout/LETypes.h"
+#include "layout/LEFontInstance.h"
+
+#include "FontTableCache.h"
+
+#include "sfnt.h"
+#include "cmaps.h"
+
+class PortableFontInstance : public LEFontInstance, protected FontTableCache
+{
+private:
+    FILE *fFile;
+
+    float     fPointSize;
+    le_int32  fUnitsPerEM;
+    le_uint32 fFontChecksum;
+    le_int32  fAscent;
+    le_int32  fDescent;
+    le_int32  fLeading;
+
+    const SFNTDirectory *fDirectory;
+    le_uint16 fDirPower;
+    le_uint16 fDirExtra;
+
+    float fDeviceScaleX;
+    float fDeviceScaleY;
+
+    const NAMETable *fNAMETable;
+    le_uint16 fNameCount;
+    le_uint16 fNameStringOffset;
+
+    CMAPMapper *fCMAPMapper;
+
+    const HMTXTable *fHMTXTable;
+    le_uint16 fNumGlyphs;
+    le_uint16 fNumLongHorMetrics;
+
+    static le_int8 highBit(le_int32 value);
+
+    const DirectoryEntry *findTable(LETag tag) const;
+    const void *readTable(LETag tag, le_uint32 *length) const;
+    void getMetrics();
+
+    CMAPMapper *findUnicodeMapper();
+
+protected:
+    const void *readFontTable(LETag tableTag) const;
+
+public:
+    PortableFontInstance(const char *fileName, float pointSize, LEErrorCode &status);
+
+    virtual ~PortableFontInstance();
+
+    virtual const void *getFontTable(LETag tableTag) const;
+
+    virtual const char *getNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
+
+    virtual const LEUnicode16 *getUnicodeNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
+
+    virtual void deleteNameString(const char *name) const;
+
+    virtual void deleteNameString(const LEUnicode16 *name) const;
+
+    virtual le_int32 getUnitsPerEM() const;
+
+    virtual le_uint32 getFontChecksum() const;
+
+    virtual le_int32 getAscent() const;
+
+    virtual le_int32 getDescent() const;
+
+    virtual le_int32 getLeading() const;
+
+    // We really want to inherit this method from the superclass, but some compilers
+    // issue a warning if we don't implement it...
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const;
+    
+    // We really want to inherit this method from the superclass, but some compilers
+    // issue a warning if we don't implement it...
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const;
+
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch) const;
+
+    virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;
+
+    virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;
+
+    float getXPixelsPerEm() const;
+
+    float getYPixelsPerEm() const;
+
+    float getScaleFactorX() const;
+
+    float getScaleFactorY() const;
+
+};
+
+#endif
diff --git a/src/hb-icu-le/README b/src/hb-icu-le/README
new file mode 100644 (file)
index 0000000..cb4d2cf
--- /dev/null
@@ -0,0 +1,2 @@
+This is PortableFontInstance from icu/test/testle of ICU50.
+For license information, see the file license.html.
diff --git a/src/hb-icu-le/cmaps.cpp b/src/hb-icu-le/cmaps.cpp
new file mode 100644 (file)
index 0000000..87087aa
--- /dev/null
@@ -0,0 +1,200 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2003, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+#include "layout/LETypes.h"
+#include "layout/LESwaps.h"
+
+#include "sfnt.h"
+#include "cmaps.h"
+
+#define SWAPU16(code) ((LEUnicode16) SWAPW(code))
+#define SWAPU32(code) ((LEUnicode32) SWAPL(code))
+
+//
+// Finds the high bit by binary searching
+// through the bits in value.
+//
+le_int8 highBit(le_uint32 value)
+{
+    le_uint8 bit = 0;
+
+    if (value >= 1 << 16) {
+        value >>= 16;
+        bit += 16;
+    }
+
+    if (value >= 1 << 8) {
+        value >>= 8;
+        bit += 8;
+    }
+
+    if (value >= 1 << 4) {
+        value >>= 4;
+        bit += 4;
+    }
+
+    if (value >= 1 << 2) {
+        value >>= 2;
+        bit += 2;
+    }
+
+    if (value >= 1 << 1) {
+        value >>= 1;
+        bit += 1;
+    }
+
+    return bit;
+}
+
+CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
+{
+    le_uint16 i;
+    le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
+    const CMAPEncodingSubtable *subtable = NULL;
+    le_uint32 offset1 = 0, offset10 = 0;
+
+    for (i = 0; i < nSubtables; i += 1) {
+        const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
+
+        if (SWAPW(esh->platformID) == 3) {
+            switch (SWAPW(esh->platformSpecificID)) {
+            case 1:
+                offset1 = SWAPL(esh->encodingOffset);
+                break;
+
+            case 10:
+                offset10 = SWAPL(esh->encodingOffset);
+                break;
+            }
+        }
+    }
+
+
+    if (offset10 != 0)
+    {
+        subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset10);
+    } else if (offset1 != 0) {
+        subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + offset1);
+    } else {
+        return NULL;
+    }
+
+    switch (SWAPW(subtable->format)) {
+    case 4:
+        return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
+
+    case 12:
+    {
+        const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
+
+        return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
+    }
+
+    default:
+        break;
+    }
+
+    return NULL;
+}
+
+CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
+    : CMAPMapper(cmap)
+{
+    le_uint16 segCount = SWAPW(header->segCountX2) / 2;
+
+    fEntrySelector = SWAPW(header->entrySelector);
+    fRangeShift = SWAPW(header->rangeShift) / 2;
+    fEndCodes = &header->endCodes[0];
+    fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
+    fIdDelta = &fStartCodes[segCount];
+    fIdRangeOffset = &fIdDelta[segCount];
+}
+
+LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
+{
+    if (unicode32 >= 0x10000) {
+        return 0;
+    }
+
+    LEUnicode16 unicode = (LEUnicode16) unicode32;
+    le_uint16 index = 0;
+    le_uint16 probe = 1 << fEntrySelector;
+    TTGlyphID result = 0;
+
+    if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) {
+        index = fRangeShift;
+    }
+
+    while (probe > (1 << 0)) {
+        probe >>= 1;
+
+        if (SWAPU16(fStartCodes[index + probe]) <= unicode) {
+            index += probe;
+        }
+    }
+
+    if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) {
+        if (fIdRangeOffset[index] == 0) {
+            result = (TTGlyphID) unicode;
+        } else {
+            le_uint16 offset = unicode - SWAPU16(fStartCodes[index]);
+            le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
+            le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
+
+            result = SWAPW(glyphIndexTable[offset]);
+        }
+
+        result += SWAPW(fIdDelta[index]);
+    } else {
+        result = 0;
+    }
+
+    return LE_SET_GLYPH(0, result);
+}
+
+CMAPFormat4Mapper::~CMAPFormat4Mapper()
+{
+    // parent destructor does it all
+}
+
+CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
+    : CMAPMapper(cmap), fGroups(groups)
+{
+    le_uint8 bit = highBit(nGroups);
+    fPower = 1 << bit;
+    fRangeOffset = nGroups - fPower;
+}
+
+LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
+{
+    le_int32 probe = fPower;
+    le_int32 range = 0;
+
+    if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) {
+        range = fRangeOffset;
+    }
+
+    while (probe > (1 << 0)) {
+        probe >>= 1;
+
+        if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) {
+            range += probe;
+        }
+    }
+
+    if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) {
+        return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode));
+    }
+
+    return 0;
+}
+
+CMAPGroupMapper::~CMAPGroupMapper()
+{
+    // parent destructor does it all
+}
+
diff --git a/src/hb-icu-le/cmaps.h b/src/hb-icu-le/cmaps.h
new file mode 100644 (file)
index 0000000..df0bb11
--- /dev/null
@@ -0,0 +1,85 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2006, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+
+#ifndef __CMAPS_H
+#define __CMAPS_H
+
+#include "layout/LETypes.h"
+#include "letest.h"
+#include "sfnt.h"
+
+class CMAPMapper
+{
+public:
+    virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const = 0;
+
+    virtual ~CMAPMapper();
+
+    static CMAPMapper *createUnicodeMapper(const CMAPTable *cmap);
+
+protected:
+    CMAPMapper(const CMAPTable *cmap);
+
+    CMAPMapper() {};
+
+private:
+    const CMAPTable *fcmap;
+};
+
+class CMAPFormat4Mapper : public CMAPMapper
+{
+public:
+    CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header);
+
+    virtual ~CMAPFormat4Mapper();
+
+    virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
+
+protected:
+    CMAPFormat4Mapper() {};
+
+private:
+    le_uint16       fEntrySelector;
+    le_uint16       fRangeShift;
+    const le_uint16 *fEndCodes;
+    const le_uint16 *fStartCodes;
+    const le_uint16 *fIdDelta;
+    const le_uint16 *fIdRangeOffset;
+};
+
+class CMAPGroupMapper : public CMAPMapper
+{
+public:
+    CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups);
+
+    virtual ~CMAPGroupMapper();
+
+    virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
+
+protected:
+    CMAPGroupMapper() {};
+
+private:
+    le_int32 fPower;
+    le_int32 fRangeOffset;
+    const CMAPGroup *fGroups;
+};
+
+inline CMAPMapper::CMAPMapper(const CMAPTable *cmap)
+    : fcmap(cmap)
+{
+    // nothing else to do
+}
+
+inline CMAPMapper::~CMAPMapper()
+{
+    DELETE_ARRAY(fcmap);
+}
+
+#endif
+
diff --git a/src/hb-icu-le/letest.h b/src/hb-icu-le/letest.h
new file mode 100644 (file)
index 0000000..f924ca8
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2011, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ *   file name:  letest.h
+ *
+ *   created on: 11/06/2000
+ *   created by: Eric R. Mader
+ */
+
+#ifndef __LETEST_H
+#define __LETEST_H
+
+#include "layout/LETypes.h"
+/*#include "unicode/ctest.h"*/
+
+#include <stdlib.h>
+#include <string.h>
+
+U_NAMESPACE_USE
+
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+
+#define ARRAY_COPY(dst, src, count) memcpy((void *) (dst), (void *) (src), (count) * sizeof (src)[0])
+
+#define NEW_ARRAY(type,count) (type *) malloc((count) * sizeof(type))
+
+#define DELETE_ARRAY(array) free((void *) (array))
+
+#define GROW_ARRAY(array,newSize) realloc((void *) (array), (newSize) * sizeof (array)[0])
+
+struct TestResult
+{
+    le_int32   glyphCount;
+    LEGlyphID *glyphs;
+    le_int32  *indices;
+    float     *positions;
+};
+
+#ifndef __cplusplus
+typedef struct TestResult TestResult;
+#endif
+
+//U_CFUNC void addCTests(TestNode **root);
+
+#endif
diff --git a/src/hb-icu-le/license.html b/src/hb-icu-le/license.html
new file mode 100644 (file)
index 0000000..d078d05
--- /dev/null
@@ -0,0 +1,51 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></meta>
+<title>ICU License - ICU 1.8.1 and later</title>
+</head>
+
+<body BGCOLOR="#ffffff">
+<h2>ICU License - ICU 1.8.1 and later</h2>
+
+<p>COPYRIGHT AND PERMISSION NOTICE</p>
+
+<p>
+Copyright (c) 1995-2012 International Business Machines Corporation and others
+</p>
+<p>
+All rights reserved.
+</p>
+<p>
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, and/or sell
+copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies
+of the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+</p>
+<p>
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL
+THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM,
+OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+USE OR PERFORMANCE OF THIS SOFTWARE.
+</p>
+<p>
+Except as contained in this notice, the name of a copyright holder shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization of the copyright holder.
+</p>
+
+<hr>
+<p><small>
+All trademarks and registered trademarks mentioned herein are the property of their respective owners.
+</small></p>
+</body>
+</html>
diff --git a/src/hb-icu-le/sfnt.h b/src/hb-icu-le/sfnt.h
new file mode 100644 (file)
index 0000000..4a8f2f3
--- /dev/null
@@ -0,0 +1,449 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2011, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+#ifndef __SFNT_H
+#define __SFNT_H
+
+#include "layout/LETypes.h"
+
+U_NAMESPACE_USE
+
+#ifndef ANY_NUMBER
+#define ANY_NUMBER 1
+#endif
+
+struct DirectoryEntry
+{
+    le_uint32   tag;
+    le_uint32   checksum;
+    le_uint32   offset;
+    le_uint32   length;
+};
+
+#ifndef __cplusplus
+typedef struct DirectoryEntry DirectoryEntry;
+#endif
+
+struct SFNTDirectory
+{
+    le_uint32       scalerType;
+    le_uint16       numTables;
+    le_uint16       searchRange;
+    le_uint16       entrySelector;
+    le_uint16       rangeShift;
+    DirectoryEntry  tableDirectory[ANY_NUMBER];
+};
+
+#ifndef __cplusplus
+typedef struct SFNTDirectory SFNTDirectory;
+#endif
+
+
+struct CMAPEncodingSubtableHeader
+{
+    le_uint16   platformID;
+    le_uint16   platformSpecificID;
+    le_uint32   encodingOffset;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPEncodingSubtableHeader CMAPEncodingSubtableHeader;
+#endif
+
+struct CMAPTable
+{
+    le_uint16   version;
+    le_uint16   numberSubtables;
+    CMAPEncodingSubtableHeader encodingSubtableHeaders[ANY_NUMBER];
+};
+
+#ifndef __cplusplus
+typedef struct CMAPTable CMAPTable;
+#endif
+
+struct CMAPEncodingSubtable
+{
+    le_uint16   format;
+    le_uint16   length;
+    le_uint16   language;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPEncodingSubtable CMAPEncodingSubtable;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat0Encoding : CMAPEncodingSubtable
+{
+    le_uint8    glyphIndexArray[256];
+};
+#else
+struct CMAPFormat0Encoding
+{
+       CMAPEncodingSubtable base;
+
+       le_uint8 glyphIndexArray[256];
+};
+
+typedef struct CMAPFormat0Encoding CMAPFormat0Encoding;
+#endif
+
+struct CMAPFormat2Subheader
+{
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_int16    idDelta;
+    le_uint16   idRangeOffset;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPFormat2Subheader CMAPFormat2Subheader;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat2Encoding : CMAPEncodingSubtable
+{
+    le_uint16  subHeadKeys[256];
+    CMAPFormat2Subheader subheaders[ANY_NUMBER];
+};
+#else
+struct CMAPFormat2Encoding
+{
+       CMAPEncodingSubtable base;
+
+    le_uint16  subHeadKeys[256];
+    CMAPFormat2Subheader subheaders[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat2Encoding CMAPFormat2Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat4Encoding : CMAPEncodingSubtable
+{
+    le_uint16   segCountX2;
+    le_uint16   searchRange;
+    le_uint16   entrySelector;
+    le_uint16   rangeShift;
+    le_uint16   endCodes[ANY_NUMBER];
+/*
+    le_uint16   reservedPad;
+    le_uint16   startCodes[ANY_NUMBER];
+    le_uint16   idDelta[ANY_NUMBER];
+    le_uint16   idRangeOffset[ANY_NUMBER];
+    le_uint16   glyphIndexArray[ANY_NUMBER];
+*/
+};
+#else
+struct CMAPFormat4Encoding
+{
+       CMAPEncodingSubtable base;
+
+    le_uint16   segCountX2;
+    le_uint16   searchRange;
+    le_uint16   entrySelector;
+    le_uint16   rangeShift;
+    le_uint16   endCodes[ANY_NUMBER];
+/*
+//  le_uint16   reservedPad;
+//  le_uint16   startCodes[ANY_NUMBER];
+//  le_uint16   idDelta[ANY_NUMBER];
+//  le_uint16   idRangeOffset[ANY_NUMBER];
+//  le_uint16   glyphIndexArray[ANY_NUMBER];
+*/
+};
+
+typedef struct CMAPFormat4Encoding CMAPFormat4Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat6Encoding : CMAPEncodingSubtable
+{
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_uint16   glyphIndexArray[ANY_NUMBER];
+};
+#else
+struct CMAPFormat6Encoding
+{
+       CMAPEncodingSubtable base;
+
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_uint16   glyphIndexArray[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat6Encoding CMAPFormat6Encoding;
+#endif
+
+struct CMAPEncodingSubtable32
+{
+    le_uint32   format;
+    le_uint32   length;
+    le_uint32   language;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPEncodingSubtable32 CMAPEncodingSubtable32;
+#endif
+
+struct CMAPGroup
+{
+    le_uint32   startCharCode;
+    le_uint32   endCharCode;
+    le_uint32   startGlyphCode;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPGroup CMAPGroup;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat8Encoding : CMAPEncodingSubtable32
+{
+    le_uint32   is32[65536/32];
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+#else
+struct CMAPFormat8Encoding
+{
+       CMAPEncodingSubtable32 base;
+
+    le_uint32   is32[65536/32];
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat8Encoding CMAPFormat8Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat10Encoding : CMAPEncodingSubtable32
+{
+    le_uint32   startCharCode;
+    le_uint32   numCharCodes;
+    le_uint16   glyphs[ANY_NUMBER];
+};
+#else
+struct CMAPFormat10Encoding
+{
+       CMAPEncodingSubtable32 base;
+
+    le_uint32   startCharCode;
+    le_uint32   numCharCodes;
+    le_uint16   glyphs[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat10Encoding CMAPFormat10Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat12Encoding : CMAPEncodingSubtable32
+{
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+#else
+struct CMAPFormat12Encoding
+{
+       CMAPEncodingSubtable32 base;
+
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat12Encoding CMAPFormat12Encoding;
+#endif
+
+typedef le_int32 fixed;
+
+struct BigDate
+{
+    le_uint32   bc;
+    le_uint32   ad;
+};
+
+#ifndef __cplusplus
+typedef struct BigDate BigDate;
+#endif
+
+struct HEADTable
+{
+    fixed       version;
+    fixed       fontRevision;
+    le_uint32   checksumAdjustment;
+    le_uint32   magicNumber;
+    le_uint16   flags;
+    le_uint16   unitsPerEm;
+    BigDate     created;
+    BigDate     modified;
+    le_int16    xMin;
+    le_int16    yMin;
+    le_int16    xMax;
+    le_int16    yMax;
+    le_int16    lowestRecPPEM;
+    le_int16    fontDirectionHint;
+    le_int16    indexToLocFormat;
+    le_int16    glyphDataFormat;
+};
+
+#ifndef __cplusplus
+typedef struct HEADTable HEADTable;
+#endif
+
+struct MAXPTable
+{
+    fixed       version;
+    le_uint16   numGlyphs;
+    le_uint16   maxPoints;
+    le_uint16   maxContours;
+    le_uint16   maxComponentPoints;
+    le_uint16   maxComponentContours;
+    le_uint16   maxZones;
+    le_uint16   maxTwilightPoints;
+    le_uint16   maxStorage;
+    le_uint16   maxFunctionDefs;
+    le_uint16   maxInstructionDefs;
+    le_uint16   maxStackElements;
+    le_uint16   maxSizeOfInstructions;
+    le_uint16   maxComponentElements;
+    le_uint16   maxComponentDepth;
+};
+
+#ifndef __cplusplus
+typedef struct MAXPTable MAXPTable;
+#endif
+
+struct HHEATable
+{
+    fixed       version;
+    le_int16    ascent;
+    le_int16    descent;
+    le_int16    lineGap;
+    le_uint16   advanceWidthMax;
+    le_int16    minLeftSideBearing;
+    le_int16    minRightSideBearing;
+    le_int16    xMaxExtent;
+    le_int16    caretSlopeRise;
+    le_int16    caretSlopeRun;
+    le_int16    caretOffset;
+    le_int16    reserved1;
+    le_int16    reserved2;
+    le_int16    reserved3;
+    le_int16    reserved4;
+    le_int16    metricDataFormat;
+    le_uint16   numOfLongHorMetrics;
+};
+
+#ifndef __cplusplus
+typedef struct HHEATable HHEATable;
+#endif
+
+struct LongHorMetric
+{
+    le_uint16   advanceWidth;
+    le_int16    leftSideBearing;
+};
+
+#ifndef __cplusplus
+typedef struct LongHorMetric LongHorMetric;
+#endif
+
+struct HMTXTable
+{
+    LongHorMetric hMetrics[ANY_NUMBER];       /* ANY_NUMBER = numOfLongHorMetrics from hhea table */
+/* le_int16        leftSideBearing[ANY_NUMBER];  ANY_NUMBER = numGlyphs - numOfLongHorMetrics     */
+};
+
+#ifndef __cplusplus
+typedef struct HMTXTable HMTXTable;
+#endif
+
+enum PlatformID
+{
+    PLATFORM_UNICODE = 0,
+    PLATFORM_MACINTOSH = 1,
+    PLATFORM_ISO       = 2,
+    PLATFORM_MICROSOFT = 3,
+    PLATFORM_CUSTOM    = 4
+};
+
+enum MacintoshEncodingID
+{
+    MACINTOSH_ROMAN = 0
+};
+
+enum MacintoshLanguageID
+{
+    MACINTOSH_ENGLISH = 0
+};
+
+enum MicrosoftEncodingID
+{
+    MICROSOFT_UNICODE_BMP  =  1,
+    MICROSOFT_UNICODE_FULL = 10
+};
+
+enum MicrosoftLanguageID
+{
+    MICROSOFT_ENGLISH = 0x409
+};
+
+enum NameID
+{
+    NAME_COPYRIGHT_NOTICE     = 0,
+    NAME_FONT_FAMILY          = 1,
+    NAME_FONT_SUB_FAMILY      = 2,
+    NAME_UNIQUE_FONT_ID       = 3,
+    NAME_FULL_FONT_NAME       = 4,
+    NAME_VERSION_STRING       = 5,
+    NAME_POSTSCRIPT_NAME      = 6,
+    NAME_TRADEMARK            = 7,
+    NAME_MANUFACTURER         = 8,
+    NAME_DESIGNER             = 9,
+    NAME_DESCRIPTION          = 10,
+    NAME_VENDOR_URL           = 11,
+    NAME_DESIGNER_URL         = 12,
+    NAME_LICENSE_DESCRIPTION  = 13,
+    NAME_LICENSE_URL          = 14,
+    NAME_RESERVED             = 15,
+    NAME_PREFERRED_FAMILY     = 16,
+    NAME_PREFERRED_SUB_FAMILY = 17,
+    NAME_COMPATIBLE_FULL      = 18,
+    NAME_SAMPLE_TEXT          = 19,
+    NAME_POSTSCRIPT_CID       = 20
+};
+
+struct NameRecord
+{
+    le_uint16 platformID;
+    le_uint16 encodingID;
+    le_uint16 languageID;
+    le_uint16 nameID;
+    le_uint16 length;
+    le_uint16 offset;
+};
+
+#ifndef __cplusplus
+typedef struct NameRecord NameRecord;
+#endif
+
+struct NAMETable
+{
+    le_uint16 version;
+    le_uint16 count;
+    le_uint16 stringOffset;
+    NameRecord nameRecords[ANY_NUMBER];
+};
+
+#ifndef __cplusplus
+typedef struct NAMETable NAMETable;
+#endif
+
+#endif
+