[HarfBuzz] harfbuzz: Branch 'master' - 5 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Aug 23 21:42:43 PDT 2012


 configure.ac                           |    9 
 src/Makefile.am                        |    8 
 src/hb-graphite2.cc                    |   77 +++--
 src/hb-icu-le.cc                       |  213 +++++++++++++++
 src/hb-icu-le/FontTableCache.cpp       |   91 ++++++
 src/hb-icu-le/FontTableCache.h         |   44 +++
 src/hb-icu-le/Makefile.am              |   25 +
 src/hb-icu-le/PortableFontInstance.cpp |  307 ++++++++++++++++++++++
 src/hb-icu-le/PortableFontInstance.h   |  112 ++++++++
 src/hb-icu-le/README                   |    3 
 src/hb-icu-le/cmaps.cpp                |  200 ++++++++++++++
 src/hb-icu-le/cmaps.h                  |   84 ++++++
 src/hb-icu-le/letest.h                 |   49 +++
 src/hb-icu-le/license.html             |   51 +++
 src/hb-icu-le/sfnt.h                   |  449 +++++++++++++++++++++++++++++++++
 src/hb-shaper-list.hh                  |    4 
 16 files changed, 1693 insertions(+), 33 deletions(-)

New commits:
commit 56e878ab875ff06d74702145e380e198be967bd6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Aug 24 00:41:51 2012 -0400

    [graphite2] Cleanup scratch buffer allocation

diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index a30c42e..6c890d4 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -211,11 +211,6 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
   gr_font *grfont = HB_SHAPER_DATA_GET (font);
 
-  unsigned int charlen;
-  hb_glyph_info_t *bufferi = hb_buffer_get_glyph_infos (buffer, &charlen);
-
-  int success = 0;
-
   const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
   const char *lang_end = strchr (lang, '-');
   int lang_len = lang_end ? lang_end - lang : -1;
@@ -229,24 +224,23 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
     features++;
   }
 
-  /* TODO Use scratch buffer for these. */
-  hb_codepoint_t *gids = NULL, *pg;
-  hb_graphite2_cluster_t *clusters = NULL;
   gr_segment *seg = NULL;
-  uint32_t *text = NULL;
   const gr_slot *is;
   unsigned int ci = 0, ic = 0;
   float curradvx = 0., curradvy = 0.;
-  unsigned int glyphlen = 0;
-  unsigned int *p;
 
-  text = (uint32_t *) malloc ((charlen + 1) * sizeof (uint32_t));
-  if (!text) goto dieout;
+  unsigned int scratch_size;
+  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+
+#define ALLOCATE_ARRAY(Type, name, len) \
+  Type *name = (Type *) scratch; \
+  scratch += (len) * sizeof ((name)[0]); \
+  scratch_size -= (len) * sizeof ((name)[0]);
+
+  ALLOCATE_ARRAY (uint32_t, chars, buffer->len);
 
-  p = text;
-  for (unsigned int i = 0; i < charlen; ++i)
-    *p++ = bufferi++->codepoint;
-  *p = 0;
+  for (unsigned int i = 0; i < buffer->len; ++i)
+    chars[i] = buffer->info[i].codepoint;
 
   hb_tag_t script_tag[2];
   hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
@@ -254,18 +248,40 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   seg = gr_make_seg (grfont, grface,
 		     script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
 		     feats,
-		     gr_utf32, text, charlen,
+		     gr_utf32, chars, buffer->len,
 		     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
-  if (!seg) goto dieout;
 
-  glyphlen = gr_seg_n_slots (seg);
-  clusters = (hb_graphite2_cluster_t *) calloc (charlen, sizeof (hb_graphite2_cluster_t));
-  if (!glyphlen || !clusters) goto dieout;
+  if (unlikely (!seg)) {
+    if (feats) gr_featureval_destroy (feats);
+    return false;
+  }
+
+  unsigned int glyph_count = gr_seg_n_slots (seg);
+  if (unlikely (!glyph_count)) {
+    if (feats) gr_featureval_destroy (feats);
+    gr_seg_destroy (seg);
+    return false;
+  }
+
+  scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+  while ((sizeof (hb_graphite2_cluster_t) * buffer->len +
+	  sizeof (hb_codepoint_t) * glyph_count) > scratch_size)
+  {
+    buffer->ensure (buffer->allocated * 2);
+    if (unlikely (buffer->in_error)) {
+      if (feats) gr_featureval_destroy (feats);
+      gr_seg_destroy (seg);
+      return false;
+    }
+    scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+  }
 
-  gids = (hb_codepoint_t *) malloc (glyphlen * sizeof (hb_codepoint_t));
-  if (!gids) goto dieout;
+  ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
+  ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
 
-  pg = gids;
+  memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
+
+  hb_codepoint_t *pg = gids;
   for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
   {
     unsigned int before = gr_slot_before (is);
@@ -325,13 +341,8 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
     hb_buffer_reverse_clusters (buffer);
 
-  success = 1;
-
-dieout:
   if (feats) gr_featureval_destroy (feats);
-  if (gids) free (gids);
-  if (clusters) free (clusters);
-  if (seg) gr_seg_destroy (seg);
-  if (text) free (text);
-  return success;
+  gr_seg_destroy (seg);
+
+  return true;
 }
commit 2f7586c6229096143ca0a96712a27416ee0d3c85
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Aug 23 23:59:55 2012 -0400

    [icu-le] Implement icu layout engine shaper

diff --git a/configure.ac b/configure.ac
index de3c55c..47a7b2b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -160,7 +160,7 @@ AM_CONDITIONAL(HAVE_ICU, $have_icu)
 
 dnl ==========================================================================
 
-PKG_CHECK_MODULES(ICU_LE, icu-le, have_icu_le=true, have_icu_le=false)
+PKG_CHECK_MODULES(ICU_LE, icu-le icu-uc, 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
diff --git a/src/hb-icu-le.cc b/src/hb-icu-le.cc
index 07f766d..68c9c42 100644
--- a/src/hb-icu-le.cc
+++ b/src/hb-icu-le.cc
@@ -30,14 +30,10 @@
 
 #include "hb-icu-le/PortableFontInstance.h"
 
-#include "layout/loengine.h"
+#include "layout/LayoutEngine.h"
+#include "unicode/unistr.h"
 
-#include <harfbuzz.h>
-
-
-#ifndef HB_DEBUG_ICU_LE
-#define HB_DEBUG_ICU_LE (HB_DEBUG+0)
-#endif
+#include "hb-icu.h"
 
 
 /*
@@ -93,8 +89,8 @@ 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)
+					  const hb_feature_t *user_features,
+					  unsigned int        num_user_features)
 {
   return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
@@ -116,5 +112,102 @@ _hb_icu_le_shape (hb_shape_plan_t    *shape_plan,
 		  const hb_feature_t *features,
 		  unsigned int        num_features)
 {
-  return false;
+  LEFontInstance *font_instance = HB_SHAPER_DATA_GET (font);
+  le_int32 script_code = hb_icu_script_from_script (shape_plan->props.script);
+  le_int32 language_code = -1 /* TODO */;
+  le_int32 typography_flags = 3; // essential for ligatures and kerning
+  LEErrorCode status = LE_NO_ERROR;
+  LayoutEngine *le = LayoutEngine::layoutEngineFactory (font_instance,
+							script_code,
+							language_code,
+							typography_flags,
+							status);
+  if (status != LE_NO_ERROR)
+  { delete (le); return false; }
+
+retry:
+
+  unsigned int scratch_size;
+  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+
+#define ALLOCATE_ARRAY(Type, name, len) \
+  Type *name = (Type *) scratch; \
+  scratch += (len) * sizeof ((name)[0]); \
+  scratch_size -= (len) * sizeof ((name)[0]);
+
+  ALLOCATE_ARRAY (LEUnicode, chars, buffer->len);
+  ALLOCATE_ARRAY (unsigned int, clusters, buffer->len);
+
+  for (unsigned int i = 0; i < buffer->len; i++) {
+    chars[i] = buffer->info[i].codepoint;
+    clusters[i] = buffer->info[i].cluster;
+  }
+
+  unsigned int glyph_count = le->layoutChars(chars,
+					     0,
+					     buffer->len,
+					     buffer->len,
+					     HB_DIRECTION_IS_BACKWARD (buffer->props.direction),
+					     0., 0.,
+					     status);
+  if (status != LE_NO_ERROR)
+  { delete (le); return false; }
+
+  unsigned int num_glyphs = scratch_size / (sizeof (LEGlyphID) +
+					    sizeof (le_int32) +
+					    sizeof (float) * 2);
+
+  if (unlikely (glyph_count >= num_glyphs || glyph_count > buffer->allocated)) {
+    buffer->ensure (buffer->allocated * 2);
+    if (buffer->in_error)
+    { delete (le); return false; }
+    goto retry;
+  }
+
+  ALLOCATE_ARRAY (LEGlyphID, glyphs, glyph_count);
+  ALLOCATE_ARRAY (le_int32, indices, glyph_count);
+  ALLOCATE_ARRAY (float, positions, glyph_count * 2 + 2);
+
+  le->getGlyphs(glyphs, status);
+  le->getCharIndices(indices, status);
+  le->getGlyphPositions(positions, status);
+
+#undef ALLOCATE_ARRAY
+
+  /* Ok, we've got everything we need, now compose output buffer,
+   * very, *very*, carefully! */
+
+  unsigned int j = 0;
+  hb_glyph_info_t *info = buffer->info;
+  for (unsigned int i = 0; i < glyph_count; i++)
+  {
+    if (glyphs[i] >= 0xFFFE)
+	continue;
+
+    info[j].codepoint = glyphs[i];
+    info[j].cluster = clusters[indices[i]];
+
+    /* icu-le doesn't seem to have separapte advance values. */
+    info[j].mask = positions[2 * i + 2] - positions[2 * i];
+    info[j].var1.u32 = 0;
+    info[j].var2.u32 = -positions[2 * i + 1];
+
+    j++;
+  }
+  buffer->len = j;
+
+  buffer->clear_positions ();
+
+  for (unsigned int i = 0; i < buffer->len; i++) {
+    hb_glyph_info_t *info = &buffer->info[i];
+    hb_glyph_position_t *pos = &buffer->pos[i];
+
+    /* TODO vertical */
+    pos->x_advance = info->mask;
+    pos->x_offset = info->var1.u32;
+    pos->y_offset = info->var2.u32;
+  }
+
+  delete (le);
+  return true;
 }
diff --git a/src/hb-icu-le/cmaps.h b/src/hb-icu-le/cmaps.h
index df0bb11..fcad788 100644
--- a/src/hb-icu-le/cmaps.h
+++ b/src/hb-icu-le/cmaps.h
@@ -78,7 +78,6 @@ inline CMAPMapper::CMAPMapper(const CMAPTable *cmap)
 
 inline CMAPMapper::~CMAPMapper()
 {
-    DELETE_ARRAY(fcmap);
 }
 
 #endif
diff --git a/src/hb-shaper-list.hh b/src/hb-shaper-list.hh
index 8e67dbd..6c02de4 100644
--- a/src/hb-shaper-list.hh
+++ b/src/hb-shaper-list.hh
@@ -47,4 +47,8 @@ HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
 HB_SHAPER_IMPLEMENT (old)
 #endif
 
+#ifdef HAVE_ICU_LE
+HB_SHAPER_IMPLEMENT (icu_le)
+#endif
+
 HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
commit ba7f6c3797e5b440557bacd9b666bf09713dca76
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Aug 23 21:52:44 2012 -0400

    [icu-le] Hook up to hb_face_t

diff --git a/src/hb-icu-le.cc b/src/hb-icu-le.cc
index 9629534..07f766d 100644
--- a/src/hb-icu-le.cc
+++ b/src/hb-icu-le.cc
@@ -25,6 +25,7 @@
  */
 
 #define HB_SHAPER icu_le
+#define hb_icu_le_shaper_font_data_t PortableFontInstance
 #include "hb-shaper-impl-private.hh"
 
 #include "hb-icu-le/PortableFontInstance.h"
@@ -61,18 +62,26 @@ _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;
+  LEErrorCode status = LE_NO_ERROR;
+  hb_icu_le_shaper_font_data_t *data = new PortableFontInstance (font->face,
+								 font->x_scale,
+								 font->y_scale,
+								 status);
+  if (status != LE_NO_ERROR) {
+    delete (data);
+    return NULL;
+  }
+
+  return data;
 }
 
 void
 _hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t *data)
 {
-  free (data);
+  delete (data);
 }
 
 
diff --git a/src/hb-icu-le/FontTableCache.cpp b/src/hb-icu-le/FontTableCache.cpp
index 84d5507..93db6cc 100644
--- a/src/hb-icu-le/FontTableCache.cpp
+++ b/src/hb-icu-le/FontTableCache.cpp
@@ -16,7 +16,7 @@
 struct FontTableCacheEntry
 {
     LETag tag;
-    const void *table;
+    hb_blob_t *blob;
 };
 
 FontTableCache::FontTableCache()
@@ -30,18 +30,18 @@ FontTableCache::FontTableCache()
     }
 
     for (int i = 0; i < fTableCacheSize; i += 1) {
-        fTableCache[i].tag   = 0;
-        fTableCache[i].table = NULL;
+        fTableCache[i].tag  = 0;
+        fTableCache[i].blob = NULL;
     }
 }
 
 FontTableCache::~FontTableCache()
 {
     for (int i = fTableCacheCurr - 1; i >= 0; i -= 1) {
-        DELETE_ARRAY(fTableCache[i].table);
+        hb_blob_destroy(fTableCache[i].blob);
 
-        fTableCache[i].tag   = 0;
-        fTableCache[i].table = NULL;
+        fTableCache[i].tag  = 0;
+        fTableCache[i].blob = NULL;
     }
 
     fTableCacheCurr = 0;
@@ -49,27 +49,27 @@ FontTableCache::~FontTableCache()
     DELETE_ARRAY(fTableCache);
 }
 
-void FontTableCache::freeFontTable(const void *table) const
+void FontTableCache::freeFontTable(hb_blob_t *blob) const
 {
-    DELETE_ARRAY(table);
+    hb_blob_destroy(blob);
 }
 
 const void *FontTableCache::find(LETag tableTag) const
 {
     for (int i = 0; i < fTableCacheCurr; i += 1) {
         if (fTableCache[i].tag == tableTag) {
-            return fTableCache[i].table;
+            return hb_blob_get_data(fTableCache[i].blob, NULL);
         }
     }
 
-    const void *table = readFontTable(tableTag);
+    hb_blob_t *blob = readFontTable(tableTag);
 
-    ((FontTableCache *) this)->add(tableTag, table);
+    ((FontTableCache *) this)->add(tableTag, blob);
 
-    return table;
+    return hb_blob_get_data (blob, NULL);
 }
 
-void FontTableCache::add(LETag tableTag, const void *table)
+void FontTableCache::add(LETag tableTag, hb_blob_t *blob)
 {
     if (fTableCacheCurr >= fTableCacheSize) {
         le_int32 newSize = fTableCacheSize + TABLE_CACHE_GROW;
@@ -77,15 +77,15 @@ void FontTableCache::add(LETag tableTag, const void *table)
         fTableCache = (FontTableCacheEntry *) GROW_ARRAY(fTableCache, newSize);
 
         for (le_int32 i = fTableCacheSize; i < newSize; i += 1) {
-            fTableCache[i].tag   = 0;
-            fTableCache[i].table = NULL;
+            fTableCache[i].tag  = 0;
+            fTableCache[i].blob = NULL;
         }
 
         fTableCacheSize = newSize;
     }
 
-    fTableCache[fTableCacheCurr].tag   = tableTag;
-    fTableCache[fTableCacheCurr].table = table;
+    fTableCache[fTableCacheCurr].tag  = tableTag;
+    fTableCache[fTableCacheCurr].blob = blob;
 
     fTableCacheCurr += 1;
 }
diff --git a/src/hb-icu-le/FontTableCache.h b/src/hb-icu-le/FontTableCache.h
index 36971e4..d41d7c7 100644
--- a/src/hb-icu-le/FontTableCache.h
+++ b/src/hb-icu-le/FontTableCache.h
@@ -9,6 +9,9 @@
 
 #define __FONTTABLECACHE_H
 
+#define HB_H_IN
+#include <hb-blob.h>
+
 #include "layout/LETypes.h"
 
 U_NAMESPACE_USE
@@ -25,12 +28,12 @@ public:
     const void *find(LETag tableTag) const;
 
 protected:
-    virtual const void *readFontTable(LETag tableTag) const = 0;
-    virtual void freeFontTable(const void *table) const;
+    virtual hb_blob_t *readFontTable(LETag tableTag) const = 0;
+    virtual void freeFontTable(hb_blob_t *blob) const;
 
 private:
 
-    void add(LETag tableTag, const void *table);
+    void add(LETag tableTag, hb_blob_t *blob);
 
     FontTableCacheEntry *fTableCache;
     le_int32 fTableCacheCurr;
diff --git a/src/hb-icu-le/PortableFontInstance.cpp b/src/hb-icu-le/PortableFontInstance.cpp
index 5394fb8..f4eb171 100644
--- a/src/hb-icu-le/PortableFontInstance.cpp
+++ b/src/hb-icu-le/PortableFontInstance.cpp
@@ -64,83 +64,24 @@ le_int8 PortableFontInstance::highBit(le_int32 value)
     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)
+PortableFontInstance::PortableFontInstance(hb_face_t *face, float xScale, float yScale, LEErrorCode &status)
+    : fFace(face), fXScale(xScale), fYScale(yScale), fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0),
+      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 *) getFontTable(headTag);
-
-    if (headTable == NULL) {
-        status = LE_MISSING_FONT_TABLE_ERROR;
-        goto error_exit;
-    }
-
-    fUnitsPerEM   = SWAPW(headTable->unitsPerEm);
-    fFontChecksum = SWAPL(headTable->checksumAdjustment);
-
-    //nameTable = (NAMETable *) getFontTable(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;
-    //}
+    fUnitsPerEM = hb_face_get_upem (face);
 
     hheaTable = (HHEATable *) getFontTable(hheaTag);
 
     if (hheaTable == NULL) {
         status = LE_MISSING_FONT_TABLE_ERROR;
-        goto error_exit;
+	return;
     }
 
     fAscent  = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent));
@@ -153,73 +94,14 @@ PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize
 
     if (fCMAPMapper == NULL) {
         status = LE_MISSING_FONT_TABLE_ERROR;
-        goto error_exit;
+	return;
     }
-
-    return;
-
-error_exit:
-    fclose(fFile);
-    fFile = NULL;
-    return;
 }
 
 PortableFontInstance::~PortableFontInstance()
 {
-    if (fFile != NULL) {
-        fclose(fFile);
-
+    if (fCMAPMapper)
         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
@@ -227,11 +109,9 @@ const void *PortableFontInstance::getFontTable(LETag tableTag) const
     return FontTableCache::find(tableTag);
 }
 
-const void *PortableFontInstance::readFontTable(LETag tableTag) const
+hb_blob_t *PortableFontInstance::readFontTable(LETag tableTag) const
 {
-    le_uint32 len;
-
-    return readTable(tableTag, &len);
+  return hb_face_reference_table(fFace, tableTag);
 }
 
 CMAPMapper *PortableFontInstance::findUnicodeMapper()
@@ -369,7 +249,7 @@ le_int32 PortableFontInstance::getUnitsPerEM() const
 
 le_uint32 PortableFontInstance::getFontChecksum() const
 {
-    return fFontChecksum;
+    return 0;
 }
 
 le_int32 PortableFontInstance::getAscent() const
@@ -408,12 +288,12 @@ LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const
 
 float PortableFontInstance::getXPixelsPerEm() const
 {
-    return fPointSize;
+    return fXScale;
 }
 
 float PortableFontInstance::getYPixelsPerEm() const
 {
-    return fPointSize;
+    return fYScale;
 }
 
 float PortableFontInstance::getScaleFactorX() const
diff --git a/src/hb-icu-le/PortableFontInstance.h b/src/hb-icu-le/PortableFontInstance.h
index 3e86112..a444772 100644
--- a/src/hb-icu-le/PortableFontInstance.h
+++ b/src/hb-icu-le/PortableFontInstance.h
@@ -15,32 +15,29 @@
 #ifndef __PORTABLEFONTINSTANCE_H
 #define __PORTABLEFONTINSTANCE_H
 
-#include <stdio.h>
+#define HB_H_IN
+#include <hb-font.h>
+#include <hb-blob.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;
+    hb_face_t *fFace;
 
-    float     fPointSize;
+    float     fXScale;
+    float     fYScale;
     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;
 
@@ -56,17 +53,15 @@ private:
 
     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;
+    hb_blob_t *readFontTable(LETag tableTag) const;
 
 public:
-    PortableFontInstance(const char *fileName, float pointSize, LEErrorCode &status);
+    PortableFontInstance(hb_face_t *face, float xScale, float yScale, LEErrorCode &status);
 
     virtual ~PortableFontInstance();
 
diff --git a/src/hb-icu-le/README b/src/hb-icu-le/README
index cb4d2cf..329a218 100644
--- a/src/hb-icu-le/README
+++ b/src/hb-icu-le/README
@@ -1,2 +1,3 @@
 This is PortableFontInstance from icu/test/testle of ICU50.
+Modified to use a hb_face_t.
 For license information, see the file license.html.
commit e96bb36995b2a5321b4d32bb11906e1701aaf115
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Aug 23 21:37:51 2012 -0400

    [icu-le] Actually use the FontTableCache

diff --git a/src/hb-icu-le/PortableFontInstance.cpp b/src/hb-icu-le/PortableFontInstance.cpp
index 14e3f52..5394fb8 100644
--- a/src/hb-icu-le/PortableFontInstance.cpp
+++ b/src/hb-icu-le/PortableFontInstance.cpp
@@ -112,7 +112,7 @@ PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize
     fDirExtra = numTables - fDirPower;
 
     // read unitsPerEm from 'head' table
-    headTable = (const HEADTable *) readFontTable(headTag);
+    headTable = (const HEADTable *) getFontTable(headTag);
 
     if (headTable == NULL) {
         status = LE_MISSING_FONT_TABLE_ERROR;
@@ -121,9 +121,8 @@ PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize
 
     fUnitsPerEM   = SWAPW(headTable->unitsPerEm);
     fFontChecksum = SWAPL(headTable->checksumAdjustment);
-    freeFontTable(headTable);
 
-    //nameTable = (NAMETable *) readFontTable(nameTag);
+    //nameTable = (NAMETable *) getFontTable(nameTag);
 
     //if (nameTable == NULL) {
     //    status = LE_MISSING_FONT_TABLE_ERROR;
@@ -137,9 +136,7 @@ PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize
     //    goto error_exit;
     //}
 
-    //freeFontTable(nameTable);
-
-    hheaTable = (HHEATable *) readFontTable(hheaTag);
+    hheaTable = (HHEATable *) getFontTable(hheaTag);
 
     if (hheaTable == NULL) {
         status = LE_MISSING_FONT_TABLE_ERROR;
@@ -152,8 +149,6 @@ PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize
 
     fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
 
-    freeFontTable((void *) hheaTable);
-
     fCMAPMapper = findUnicodeMapper();
 
     if (fCMAPMapper == NULL) {
@@ -174,9 +169,6 @@ PortableFontInstance::~PortableFontInstance()
     if (fFile != NULL) {
         fclose(fFile);
 
-        freeFontTable(fHMTXTable);
-        freeFontTable(fNAMETable);
-
         delete fCMAPMapper;
 
         DELETE_ARRAY(fDirectory);
@@ -245,7 +237,7 @@ const void *PortableFontInstance::readFontTable(LETag tableTag) const
 CMAPMapper *PortableFontInstance::findUnicodeMapper()
 {
     LETag cmapTag = LE_CMAP_TABLE_TAG;
-    const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag);
+    const CMAPTable *cmap = (CMAPTable *) getFontTable(cmapTag);
 
     if (cmap == NULL) {
         return NULL;
@@ -260,7 +252,7 @@ const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 plat
         LETag nameTag = LE_NAME_TABLE_TAG;
         PortableFontInstance *realThis = (PortableFontInstance *) this;
 
-        realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
+        realThis->fNAMETable = (const NAMETable *) getFontTable(nameTag);
 
         if (realThis->fNAMETable != NULL) {
             realThis->fNameCount        = SWAPW(realThis->fNAMETable->count);
@@ -293,7 +285,7 @@ const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID,
         LETag nameTag = LE_NAME_TABLE_TAG;
         PortableFontInstance *realThis = (PortableFontInstance *) this;
 
-        realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
+        realThis->fNAMETable = (const NAMETable *) getFontTable(nameTag);
 
         if (realThis->fNAMETable != NULL) {
             realThis->fNameCount        = SWAPW(realThis->fNAMETable->count);
@@ -340,15 +332,14 @@ void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) co
     if (fHMTXTable == NULL) {
         LETag maxpTag = LE_MAXP_TABLE_TAG;
         LETag hmtxTag = LE_HMTX_TABLE_TAG;
-        const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag);
+        const MAXPTable *maxpTable = (MAXPTable *) getFontTable(maxpTag);
         PortableFontInstance *realThis = (PortableFontInstance *) this;
 
         if (maxpTable != NULL) {
             realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
-            freeFontTable(maxpTable);
         }
 
-        realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag);
+        realThis->fHMTXTable = (const HMTXTable *) getFontTable(hmtxTag);
     }
 
     le_uint16 index = ttGlyph;
commit 7d242364ea647f655a7092bda25f9a10774c57f5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Aug 23 21:23:41 2012 -0400

    [icu-le] Start adding a icu-layout-engine backend
    
    Import PortableFontInstance and add shaper stub.

diff --git a/configure.ac b/configure.ac
index 916a5d4..de3c55c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/src/Makefile.am b/src/Makefile.am
index 5894b20..166ba79 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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
index 0000000..9629534
--- /dev/null
+++ b/src/hb-icu-le.cc
@@ -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
index 0000000..84d5507
--- /dev/null
+++ b/src/hb-icu-le/FontTableCache.cpp
@@ -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
index 0000000..36971e4
--- /dev/null
+++ b/src/hb-icu-le/FontTableCache.h
@@ -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
index 0000000..dd99dc1
--- /dev/null
+++ b/src/hb-icu-le/Makefile.am
@@ -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
index 0000000..14e3f52
--- /dev/null
+++ b/src/hb-icu-le/PortableFontInstance.cpp
@@ -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
index 0000000..3e86112
--- /dev/null
+++ b/src/hb-icu-le/PortableFontInstance.h
@@ -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
index 0000000..cb4d2cf
--- /dev/null
+++ b/src/hb-icu-le/README
@@ -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
index 0000000..87087aa
--- /dev/null
+++ b/src/hb-icu-le/cmaps.cpp
@@ -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
index 0000000..df0bb11
--- /dev/null
+++ b/src/hb-icu-le/cmaps.h
@@ -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
index 0000000..f924ca8
--- /dev/null
+++ b/src/hb-icu-le/letest.h
@@ -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
index 0000000..d078d05
--- /dev/null
+++ b/src/hb-icu-le/license.html
@@ -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
index 0000000..4a8f2f3
--- /dev/null
+++ b/src/hb-icu-le/sfnt.h
@@ -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
+



More information about the HarfBuzz mailing list