Advance C++ port to Aug 11 Java snapshot



git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@70 672e30a5-4c29-85ac-ac6d-611c735e0a51
diff --git a/sample/subsetter/subset_util.cc b/sample/subsetter/subset_util.cc
index 26da65f..f35eb25 100644
--- a/sample/subsetter/subset_util.cc
+++ b/sample/subsetter/subset_util.cc
@@ -56,12 +56,11 @@
   UNREFERENCED_PARAMETER(bytes_read);
   fclose(input_file);
 
-  ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), file_size);
   FontFactoryPtr factory;
   factory.Attach(FontFactory::GetInstance());
 
   FontArray font_array;
-  factory->LoadFonts(ba, &font_array);
+  factory->LoadFonts(&input_buffer, &font_array);
   if (font_array.empty() || font_array[0] == NULL)
     return;
 
diff --git a/sfntly/font.cc b/sfntly/font.cc
index d66c9f6..e5e4401 100644
--- a/sfntly/font.cc
+++ b/sfntly/font.cc
@@ -23,6 +23,7 @@
 #include <map>
 #include <string>
 #include <typeinfo>
+#include <iterator>
 
 #include "sfntly/data/font_input_stream.h"
 #include "sfntly/font_factory.h"
@@ -58,14 +59,14 @@
   return tables_[tag];
 }
 
-TableMap* Font::Tables() {
+const TableMap* Font::GetTableMap() {
   return &tables_;
 }
 
 void Font::Serialize(OutputStream* os, IntegerList* table_ordering) {
   assert(table_ordering);
   IntegerList final_table_ordering;
-  TableOrdering(table_ordering, &final_table_ordering);
+  GenerateTableOrdering(table_ordering, &final_table_ordering);
   TableHeaderList table_records;
   BuildTableHeadersForSerialization(&final_table_ordering, &table_records);
 
@@ -74,18 +75,11 @@
   SerializeTables(&fos, &table_records);
 }
 
-CALLER_ATTACH WritableFontData* Font::GetNewData(int32_t size) {
-  return factory_->GetNewData(size);
-}
-
-Font::Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest,
-           TableMap* tables)
-    : factory_(factory),
-      sfnt_version_(sfnt_version) {
+Font::Font(int32_t sfnt_version, ByteVector* digest)
+    : sfnt_version_(sfnt_version) {
   // non-trivial assignments that makes debugging hard if placed in
   // initialization list
   digest_ = *digest;
-  tables_ = *tables;
 }
 
 void Font::BuildTableHeadersForSerialization(IntegerList* table_ordering,
@@ -94,19 +88,22 @@
   assert(table_ordering);
 
   IntegerList final_table_ordering;
-  TableOrdering(table_ordering, &final_table_ordering);
+  GenerateTableOrdering(table_ordering, &final_table_ordering);
   int32_t table_offset = Offset::kTableRecordBegin + num_tables() *
                          Offset::kTableRecordSize;
   for (IntegerList::iterator tag = final_table_ordering.begin(),
                              tag_end = final_table_ordering.end();
                              tag != tag_end; ++tag) {
+    if (tables_.find(*tag) == tables_.end()) {
+      continue;
+    }
     TablePtr table = tables_[*tag];
     if (table != NULL) {
       TableHeaderPtr header =
           new Table::Header(*tag, table->CalculatedChecksum(), table_offset,
-                            table->Length());
+                            table->header()->length());
       table_headers->push_back(header);
-      table_offset += (table->Length() + 3) & ~3;
+      table_offset += (table->DataLength() + 3) & ~3;
     }
   }
 }
@@ -121,9 +118,14 @@
   fos->WriteUShort(log2_of_max_power_of_2);
   fos->WriteUShort((table_headers->size() * 16) - search_range);
 
-  for (TableHeaderList::iterator record = table_headers->begin(),
-                                 record_end = table_headers->end();
-                                 record != record_end; ++record) {
+  HeaderTagSortedSet sorted_headers;
+  std::copy(table_headers->begin(),
+            table_headers->end(),
+            std::inserter(sorted_headers, sorted_headers.end()));
+
+  for (HeaderTagSortedSet::iterator record = sorted_headers.begin(),
+                                    record_end = sorted_headers.end();
+                                    record != record_end; ++record) {
     fos->WriteULong((*record)->tag());
     fos->WriteULong((int32_t)((*record)->checksum()));
     fos->WriteULong((*record)->offset());
@@ -133,30 +135,31 @@
 
 void Font::SerializeTables(FontOutputStream* fos,
                            TableHeaderList* table_headers) {
-  ByteVector SERIALIZATION_FILLER(3);
-  std::fill(SERIALIZATION_FILLER.begin(), SERIALIZATION_FILLER.end(), 0);
+  assert(fos);
+  assert(table_headers);
   for (TableHeaderList::iterator record = table_headers->begin(),
                                  end_of_headers = table_headers->end();
                                  record != end_of_headers; ++record) {
     TablePtr target_table = GetTable((*record)->tag());
     if (target_table == NULL) {
-#if defined (SFNTLY_NO_EXCEPTION)
-      return;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
       throw IOException("Table out of sync with font header.");
 #endif
+      return;
     }
     int32_t table_size = target_table->Serialize(fos);
     if (table_size != (*record)->length()) {
       assert(false);
     }
     int32_t filler_size = ((table_size + 3) & ~3) - table_size;
-    fos->Write(&SERIALIZATION_FILLER, 0, filler_size);
+    for (int32_t i = 0; i < filler_size; ++i) {
+      fos->Write(static_cast<byte_t>(0));
+    }
   }
 }
 
-void Font::TableOrdering(IntegerList* default_table_ordering,
-                         IntegerList* table_ordering) {
+void Font::GenerateTableOrdering(IntegerList* default_table_ordering,
+                                 IntegerList* table_ordering) {
   assert(default_table_ordering);
   assert(table_ordering);
   table_ordering->clear();
@@ -207,17 +210,19 @@
  ******************************************************************************/
 Font::Builder::~Builder() {}
 
-CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
-    FontFactory* factory, InputStream* is) {
+CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(FontFactory* factory,
+                                                          InputStream* is) {
   FontBuilderPtr builder = new Builder(factory);
   builder->LoadFont(is);
   return builder.Detach();
 }
 
 CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
-    FontFactory* factory, ByteArray* ba, int32_t offset_to_offset_table) {
+    FontFactory* factory,
+    WritableFontData* wfd,
+    int32_t offset_to_offset_table) {
   FontBuilderPtr builder = new Builder(factory);
-  builder->LoadFont(ba, offset_to_offset_table);
+  builder->LoadFont(wfd, offset_to_offset_table);
   return builder.Detach();
 }
 
@@ -233,7 +238,7 @@
     return true;
   }
 
-  // TODO(stuartg): font level checks - required tables etc.
+  // TODO(stuartg): font level checks - required tables etc?
   for (TableBuilderMap::iterator table_builder = table_builders_.begin(),
                                  table_builder_end = table_builders_.end();
                                  table_builder != table_builder_end;
@@ -245,31 +250,25 @@
 }
 
 CALLER_ATTACH Font* Font::Builder::Build() {
-  TableMap tables;
+  FontPtr font = new Font(sfnt_version_, &digest_);
+
   if (!table_builders_.empty()) {
-    BuildTablesFromBuilders(&table_builders_, &tables);
+    // Note: Different from Java. Directly use font->tables_ here to avoid
+    //       STL container copying.
+    BuildTablesFromBuilders(font, &table_builders_, &font->tables_);
   }
-  FontPtr font = new Font(factory_, sfnt_version_, &digest_, &tables);
+
   table_builders_.clear();
   data_blocks_.clear();
   return font.Detach();
 }
 
-CALLER_ATTACH WritableFontData* Font::Builder::GetNewData(int32_t capacity) {
-  return factory_->GetNewData(capacity);
-}
-
-CALLER_ATTACH WritableFontData* Font::Builder::GetNewGrowableData(
-    ReadableFontData* src_data) {
-  return factory_->GetNewGrowableData(src_data);
-}
-
 void Font::Builder::SetDigest(ByteVector* digest) {
   digest_.clear();
   digest_ = *digest;
 }
 
-void Font::Builder::CleanTableBuilders() {
+void Font::Builder::ClearTableBuilders() {
   table_builders_.clear();
 }
 
@@ -286,31 +285,32 @@
 Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) {
   TableHeaderPtr header = new Table::Header(tag);
   TableBuilderPtr builder;
-  builder.Attach(Table::Builder::GetBuilder(this, header, NULL));
+  builder.Attach(Table::Builder::GetBuilder(header, NULL));
   table_builders_.insert(TableBuilderEntry(header->tag(), builder));
   return builder;
 }
 
 Table::Builder* Font::Builder::NewTableBuilder(int32_t tag,
                                                ReadableFontData* src_data) {
+  assert(src_data);
   WritableFontDataPtr data;
-  data.Attach(GetNewGrowableData(src_data));
-  TableHeaderPtr header = new Table::Header(tag);
+  data.Attach(WritableFontData::CreateWritableFontData(src_data->Length()));
+#if !defined (SFNTLY_NO_EXCEPTION)
+  try {
+#endif
+    src_data->CopyTo(data);
+#if !defined (SFNTLY_NO_EXCEPTION)
+  } catch (IOException& e) {
+    return NULL;
+  }
+#endif
+  TableHeaderPtr header = new Table::Header(tag, data->Length());
   TableBuilderPtr builder;
-  builder.Attach(Table::Builder::GetBuilder(this, header, data));
+  builder.Attach(Table::Builder::GetBuilder(header, data));
   table_builders_.insert(TableBuilderEntry(tag, builder));
   return builder;
 }
 
-void Font::Builder::TableBuilderTags(IntegerSet* key_set) {
-  assert(key_set);
-  key_set->clear();
-  for (TableBuilderMap::iterator i = table_builders_.begin(),
-                                 e = table_builders_.end(); i != e; ++i) {
-    key_set->insert(i->first);
-  }
-}
-
 void Font::Builder::RemoveTableBuilder(int32_t tag) {
   TableBuilderMap::iterator target = table_builders_.find(tag);
   if (target != table_builders_.end()) {
@@ -326,21 +326,20 @@
   // Note: we do not throw exception here for is.  This is more of an assertion.
   assert(is);
   FontInputStream font_is(is);
-  TableHeaderSortedSet records;
+  HeaderOffsetSortedSet records;
   ReadHeader(&font_is, &records);
   LoadTableData(&records, &font_is, &data_blocks_);
   BuildAllTableBuilders(&data_blocks_, &table_builders_);
   font_is.Close();
 }
 
-void Font::Builder::LoadFont(ByteArray* ba,
+void Font::Builder::LoadFont(WritableFontData* wfd,
                              int32_t offset_to_offset_table) {
   // Note: we do not throw exception here for is.  This is more of an assertion.
-  assert(ba);
-  WritableFontDataPtr fd = new WritableFontData(ba);
-  TableHeaderSortedSet records;
-  ReadHeader(fd, offset_to_offset_table, &records);
-  LoadTableData(&records, fd, &data_blocks_);
+  assert(wfd);
+  HeaderOffsetSortedSet records;
+  ReadHeader(wfd, offset_to_offset_table, &records);
+  LoadTableData(&records, wfd, &data_blocks_);
   BuildAllTableBuilders(&data_blocks_, &table_builders_);
 }
 
@@ -361,14 +360,16 @@
   InterRelateBuilders(&table_builders_);
 }
 
-CALLER_ATTACH Table::Builder*
-    Font::Builder::GetTableBuilder(Table::Header* header,
-                                   WritableFontData* data) {
-  return Table::Builder::GetBuilder(this, header, data);
+CALLER_ATTACH
+Table::Builder* Font::Builder::GetTableBuilder(Table::Header* header,
+                                               WritableFontData* data) {
+  return Table::Builder::GetBuilder(header, data);
 }
 
-void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map,
+void Font::Builder::BuildTablesFromBuilders(Font* font,
+                                            TableBuilderMap* builder_map,
                                             TableMap* table_map) {
+  UNREFERENCED_PARAMETER(font);
   InterRelateBuilders(builder_map);
 
   // Now build all the tables.
@@ -384,7 +385,7 @@
 #if !defined (SFNTLY_NO_EXCEPTION)
       } catch(IOException& e) {
         std::string builder_string = "Unable to build table - ";
-        char *table_name = TagToString(builder->first);
+        char* table_name = TagToString(builder->first);
         builder_string += table_name;
         delete[] table_name;
         throw RuntimeException(builder_string.c_str());
@@ -392,20 +393,19 @@
 #endif
     }
     if (table == NULL) {
-      std::string builder_string = "Unable to build table - ";
-      char *table_name = TagToString(builder->first);
-      builder_string += table_name;
-      delete[] table_name;
-#if defined (SFNTLY_NO_EXCEPTION)
 #if defined (SFNTLY_DEBUG)
       fprintf(stderr, "Aborting table construction: %s\n",
               builder_string.c_str());
 #endif
       table_map->clear();
-      return;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
+      std::string builder_string = "Unable to build table - ";
+      char* table_name = TagToString(builder->first);
+      builder_string += table_name;
+      delete[] table_name;
       throw RuntimeException(builder_string.c_str());
 #endif
+      return;
     }
     table_map->insert(TableMapEntry(table->header()->tag(), table));
   }
@@ -474,14 +474,14 @@
       loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
     }
     if (header_table_builder != NULL) {
-      loca_table_builder->SetFormatVersion(
+      loca_table_builder->set_format_version(
           header_table_builder->IndexToLocFormat());
     }
   }
 }
 
 void Font::Builder::ReadHeader(FontInputStream* is,
-                               TableHeaderSortedSet* records) {
+                               HeaderOffsetSortedSet* records) {
   assert(records);
   sfnt_version_ = is->ReadFixed();
   num_tables_ = is->ReadUShort();
@@ -503,7 +503,7 @@
 
 void Font::Builder::ReadHeader(ReadableFontData* fd,
                                int32_t offset,
-                               TableHeaderSortedSet* records) {
+                               HeaderOffsetSortedSet* records) {
   assert(records);
   sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion);
   num_tables_ = fd->ReadUShort(offset + Offset::kNumTables);
@@ -524,13 +524,14 @@
   }
 }
 
-void Font::Builder::LoadTableData(TableHeaderSortedSet* headers,
+void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
                                   FontInputStream* is,
                                   DataBlockMap* table_data) {
   assert(table_data);
-  for (TableHeaderSortedSet::iterator
-           table_header = headers->begin(), table_end = headers->end();
-           table_header != table_end; ++table_header) {
+  for (HeaderOffsetSortedSet::iterator table_header = headers->begin(),
+                                       table_end = headers->end();
+                                       table_header != table_end;
+                                       ++table_header) {
     is->Skip((*table_header)->offset() - is->position());
     FontInputStream table_is(is, (*table_header)->length());
     WritableFontDataPtr data;
@@ -541,12 +542,13 @@
   }
 }
 
-void Font::Builder::LoadTableData(TableHeaderSortedSet* headers,
+void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
                                   WritableFontData* fd,
                                   DataBlockMap* table_data) {
-  for (TableHeaderSortedSet::iterator
-           table_header = headers->begin(), table_end = headers->end();
-           table_header != table_end; ++table_header) {
+  for (HeaderOffsetSortedSet::iterator table_header = headers->begin(),
+                                       table_end = headers->end();
+                                       table_header != table_end;
+                                       ++table_header) {
     FontDataPtr sliced_data;
     sliced_data.Attach(
         fd->Slice((*table_header)->offset(), (*table_header)->length()));
diff --git a/sfntly/font.h b/sfntly/font.h
index 2badece..1a714a6 100644
--- a/sfntly/font.h
+++ b/sfntly/font.h
@@ -22,7 +22,6 @@
 #include "sfntly/port/refcount.h"
 #include "sfntly/port/type.h"
 #include "sfntly/port/endian.h"
-#include "sfntly/font_data_table_builder_container.h"
 #include "sfntly/data/font_input_stream.h"
 #include "sfntly/data/font_output_stream.h"
 #include "sfntly/data/writable_font_data.h"
@@ -121,10 +120,16 @@
 extern const int32_t SFNTVERSION_1;
 
 class FontFactory;
+
+// An sfnt container font object. This object is immutable and thread safe. To
+// construct one use an instance of Font::Builder.
 class Font : public RefCounted<Font> {
  public:
-  class Builder : public FontDataTableBuilderContainer,
-                  public RefCounted<Builder> {
+  // A builder for a font object. The builder allows the for the creation of
+  // immutable Font objects. The builder is a one use non-thread safe object and
+  // once the Font object has been created it is no longer usable. To create a
+  // further Font object new builder will be required.
+  class Builder : public RefCounted<Builder> {
    public:
     virtual ~Builder();
 
@@ -132,18 +137,31 @@
         GetOTFBuilder(FontFactory* factory, InputStream* is);
     static CALLER_ATTACH Builder*
         GetOTFBuilder(FontFactory* factory,
-                      ByteArray* ba,
+                      WritableFontData* ba,
                       int32_t offset_to_offset_table);
     static CALLER_ATTACH Builder* GetOTFBuilder(FontFactory* factory);
-    virtual bool ReadyToBuild();
-    virtual CALLER_ATTACH Font* Build();
-    virtual CALLER_ATTACH WritableFontData* GetNewData(int32_t capacity);
-    virtual CALLER_ATTACH WritableFontData*
-        GetNewGrowableData(ReadableFontData* data);
-    virtual void SetDigest(ByteVector* digest);
-    virtual void CleanTableBuilders();
-    virtual bool HasTableBuilder(int32_t tag);
-    virtual Table::Builder* GetTableBuilder(int32_t tag);
+
+    // Get the font factory that created this font builder.
+    FontFactory* GetFontFactory() { return factory_; }
+
+    // Is the font ready to build?
+    bool ReadyToBuild();
+
+    // Build the Font. After this call this builder will no longer be usable.
+    CALLER_ATTACH Font* Build();
+
+    // Set a unique fingerprint for the font object.
+    void SetDigest(ByteVector* digest);
+
+    // Clear all table builders.
+    void ClearTableBuilders();
+
+    // Does this font builder have the specified table builder.
+    bool HasTableBuilder(int32_t tag);
+
+    // Get the table builder for the given tag. If there is no builder for that
+    // tag then return a null.
+    Table::Builder* GetTableBuilder(int32_t tag);
 
     // Creates a new table builder for the table type given by the table id tag.
     // This new table has been added to the font and will replace any existing
@@ -151,12 +169,23 @@
     // @return new empty table of the type specified by tag; if tag is not known
     //         then a generic OpenTypeTable is returned
     virtual Table::Builder* NewTableBuilder(int32_t tag);
+
+    // Creates a new table builder for the table type given by the table id tag.
+    // It makes a copy of the data provided and uses that copy for the table.
+    // This new table has been added to the font and will replace any existing
+    // builder for that table.
     virtual Table::Builder* NewTableBuilder(int32_t tag,
                                             ReadableFontData* src_data);
+
+    // Get a map of the table builders in this font builder accessed by table
+    // tag.
     virtual TableBuilderMap* table_builders() { return &table_builders_; }
-    virtual void TableBuilderTags(IntegerSet* key_set);
+
+    // Remove the specified table builder from the font builder.
     // Note: different from Java: we don't return object in removeTableBuilder
     virtual void RemoveTableBuilder(int32_t tag);
+
+    // Get the number of table builders in the font builder.
     virtual int32_t number_of_table_builders() {
       return (int32_t)table_builders_.size();
     }
@@ -164,23 +193,30 @@
    private:
     explicit Builder(FontFactory* factory);
     virtual void LoadFont(InputStream* is);
-    virtual void LoadFont(ByteArray* buffer, int32_t offset_to_offset_table);
+    virtual void LoadFont(WritableFontData* wfd,
+                          int32_t offset_to_offset_table);
     int32_t SfntWrapperSize();
     void BuildAllTableBuilders(DataBlockMap* table_data,
                                TableBuilderMap* builder_map);
     CALLER_ATTACH Table::Builder*
         GetTableBuilder(Table::Header* header, WritableFontData* data);
-    void BuildTablesFromBuilders(TableBuilderMap* builder_map,
+    void BuildTablesFromBuilders(Font* font,
+                                 TableBuilderMap* builder_map,
                                  TableMap* tables);
     static void InterRelateBuilders(TableBuilderMap* builder_map);
-    void ReadHeader(FontInputStream* is, TableHeaderSortedSet* records);
+
+    void ReadHeader(FontInputStream* is,
+                    HeaderOffsetSortedSet* records);
+
     void ReadHeader(ReadableFontData* fd,
                     int32_t offset,
-                    TableHeaderSortedSet* records);
-    void LoadTableData(TableHeaderSortedSet* headers,
+                    HeaderOffsetSortedSet* records);
+
+    void LoadTableData(HeaderOffsetSortedSet* headers,
                        FontInputStream* is,
                        DataBlockMap* table_data);
-    void LoadTableData(TableHeaderSortedSet* headers,
+
+    void LoadTableData(HeaderOffsetSortedSet* headers,
                        WritableFontData* fd,
                        DataBlockMap* table_data);
 
@@ -198,7 +234,7 @@
   virtual ~Font();
 
   // Gets the sfnt version set in the sfnt wrapper of the font.
-  int32_t version() { return sfnt_version_; }
+  int32_t sfnt_version() { return sfnt_version_; }
 
   // Gets a copy of the fonts digest that was created when the font was read. If
   // no digest was set at creation time then the return result will be null.
@@ -223,24 +259,16 @@
 
   // Get a map of the tables in this font accessed by table tag.
   // @return an unmodifiable view of the tables in this font
-  TableMap* Tables();
+  // Note: renamed tableMap() to GetTableMap()
+  const TableMap* GetTableMap();
+
+  // UNIMPLEMENTED: toString()
 
   // Serialize the font to the output stream.
   // @param os the destination for the font serialization
   // @param tableOrdering the table ordering to apply
   void Serialize(OutputStream* os, IntegerList* table_ordering);
 
-  // Get a new data object. The size is a request for a data object and the
-  // returned data object will support at least that amount. A value greater
-  // than zero for the size is a request for a fixed size data object. A
-  // negative or zero value for the size is a request for a variable sized data
-  // object with the absolute value of the size being an estimate of the space
-  // required.
-  // @param size greater than zero is a request for a fixed size data object of
-  //        the given size; less than or equal to zero is a request for a
-  //        variable size data object with the absolute size as an estimate
-  CALLER_ATTACH WritableFontData* GetNewData(int32_t size);
-
  private:
   // Offsets to specific elements in the underlying data. These offsets are
   // relative to the start of the table or the start of sub-blocks within the
@@ -269,18 +297,48 @@
 //  static const int32_t CFF_TABLE_ORDERING[];
 //  static const int32_t TRUE_TYPE_TABLE_ORDERING[];
 
-  Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest,
-       TableMap* tables);
+  // Constructor.
+  // @param sfntVersion the sfnt version
+  // @param digest the computed digest for the font; null if digest was not
+  //        computed
+  // Note: Current C++ port does not support SHA digest validation.
+  Font(int32_t sfnt_version, ByteVector* digest);
 
+  // Build the table headers to be used for serialization. These headers will be
+  // filled out with the data required for serialization. The headers will be
+  // sorted in the order specified and only those specified will have headers
+  // generated.
+  // @param tableOrdering the tables to generate headers for and the order to
+  //        sort them
+  // @return a list of table headers ready for serialization
   void BuildTableHeadersForSerialization(IntegerList* table_ordering,
                                          TableHeaderList* table_headers);
+
+  // Searialize the headers.
+  // @param fos the destination stream for the headers
+  // @param tableHeaders the headers to serialize
+  // @throws IOException
   void SerializeHeader(FontOutputStream* fos, TableHeaderList* table_headers);
+
+  // Serialize the tables.
+  // @param fos the destination stream for the headers
+  // @param tableHeaders the headers for the tables to serialize
+  // @throws IOException
   void SerializeTables(FontOutputStream* fos, TableHeaderList* table_headers);
-  void TableOrdering(IntegerList* default_table_ordering,
-                     IntegerList* table_ordering);
+
+  // Generate the full table ordering to used for serialization. The full
+  // ordering uses the partial ordering as a seed and then adds all remaining
+  // tables in the font in an undefined order.
+  // @param defaultTableOrdering the partial ordering to be used as a seed for
+  //        the full ordering
+  // @param (out) table_ordering the full ordering for serialization
+  void GenerateTableOrdering(IntegerList* default_table_ordering,
+                             IntegerList* table_ordering);
+
+  // Get the default table ordering based on the type of the font.
+  // @param (out) default_table_ordering the default table ordering
   void DefaultTableOrdering(IntegerList* default_table_ordering);
 
-  FontFactory* factory_;  // dumb pointer, avoid circular ref-counting
   int32_t sfnt_version_;
   ByteVector digest_;
   int64_t checksum_;
diff --git a/sfntly/font_data_table_builder_container.h b/sfntly/font_data_table_builder_container.h
deleted file mode 100644
index 2818464..0000000
--- a/sfntly/font_data_table_builder_container.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_
-#define SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_
-
-#include "sfntly/data/writable_font_data.h"
-
-namespace sfntly {
-
-class FontDataTableBuilderContainer {
- public:
-  virtual WritableFontData* GetNewData(int32_t size) = 0;
-  // Make gcc -Wnon-virtual-dtor happy.
-  virtual ~FontDataTableBuilderContainer() {}
-};
-typedef Ptr<FontDataTableBuilderContainer> FontDataTableBuilderContainerPtr;
-
-}  // namespace sfntly
-
-#endif  // SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_
diff --git a/sfntly/font_factory.cc b/sfntly/font_factory.cc
index a306bcd..c162a77 100644
--- a/sfntly/font_factory.cc
+++ b/sfntly/font_factory.cc
@@ -19,8 +19,6 @@
 #include <string.h>
 
 #include "sfntly/tag.h"
-#include "sfntly/data/memory_byte_array.h"
-#include "sfntly/data/growable_memory_byte_array.h"
 
 namespace sfntly {
 
@@ -54,13 +52,15 @@
   }
 }
 
-void FontFactory::LoadFonts(ByteArray* ba, FontArray* output) {
-  if (IsCollection(ba)) {
-    LoadCollection(ba, output);
+void FontFactory::LoadFonts(ByteVector* b, FontArray* output) {
+  WritableFontDataPtr wfd;
+  wfd.Attach(WritableFontData::CreateWritableFontData(b));
+  if (IsCollection(wfd)) {
+    LoadCollection(wfd, output);
     return;
   }
   FontPtr font;
-  font.Attach(LoadSingleOTF(ba));
+  font.Attach(LoadSingleOTF(wfd));
   if (font) {
     output->push_back(font);
   }
@@ -80,59 +80,21 @@
   }
 }
 
-void FontFactory::LoadFontsForBuilding(ByteArray* ba,
+void FontFactory::LoadFontsForBuilding(ByteVector* b,
                                        FontBuilderArray* output) {
-  if (IsCollection(ba)) {
-    LoadCollectionForBuilding(ba, output);
+  WritableFontDataPtr wfd;
+  wfd.Attach(WritableFontData::CreateWritableFontData(b));
+  if (IsCollection(wfd)) {
+    LoadCollectionForBuilding(wfd, output);
     return;
   }
   FontBuilderPtr builder;
-  builder.Attach(LoadSingleOTFForBuilding(ba, 0));
+  builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
   if (builder) {
     output->push_back(builder);
   }
 }
 
-CALLER_ATTACH WritableFontData* FontFactory::GetNewData(int32_t capacity) {
-  // UNIMPLMENTED: if (capacity > 0) { this.GetNewFixedData(capacity); }
-  // Seems a no-op.
-  return GetNewGrowableData(capacity);
-}
-
-CALLER_ATTACH WritableFontData* FontFactory::GetNewFixedData(int32_t capacity) {
-  ByteArrayPtr buffer;
-  buffer.Attach(GetNewArray(capacity));
-  WritableFontDataPtr new_fixed_data = new WritableFontData(buffer);
-  return new_fixed_data.Detach();
-}
-
-CALLER_ATTACH WritableFontData* FontFactory::GetNewGrowableData(
-    int32_t capacity) {
-  ByteArrayPtr buffer;
-  buffer.Attach(GetNewGrowableArray(capacity));
-  WritableFontDataPtr new_growable_data = new WritableFontData(buffer);
-  return new_growable_data.Detach();
-}
-
-CALLER_ATTACH WritableFontData* FontFactory::GetNewGrowableData(
-    ReadableFontData* src_data) {
-  WritableFontDataPtr data;
-  data.Attach(GetNewGrowableData(src_data->Length()));
-  src_data->CopyTo(data);
-  return data.Detach();
-}
-
-CALLER_ATTACH ByteArray* FontFactory::GetNewArray(int32_t length) {
-  ByteArrayPtr new_fixed_array = new MemoryByteArray(length);
-  return new_fixed_array.Detach();
-}
-
-CALLER_ATTACH ByteArray* FontFactory::GetNewGrowableArray(int32_t length) {
-  UNREFERENCED_PARAMETER(length);
-  ByteArrayPtr new_growable_array = new GrowableMemoryByteArray();
-  return new_growable_array.Detach();
-}
-
 void FontFactory::SerializeFont(Font* font, OutputStream* os) {
   font->Serialize(os, &table_ordering_);
 }
@@ -152,9 +114,9 @@
   return builder->Build();
 }
 
-CALLER_ATTACH Font* FontFactory::LoadSingleOTF(ByteArray* ba) {
+CALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) {
   FontBuilderPtr builder;
-  builder.Attach(LoadSingleOTFForBuilding(ba, 0));
+  builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
   return builder->Build();
 }
 
@@ -170,21 +132,21 @@
   }
 }
 
-void FontFactory::LoadCollection(ByteArray* ba, FontArray* output) {
+void FontFactory::LoadCollection(WritableFontData* wfd, FontArray* output) {
   FontBuilderArray builders;
-  LoadCollectionForBuilding(ba, &builders);
-  output->reserve(ba->Size());
-  for (FontBuilderArray::iterator
-           builder = builders.begin(), builders_end = builders.end();
-       builder != builders_end; ++builder) {
+  LoadCollectionForBuilding(wfd, &builders);
+  output->reserve(builders.size());
+  for (FontBuilderArray::iterator builder = builders.begin(),
+                                  builders_end = builders.end();
+                                  builder != builders_end; ++builder) {
     FontPtr font;
     font.Attach((*builder)->Build());
     output->push_back(font);
   }
 }
 
-CALLER_ATTACH Font::Builder*
-    FontFactory::LoadSingleOTFForBuilding(InputStream* is) {
+CALLER_ATTACH
+Font::Builder* FontFactory::LoadSingleOTFForBuilding(InputStream* is) {
   // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
   Font::Builder* builder = Font::Builder::GetOTFBuilder(this, is);
   // UNIMPLEMENTED: setDigest
@@ -192,38 +154,41 @@
 }
 
 CALLER_ATTACH Font::Builder*
-    FontFactory::LoadSingleOTFForBuilding(ByteArray* ba,
+    FontFactory::LoadSingleOTFForBuilding(WritableFontData* wfd,
                                           int32_t offset_to_offset_table) {
   // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
   Font::Builder* builder =
-      Font::Builder::GetOTFBuilder(this, ba, offset_to_offset_table);
+      Font::Builder::GetOTFBuilder(this, wfd, offset_to_offset_table);
   // UNIMPLEMENTED: setDigest
   return builder;
 }
 
 void FontFactory::LoadCollectionForBuilding(InputStream* is,
                                             FontBuilderArray* builders) {
-  ByteArrayPtr ba = new GrowableMemoryByteArray();
-  ba->CopyFrom(is);
-  LoadCollectionForBuilding(ba, builders);
+  assert(is);
+  assert(builders);
+  WritableFontDataPtr wfd;
+  wfd.Attach(WritableFontData::CreateWritableFontData(is->Available()));
+  wfd->CopyFrom(is);
+  LoadCollectionForBuilding(wfd, builders);
 }
 
-void FontFactory::LoadCollectionForBuilding(ByteArray* ba,
+void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd,
                                             FontBuilderArray* builders) {
-  ReadableFontDataPtr rfd = new ReadableFontData(ba);
-  int32_t ttc_tag = rfd->ReadULongAsInt(Offset::kTTCTag);
+  int32_t ttc_tag = wfd->ReadULongAsInt(Offset::kTTCTag);
   UNREFERENCED_PARAMETER(ttc_tag);
-  int32_t version = rfd->ReadFixed(Offset::kVersion);
+  int32_t version = wfd->ReadFixed(Offset::kVersion);
   UNREFERENCED_PARAMETER(version);
-  int32_t num_fonts = rfd->ReadULongAsInt(Offset::kNumFonts);
+  int32_t num_fonts = wfd->ReadULongAsInt(Offset::kNumFonts);
 
   builders->reserve(num_fonts);
   int32_t offset_table_offset = Offset::kOffsetTable;
-  for (int32_t font_number = 0; font_number < num_fonts;
-       font_number++, offset_table_offset += DataSize::kULONG) {
-    int32_t offset = rfd->ReadULongAsInt(offset_table_offset);
+  for (int32_t font_number = 0;
+               font_number < num_fonts;
+               font_number++, offset_table_offset += DataSize::kULONG) {
+    int32_t offset = wfd->ReadULongAsInt(offset_table_offset);
     FontBuilderPtr builder;
-    builder.Attach(LoadSingleOTFForBuilding(ba, offset));
+    builder.Attach(LoadSingleOTFForBuilding(wfd, offset));
     builders->push_back(builder);
   }
 }
@@ -235,9 +200,11 @@
   return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]);
 }
 
-bool FontFactory::IsCollection(ByteArray* ba) {
+bool FontFactory::IsCollection(ReadableFontData* rfd) {
+  ByteVector tag(4);
+  rfd->ReadBytes(0, &(tag[0]), 0, tag.size());
   return Tag::ttcf ==
-         GenerateTag(ba->Get(0), ba->Get(1), ba->Get(2), ba->Get(3));
+         GenerateTag(tag[0], tag[1], tag[2], tag[3]);
 }
 
 FontFactory::FontFactory()
diff --git a/sfntly/font_factory.h b/sfntly/font_factory.h
index b706b92..63deff4 100644
--- a/sfntly/font_factory.h
+++ b/sfntly/font_factory.h
@@ -56,7 +56,7 @@
   // than one font and in this case multiple font objects will be returned. If
   // the data in the stream cannot be parsed or is invalid an array of size zero
   // will be returned.
-  void LoadFonts(ByteArray* ba, FontArray* output);
+  void LoadFonts(ByteVector* b, FontArray* output);
 
   // Load the font(s) from the input stream into font builders. The current
   // settings on the factory are used during the loading process. One or more
@@ -72,15 +72,7 @@
   // font container formats may have more than one font and in this case
   // multiple font builder objects will be returned. If the data in the stream
   // cannot be parsed or is invalid an array of size zero will be returned.
-  void LoadFontsForBuilding(ByteArray* ba, FontBuilderArray* output);
-
-  CALLER_ATTACH WritableFontData* GetNewData(int32_t capacity);
-  CALLER_ATTACH WritableFontData* GetNewFixedData(int32_t capacity);
-  CALLER_ATTACH WritableFontData* GetNewGrowableData(int32_t capacity);
-  CALLER_ATTACH WritableFontData*
-      GetNewGrowableData(ReadableFontData* src_data);
-  CALLER_ATTACH ByteArray* GetNewArray(int32_t length);
-  CALLER_ATTACH ByteArray* GetNewGrowableArray(int32_t length);
+  void LoadFontsForBuilding(ByteVector* b, FontBuilderArray* output);
 
   // Font serialization
   // Serialize the font to the output stream.
@@ -121,20 +113,22 @@
   FontFactory();
 
   CALLER_ATTACH Font* LoadSingleOTF(InputStream* is);
-  CALLER_ATTACH Font* LoadSingleOTF(ByteArray* ba);
+  CALLER_ATTACH Font* LoadSingleOTF(WritableFontData* wfd);
 
   void LoadCollection(InputStream* is, FontArray* output);
-  void LoadCollection(ByteArray* ba, FontArray* output);
+  void LoadCollection(WritableFontData* wfd, FontArray* output);
 
   CALLER_ATTACH Font::Builder* LoadSingleOTFForBuilding(InputStream* is);
   CALLER_ATTACH Font::Builder*
-      LoadSingleOTFForBuilding(ByteArray* ba, int32_t offset_to_offset_table);
+      LoadSingleOTFForBuilding(WritableFontData* wfd,
+                               int32_t offset_to_offset_table);
 
   void LoadCollectionForBuilding(InputStream* is, FontBuilderArray* builders);
-  void LoadCollectionForBuilding(ByteArray* ba, FontBuilderArray* builders);
+  void LoadCollectionForBuilding(WritableFontData* ba,
+                                 FontBuilderArray* builders);
 
   static bool IsCollection(PushbackInputStream* pbis);
-  static bool IsCollection(ByteArray* ba);
+  static bool IsCollection(ReadableFontData* wfd);
 
   bool fingerprint_;
   IntegerList table_ordering_;
diff --git a/sfntly/port/config.h b/sfntly/port/config.h
index 01c4685..0fcdffe 100644
--- a/sfntly/port/config.h
+++ b/sfntly/port/config.h
@@ -19,9 +19,9 @@
 
 #if !defined(SFNTLY_BIG_ENDIAN) && !defined(SFNTLY_LITTLE_ENDIAN)
   #if defined (__ppc__) || defined (__ppc64__)
-    #define SFNTLY_CPP_BIG_ENDIAN
+    #define SFNTLY_BIG_ENDIAN
   #else
-    #define SFNTLY_CPP_LITTLE_ENDIAN
+    #define SFNTLY_LITTLE_ENDIAN
   #endif
 #endif
 
diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc
index 661b6fd..5bcb434 100644
--- a/sfntly/port/file_input_stream.cc
+++ b/sfntly/port/file_input_stream.cc
@@ -57,18 +57,16 @@
 
 int32_t FileInputStream::Read() {
   if (!file_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IOException("no opened file");
 #endif
+    return 0;
   }
   if (feof(file_)) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IOException("eof reached");
 #endif
+    return 0;
   }
   byte_t value;
   size_t length = fread(&value, 1, 1, file_);
@@ -77,24 +75,22 @@
 }
 
 int32_t FileInputStream::Read(ByteVector* b) {
-  return Read(b, 0, b->capacity());
+  return Read(b, 0, b->size());
 }
 
 int32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) {
   assert(b);
   if (!file_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IOException("no opened file");
 #endif
+    return 0;
   }
   if (feof(file_)) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IOException("eof reached");
 #endif
+    return 0;
   }
   size_t read_count = std::min<size_t>(length_ - position_, length);
   if (b->size() < (size_t)(offset + read_count)) {
@@ -111,11 +107,10 @@
 
 int64_t FileInputStream::Skip(int64_t n) {
   if (!file_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IOException("no opened file");
 #endif
+    return 0;
   }
   int64_t skip_count = 0;
   if (n < 0) {  // move backwards
@@ -131,18 +126,17 @@
 }
 
 void FileInputStream::Unread(ByteVector* b) {
-  Unread(b, 0, b->capacity());
+  Unread(b, 0, b->size());
 }
 
 void FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) {
   assert(b);
   assert(b->size() >= size_t(offset + length));
   if (!file_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IOException("no opened file");
 #endif
+    return;
   }
   size_t unread_count = std::min<size_t>(position_, length);
   fseek(file_, position_ - unread_count, SEEK_SET);
diff --git a/sfntly/port/memory_input_stream.cc b/sfntly/port/memory_input_stream.cc
new file mode 100755
index 0000000..56ee81e
--- /dev/null
+++ b/sfntly/port/memory_input_stream.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined (WIN32)
+#include <windows.h>
+#endif
+
+#include <string.h>
+
+#include "sfntly/port/memory_input_stream.h"
+#include "sfntly/port/exception_type.h"
+
+namespace sfntly {
+
+MemoryInputStream::MemoryInputStream()
+    : buffer_(NULL),
+      position_(0),
+      length_(0) {
+}
+
+MemoryInputStream::~MemoryInputStream() {
+  Close();
+}
+
+int32_t MemoryInputStream::Available() {
+  return length_ - position_;
+}
+
+void MemoryInputStream::Close() {
+}
+
+void MemoryInputStream::Mark(int32_t readlimit) {
+  // NOP
+  UNREFERENCED_PARAMETER(readlimit);
+}
+
+bool MemoryInputStream::MarkSupported() {
+  return false;
+}
+
+int32_t MemoryInputStream::Read() {
+  if (!buffer_) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IOException("no memory attached");
+#endif
+    return 0;
+  }
+  if (position_ >= length_) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IOException("eof reached");
+#endif
+    return 0;
+  }
+  byte_t value = buffer_[position_++];
+  return value;
+}
+
+int32_t MemoryInputStream::Read(ByteVector* b) {
+  return Read(b, 0, b->size());
+}
+
+int32_t MemoryInputStream::Read(ByteVector* b, int32_t offset, int32_t length) {
+  assert(b);
+  if (!buffer_) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IOException("no memory attached");
+#endif
+    return 0;
+  }
+  if (position_ >= length_) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IOException("eof reached");
+#endif
+    return 0;
+  }
+  size_t read_count = std::min<size_t>(length_ - position_, length);
+  if (b->size() < (size_t)(offset + read_count)) {
+    b->resize((size_t)(offset + read_count));
+  }
+  memcpy(&((*b)[offset]), buffer_ + position_, read_count);
+  position_ += read_count;
+  return read_count;
+}
+
+void MemoryInputStream::Reset() {
+  // NOP
+}
+
+int64_t MemoryInputStream::Skip(int64_t n) {
+  if (!buffer_) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IOException("no memory attached");
+#endif
+    return 0;
+  }
+  int64_t skip_count = 0;
+  if (n < 0) {  // move backwards
+    skip_count = std::max<int64_t>(0 - (int64_t)position_, n);
+    position_ -= (size_t)(0 - skip_count);
+  } else {
+    skip_count = std::min<size_t>(length_ - position_, (size_t)n);
+    position_ += (size_t)skip_count;
+  }
+  return skip_count;
+}
+
+void MemoryInputStream::Unread(ByteVector* b) {
+  Unread(b, 0, b->size());
+}
+
+void MemoryInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) {
+  assert(b);
+  assert(b->size() >= size_t(offset + length));
+  if (!buffer_) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IOException("no memory attached");
+#endif
+    return;
+  }
+  size_t unread_count = std::min<size_t>(position_, length);
+  position_ -= unread_count;
+  Read(b, offset, length);
+  position_ -= unread_count;
+}
+
+bool MemoryInputStream::Attach(const byte_t* buffer, size_t length) {
+  assert(buffer);
+  assert(length);
+  buffer_ = buffer;
+  length_ = length;
+  return true;
+}
+
+}  // namespace sfntly
diff --git a/sfntly/port/memory_input_stream.h b/sfntly/port/memory_input_stream.h
new file mode 100755
index 0000000..bc861c3
--- /dev/null
+++ b/sfntly/port/memory_input_stream.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_
+#define SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_
+
+#include <stdio.h>
+
+#include "sfntly/port/input_stream.h"
+
+namespace sfntly {
+
+class MemoryInputStream : public PushbackInputStream {
+ public:
+  MemoryInputStream();
+  virtual ~MemoryInputStream();
+
+  // InputStream methods
+  virtual int32_t Available();
+  virtual void Close();
+  virtual void Mark(int32_t readlimit);
+  virtual bool MarkSupported();
+  virtual int32_t Read();
+  virtual int32_t Read(ByteVector* b);
+  virtual int32_t Read(ByteVector* b, int32_t offset, int32_t length);
+  virtual void Reset();
+  virtual int64_t Skip(int64_t n);
+
+  // PushbackInputStream methods
+  virtual void Unread(ByteVector* b);
+  virtual void Unread(ByteVector* b, int32_t offset, int32_t length);
+
+  // Own methods
+  virtual bool Attach(const byte_t* buffer, size_t length);
+
+ private:
+  const byte_t* buffer_;
+  size_t position_;
+  size_t length_;
+};
+
+}  // namespace sfntly
+
+#endif  // SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_
diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc
index 7217265..dd43996 100644
--- a/sfntly/table/core/cmap_table.cc
+++ b/sfntly/table/core/cmap_table.cc
@@ -60,7 +60,7 @@
 }
 
 CMapTable::CMapTable(Header* header, ReadableFontData* data)
-    : Table(header, data) {
+    : SubTableContainerTable(header, data) {
 }
 
 int32_t CMapTable::OffsetForEncodingRecord(int32_t index) {
@@ -126,20 +126,18 @@
 }
 
 CALLER_ATTACH CMapTable::CMap::Builder*
-    CMapTable::CMap::Builder::GetBuilder(
-        FontDataTableBuilderContainer* container,
-        ReadableFontData* data,
-        int32_t offset,
-        const CMapId& cmap_id) {
+    CMapTable::CMap::Builder::GetBuilder(ReadableFontData* data,
+                                         int32_t offset,
+                                         const CMapId& cmap_id) {
   // NOT IMPLEMENTED: Java enum value validation
   int32_t format = data->ReadUShort(offset);
   CMapBuilderPtr builder;
   switch (format) {
     case CMapFormat::kFormat0:
-      builder = new CMapFormat0::Builder(container, data, offset, cmap_id);
+      builder = new CMapFormat0::Builder(data, offset, cmap_id);
       break;
     case CMapFormat::kFormat2:
-      builder = new CMapFormat0::Builder(container, data, offset, cmap_id);
+      builder = new CMapFormat0::Builder(data, offset, cmap_id);
       break;
     default:
       break;
@@ -147,18 +145,18 @@
   return builder.Detach();
 }
 
-CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container,
-                                  ReadableFontData* data, int32_t format,
+CMapTable::CMap::Builder::Builder(ReadableFontData* data,
+                                  int32_t format,
                                   const CMapId& cmap_id)
-    : SubTable::Builder(container, data),
+    : SubTable::Builder(data),
       format_(format),
       cmap_id_(cmap_id) {
 }
 
-CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container,
-                                  WritableFontData* data, int32_t format,
+CMapTable::CMap::Builder::Builder(WritableFontData* data,
+                                  int32_t format,
                                   const CMapId& cmap_id)
-    : SubTable::Builder(container, data),
+    : SubTable::Builder(data),
       format_(format),
       cmap_id_(cmap_id) {
 }
@@ -204,13 +202,10 @@
 /******************************************************************************
  * CMapTable::CMapFormat0::Builder
  ******************************************************************************/
-CMapTable::CMapFormat0::Builder::Builder(
-    FontDataTableBuilderContainer* container,
-    WritableFontData* data,
-    int32_t offset,
-    const CMapId& cmap_id)
-    : CMapTable::CMap::Builder(container,
-                               data ? down_cast<WritableFontData*>(
+CMapTable::CMapFormat0::Builder::Builder(WritableFontData* data,
+                                         int32_t offset,
+                                         const CMapId& cmap_id)
+    : CMapTable::CMap::Builder(data ? down_cast<WritableFontData*>(
                                    data->Slice(offset, data->ReadUShort(
                                        offset + Offset::kFormat0Length)))
                                : reinterpret_cast<WritableFontData*>(NULL),
@@ -218,13 +213,10 @@
   // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix.
 }
 
-CMapTable::CMapFormat0::Builder::Builder(
-    FontDataTableBuilderContainer* container,
-    ReadableFontData* data,
-    int32_t offset,
-    const CMapId& cmap_id)
-    : CMapTable::CMap::Builder(container,
-                               data ? down_cast<ReadableFontData*>(
+CMapTable::CMapFormat0::Builder::Builder(ReadableFontData* data,
+                                         int32_t offset,
+                                         const CMapId& cmap_id)
+    : CMapTable::CMap::Builder(data ? down_cast<ReadableFontData*>(
                                    data->Slice(offset, data->ReadUShort(
                                        offset + Offset::kFormat0Length)))
                                : reinterpret_cast<WritableFontData*>(NULL),
@@ -340,13 +332,10 @@
 /******************************************************************************
  * CMapTable::CMapFormat2::Builder
  ******************************************************************************/
-CMapTable::CMapFormat2::Builder::Builder(
-    FontDataTableBuilderContainer* container,
-    WritableFontData* data,
-    int32_t offset,
-    const CMapId& cmap_id)
-    : CMapTable::CMap::Builder(container,
-                               data ? down_cast<WritableFontData*>(
+CMapTable::CMapFormat2::Builder::Builder(WritableFontData* data,
+                                         int32_t offset,
+                                         const CMapId& cmap_id)
+    : CMapTable::CMap::Builder(data ? down_cast<WritableFontData*>(
                                    data->Slice(offset, data->ReadUShort(
                                        offset + Offset::kFormat0Length)))
                                : reinterpret_cast<WritableFontData*>(NULL),
@@ -354,13 +343,10 @@
   // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix.
 }
 
-CMapTable::CMapFormat2::Builder::Builder(
-    FontDataTableBuilderContainer* container,
-    ReadableFontData* data,
-    int32_t offset,
-    const CMapId& cmap_id)
-    : CMapTable::CMap::Builder(container,
-                               data ? down_cast<ReadableFontData*>(
+CMapTable::CMapFormat2::Builder::Builder(ReadableFontData* data,
+                                         int32_t offset,
+                                         const CMapId& cmap_id)
+    : CMapTable::CMap::Builder(data ? down_cast<ReadableFontData*>(
                                    data->Slice(offset, data->ReadUShort(
                                        offset + Offset::kFormat0Length)))
                                : reinterpret_cast<ReadableFontData*>(NULL),
@@ -402,16 +388,12 @@
 /******************************************************************************
  * CMapTable::Builder class
  ******************************************************************************/
-CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                            Header* header,
-                            WritableFontData* data)
-    : Table::ArrayElementTableBuilder(font_builder, header, data) {
+CMapTable::Builder::Builder(Header* header, WritableFontData* data)
+    : SubTableContainerTable::Builder(header, data) {
 }
 
-CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                            Header* header,
-                            ReadableFontData* data)
-    : Table::ArrayElementTableBuilder(font_builder, header, data) {
+CMapTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : SubTableContainerTable::Builder(header, data) {
 }
 
 CMapTable::Builder::~Builder() {
@@ -483,22 +465,32 @@
   return table.Detach();
 }
 
-CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::CMapBuilder(
-    FontDataTableBuilderContainer* container, ReadableFontData* data,
-    int32_t index) {
-  if (index < 0 || index > NumCMaps(data))
-    return NULL;
+CALLER_ATTACH CMapTable::Builder*
+    CMapTable::Builder::CreateBuilder(Header* header,
+                                      WritableFontData* data) {
+  Ptr<CMapTable::Builder> builder;
+  builder = new CMapTable::Builder(header, data);
+  return builder.Detach();
+}
 
-  int32_t record_offset = Offset::kEncodingRecordOffset + index *
-      Offset::kEncodingRecordSize;
-  int32_t platform_id =
-      data->ReadUShort(Offset::kEncodingRecordPlatformId + record_offset);
-  int32_t encoding_id =
-      data->ReadUShort(Offset::kEncodingRecordEncodingId + record_offset);
+CALLER_ATTACH CMapTable::CMap::Builder*
+    CMapTable::Builder::CMapBuilder(ReadableFontData* data, int32_t index) {
+  if (index < 0 || index > NumCMaps(data)) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IndexOutOfBoundException(
+              "CMap table is outside of the bounds of the known tables.");
+#endif
+    return NULL;
+  }
+
+  int32_t platform_id = data->ReadUShort(Offset::kEncodingRecordPlatformId +
+                                         OffsetForEncodingRecord(index));
+  int32_t encoding_id = data->ReadUShort(Offset::kEncodingRecordEncodingId +
+                                         OffsetForEncodingRecord(index));
+  int32_t offset = data->ReadULongAsInt(Offset::kEncodingRecordOffset +
+                                        OffsetForEncodingRecord(index));
   CMapId cmap_id(platform_id, encoding_id);
-  int32_t offset =
-      data->ReadULongAsInt(Offset::kEncodingRecordOffset + record_offset);
-  return CMap::Builder::GetBuilder(container, data, offset, cmap_id);
+  return CMap::Builder::GetBuilder(data, offset, cmap_id);
 }
 
 int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) {
diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h
index 76b4266..6455ef6 100644
--- a/sfntly/table/core/cmap_table.h
+++ b/sfntly/table/core/cmap_table.h
@@ -22,8 +22,8 @@
 #include <map>
 
 #include "sfntly/port/refcount.h"
-#include "sfntly/table/table.h"
 #include "sfntly/table/subtable.h"
+#include "sfntly/table/subtable_container_table.h"
 
 namespace sfntly {
 
@@ -43,7 +43,7 @@
 };
 
 // A CMap table
-class CMapTable : public Table, public RefCounted<CMapTable> {
+class CMapTable : public SubTableContainerTable, public RefCounted<CMapTable> {
 public:
   // CMapTable::CMapId
   class CMapId {
@@ -113,8 +113,7 @@
       virtual ~Builder();
 
       CALLER_ATTACH static Builder*
-          GetBuilder(FontDataTableBuilderContainer* container,
-                     ReadableFontData* data,
+          GetBuilder(ReadableFontData* data,
                      int32_t offset,
                      const CMapId& cmap_id);
 
@@ -124,12 +123,10 @@
       virtual int32_t encoding_id() { return cmap_id_.encoding_id(); }
 
      protected:
-      Builder(FontDataTableBuilderContainer* container,
-              ReadableFontData* data,
+      Builder(ReadableFontData* data,
               int32_t format,
               const CMapId& cmap_id);
-      Builder(FontDataTableBuilderContainer* container,
-              WritableFontData* data,
+      Builder(WritableFontData* data,
               int32_t format,
               const CMapId& cmap_id);
 
@@ -186,12 +183,10 @@
     class Builder : public CMap::Builder,
                     public RefCounted<Builder> {
      public:
-      Builder(FontDataTableBuilderContainer* container,
-              ReadableFontData* data,
+      Builder(ReadableFontData* data,
               int32_t offset,
               const CMapId& cmap_id);
-      Builder(FontDataTableBuilderContainer* container,
-              WritableFontData* data,
+      Builder(WritableFontData* data,
               int32_t offset,
               const CMapId& cmap_id);
       virtual ~Builder();
@@ -218,12 +213,10 @@
     class Builder : public CMap::Builder,
                     public RefCounted<Builder> {
      public:
-      Builder(FontDataTableBuilderContainer* container,
-              ReadableFontData* data,
+      Builder(ReadableFontData* data,
               int32_t offset,
               const CMapId& cmap_id);
-      Builder(FontDataTableBuilderContainer* container,
-              WritableFontData* data,
+      Builder(WritableFontData* data,
               int32_t offset,
               const CMapId& cmap_id);
       virtual ~Builder();
@@ -254,17 +247,13 @@
   };
 
   // CMapTable::Builder
-  class Builder : public Table::ArrayElementTableBuilder,
+  class Builder : public SubTableContainerTable::Builder,
                   public RefCounted<Builder> {
    public:
     // Constructor scope altered to public because C++ does not allow base
     // class to instantiate derived class with protected constructors.
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            ReadableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
 
     virtual int32_t SubSerialize(WritableFontData* new_data);
@@ -273,11 +262,12 @@
     virtual void SubDataSet();
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
 
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
+
    protected:
-    static CALLER_ATTACH CMap::Builder*
-        CMapBuilder(FontDataTableBuilderContainer* container,
-                    ReadableFontData* data,
-                    int32_t index);
+    static CALLER_ATTACH CMap::Builder* CMapBuilder(ReadableFontData* data,
+                                                    int32_t index);
 
    private:
     static int32_t NumCMaps(ReadableFontData* data);
@@ -354,6 +344,7 @@
       kFormat4EntrySelector = 10,
       kFormat4RangeShift = 12,
       kFormat4EndCount = 14,
+      kFormat4FixedSize = 16,
 
       // format 6: Trimmed table mapping
       kFormat6Format = 0,
@@ -437,7 +428,7 @@
 
   // Get the offset in the table data for the encoding record for the cmap with
   // the given index. The offset is from the beginning of the table.
-  int32_t OffsetForEncodingRecord(int32_t index);
+  static int32_t OffsetForEncodingRecord(int32_t index);
 };
 typedef std::vector<CMapTable::CMapId> CMapIdList;
 typedef Ptr<CMapTable> CMapTablePtr;
diff --git a/sfntly/table/core/font_header_table.cc b/sfntly/table/core/font_header_table.cc
index da19258..3713b02 100644
--- a/sfntly/table/core/font_header_table.cc
+++ b/sfntly/table/core/font_header_table.cc
@@ -102,14 +102,12 @@
 /******************************************************************************
  * FontHeaderTable::Builder class
  ******************************************************************************/
-FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                                  Header* header, WritableFontData* data) :
-    Table::TableBasedTableBuilder(font_builder, header, data) {
+FontHeaderTable::Builder::Builder(Header* header, WritableFontData* data)
+    : Table::TableBasedTableBuilder(header, data) {
 }
 
-FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                                  Header* header, ReadableFontData* data) :
-    Table::TableBasedTableBuilder(font_builder, header, data) {
+FontHeaderTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : Table::TableBasedTableBuilder(header, data) {
 }
 
 FontHeaderTable::Builder::~Builder() {}
@@ -256,4 +254,12 @@
   InternalWriteData()->WriteShort(Offset::kGlyphDataFormat, format);
 }
 
+CALLER_ATTACH FontHeaderTable::Builder*
+    FontHeaderTable::Builder::CreateBuilder(Header* header,
+                                            WritableFontData* data) {
+  Ptr<FontHeaderTable::Builder> builder;
+  builder = new FontHeaderTable::Builder(header, data);
+  return builder.Detach();
+}
+
 }  // namespace sfntly
diff --git a/sfntly/table/core/font_header_table.h b/sfntly/table/core/font_header_table.h
index 343e62c..3b20863 100644
--- a/sfntly/table/core/font_header_table.h
+++ b/sfntly/table/core/font_header_table.h
@@ -45,10 +45,8 @@
    public:
     // Constructor scope altered to public because C++ does not allow base
     // class to instantiate derived class with protected constructors.
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            ReadableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
 
@@ -90,6 +88,9 @@
     virtual void SetIndexToLocFormat(int32_t format);
     virtual int32_t GlyphDataFormat();
     virtual void SetGlyphDataFormat(int32_t format);
+
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
   };
 
   virtual ~FontHeaderTable();
diff --git a/sfntly/table/core/horizontal_header_table.cc b/sfntly/table/core/horizontal_header_table.cc
index 52b0de2..f07ab01 100644
--- a/sfntly/table/core/horizontal_header_table.cc
+++ b/sfntly/table/core/horizontal_header_table.cc
@@ -22,7 +22,7 @@
  ******************************************************************************/
 HorizontalHeaderTable:: ~HorizontalHeaderTable() {}
 
-int32_t HorizontalHeaderTable::Version() {
+int32_t HorizontalHeaderTable::TableVersion() {
   return data_->ReadFixed(Offset::kVersion);
 }
 
@@ -82,18 +82,12 @@
 /******************************************************************************
  * HorizontalHeaderTable::Builder class
  ******************************************************************************/
-HorizontalHeaderTable::Builder::Builder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    WritableFontData* data)
-    : Table::TableBasedTableBuilder(font_builder, header, data) {
+HorizontalHeaderTable::Builder::Builder(Header* header, WritableFontData* data)
+    : Table::TableBasedTableBuilder(header, data) {
 }
 
-HorizontalHeaderTable::Builder::Builder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    ReadableFontData* data)
-    : Table::TableBasedTableBuilder(font_builder, header, data) {
+HorizontalHeaderTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : Table::TableBasedTableBuilder(header, data) {
 }
 
 HorizontalHeaderTable::Builder::~Builder() {}
@@ -104,11 +98,19 @@
   return table.Detach();
 }
 
-int32_t HorizontalHeaderTable::Builder::Version() {
+CALLER_ATTACH HorizontalHeaderTable::Builder*
+    HorizontalHeaderTable::Builder::CreateBuilder(Header* header,
+                                                  WritableFontData* data) {
+  Ptr<HorizontalHeaderTable::Builder> builder;
+  builder = new HorizontalHeaderTable::Builder(header, data);
+  return builder.Detach();
+}
+
+int32_t HorizontalHeaderTable::Builder::TableVersion() {
   return InternalReadData()->ReadFixed(Offset::kVersion);
 }
 
-void HorizontalHeaderTable::Builder::SetVersion(int32_t version) {
+void HorizontalHeaderTable::Builder::SetTableVersion(int32_t version) {
   InternalWriteData()->WriteFixed(Offset::kVersion, version);
 }
 
diff --git a/sfntly/table/core/horizontal_header_table.h b/sfntly/table/core/horizontal_header_table.h
index 3a3eb6f..c79a7b6 100644
--- a/sfntly/table/core/horizontal_header_table.h
+++ b/sfntly/table/core/horizontal_header_table.h
@@ -21,25 +21,26 @@
 
 namespace sfntly {
 
+// A Horizontal Header table - 'hhea'.
 class HorizontalHeaderTable : public Table,
                               public RefCounted<HorizontalHeaderTable> {
  public:
+  // Builder for a Horizontal Header table - 'hhea'.
   class Builder : public Table::TableBasedTableBuilder,
                   public RefCounted<Builder> {
    public:
     // Constructor scope altered to public because C++ does not allow base
     // class to instantiate derived class with protected constructors.
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            ReadableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
 
-    int32_t Version();
-    void SetVersion(int32_t version);
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
+
+    int32_t TableVersion();
+    void SetTableVersion(int32_t version);
     int32_t Ascender();
     void SetAscender(int32_t ascender);
     int32_t Descender();
@@ -67,7 +68,7 @@
   };
 
   virtual ~HorizontalHeaderTable();
-  int32_t Version();
+  int32_t TableVersion();
   int32_t Ascender();
   int32_t Descender();
   int32_t LineGap();
diff --git a/sfntly/table/core/horizontal_metrics_table.cc b/sfntly/table/core/horizontal_metrics_table.cc
index b2463b9..67e99e0 100644
--- a/sfntly/table/core/horizontal_metrics_table.cc
+++ b/sfntly/table/core/horizontal_metrics_table.cc
@@ -33,11 +33,10 @@
 
 int32_t HorizontalMetricsTable::HMetricAdvanceWidth(int32_t entry) {
   if (entry > num_hmetrics_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException();
 #endif
+    return 0;
   }
   int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) +
                    Offset::kHMetricsAdvanceWidth;
@@ -46,11 +45,10 @@
 
 int32_t HorizontalMetricsTable::HMetricLSB(int32_t entry) {
   if (entry > num_hmetrics_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException();
 #endif
+    return 0;
   }
   int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) +
                    Offset::kHMetricsLeftSideBearing;
@@ -59,11 +57,10 @@
 
 int32_t HorizontalMetricsTable::LsbTableEntry(int32_t entry) {
   if (entry > num_hmetrics_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException();
 #endif
+    return 0;
   }
   int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) +
                    Offset::kLeftSideBearingSize;
@@ -85,11 +82,6 @@
 }
 
 HorizontalMetricsTable::HorizontalMetricsTable(Header* header,
-                                               ReadableFontData* data)
-    : Table(header, data) {
-}
-
-HorizontalMetricsTable::HorizontalMetricsTable(Header* header,
                                                ReadableFontData* data,
                                                int32_t num_hmetrics,
                                                int32_t num_glyphs)
@@ -101,20 +93,16 @@
 /******************************************************************************
  * HorizontalMetricsTable::Builder class
  ******************************************************************************/
-HorizontalMetricsTable::Builder::Builder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    WritableFontData* data)
-    : Table::TableBasedTableBuilder(font_builder, header, data) {
-  Init();
+HorizontalMetricsTable::Builder::Builder(Header* header, WritableFontData* data)
+    : Table::TableBasedTableBuilder(header, data),
+      num_hmetrics_(-1),
+      num_glyphs_(-1) {
 }
 
-HorizontalMetricsTable::Builder::Builder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    ReadableFontData* data)
-    : Table::TableBasedTableBuilder(font_builder, header, data) {
-  Init();
+HorizontalMetricsTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : Table::TableBasedTableBuilder(header, data),
+      num_hmetrics_(-1),
+      num_glyphs_(-1) {
 }
 
 HorizontalMetricsTable::Builder::~Builder() {}
@@ -126,6 +114,14 @@
   return table.Detach();
 }
 
+CALLER_ATTACH HorizontalMetricsTable::Builder*
+    HorizontalMetricsTable::Builder::CreateBuilder(Header* header,
+                                                   WritableFontData* data) {
+  Ptr<HorizontalMetricsTable::Builder> builder;
+  builder = new HorizontalMetricsTable::Builder(header, data);
+  return builder.Detach();
+}
+
 void HorizontalMetricsTable::Builder::SetNumberOfHMetrics(
     int32_t num_hmetrics) {
   assert(num_hmetrics >= 0);
@@ -143,9 +139,4 @@
   table->num_glyphs_ = num_glyphs;
 }
 
-void HorizontalMetricsTable::Builder::Init() {
-  num_hmetrics_ = -1;
-  num_glyphs_ = -1;
-}
-
 }  // namespace sfntly
diff --git a/sfntly/table/core/horizontal_metrics_table.h b/sfntly/table/core/horizontal_metrics_table.h
index aa3fa65..eaf79e4 100644
--- a/sfntly/table/core/horizontal_metrics_table.h
+++ b/sfntly/table/core/horizontal_metrics_table.h
@@ -21,29 +21,28 @@
 
 namespace sfntly {
 
+// A Horizontal Metrics table - 'hmtx'.
 class HorizontalMetricsTable : public Table,
                                public RefCounted<HorizontalMetricsTable> {
  public:
+  // Builder for a Horizontal Metrics Table - 'hmtx'.
   class Builder : public Table::TableBasedTableBuilder,
                   public RefCounted<Builder> {
    public:
     // Constructor scope altered to public because C++ does not allow base
     // class to instantiate derived class with protected constructors.
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            ReadableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
 
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
+
     void SetNumberOfHMetrics(int32_t num_hmetrics);
     void SetNumGlyphs(int32_t num_glyphs);
 
    private:
-    void Init();
-
     int32_t num_hmetrics_;
     int32_t num_glyphs_;
   };
@@ -72,7 +71,6 @@
     };
   };
 
-  HorizontalMetricsTable(Header* header, ReadableFontData* data);
   HorizontalMetricsTable(Header* header,
                          ReadableFontData* data,
                          int32_t num_hmetrics,
diff --git a/sfntly/table/core/maximum_profile_table.cc b/sfntly/table/core/maximum_profile_table.cc
index fec508a..e457621 100644
--- a/sfntly/table/core/maximum_profile_table.cc
+++ b/sfntly/table/core/maximum_profile_table.cc
@@ -22,7 +22,7 @@
  ******************************************************************************/
 MaximumProfileTable::~MaximumProfileTable() {}
 
-int32_t MaximumProfileTable::Version() {
+int32_t MaximumProfileTable::TableVersion() {
   return data_->ReadFixed(Offset::kVersion);
 }
 
@@ -42,6 +42,10 @@
   return data_->ReadUShort(Offset::kMaxCompositePoints);
 }
 
+int32_t MaximumProfileTable::MaxCompositeContours() {
+  return data_->ReadUShort(Offset::kMaxCompositeContours);
+}
+
 int32_t MaximumProfileTable::MaxZones() {
   return data_->ReadUShort(Offset::kMaxZones);
 }
@@ -82,18 +86,12 @@
 /******************************************************************************
  * MaximumProfileTable::Builder class
  ******************************************************************************/
-MaximumProfileTable::Builder::Builder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    WritableFontData* data)
-    : Table::TableBasedTableBuilder(font_builder, header, data) {
+MaximumProfileTable::Builder::Builder(Header* header, WritableFontData* data)
+    : Table::TableBasedTableBuilder(header, data) {
 }
 
-MaximumProfileTable::Builder::Builder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    ReadableFontData* data)
-    : Table::TableBasedTableBuilder(font_builder, header, data) {
+MaximumProfileTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : Table::TableBasedTableBuilder(header, data) {
 }
 
 MaximumProfileTable::Builder::~Builder() {}
@@ -104,11 +102,19 @@
   return table.Detach();
 }
 
-int32_t MaximumProfileTable::Builder::Version() {
+CALLER_ATTACH MaximumProfileTable::Builder*
+    MaximumProfileTable::Builder::CreateBuilder(Header* header,
+                                                WritableFontData* data) {
+  Ptr<MaximumProfileTable::Builder> builder;
+  builder = new MaximumProfileTable::Builder(header, data);
+  return builder.Detach();
+}
+
+int32_t MaximumProfileTable::Builder::TableVersion() {
   return InternalReadData()->ReadUShort(Offset::kVersion);
 }
 
-void MaximumProfileTable::Builder::SetVersion(int32_t version) {
+void MaximumProfileTable::Builder::SetTableVersion(int32_t version) {
   InternalWriteData()->WriteUShort(Offset::kVersion, version);
 }
 
@@ -146,6 +152,16 @@
                                    max_composite_points);
 }
 
+int32_t MaximumProfileTable::Builder::MaxCompositeContours() {
+  return InternalReadData()->ReadUShort(Offset::kMaxCompositeContours);
+}
+
+void MaximumProfileTable::Builder::SetMaxCompositeContours(
+    int32_t max_composite_contours) {
+  InternalWriteData()->WriteUShort(Offset::kMaxCompositeContours,
+      max_composite_contours);
+}
+
 int32_t MaximumProfileTable::Builder::MaxZones() {
   return InternalReadData()->ReadUShort(Offset::kMaxZones);
 }
diff --git a/sfntly/table/core/maximum_profile_table.h b/sfntly/table/core/maximum_profile_table.h
index 10ec872..9b89617 100644
--- a/sfntly/table/core/maximum_profile_table.h
+++ b/sfntly/table/core/maximum_profile_table.h
@@ -22,24 +22,26 @@
 
 namespace sfntly {
 
+// A Maximum Profile table - 'maxp'.
 class MaximumProfileTable : public Table,
                             public RefCounted<MaximumProfileTable> {
  public:
+  // Builder for a Maximum Profile table - 'maxp'.
   class Builder : public Table::TableBasedTableBuilder,
                   public RefCounted<Builder> {
    public:
     // Constructor scope altered to public because C++ does not allow base
     // class to instantiate derived class with protected constructors.
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            ReadableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
 
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
 
-    int32_t Version();
-    void SetVersion(int32_t version);
+    int32_t TableVersion();
+    void SetTableVersion(int32_t version);
     int32_t NumGlyphs();
     void SetNumGlyphs(int32_t num_glyphs);
     int32_t MaxPoints();
@@ -48,6 +50,8 @@
     void SetMaxContours(int32_t max_contours);
     int32_t MaxCompositePoints();
     void SetMaxCompositePoints(int32_t max_composite_points);
+    int32_t MaxCompositeContours();
+    void SetMaxCompositeContours(int32_t max_composite_contours);
     int32_t MaxZones();
     void SetMaxZones(int32_t max_zones);
     int32_t MaxTwilightPoints();
@@ -67,11 +71,12 @@
   };
 
   virtual ~MaximumProfileTable();
-  int32_t Version();
+  int32_t TableVersion();
   int32_t NumGlyphs();
   int32_t MaxPoints();
   int32_t MaxContours();
   int32_t MaxCompositePoints();
+  int32_t MaxCompositeContours();
   int32_t MaxZones();
   int32_t MaxTwilightPoints();
   int32_t MaxStorage();
diff --git a/sfntly/table/core/name_table.cc b/sfntly/table/core/name_table.cc
index 00c4519..9853130 100644
--- a/sfntly/table/core/name_table.cc
+++ b/sfntly/table/core/name_table.cc
@@ -137,8 +137,8 @@
   Init(0, 0, 0, 0, NULL);
 }
 
-NameTable::NameEntryBuilder::NameEntryBuilder(
-    const NameEntryId& name_entry_id, const ByteVector& name_bytes) {
+NameTable::NameEntryBuilder::NameEntryBuilder(const NameEntryId& name_entry_id,
+                                              const ByteVector& name_bytes) {
   Init(name_entry_id.platform_id(),
        name_entry_id.encoding_id(),
        name_entry_id.language_id(),
@@ -263,7 +263,7 @@
 void NameTable::NameEntryIterator::Remove() {
 #if !defined (SFNTLY_NO_EXCEPTION)
   throw UnsupportedOperationException(
-            "Cannot remove a CMap table from an existing font.");
+            "Cannot remove a name table from an existing font.");
 #endif
 }
 
@@ -277,16 +277,20 @@
 /******************************************************************************
  * NameTable::Builder class
  ******************************************************************************/
-NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                            Header* header,
-                            WritableFontData* data)
-    : Table::ArrayElementTableBuilder(font_builder, header, data) {
+NameTable::Builder::Builder(Header* header, WritableFontData* data)
+    : SubTableContainerTable::Builder(header, data) {
 }
 
-NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                            Header* header,
-                            ReadableFontData* data)
-    : Table::ArrayElementTableBuilder(font_builder, header, data) {
+NameTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : SubTableContainerTable::Builder(header, data) {
+}
+
+CALLER_ATTACH NameTable::Builder*
+    NameTable::Builder::CreateBuilder(Header* header,
+                                      WritableFontData* data) {
+  Ptr<NameTable::Builder> builder;
+  builder = new NameTable::Builder(header, data);
+  return builder.Detach();
 }
 
 void NameTable::Builder::RevertNames() {
@@ -546,7 +550,7 @@
 }
 
 NameTable::NameTable(Header* header, ReadableFontData* data)
-    : Table(header, data) {}
+    : SubTableContainerTable(header, data) {}
 
 int32_t NameTable::StringOffset() {
   return data_->ReadUShort(Offset::kStringOffset);
diff --git a/sfntly/table/core/name_table.h b/sfntly/table/core/name_table.h
index b5a7f9a..0c657da 100644
--- a/sfntly/table/core/name_table.h
+++ b/sfntly/table/core/name_table.h
@@ -26,7 +26,7 @@
 #include <map>
 #include <utility>
 
-#include "sfntly/table/table.h"
+#include "sfntly/table/subtable_container_table.h"
 
 #if defined U_USING_ICU_NAMESPACE
   U_NAMESPACE_USE
@@ -412,7 +412,7 @@
   };
 };
 
-class NameTable : public Table, public RefCounted<NameTable> {
+class NameTable : public SubTableContainerTable, public RefCounted<NameTable> {
  public:
   // Unique identifier for a given name record.
   class NameEntryId {
@@ -433,6 +433,9 @@
     bool operator==(const NameEntryId& rhs) const;
     bool operator<(const NameEntryId& rhs) const;
 
+    // UNIMPLEMENTED: int hashCode()
+    //                String toString()
+
    private:
     mutable int32_t platform_id_;
     mutable int32_t encoding_id_;
@@ -447,8 +450,11 @@
    public:
     NameEntry();
     NameEntry(const NameEntryId& name_entry_id, const ByteVector& name_bytes);
-    NameEntry(int32_t platform_id, int32_t encoding_id, int32_t language_id,
-              int32_t name_id, const ByteVector& name_bytes);
+    NameEntry(int32_t platform_id,
+              int32_t encoding_id,
+              int32_t language_id,
+              int32_t name_id,
+              const ByteVector& name_bytes);
     virtual ~NameEntry();
 
     NameEntryId& name_entry_id() { return name_entry_id_; }
@@ -469,6 +475,9 @@
     UChar* Name();
     bool operator==(const NameEntry& rhs) const;
 
+    // UNIMPLEMENTED: String toString()
+    //                int hashCode()
+
    private:
     void Init(int32_t platform_id, int32_t encoding_id, int32_t language_id,
               int32_t name_id, const ByteVector* name_bytes);
@@ -494,7 +503,8 @@
 
     virtual void SetName(const UChar* name);
     virtual void SetName(const ByteVector& name_bytes);
-    virtual void SetName(const ByteVector& name_bytes, int32_t offset,
+    virtual void SetName(const ByteVector& name_bytes,
+                         int32_t offset,
                          int32_t length);
 
     // C++ port only. CALLER_ATTACH is not added because the lifetime shall be
@@ -515,8 +525,10 @@
   // returned.
   class NameEntryFilter {
    public:
-    virtual bool Accept(int32_t platform_id, int32_t encoding_id,
-                        int32_t language_id, int32_t name_id) = 0;
+    virtual bool Accept(int32_t platform_id,
+                        int32_t encoding_id,
+                        int32_t language_id,
+                        int32_t name_id) = 0;
     // Make gcc -Wnon-virtual-dtor happy.
     virtual ~NameEntryFilter() {}
   };
@@ -524,13 +536,17 @@
   // C++ port only: an in-place filter to mimic Java Iterator's filtering.
   class NameEntryFilterInPlace : public NameEntryFilter {
    public:
-    NameEntryFilterInPlace(int32_t platform_id, int32_t encoding_id,
-                           int32_t language_id, int32_t name_id);
+    NameEntryFilterInPlace(int32_t platform_id,
+                           int32_t encoding_id,
+                           int32_t language_id,
+                           int32_t name_id);
     // Make gcc -Wnon-virtual-dtor happy.
     virtual ~NameEntryFilterInPlace() {}
 
-    virtual bool Accept(int32_t platform_id, int32_t encoding_id,
-                        int32_t language_id, int32_t name_id);
+    virtual bool Accept(int32_t platform_id,
+                        int32_t encoding_id,
+                        int32_t language_id,
+                        int32_t name_id);
 
    private:
     int32_t platform_id_;
@@ -561,15 +577,16 @@
   };
 
   // The builder to construct name table for outputting.
-  class Builder : public Table::ArrayElementTableBuilder,
+  class Builder : public SubTableContainerTable::Builder,
                   public RefCounted<Builder> {
    public:
     // Constructor scope altered to public because C++ does not allow base
     // class to instantiate derived class with protected constructors.
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            ReadableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
+
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
 
     // Revert the name builders for the name table to the last version that came
     // from data.
diff --git a/sfntly/table/core/os2_table.cc b/sfntly/table/core/os2_table.cc
index 8ab435b..024b03a 100644
--- a/sfntly/table/core/os2_table.cc
+++ b/sfntly/table/core/os2_table.cc
@@ -100,7 +100,7 @@
  ******************************************************************************/
 OS2Table::~OS2Table() {}
 
-int32_t OS2Table::Version() {
+int32_t OS2Table::TableVersion() {
   return data_->ReadUShort(Offset::kVersion);
 }
 
@@ -165,6 +165,7 @@
 }
 
 void OS2Table::Panose(ByteVector* value) {
+  assert(value);
   value->clear();
   value->resize(10);
   data_->ReadBytes(Offset::kPanose, &((*value)[0]), 0, 10);
@@ -187,6 +188,7 @@
 }
 
 void OS2Table::AchVendId(ByteVector* b) {
+  assert(b);
   b->clear();
   b->resize(4);
   data_->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4);
@@ -232,16 +234,14 @@
   return data_->ReadULong(Offset::kUlCodePageRange2);
 }
 
-int64_t OS2Table::UlCodePageRange() {
-  // TODO(arthurhsu): Possible bug point, check with stuartg.
-  return ((0xffffffff & UlCodePageRange2()) << 32) |
-         (0xffffffff & UlCodePageRange1());
-}
-
 int32_t OS2Table::SxHeight() {
   return data_->ReadShort(Offset::kSxHeight);
 }
 
+int32_t OS2Table::SCapHeight() {
+  return data_->ReadShort(Offset::kSCapHeight);
+}
+
 int32_t OS2Table::UsDefaultChar() {
   return data_->ReadUShort(Offset::kUsDefaultChar);
 }
@@ -261,9 +261,12 @@
 /******************************************************************************
  * class OS2Table::Builder
  ******************************************************************************/
-OS2Table::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                           Header* header, WritableFontData* data) :
-    Table::TableBasedTableBuilder(font_builder, header, data) {
+OS2Table::Builder::Builder(Header* header, WritableFontData* data) :
+    Table::TableBasedTableBuilder(header, data) {
+}
+
+OS2Table::Builder::Builder(Header* header, ReadableFontData* data) :
+    Table::TableBasedTableBuilder(header, data) {
 }
 
 OS2Table::Builder::~Builder() {}
@@ -274,4 +277,331 @@
   return table.Detach();
 }
 
+CALLER_ATTACH OS2Table::Builder*
+    OS2Table::Builder::CreateBuilder(Header* header,
+                                     WritableFontData* data) {
+  Ptr<OS2Table::Builder> builder;
+  builder = new OS2Table::Builder(header, data);
+  return builder.Detach();
+}
+
+int32_t OS2Table::Builder::TableVersion() {
+  return InternalReadData()->ReadUShort(Offset::kVersion);
+}
+
+void OS2Table::Builder::SetTableVersion(int32_t version) {
+  InternalWriteData()->WriteUShort(Offset::kVersion, version);
+}
+
+int32_t OS2Table::Builder::XAvgCharWidth() {
+  return InternalReadData()->ReadShort(Offset::kXAvgCharWidth);
+}
+
+void OS2Table::Builder::SetXAvgCharWidth(int32_t width) {
+  InternalWriteData()->WriteShort(Offset::kXAvgCharWidth, width);
+}
+
+int32_t OS2Table::Builder::UsWeightClass() {
+  return InternalReadData()->ReadUShort(Offset::kUsWeightClass);
+}
+
+void OS2Table::Builder::SetUsWeightClass(int32_t weight) {
+  InternalWriteData()->WriteUShort(Offset::kUsWeightClass, weight);
+}
+
+int32_t OS2Table::Builder::UsWidthClass() {
+  return InternalReadData()->ReadUShort(Offset::kUsWidthClass);
+}
+
+void OS2Table::Builder::SetUsWidthClass(int32_t width) {
+  InternalWriteData()->WriteUShort(Offset::kUsWidthClass, width);
+}
+
+int32_t OS2Table::Builder::FsType() {
+  return InternalReadData()->ReadUShort(Offset::kFsType);
+}
+
+void OS2Table::Builder::SetFsType(int32_t fs_type) {
+  InternalWriteData()->WriteUShort(Offset::kFsType, fs_type);
+}
+
+int32_t OS2Table::Builder::YSubscriptXSize() {
+  return InternalReadData()->ReadShort(Offset::kYSubscriptXSize);
+}
+
+void OS2Table::Builder::SetYSubscriptXSize(int32_t size) {
+  InternalWriteData()->WriteShort(Offset::kYSubscriptXSize, size);
+}
+
+int32_t OS2Table::Builder::YSubscriptYSize() {
+  return InternalReadData()->ReadShort(Offset::kYSubscriptYSize);
+}
+
+void OS2Table::Builder::SetYSubscriptYSize(int32_t size) {
+  InternalWriteData()->WriteShort(Offset::kYSubscriptYSize, size);
+}
+
+int32_t OS2Table::Builder::YSubscriptXOffset() {
+  return InternalReadData()->ReadShort(Offset::kYSubscriptXOffset);
+}
+
+void OS2Table::Builder::SetYSubscriptXOffset(int32_t offset) {
+  InternalWriteData()->WriteShort(Offset::kYSubscriptXOffset, offset);
+}
+
+int32_t OS2Table::Builder::YSubscriptYOffset() {
+  return InternalReadData()->ReadShort(Offset::kYSubscriptYOffset);
+}
+
+void OS2Table::Builder::SetYSubscriptYOffset(int32_t offset) {
+  InternalWriteData()->WriteShort(Offset::kYSubscriptYOffset, offset);
+}
+
+int32_t OS2Table::Builder::YSuperscriptXSize() {
+  return InternalReadData()->ReadShort(Offset::kYSuperscriptXSize);
+}
+
+void OS2Table::Builder::SetYSuperscriptXSize(int32_t size) {
+  InternalWriteData()->WriteShort(Offset::kYSuperscriptXSize, size);
+}
+
+int32_t OS2Table::Builder::YSuperscriptYSize() {
+  return InternalReadData()->ReadShort(Offset::kYSuperscriptYSize);
+}
+
+void OS2Table::Builder::SetYSuperscriptYSize(int32_t size) {
+  InternalWriteData()->WriteShort(Offset::kYSuperscriptYSize, size);
+}
+
+int32_t OS2Table::Builder::YSuperscriptXOffset() {
+  return InternalReadData()->ReadShort(Offset::kYSuperscriptXOffset);
+}
+
+void OS2Table::Builder::SetYSuperscriptXOffset(int32_t offset) {
+  InternalWriteData()->WriteShort(Offset::kYSuperscriptXOffset, offset);
+}
+
+int32_t OS2Table::Builder::YSuperscriptYOffset() {
+  return InternalReadData()->ReadShort(Offset::kYSuperscriptYOffset);
+}
+
+void OS2Table::Builder::SetYSuperscriptYOffset(int32_t offset) {
+  InternalWriteData()->WriteShort(Offset::kYSuperscriptYOffset, offset);
+}
+
+int32_t OS2Table::Builder::YStrikeoutSize() {
+  return InternalReadData()->ReadShort(Offset::kYStrikeoutSize);
+}
+
+void OS2Table::Builder::SetYStrikeoutSize(int32_t size) {
+  InternalWriteData()->WriteShort(Offset::kYStrikeoutSize, size);
+}
+
+int32_t OS2Table::Builder::YStrikeoutPosition() {
+  return InternalReadData()->ReadShort(Offset::kYStrikeoutPosition);
+}
+
+void OS2Table::Builder::SetYStrikeoutPosition(int32_t position) {
+  InternalWriteData()->WriteShort(Offset::kYStrikeoutPosition, position);
+}
+
+int32_t OS2Table::Builder::SFamilyClass() {
+  return InternalReadData()->ReadShort(Offset::kSFamilyClass);
+}
+
+void OS2Table::Builder::SetSFamilyClass(int32_t family) {
+  InternalWriteData()->WriteShort(Offset::kSFamilyClass, family);
+}
+
+void OS2Table::Builder::Panose(ByteVector* value) {
+  assert(value);
+  value->clear();
+  value->resize(Offset::kPanoseLength);
+  InternalReadData()->ReadBytes(Offset::kPanose,
+                                &((*value)[0]),
+                                0,
+                                Offset::kPanoseLength);
+}
+
+void OS2Table::Builder::SetPanose(ByteVector* panose) {
+  assert(panose);
+  if (panose->size() != Offset::kPanoseLength) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+    throw IllegalArgumentException("Panose bytes must be exactly 10 in length");
+#endif
+    return;
+  }
+  InternalWriteData()->WriteBytes(Offset::kPanose, panose);
+}
+
+int64_t OS2Table::Builder::UlUnicodeRange1() {
+  return InternalReadData()->ReadULong(Offset::kUlUnicodeRange1);
+}
+
+void OS2Table::Builder::SetUlUnicodeRange1(int64_t range) {
+  InternalWriteData()->WriteULong(Offset::kUlUnicodeRange1, range);
+}
+
+int64_t OS2Table::Builder::UlUnicodeRange2() {
+  return InternalReadData()->ReadULong(Offset::kUlUnicodeRange2);
+}
+
+void OS2Table::Builder::SetUlUnicodeRange2(int64_t range) {
+  InternalWriteData()->WriteULong(Offset::kUlUnicodeRange2, range);
+}
+
+int64_t OS2Table::Builder::UlUnicodeRange3() {
+  return InternalReadData()->ReadULong(Offset::kUlUnicodeRange3);
+}
+
+void OS2Table::Builder::SetUlUnicodeRange3(int64_t range) {
+  InternalWriteData()->WriteULong(Offset::kUlUnicodeRange3, range);
+}
+
+int64_t OS2Table::Builder::UlUnicodeRange4() {
+  return InternalReadData()->ReadULong(Offset::kUlUnicodeRange4);
+}
+
+void OS2Table::Builder::SetUlUnicodeRange4(int64_t range) {
+  InternalWriteData()->WriteULong(Offset::kUlUnicodeRange4, range);
+}
+
+void OS2Table::Builder::AchVendId(ByteVector* b) {
+  assert(b);
+  b->clear();
+  b->resize(4);
+  InternalReadData()->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4);
+}
+
+void OS2Table::Builder::SetAchVendId(ByteVector* b) {
+  assert(b);
+  assert(b->size());
+  InternalWriteData()->WriteBytes(Offset::kAchVendId,
+                                  &((*b)[0]),
+                                  0,
+                                  std::min<size_t>(
+                                      (size_t)Offset::kAchVendIdLength,
+                                      b->size()));
+}
+
+int32_t OS2Table::Builder::FsSelection() {
+  return InternalReadData()->ReadUShort(Offset::kFsSelection);
+}
+
+void OS2Table::Builder::SetFsSelection(int32_t fs_selection) {
+  InternalWriteData()->WriteUShort(Offset::kFsSelection, fs_selection);
+}
+
+int32_t OS2Table::Builder::UsFirstCharIndex() {
+  return InternalReadData()->ReadUShort(Offset::kUsFirstCharIndex);
+}
+
+void OS2Table::Builder::SetUsFirstCharIndex(int32_t first_index) {
+  InternalWriteData()->WriteUShort(Offset::kUsFirstCharIndex, first_index);
+}
+
+int32_t OS2Table::Builder::UsLastCharIndex() {
+  return InternalReadData()->ReadUShort(Offset::kUsLastCharIndex);
+}
+
+void OS2Table::Builder::SetUsLastCharIndex(int32_t last_index) {
+  InternalWriteData()->WriteUShort(Offset::kUsLastCharIndex, last_index);
+}
+
+int32_t OS2Table::Builder::STypoAscender() {
+  return InternalReadData()->ReadShort(Offset::kSTypoAscender);
+}
+
+void OS2Table::Builder::SetSTypoAscender(int32_t ascender) {
+  InternalWriteData()->WriteShort(Offset::kSTypoAscender, ascender);
+}
+
+int32_t OS2Table::Builder::STypoDescender() {
+  return InternalReadData()->ReadShort(Offset::kSTypoDescender);
+}
+
+void OS2Table::Builder::SetSTypoDescender(int32_t descender) {
+  InternalWriteData()->WriteShort(Offset::kSTypoDescender, descender);
+}
+
+int32_t OS2Table::Builder::STypoLineGap() {
+  return InternalReadData()->ReadShort(Offset::kSTypoLineGap);
+}
+
+void OS2Table::Builder::SetSTypoLineGap(int32_t line_gap) {
+  InternalWriteData()->WriteShort(Offset::kSTypoLineGap, line_gap);
+}
+
+int32_t OS2Table::Builder::UsWinAscent() {
+  return InternalReadData()->ReadUShort(Offset::kUsWinAscent);
+}
+
+void OS2Table::Builder::SetUsWinAscent(int32_t ascent) {
+  InternalWriteData()->WriteUShort(Offset::kUsWinAscent, ascent);
+}
+
+int32_t OS2Table::Builder::UsWinDescent() {
+  return InternalReadData()->ReadUShort(Offset::kUsWinDescent);
+}
+
+void OS2Table::Builder::SetUsWinDescent(int32_t descent) {
+  InternalWriteData()->WriteUShort(Offset::kUsWinDescent, descent);
+}
+
+int64_t OS2Table::Builder::UlCodePageRange1() {
+  return InternalReadData()->ReadULong(Offset::kUlCodePageRange1);
+}
+
+void OS2Table::Builder::SetUlCodePageRange1(int64_t range) {
+  InternalWriteData()->WriteULong(Offset::kUlCodePageRange1, range);
+}
+
+int64_t OS2Table::Builder::UlCodePageRange2() {
+  return InternalReadData()->ReadULong(Offset::kUlCodePageRange2);
+}
+
+void OS2Table::Builder::SetUlCodePageRange2(int64_t range) {
+  InternalWriteData()->WriteULong(Offset::kUlCodePageRange2, range);
+}
+
+int32_t OS2Table::Builder::SxHeight() {
+  return InternalReadData()->ReadShort(Offset::kSxHeight);
+}
+
+void OS2Table::Builder::SetSxHeight(int32_t height) {
+  InternalWriteData()->WriteShort(Offset::kSxHeight, height);
+}
+
+int32_t OS2Table::Builder::SCapHeight() {
+  return InternalReadData()->ReadShort(Offset::kSCapHeight);
+}
+
+void OS2Table::Builder::SetSCapHeight(int32_t height) {
+  InternalWriteData()->WriteShort(Offset::kSCapHeight, height);
+}
+
+int32_t OS2Table::Builder::UsDefaultChar() {
+  return InternalReadData()->ReadUShort(Offset::kUsDefaultChar);
+}
+
+void OS2Table::Builder::SetUsDefaultChar(int32_t default_char) {
+  InternalWriteData()->WriteUShort(Offset::kUsDefaultChar, default_char);
+}
+
+int32_t OS2Table::Builder::UsBreakChar() {
+  return InternalReadData()->ReadUShort(Offset::kUsBreakChar);
+}
+
+void OS2Table::Builder::SetUsBreakChar(int32_t break_char) {
+  InternalWriteData()->WriteUShort(Offset::kUsBreakChar, break_char);
+}
+
+int32_t OS2Table::Builder::UsMaxContext() {
+  return InternalReadData()->ReadUShort(Offset::kUsMaxContext);
+}
+
+void OS2Table::Builder::SetUsMaxContext(int32_t max_context) {
+  InternalWriteData()->WriteUShort(Offset::kUsMaxContext, max_context);
+}
+
 }  // namespace sfntly
diff --git a/sfntly/table/core/os2_table.h b/sfntly/table/core/os2_table.h
index 24b6027..cd34ff8 100644
--- a/sfntly/table/core/os2_table.h
+++ b/sfntly/table/core/os2_table.h
@@ -56,6 +56,7 @@
   };
 };
 
+// Flags to indicate the embedding licensing rights for a font.
 struct EmbeddingFlags {
   enum {
     kReserved0 = 1 << 0,
@@ -79,8 +80,8 @@
 
 struct UnicodeRange {
   enum {
-    // This enum relies on the ordering of the data matching the ordinal numbers
-    // of the properties.
+    // Do NOT reorder. This enum relies on the ordering of the data matching the
+    // ordinal numbers of the properties.
     kBasicLatin,
     kLatin1Supplement,
     kLatinExtendedA,
@@ -213,6 +214,7 @@
   int32_t range(int32_t bit);
   // UNIMPLEMENTED: EnumSet<UnicodeRange> asSet(long range1, long range2,
   //                                            long range3, long range4)
+  //                long[] asArray(EnumSet<UnicodeRange> rangeSet)
 };
 
 struct FsSelection {
@@ -228,6 +230,9 @@
     kWWS = 1 << 8,
     kOBLIQUE = 1 << 9
   };
+  // UNIMPLEMENTED: EnumSet<FsSelection> asSet(long range1, long range2,
+  //                                           long range3, long range4)
+  //                long[] asArray(EnumSet<FsSelection> rangeSet)
 };
 
 // C++ port only: C++ does not support 64-bit enums until C++0x.  For better
@@ -297,22 +302,113 @@
   static const int64_t kArabic_708;
   static const int64_t kLatin1_850;
   static const int64_t kUS_437;
+
+  // UNIMPLEMENTED: EnumSet<CodePageRange> asSet(long range1, long range2,
+  //                                             long range3, long range4)
+  //                long[] asArray(EnumSet<CodePageRange> rangeSet)
 };
 
+// An OS/2 table - 'OS/2'.
 class OS2Table : public Table, public RefCounted<OS2Table> {
  public:
+  // A builder for the OS/2 table = 'OS/2'.
   class Builder : public Table::TableBasedTableBuilder,
                   public RefCounted<Builder> {
    public:
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            WritableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
+
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
+
+    int32_t TableVersion();
+    void SetTableVersion(int32_t version);
+    int32_t XAvgCharWidth();
+    void SetXAvgCharWidth(int32_t width);
+    int32_t UsWeightClass();
+    void SetUsWeightClass(int32_t weight);
+    int32_t UsWidthClass();
+    void SetUsWidthClass(int32_t width);
+    // UNIMPLEMENTED: EnumSet<EmbeddingFlags> fsType()
+    //                void setFsType(EnumSeT<EmbeddingFlags> flagSet)
+    int32_t FsType();
+    void SetFsType(int32_t fs_type);
+    int32_t YSubscriptXSize();
+    void SetYSubscriptXSize(int32_t size);
+    int32_t YSubscriptYSize();
+    void SetYSubscriptYSize(int32_t size);
+    int32_t YSubscriptXOffset();
+    void SetYSubscriptXOffset(int32_t offset);
+    int32_t YSubscriptYOffset();
+    void SetYSubscriptYOffset(int32_t offset);
+    int32_t YSuperscriptXSize();
+    void SetYSuperscriptXSize(int32_t size);
+    int32_t YSuperscriptYSize();
+    void SetYSuperscriptYSize(int32_t size);
+    int32_t YSuperscriptXOffset();
+    void SetYSuperscriptXOffset(int32_t offset);
+    int32_t YSuperscriptYOffset();
+    void SetYSuperscriptYOffset(int32_t offset);
+    int32_t YStrikeoutSize();
+    void SetYStrikeoutSize(int32_t size);
+    int32_t YStrikeoutPosition();
+    void SetYStrikeoutPosition(int32_t position);
+    int32_t SFamilyClass();
+    void SetSFamilyClass(int32_t family);
+    void Panose(ByteVector* value);
+    void SetPanose(ByteVector* panose);
+    int64_t UlUnicodeRange1();
+    void SetUlUnicodeRange1(int64_t range);
+    int64_t UlUnicodeRange2();
+    void SetUlUnicodeRange2(int64_t range);
+    int64_t UlUnicodeRange3();
+    void SetUlUnicodeRange3(int64_t range);
+    int64_t UlUnicodeRange4();
+    void SetUlUnicodeRange4(int64_t range);
+    // UNIMPLEMENTED: EnumSet<UnicodeRange> UlUnicodeRange()
+    //                setUlUnicodeRange(EnumSet<UnicodeRange> rangeSet)
+    void AchVendId(ByteVector* b);
+    void SetAchVendId(ByteVector* b);
+    // UNIMPLEMENTED: public EnumSet<FsSelection> fsSelection()
+    int32_t FsSelection();
+    void SetFsSelection(int32_t fs_selection);
+    int32_t UsFirstCharIndex();
+    void SetUsFirstCharIndex(int32_t first_index);
+    int32_t UsLastCharIndex();
+    void SetUsLastCharIndex(int32_t last_index);
+    int32_t STypoAscender();
+    void SetSTypoAscender(int32_t ascender);
+    int32_t STypoDescender();
+    void SetSTypoDescender(int32_t descender);
+    int32_t STypoLineGap();
+    void SetSTypoLineGap(int32_t line_gap);
+    int32_t UsWinAscent();
+    void SetUsWinAscent(int32_t ascent);
+    int32_t UsWinDescent();
+    void SetUsWinDescent(int32_t descent);
+    int64_t UlCodePageRange1();
+    void SetUlCodePageRange1(int64_t range);
+    int64_t UlCodePageRange2();
+    void SetUlCodePageRange2(int64_t range);
+    // UNIMPLEMENTED: EnumSet<CodePageRange> ulCodePageRange()
+    //                void setUlCodePageRange(EnumSet<CodePageRange> rangeSet)
+    int32_t SxHeight();
+    void SetSxHeight(int32_t height);
+    int32_t SCapHeight();
+    void SetSCapHeight(int32_t height);
+    int32_t UsDefaultChar();
+    void SetUsDefaultChar(int32_t default_char);
+    int32_t UsBreakChar();
+    void SetUsBreakChar(int32_t break_char);
+    int32_t UsMaxContext();
+    void SetUsMaxContext(int32_t max_context);
   };
 
   ~OS2Table();
 
-  int32_t Version();
+  int32_t TableVersion();
   int32_t XAvgCharWidth();
   int32_t UsWeightClass();
   int32_t UsWidthClass();
@@ -348,7 +444,6 @@
   int64_t UlCodePageRange1();
   int64_t UlCodePageRange2();
   // UNIMPLEMENTED: public EnumSet<CodePageRange> ulCodePageRange()
-  int64_t UlCodePageRange();
   int32_t SxHeight();
   int32_t SCapHeight();
   int32_t UsDefaultChar();
@@ -375,11 +470,13 @@
       kYStrikeoutPosition = 28,
       kSFamilyClass = 30,
       kPanose = 32,
+      kPanoseLength = 10,  // Length of panose bytes.
       kUlUnicodeRange1 = 42,
       kUlUnicodeRange2 = 46,
       kUlUnicodeRange3 = 50,
       kUlUnicodeRange4 = 54,
       kAchVendId = 58,
+      kAchVendIdLength = 4,  // Length of ach vend id bytes.
       kFsSelection = 62,
       kUsFirstCharIndex = 64,
       kUsLastCharIndex = 66,
diff --git a/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc
index 7be3f77..d662e42 100644
--- a/sfntly/table/font_data_table.cc
+++ b/sfntly/table/font_data_table.cc
@@ -34,23 +34,18 @@
   return data_;
 }
 
-int32_t FontDataTable::Length() {
-  return data_->Length();
-}
-
-int32_t FontDataTable::Padding() {
-  return -1;
-}
-
 int32_t FontDataTable::DataLength() {
-  int32_t paddings = Padding();
-  return (paddings == -1) ? Length() : Length() - paddings;
+  return data_->Length();
 }
 
 int32_t FontDataTable::Serialize(OutputStream* os) {
   return data_->CopyTo(os);
 }
 
+int32_t FontDataTable::Serialize(WritableFontData* data) {
+  return data_->CopyTo(data);
+}
+
 /******************************************************************************
  * FontDataTable::Builder class
  ******************************************************************************/
@@ -61,11 +56,12 @@
       return NULL;
     }
     int32_t size = SubDataSizeToSerialize();
-    new_data.Attach(container_->GetNewData(size));
+    new_data.Attach(WritableFontData::CreateWritableFontData(size));
     SubSerialize(new_data);
   } else {
     ReadableFontDataPtr data = InternalReadData();
-    new_data.Attach(container_->GetNewData(data != NULL ? data->Length() : 0));
+    new_data.Attach(WritableFontData::CreateWritableFontData(
+                        data != NULL ? data->Length() : 0));
     data->CopyTo(new_data);
   }
   return new_data.Detach();
@@ -85,7 +81,7 @@
     }
     int32_t size = SubDataSizeToSerialize();
     WritableFontDataPtr new_data;
-    new_data.Attach(container_->GetNewData(size));
+    new_data.Attach(WritableFontData::CreateWritableFontData(size));
     SubSerialize(new_data);
     data = new_data;
   }
@@ -111,43 +107,32 @@
 WritableFontData* FontDataTable::Builder::InternalWriteData() {
   if (w_data_ == NULL) {
     WritableFontDataPtr new_data;
-    new_data.Attach(container_->GetNewData(r_data_->Length()));
-    r_data_->CopyTo(new_data);
+    new_data.Attach(WritableFontData::CreateWritableFontData(
+                        r_data_ == NULL ? 0 : r_data_->Length()));
+    if (r_data_) {
+      r_data_->CopyTo(new_data);
+    }
     InternalSetData(new_data, false);
   }
   return w_data_.p_;
 }
 
-CALLER_ATTACH WritableFontData*
-    FontDataTable::Builder::InternalNewData(int32_t size) {
-  return container_->GetNewData(size);
+FontDataTable::Builder::Builder() {
 }
 
-FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container) {
-  Init(container);
-}
-
-FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container,
-                                WritableFontData* data) {
-  Init(container);
+FontDataTable::Builder::Builder(WritableFontData* data)
+    : model_changed_(false), data_changed_(false) {
   w_data_ = data;
 }
 
-FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container,
-                                ReadableFontData* data) {
-  Init(container);
+FontDataTable::Builder::Builder(ReadableFontData* data)
+    : model_changed_(false), data_changed_(false) {
   r_data_ = data;
 }
 
 FontDataTable::Builder::~Builder() {
 }
 
-void FontDataTable::Builder::Init(FontDataTableBuilderContainer* container) {
-  container_ = container;
-  model_changed_ = false;
-  data_changed_ = false;
-}
-
 void FontDataTable::Builder::NotifyPostTableBuild(FontDataTable* table) {
   // Default: NOP.
   UNREFERENCED_PARAMETER(table);
diff --git a/sfntly/table/font_data_table.h b/sfntly/table/font_data_table.h
index a2b026f..ce5433b 100644
--- a/sfntly/table/font_data_table.h
+++ b/sfntly/table/font_data_table.h
@@ -18,11 +18,13 @@
 #define SFNTLY_CPP_SRC_SFNTLY_TABLE_FONT_DATA_TABLE_H_
 
 #include "sfntly/data/readable_font_data.h"
-#include "sfntly/font_data_table_builder_container.h"
+#include "sfntly/data/writable_font_data.h"
 #include "sfntly/port/refcount.h"
 
 namespace sfntly {
 
+// An abstract base for any table that contains a FontData. This is the root of
+// the table class hierarchy.
 class FontDataTable : virtual public RefCount {
  public:
   // Note: original version is abstract Builder<T extends FontDataTable>
@@ -45,10 +47,14 @@
 
     ReadableFontData* InternalReadData();
     WritableFontData* InternalWriteData();
-    CALLER_ATTACH WritableFontData* InternalNewData(int32_t size);
 
     bool data_changed() { return data_changed_; }
-    bool model_changed() { return model_changed_; }
+    bool model_changed() {
+      return current_model_changed() || contained_model_changed();
+    }
+    bool current_model_changed() { return model_changed_; }
+    bool contained_model_changed() { return contained_model_changed_; }
+
     bool set_model_changed() { return set_model_changed(true); }
     bool set_model_changed(bool changed) {
       bool old = model_changed_;
@@ -57,13 +63,11 @@
     }
 
    protected:
-    explicit Builder(FontDataTableBuilderContainer* container);
-    Builder(FontDataTableBuilderContainer* container, WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* container, ReadableFontData* data);
+    explicit Builder();
+    Builder(WritableFontData* data);
+    Builder(ReadableFontData* data);
     virtual ~Builder();
 
-    void Init(FontDataTableBuilderContainer* container);
-
     // subclass API
     virtual void NotifyPostTableBuild(FontDataTable* table);
     virtual int32_t SubSerialize(WritableFontData* new_data) = 0;
@@ -77,10 +81,10 @@
     void InternalSetData(WritableFontData* data, bool data_changed);
     void InternalSetData(ReadableFontData* data, bool data_changed);
 
-    FontDataTableBuilderContainer* container_;  // avoid circular ref-counting
     WritableFontDataPtr w_data_;
     ReadableFontDataPtr r_data_;
     bool model_changed_;
+    bool contained_model_changed_;  // may expand to list of submodel states
     bool data_changed_;
   };
 
@@ -91,21 +95,15 @@
   ReadableFontData* ReadFontData();
 
   // Get the length of the data for this table in bytes. This is the full
-  // allocated length of the data and may or may not include any padding.
-  virtual int32_t Length();
-
-  // Get the number of bytes of padding used in the table. The padding bytes are
-  // used to align the table length to a 4 byte boundary.
-  virtual int32_t Padding();
-
-  // Return the number of bytes of non-padded data in the table. If the padding
-  // is unknown or unknowable then the total number of bytes of data in the
-  // tables is returned.
+  // allocated length of the data underlying the table and may or may not
+  // include any padding.
   virtual int32_t DataLength();
 
   virtual int32_t Serialize(OutputStream* os);
 
  protected:
+  virtual int32_t Serialize(WritableFontData* data);
+
   // TODO(arthurhsu): style guide violation: protected member, need refactoring
   ReadableFontDataPtr data_;
 };
diff --git a/sfntly/table/subtable.cc b/sfntly/table/subtable.cc
index 4869a97..d70b18c 100644
--- a/sfntly/table/subtable.cc
+++ b/sfntly/table/subtable.cc
@@ -23,7 +23,7 @@
 SubTable::~SubTable() {}
 
 SubTable::SubTable(ReadableFontData* data)
-    : FontDataTable(data) {
+    : FontDataTable(data), padding_(0) {
 }
 
 /******************************************************************************
@@ -31,14 +31,12 @@
  ******************************************************************************/
 SubTable::Builder::~Builder() {}
 
-SubTable::Builder::Builder(FontDataTableBuilderContainer* container,
-                           WritableFontData* data)
-    : FontDataTable::Builder(container, data) {
+SubTable::Builder::Builder(WritableFontData* data)
+    : FontDataTable::Builder(data) {
 }
 
-SubTable::Builder::Builder(FontDataTableBuilderContainer* container,
-                           ReadableFontData* data)
-    : FontDataTable::Builder(container, data) {
+SubTable::Builder::Builder(ReadableFontData* data)
+    : FontDataTable::Builder(data) {
 }
 
 }  // namespace sfntly
diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h
index c542881..e5ec748 100644
--- a/sfntly/table/subtable.h
+++ b/sfntly/table/subtable.h
@@ -32,16 +32,22 @@
     virtual ~Builder();
 
    protected:
-    Builder(FontDataTableBuilderContainer* container, WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* container, ReadableFontData* data);
+    Builder(WritableFontData* data);
+    Builder(ReadableFontData* data);
   };
 
   virtual ~SubTable();
 
+  int32_t padding() { return padding_; }
+  void set_padding(int32_t padding) { padding_ = padding; }
+
  protected:
   // Note: constructor refactored in C++ to avoid heavy lifting.
   //       caller need to do data->Slice(offset, length) beforehand.
   explicit SubTable(ReadableFontData* data);
+
+ private:
+  int32_t padding_;
 };
 
 }  // namespace sfntly
diff --git a/sfntly/table/subtable_container_table.h b/sfntly/table/subtable_container_table.h
new file mode 100644
index 0000000..e77ebbb
--- /dev/null
+++ b/sfntly/table/subtable_container_table.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_
+#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_
+
+#include "sfntly/table/table.h"
+
+namespace sfntly {
+
+class SubTableContainerTable : public Table {
+ public:
+  class Builder : public Table::Builder {
+   public:
+    Builder(Header* header, WritableFontData* data)
+        : Table::Builder(header, data) {
+    }
+
+    Builder(Header* header, ReadableFontData* data)
+        : Table::Builder(header, data) {
+    }
+
+    virtual ~Builder() {}
+  };
+
+  SubTableContainerTable(Header* header, ReadableFontData* data)
+      : Table(header, data) {
+  }
+
+  virtual ~SubTableContainerTable() {}
+};
+
+}  // namespace sfntly
+
+#endif  // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_
\ No newline at end of file
diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc
index 568f889..10276aa 100644
--- a/sfntly/table/table.cc
+++ b/sfntly/table/table.cc
@@ -39,10 +39,6 @@
   return data_->Checksum();
 }
 
-WritableFontData* Table::GetNewData(int32_t size) {
-  return font_->GetNewData(size);
-}
-
 void Table::SetFont(Font* font) {
   font_ = font;
 }
@@ -58,8 +54,9 @@
 Table::Header::Header(int32_t tag)
     : tag_(tag),
       offset_(0),
-      length_(0),
       offset_valid_(false),
+      length_(0),
+      length_valid_(false),
       checksum_(0),
       checksum_valid_(false) {
 }
@@ -67,8 +64,9 @@
 Table::Header::Header(int32_t tag, int32_t length)
     : tag_(tag),
       offset_(0),
-      length_(length),
       offset_valid_(false),
+      length_(length),
+      length_valid_(true),
       checksum_(0),
       checksum_valid_(false) {
 }
@@ -79,19 +77,25 @@
                       int32_t length)
     : tag_(tag),
       offset_(offset),
-      length_(length),
       offset_valid_(true),
+      length_(length),
+      length_valid_(true),
       checksum_(checksum),
       checksum_valid_(true) {
 }
 
 Table::Header::~Header() {}
 
-bool TableHeaderComparator::operator() (const TableHeaderPtr lhs,
-                                        const TableHeaderPtr rhs) {
+bool HeaderComparatorByOffset::operator() (const TableHeaderPtr lhs,
+                                           const TableHeaderPtr rhs) {
   return lhs->offset_ > rhs->offset_;
 }
 
+bool HeaderComparatorByTag::operator() (const TableHeaderPtr lhs,
+                                        const TableHeaderPtr rhs) {
+  return lhs->tag_ > rhs->tag_;
+}
+
 /******************************************************************************
  * Table::Builder class
  ******************************************************************************/
@@ -102,91 +106,77 @@
 void Table::Builder::NotifyPostTableBuild(FontDataTable* table) {
   if (model_changed() || data_changed()) {
     Table* derived_table = down_cast<Table*>(table);
-    header_ = new Header(header()->tag(),
-                         derived_table->ReadFontData()->Length());
+    derived_table->header_ = new Header(header()->tag(),
+                                        derived_table->DataLength());
   }
 }
 
-WritableFontData* Table::Builder::GetNewData(int32_t size) {
-  UNREFERENCED_PARAMETER(size);
-  return InternalWriteData();
-}
-
-CALLER_ATTACH Table::Builder*
-    Table::Builder::GetBuilder(FontDataTableBuilderContainer* font_builder,
-                               Header* header,
-                               WritableFontData* table_data) {
+CALLER_ATTACH
+Table::Builder* Table::Builder::GetBuilder(Header* header,
+                                           WritableFontData* table_data) {
   int32_t tag = header->tag();
-  TableBuilderPtr builder;
   Table::Builder* builder_raw = NULL;
 
   // Note: Tables are commented out when they are not used/ported.
   // TODO(arthurhsu): IMPLEMENT: finish tables that are not ported.
   /*if (tag == Tag::cmap) {
     builder_raw = static_cast<Table::Builder*>(
-        new CMapTable::Builder(font_builder, header, table_data));
+        CMapTable::CreateBuilder(font_builder, header, table_data));
   } else*/ if (tag == Tag::head) {
     builder_raw = static_cast<Table::Builder*>(
-        new FontHeaderTable::Builder(font_builder, header, table_data));
+        FontHeaderTable::Builder::CreateBuilder(header, table_data));
   } else if (tag == Tag::hhea) {
     builder_raw = static_cast<Table::Builder*>(
-        new HorizontalHeaderTable::Builder(font_builder, header, table_data));
+        HorizontalHeaderTable::Builder::CreateBuilder(header, table_data));
   } else if (tag == Tag::hmtx) {
     builder_raw = static_cast<Table::Builder*>(
-        new HorizontalMetricsTable::Builder(font_builder, header, table_data));
+        HorizontalMetricsTable::Builder::CreateBuilder(header, table_data));
   } else if (tag == Tag::maxp) {
     builder_raw = static_cast<Table::Builder*>(
-        new MaximumProfileTable::Builder(font_builder, header, table_data));
+        MaximumProfileTable::Builder::CreateBuilder(header, table_data));
   } else if (tag == Tag::name) {
     builder_raw = static_cast<Table::Builder*>(
-        new NameTable::Builder(font_builder, header, table_data));
+        NameTable::Builder::CreateBuilder(header, table_data));
   } else if (tag == Tag::OS_2) {
     builder_raw = static_cast<Table::Builder*>(
-        new OS2Table::Builder(font_builder, header, table_data));
+        OS2Table::Builder::CreateBuilder(header, table_data));
   }/* else if (tag == Tag::PostScript) {
     builder_raw = static_cast<Table::Builder*>(
-        new PostScriptTable::Builder(font_builder, header, table_data));
+        PostScriptTable::Builder::CreateBuilder(header, table_data));
   } else if (tag == Tag::cvt) {
     builder_raw = static_cast<Table::Builder*>(
-        new ControlValueTable::Builder(font_builder, header, table_data));
+        ControlValueTable::Builder::CreateBuilder(header, table_data));
   }*/ else if (tag == Tag::glyf) {
     builder_raw = static_cast<Table::Builder*>(
-        new GlyphTable::Builder(font_builder, header, table_data));
+        GlyphTable::Builder::CreateBuilder(header, table_data));
   } else if (tag == Tag::loca) {
     builder_raw = static_cast<Table::Builder*>(
-        new LocaTable::Builder(font_builder, header, table_data));
+        LocaTable::Builder::CreateBuilder(header, table_data));
   }/* else if (tag == Tag::prep) {
     builder_raw = static_cast<Table::Builder*>(
-        new ControlProgramTable::Builder(font_builder, header, table_data));
+        ControlProgramTable::Builder::CreateBuilder(header, table_data));
   }*/ else if (tag == Tag::bhed) {
     builder_raw = static_cast<Table::Builder*>(
-        new FontHeaderTable::Builder(font_builder, header, table_data));
+        FontHeaderTable::Builder::CreateBuilder(header, table_data));
   } else {
     builder_raw = static_cast<Table::Builder*>(
-        new Table::GenericTableBuilder(font_builder, header, table_data));
+        Table::GenericTableBuilder::CreateBuilder(header, table_data));
   }
 
-  builder = builder_raw;
-  return builder.Detach();
+  return builder_raw;
 }
 
-Table::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                        Header* header,
-                        WritableFontData* data)
-    : FontDataTable::Builder(font_builder, data) {
+Table::Builder::Builder(Header* header, WritableFontData* data)
+    : FontDataTable::Builder(data) {
   header_ = header;
 }
 
-Table::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                        Header* header,
-                        ReadableFontData* data)
-    : FontDataTable::Builder(font_builder, data) {
+Table::Builder::Builder(Header* header, ReadableFontData* data)
+    : FontDataTable::Builder(data) {
   header_ = header;
 }
 
-Table::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                        Header* header)
-    : FontDataTable::Builder(font_builder) {
+Table::Builder::Builder(Header* header) {
   header_ = header;
 }
 
@@ -212,24 +202,23 @@
   table_ = NULL;
 }
 
-Table::TableBasedTableBuilder::TableBasedTableBuilder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    WritableFontData* data)
-    : Builder(font_builder, header, data) {
+CALLER_ATTACH FontDataTable* Table::TableBasedTableBuilder::Build() {
+  FontDataTablePtr table = static_cast<FontDataTable*>(GetTable());
+  return table.Detach();
 }
 
-Table::TableBasedTableBuilder::TableBasedTableBuilder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    ReadableFontData* data)
-    : Builder(font_builder, header, data) {
+Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header,
+                                                      WritableFontData* data)
+    : Builder(header, data) {
 }
 
-Table::TableBasedTableBuilder::TableBasedTableBuilder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header)
-    : Builder(font_builder, header) {
+Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header,
+                                                      ReadableFontData* data)
+    : Builder(header, data) {
+}
+
+Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header)
+    : Builder(header) {
 }
 
 Table* Table::TableBasedTableBuilder::GetTable() {
@@ -242,11 +231,9 @@
 /******************************************************************************
  * Table::GenericTableBuilder class
  ******************************************************************************/
-Table::GenericTableBuilder::GenericTableBuilder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    WritableFontData* data)
-    : TableBasedTableBuilder(font_builder, header, data) {
+Table::GenericTableBuilder::GenericTableBuilder(Header* header,
+                                                WritableFontData* data)
+    : TableBasedTableBuilder(header, data) {
 }
 
 CALLER_ATTACH FontDataTable*
@@ -257,23 +244,12 @@
   return table.Detach();
 }
 
-/******************************************************************************
- * Table::ArrayElementTableBuilder class
- ******************************************************************************/
-Table::ArrayElementTableBuilder::~ArrayElementTableBuilder() {}
-
-Table::ArrayElementTableBuilder::ArrayElementTableBuilder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    WritableFontData* data)
-    : Builder(font_builder, header, data) {
-}
-
-Table::ArrayElementTableBuilder::ArrayElementTableBuilder(
-    FontDataTableBuilderContainer* font_builder,
-    Header* header,
-    ReadableFontData* data)
-    : Builder(font_builder, header, data) {
+CALLER_ATTACH Table::GenericTableBuilder*
+    Table::GenericTableBuilder::CreateBuilder(Header* header,
+                                              WritableFontData* data) {
+  Ptr<Table::GenericTableBuilder> builder =
+      new Table::GenericTableBuilder(header, data);
+  return builder.Detach();
 }
 
 }  // namespace sfntly
diff --git a/sfntly/table/table.h b/sfntly/table/table.h
index 8c8fcc8..5adbfb1 100644
--- a/sfntly/table/table.h
+++ b/sfntly/table/table.h
@@ -27,61 +27,91 @@
 
 namespace sfntly {
 class Font;
-class Table : public FontDataTable, public FontDataTableBuilderContainer {
+
+// A concrete implementation of a root level table in the font. This is the base
+// class used for all specific table implementations and is used as the generic
+// table for all tables which have no specific implementations.
+class Table : public FontDataTable {
  public:
   class Header : public RefCounted<Header> {
    public:
+    // Make a partial header with only the basic info for an empty new table.
     explicit Header(int32_t tag);
+
+    // Make a partial header with only the basic info for a new table.
     Header(int32_t tag, int32_t length);
+
+    // Make a full header as read from an existing font.
     Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length);
     virtual ~Header();
 
+    // Get the table tag.
     int32_t tag() { return tag_; }
+
+    // Get the table offset. The offset is from the start of the font file.
     int32_t offset() { return offset_; }
-    int32_t length() { return length_; }
+
+    // Is the offset in the header valid. The offset will not be valid if the
+    // table was constructed during building and has no physical location in a
+    // font file.
     bool offset_valid() { return offset_valid_; }
+
+    // Get the length of the table as recorded in the table record header.
+    int32_t length() { return length_; }
+
+    // Is the length in the header valid. The length will not be valid if the
+    // table was constructed during building and has no physical location in a
+    // font file.
+    bool length_valid() { return length_valid_; }
+
+    // Get the checksum for the table as recorded in the table record header.
     int64_t checksum() { return checksum_; }
+
+    // Is the checksum valid. The checksum will not be valid if the table was
+    // constructed during building and has no physical location in a font file.
+    // Note that this does *NOT* check the validity of the checksum against
+    // the calculated checksum for the table data.
     bool checksum_valid() { return checksum_valid_; }
 
+    // UNIMPLEMENTED: boolean equals(Object obj)
+    //                int hashCode()
+    //                string toString()
+
    private:
     int32_t tag_;
     int32_t offset_;
-    int32_t length_;
     bool offset_valid_;
+    int32_t length_;
+    bool length_valid_;
     int64_t checksum_;
     bool checksum_valid_;
 
-    friend class TableHeaderComparator;
+    friend class HeaderComparatorByOffset;
+    friend class HeaderComparatorByTag;
   };
 
   // Note: original version is Builder<T extends Table>
   //       C++ template is not designed that way so plain old inheritance is
   //       chosen.
-  class Builder : public FontDataTable::Builder,
-                  public FontDataTableBuilderContainer {
+  class Builder : public FontDataTable::Builder {
    public:
     virtual ~Builder();
     virtual Header* header() { return header_; }
     virtual void NotifyPostTableBuild(FontDataTable* table);
-    virtual WritableFontData* GetNewData(int32_t size);
 
-    static CALLER_ATTACH Builder*
-        GetBuilder(FontDataTableBuilderContainer* font_builder,
-                   Header* header,
-                   WritableFontData* table_data);
+    // Get a builder for the table type specified by the data in the header.
+    // @param header the header for the table
+    // @param tableData the data to be used to build the table from
+    // @return builder for the table specified
+    static CALLER_ATTACH Builder* GetBuilder(Header* header,
+                                             WritableFontData* table_data);
+
+    // UNIMPLEMENTED: toString()
 
    protected:
-    // Note: original version is Font.Builder font_builder. This results in
-    //       mutual inclusion happiness that Java solved for C++.  Therefore,
-    //       we need to avoid that happiness when we port it to C++.
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            ReadableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
+    Builder(Header* header);
 
    private:
     Ptr<Header> header_;
@@ -95,16 +125,12 @@
     virtual bool SubReadyToSerialize();
     virtual int32_t SubDataSizeToSerialize();
     virtual void SubDataSet();
+    virtual CALLER_ATTACH FontDataTable* Build();
 
    protected:
-    TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder,
-                           Header* header,
-                           WritableFontData* data);
-    TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder,
-                           Header* header,
-                           ReadableFontData* data);
-    TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder,
-                           Header* header);
+    TableBasedTableBuilder(Header* header, WritableFontData* data);
+    TableBasedTableBuilder(Header* header, ReadableFontData* data);
+    TableBasedTableBuilder(Header* header);
 
     // C++ port: renamed table() to GetTable()
     virtual Table* GetTable();
@@ -116,33 +142,36 @@
   class GenericTableBuilder : public TableBasedTableBuilder,
                               public RefCounted<GenericTableBuilder> {
    public:
-    GenericTableBuilder(FontDataTableBuilderContainer* font_builder,
-                        Header* header,
-                        WritableFontData* data);
+    GenericTableBuilder(Header* header, WritableFontData* data);
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
-  };
 
-  class ArrayElementTableBuilder : public Builder {
-   public:
-    virtual ~ArrayElementTableBuilder();
-
-   protected:
-    ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder,
-                             Header* header,
-                             WritableFontData* data);
-    ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder,
-                             Header* header,
-                             ReadableFontData* data);
+    static CALLER_ATTACH
+           GenericTableBuilder* CreateBuilder(Header* header,
+                                              WritableFontData* data);
   };
 
   virtual ~Table();
+
+  // Get the calculated checksum for the data in the table.
   virtual int64_t CalculatedChecksum();
+
+  // Get the header for the table.
   virtual Header* header()          { return header_; }
+
+  // Get the tag for the table from the record header.
   virtual int32_t header_tag()      { return header_->tag(); }
+
+  // Get the offset for the table from the record header.
   virtual int32_t header_offset()   { return header_->offset(); }
+
+  // Get the length of the table from the record header.
   virtual int32_t header_length()   { return header_->length(); }
+
+  // Get the checksum for the table from the record header.
   virtual int64_t header_checksum() { return header_->checksum(); }
-  virtual WritableFontData* GetNewData(int32_t size);
+
+  // UNIMPLEMENTED: toString()
+
   virtual void SetFont(Font* font);
 
  protected:
@@ -172,11 +201,31 @@
 typedef std::map<int32_t, TableBuilderPtr> TableBuilderMap;
 typedef std::pair<int32_t, TableBuilderPtr> TableBuilderEntry;
 
-class TableHeaderComparator {
+class HeaderComparator {
  public:
-  bool operator()(const TableHeaderPtr h1, const TableHeaderPtr h2);
+  virtual ~HeaderComparator() {}
+  virtual bool operator()(const TableHeaderPtr h1,
+                          const TableHeaderPtr h2) = 0;
 };
-typedef std::set<TableHeaderPtr, TableHeaderComparator> TableHeaderSortedSet;
+
+class HeaderComparatorByOffset : public HeaderComparator {
+ public:
+  virtual ~HeaderComparatorByOffset() {}
+  virtual bool operator()(const TableHeaderPtr h1,
+                          const TableHeaderPtr h2);
+};
+
+class HeaderComparatorByTag : public HeaderComparator {
+ public:
+  virtual ~HeaderComparatorByTag() {}
+  virtual bool operator()(const TableHeaderPtr h1,
+                          const TableHeaderPtr h2);
+};
+
+typedef std::set<TableHeaderPtr, HeaderComparatorByOffset>
+        HeaderOffsetSortedSet;
+typedef std::set<TableHeaderPtr, HeaderComparatorByTag>
+        HeaderTagSortedSet;
 
 }  // namespace sfntly
 
diff --git a/sfntly/table/truetype/glyph_table.cc b/sfntly/table/truetype/glyph_table.cc
index ff289f3..dc1163a 100644
--- a/sfntly/table/truetype/glyph_table.cc
+++ b/sfntly/table/truetype/glyph_table.cc
@@ -52,20 +52,18 @@
 }
 
 GlyphTable::Glyph* GlyphTable::GetGlyph(int32_t offset, int32_t length) {
-  return GlyphTable::Glyph::GetGlyph(data_, offset, length);
+  return GlyphTable::Glyph::GetGlyph(this, this->data_, offset, length);
 }
 
 GlyphTable::GlyphTable(Header* header, ReadableFontData* data)
-    : Table(header, data) {
+    : SubTableContainerTable(header, data) {
 }
 
 /******************************************************************************
  * GlyphTable::Builder class
  ******************************************************************************/
-GlyphTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                             Header* header,
-                             WritableFontData* data)
-    : Table::ArrayElementTableBuilder(font_builder, header, data) {
+GlyphTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : SubTableContainerTable::Builder(header, data) {
 }
 
 GlyphTable::Builder::~Builder() {
@@ -96,6 +94,13 @@
   }
 }
 
+CALLER_ATTACH GlyphTable::Builder*
+    GlyphTable::Builder::CreateBuilder(Header* header, WritableFontData* data) {
+  Ptr<GlyphTable::Builder> builder;
+  builder = new GlyphTable::Builder(header, data);
+  return builder.Detach();
+}
+
 GlyphTable::GlyphBuilderList* GlyphTable::Builder::GlyphBuilders() {
   return GetGlyphBuilders();
 }
@@ -157,12 +162,11 @@
                                      const IntegerList& loca) {
   if (data != NULL) {
     if (loca_.empty()) {
-#if defined (SFNTLY_NO_EXCEPTION)
-      return;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
       throw IllegalStateException(
           "Loca values not set - unable to parse glyph data.");
 #endif
+      return;
     }
     int32_t loca_value;
     int32_t last_loca_value = loca[0];
@@ -199,9 +203,11 @@
 GlyphTable::Glyph::~Glyph() {}
 
 CALLER_ATTACH GlyphTable::Glyph*
-    GlyphTable::Glyph::GetGlyph(ReadableFontData* data,
+    GlyphTable::Glyph::GetGlyph(GlyphTable* table,
+                                ReadableFontData* data,
                                 int32_t offset,
                                 int32_t length) {
+  UNREFERENCED_PARAMETER(table);
   int32_t type = GlyphType(data, offset, length);
   GlyphPtr glyph;
 
@@ -239,10 +245,6 @@
   return data_->ReadShort(Offset::kYMax);
 }
 
-int32_t GlyphTable::Glyph::Padding() {
-  return padding_;
-}
-
 GlyphTable::Glyph::Glyph(ReadableFontData* data, int32_t glyph_type)
     : SubTable(data),
       glyph_type_(glyph_type) {
@@ -273,38 +275,36 @@
 GlyphTable::Glyph::Builder::~Builder() {
 }
 
-GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                                    WritableFontData* data)
-    : SubTable::Builder(font_builder, data) {
+GlyphTable::Glyph::Builder::Builder(WritableFontData* data)
+    : SubTable::Builder(data) {
 }
 
-GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                                    ReadableFontData* data)
-    : SubTable::Builder(font_builder, data) {
+GlyphTable::Glyph::Builder::Builder(ReadableFontData* data)
+    : SubTable::Builder(data) {
 }
 
 CALLER_ATTACH GlyphTable::Glyph::Builder*
     GlyphTable::Glyph::Builder::GetBuilder(
-        FontDataTableBuilderContainer* table_builder,
+        GlyphTable::Builder* table_builder,
         ReadableFontData* data) {
   return GetBuilder(table_builder, data, 0, data->Length());
 }
 
 CALLER_ATTACH GlyphTable::Glyph::Builder*
     GlyphTable::Glyph::Builder::GetBuilder(
-        FontDataTableBuilderContainer* table_builder,
+        GlyphTable::Builder* table_builder,
         ReadableFontData* data,
         int32_t offset,
         int32_t length) {
+  UNREFERENCED_PARAMETER(table_builder);
   int32_t type = Glyph::GlyphType(data, offset, length);
   GlyphBuilderPtr builder;
   ReadableFontDataPtr sliced_data;
   sliced_data.Attach(down_cast<ReadableFontData*>(data->Slice(offset, length)));
   if (type == GlyphType::kSimple) {
-    builder = new SimpleGlyph::SimpleGlyphBuilder(table_builder, sliced_data);
+    builder = new SimpleGlyph::SimpleGlyphBuilder(sliced_data);
   } else {
-    builder = new CompositeGlyph::CompositeGlyphBuilder(table_builder,
-                                                        sliced_data);
+    builder = new CompositeGlyph::CompositeGlyphBuilder(sliced_data);
   }
   return builder.Detach();
 }
@@ -411,7 +411,7 @@
     (flag_byte_count_ * DataSize::kBYTE) +
     (x_byte_count_ * DataSize::kBYTE) +
     (y_byte_count_ * DataSize::kBYTE);
-  padding_ = Length() - non_padded_data_length;
+  set_padding(DataLength() - non_padded_data_length);
   initialized_ = true;
 }
 
@@ -505,15 +505,13 @@
 }
 
 GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder(
-    FontDataTableBuilderContainer* table_builder,
     WritableFontData* data)
-    : Glyph::Builder(table_builder, data) {
+    : Glyph::Builder(data) {
 }
 
 GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder(
-    FontDataTableBuilderContainer* table_builder,
     ReadableFontData* data)
-    : Glyph::Builder(table_builder, data) {
+    : Glyph::Builder(data) {
 }
 
 CALLER_ATTACH FontDataTable*
@@ -635,7 +633,7 @@
       instructions_offset_ = index;
       non_padded_data_length = index + (instruction_size_ * DataSize::kBYTE);
     }
-    padding_ = Length() - non_padded_data_length;
+    set_padding(DataLength() - non_padded_data_length);
   }
 }
 
@@ -646,15 +644,13 @@
 }
 
 GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder(
-    FontDataTableBuilderContainer* table_builder,
     WritableFontData* data)
-    : Glyph::Builder(table_builder, data) {
+    : Glyph::Builder(data) {
 }
 
 GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder(
-    FontDataTableBuilderContainer* table_builder,
     ReadableFontData* data)
-    : Glyph::Builder(table_builder, data) {
+    : Glyph::Builder(data) {
 }
 
 CALLER_ATTACH FontDataTable*
diff --git a/sfntly/table/truetype/glyph_table.h b/sfntly/table/truetype/glyph_table.h
index 320c522..3ba9cac 100644
--- a/sfntly/table/truetype/glyph_table.h
+++ b/sfntly/table/truetype/glyph_table.h
@@ -21,6 +21,7 @@
 
 #include "sfntly/table/table.h"
 #include "sfntly/table/subtable.h"
+#include "sfntly/table/subtable_container_table.h"
 
 namespace sfntly {
 
@@ -31,10 +32,8 @@
   };
 };
 
-// Note: due to the complexity of this class, the order of declaration is
-//       different from its Java counter part.  GlyphTable::Glyph is defined
-//       before GlyphTable::Builder to avoid compilation errors.
-class GlyphTable : public Table, public RefCounted<GlyphTable> {
+class GlyphTable : public SubTableContainerTable,
+                   public RefCounted<GlyphTable> {
  public:
   class Builder;
   class Glyph : public SubTable {
@@ -54,16 +53,14 @@
       // Incoming table_builder is GlyphTable::Builder*.
       // Note: constructor refactored in C++ to avoid heavy lifting.
       //       caller need to do data->Slice(offset, length) beforehand.
-      Builder(FontDataTableBuilderContainer* table_builder,
-              WritableFontData* data);
-      Builder(FontDataTableBuilderContainer* table_builder,
-              ReadableFontData* data);
+      Builder(WritableFontData* data);
+      Builder(ReadableFontData* data);
 
       static CALLER_ATTACH Builder*
-          GetBuilder(FontDataTableBuilderContainer* table_builder,
+          GetBuilder(GlyphTable::Builder* table_builder,
                      ReadableFontData* data);
       static CALLER_ATTACH Builder*
-          GetBuilder(FontDataTableBuilderContainer* table_builder,
+          GetBuilder(GlyphTable::Builder* table_builder,
                      ReadableFontData* data,
                      int32_t offset,
                      int32_t length);
@@ -78,7 +75,8 @@
     };
 
     virtual ~Glyph();
-    static CALLER_ATTACH Glyph* GetGlyph(ReadableFontData* data,
+    static CALLER_ATTACH Glyph* GetGlyph(GlyphTable* table,
+                                         ReadableFontData* data,
                                          int32_t offset,
                                          int32_t length);
     virtual int32_t GlyphType();
@@ -87,7 +85,6 @@
     virtual int32_t XMax();
     virtual int32_t YMin();
     virtual int32_t YMax();
-    virtual int32_t Padding();  // override FontDataTable::Padding()
 
     virtual int32_t InstructionSize() = 0;
     virtual ReadableFontData* Instructions() = 0;
@@ -97,9 +94,6 @@
     //       caller need to do data->Slice(offset, length) beforehand.
     Glyph(ReadableFontData* data, int32_t glyph_type);
 
-    // TODO(arthurhsu): violating C++ style guide, need refactoring.
-    int32_t padding_;
-
    private:
     static int32_t GlyphType(ReadableFontData* data,
                              int32_t offset,
@@ -111,18 +105,19 @@
   typedef Ptr<GlyphTable::Glyph::Builder> GlyphBuilderPtr;
   typedef std::vector<GlyphBuilderPtr> GlyphBuilderList;
 
-  class Builder : public Table::ArrayElementTableBuilder,
+  class Builder : public SubTableContainerTable::Builder,
                   public RefCounted<GlyphTable::Builder> {
    public:
     // Note: Constructor scope altered to public for base class to instantiate.
-    Builder(FontDataTableBuilderContainer* font_builder,
-            Header* header,
-            WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
 
     virtual void SetLoca(const IntegerList& loca);
     virtual void GenerateLocaList(IntegerList* locas);
 
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
+
     // Gets the List of glyph builders for the glyph table builder. These may be
     // manipulated in any way by the caller and the changes will be reflected in
     // the final glyph table produced.
@@ -178,10 +173,8 @@
      protected:
       // Note: constructor refactored in C++ to avoid heavy lifting.
       //       caller need to do data->Slice(offset, length) beforehand.
-      SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder,
-                         WritableFontData* data);
-      SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder,
-                         ReadableFontData* data);
+      SimpleGlyphBuilder(WritableFontData* data);
+      SimpleGlyphBuilder(ReadableFontData* data);
       virtual CALLER_ATTACH FontDataTable*
           SubBuildTable(ReadableFontData* data);
 
@@ -251,10 +244,8 @@
      protected:
       // Note: constructor refactored in C++ to avoid heavy lifting.
       //       caller need to do data->Slice(offset, length) beforehand.
-      CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder,
-                            WritableFontData* data);
-      CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder,
-                            ReadableFontData* data);
+      CompositeGlyphBuilder(WritableFontData* data);
+      CompositeGlyphBuilder(ReadableFontData* data);
 
       virtual CALLER_ATTACH FontDataTable*
           SubBuildTable(ReadableFontData* data);
diff --git a/sfntly/table/truetype/loca_table.cc b/sfntly/table/truetype/loca_table.cc
index 537e433..0a579ae 100644
--- a/sfntly/table/truetype/loca_table.cc
+++ b/sfntly/table/truetype/loca_table.cc
@@ -23,28 +23,22 @@
  ******************************************************************************/
 LocaTable::~LocaTable() {}
 
-int32_t LocaTable::NumGlyphs() {
-  return num_glyphs_;
-}
-
 int32_t LocaTable::GlyphOffset(int32_t glyph_id) {
   if (glyph_id < 0 || glyph_id >= num_glyphs_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException("Glyph ID is out of bounds.");
 #endif
+    return 0;
   }
   return Loca(glyph_id);
 }
 
 int32_t LocaTable::GlyphLength(int32_t glyph_id) {
   if (glyph_id < 0 || glyph_id >= num_glyphs_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException("Glyph ID is out of bounds.");
 #endif
+    return 0;
   }
   return Loca(glyph_id + 1) - Loca(glyph_id);
 }
@@ -55,27 +49,24 @@
 
 int32_t LocaTable::Loca(int32_t index) {
   if (index > num_glyphs_) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException();
 #endif
+    return 0;
   }
-  if (version_ == IndexToLocFormat::kShortOffset) {
+  if (format_version_ == IndexToLocFormat::kShortOffset) {
     return 2 * data_->ReadUShort(index * DataSize::kUSHORT);
   }
   return data_->ReadULongAsInt(index * DataSize::kULONG);
 }
 
-LocaTable::LocaTable(Header* header, ReadableFontData* data)
-    : Table(header, data) {
-}
-
 LocaTable::LocaTable(Header* header,
                      ReadableFontData* data,
-                     int32_t version,
+                     int32_t format_version,
                      int32_t num_glyphs)
-    : Table(header, data), version_(version), num_glyphs_(num_glyphs) {
+    : Table(header, data),
+      format_version_(format_version),
+      num_glyphs_(num_glyphs) {
 }
 
 /******************************************************************************
@@ -97,22 +88,26 @@
 /******************************************************************************
  * LocaTable::Builder class
  ******************************************************************************/
-LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                            Header* header, WritableFontData* data) :
-    Table::ArrayElementTableBuilder(font_builder, header, data) {
-  Init();
+LocaTable::Builder::Builder(Header* header, WritableFontData* data)
+    : Table::Builder(header, data),
+      format_version_(IndexToLocFormat::kLongOffset),
+      num_glyphs_(-1) {
 }
 
-LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder,
-                            Header* header, ReadableFontData* data) :
-    Table::ArrayElementTableBuilder(font_builder, header, data) {
-  Init();
+LocaTable::Builder::Builder(Header* header, ReadableFontData* data)
+    : Table::Builder(header, data),
+      format_version_(IndexToLocFormat::kLongOffset),
+      num_glyphs_(-1) {
 }
 
 LocaTable::Builder::~Builder() {}
 
-void LocaTable::Builder::SetFormatVersion(int32_t format_version) {
-  format_version_ = format_version;
+CALLER_ATTACH
+LocaTable::Builder* LocaTable::Builder::CreateBuilder(Header* header,
+                                                      WritableFontData* data) {
+  Ptr<LocaTable::Builder> builder;
+  builder = new LocaTable::Builder(header, data);
+  return builder.Detach();
 }
 
 IntegerList* LocaTable::Builder::LocaList() {
@@ -130,22 +125,20 @@
 
 int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) {
   if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException("Glyph ID is out of bounds.");
 #endif
+    return 0;
   }
   return Loca(glyph_id);
 }
 
 int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) {
   if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return 0;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw IndexOutOfBoundException("Glyph ID is out of bounds.");
 #endif
+    return 0;
   }
   return Loca(glyph_id + 1) - Loca(glyph_id);
 }
@@ -166,10 +159,6 @@
   set_model_changed(false);
 }
 
-void LocaTable::Builder::Clear() {
-  GetLocaList()->clear();
-}
-
 int32_t LocaTable::Builder::NumLocas() {
   return GetLocaList()->size();
 }
@@ -178,8 +167,8 @@
   return GetLocaList()->at(index);
 }
 
-CALLER_ATTACH FontDataTable* LocaTable::Builder::SubBuildTable(
-    ReadableFontData* data) {
+CALLER_ATTACH
+FontDataTable* LocaTable::Builder::SubBuildTable(ReadableFontData* data) {
   FontDataTablePtr table =
       new LocaTable(header(), data, format_version_, num_glyphs_);
   return table.Detach();
@@ -216,19 +205,13 @@
   return 0;
 }
 
-void LocaTable::Builder::Init() {
-  num_glyphs_ = -1;
-  format_version_ = IndexToLocFormat::kLongOffset;
-}
-
 void LocaTable::Builder::Initialize(ReadableFontData* data) {
   if (data) {
     if (NumGlyphs() < 0) {
-#if defined (SFNTLY_NO_EXCEPTION)
-      return;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
       throw IllegalStateException("numglyphs not set on LocaTable Builder.");
 #endif
+      return;
     }
     LocaTablePtr table =
         new LocaTable(header(), data, format_version_, num_glyphs_);
diff --git a/sfntly/table/truetype/loca_table.h b/sfntly/table/truetype/loca_table.h
index ce7fa44..0ec13bd 100644
--- a/sfntly/table/truetype/loca_table.h
+++ b/sfntly/table/truetype/loca_table.h
@@ -22,6 +22,7 @@
 
 namespace sfntly {
 
+// A Loca table - 'loca'.
 class LocaTable : public Table, public RefCounted<LocaTable> {
  public:
   // Note: different implementation than Java, caller to instantiate this class
@@ -37,24 +38,33 @@
     LocaTable* table_;  // use dumb pointer since it's a composition object
   };
 
-  class Builder : public Table::ArrayElementTableBuilder,
-                  public RefCounted<Builder> {
+  class Builder : public Table::Builder, public RefCounted<Builder> {
    public:
     // Constructor scope altered to public for base class to instantiate.
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            WritableFontData* data);
-    Builder(FontDataTableBuilderContainer* font_builder, Header* header,
-            ReadableFontData* data);
+    Builder(Header* header, WritableFontData* data);
+    Builder(Header* header, ReadableFontData* data);
     virtual ~Builder();
 
-    void SetFormatVersion(int32_t format_version);
+    static CALLER_ATTACH Builder* CreateBuilder(Header* header,
+                                                WritableFontData* data);
+
+    // Get the format version that will be used when the loca table is
+    // generated.
+    // @return the loca table format version
+    int32_t format_version() { return format_version_; }
+    void set_format_version(int32_t value) { format_version_ = value; }
 
     // Gets the List of locas for loca table builder. These may be manipulated
     // in any way by the caller and the changes will be reflected in the final
-    // loca table produced.
+    // loca table produced as long as no subsequent call is made to the
+    // SetLocaList(List) method.
     // If there is no current data for the loca table builder or the loca list
     // have not been previously set then this will return an empty List.
     IntegerList* LocaList();
+
+    // Set the list of locas to be used for building this table. If any existing
+    // list was already retrieved with the LocaList() method then the
+    // connection of that previous list to this builder will be broken.
     void SetLocaList(IntegerList* list);
 
     // Return the offset for the given glyph id. Valid glyph ids are from 0 to
@@ -75,15 +85,25 @@
     // to be called (and <b>must</b> be) when the raw data for this builder has
     // been changed.
     void SetNumGlyphs(int32_t num_glyphs);
+
+    // Get the number of glyphs that this builder has support for.
     int NumGlyphs();
 
+    // Revert the loca table builder to the state contained in the last raw data
+    // set on the builder. That raw data may be that read from a font file when
+    // the font builder was created, that set by a user of the loca table
+    // builder, or null data if this builder was created as a new empty builder.
     void Revert();
-    void Clear();
 
     // Get the number of locations or locas. This will be one more than the
     // number of glyphs for this table since the last loca position is used to
     // indicate the size of the final glyph.
     int32_t NumLocas();
+
+    // Get the value from the loca table for the index specified. These are the
+    // raw values from the table that are used to compute the offset and size of
+    // a glyph in the glyph table. Valid index values run from 0 to the number
+    // of glyphs in the font.
     int32_t Loca(int32_t index);
 
     virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data);
@@ -93,8 +113,15 @@
     virtual int32_t SubSerialize(WritableFontData* new_data);
 
    private:
-    void Init();  // short hand for common code in ctors, C++ port only
-    void Initialize(ReadableFontData* data);  // ported from Java
+    // Initialize the internal state from the data. Done lazily since in many
+    // cases the builder will be just creating a table object with no parsing
+    // required.
+    // @param data the data to initialize from
+    void Initialize(ReadableFontData* data);
+
+    // Internal method to get the loca list if already generated and if not to
+    // initialize the state of the builder.
+    // @return the loca list
     IntegerList* GetLocaList();
 
     int32_t format_version_;  // Note: IndexToLocFormat
@@ -103,7 +130,9 @@
   };
 
   virtual ~LocaTable();
-  int32_t NumGlyphs();
+
+  int32_t format_version() { return format_version_; }
+  int32_t num_glyphs() { return num_glyphs_; }
 
   // Return the offset for the given glyph id. Valid glyph ids are from 0 to the
   // one less than the number of glyphs. The zero entry is the special entry for
@@ -127,13 +156,12 @@
   int32_t Loca(int32_t index);
 
  private:
-  LocaTable(Header* header, ReadableFontData* data);
   LocaTable(Header* header,
             ReadableFontData* data,
-            int32_t version,
+            int32_t format_version,
             int32_t num_glyphs);
 
-  int32_t version_;  // Note: IndexToLocFormat
+  int32_t format_version_;  // Note: Java's version, renamed to format_version_
   int32_t num_glyphs_;
 
   friend class LocaIterator;
diff --git a/sfntly/tools/subsetter/glyph_table_subsetter.cc b/sfntly/tools/subsetter/glyph_table_subsetter.cc
index 644e137..b3d6b07 100644
--- a/sfntly/tools/subsetter/glyph_table_subsetter.cc
+++ b/sfntly/tools/subsetter/glyph_table_subsetter.cc
@@ -46,11 +46,10 @@
   GlyphTablePtr glyph_table = down_cast<GlyphTable*>(font->GetTable(Tag::glyf));
   LocaTablePtr loca_table = down_cast<LocaTable*>(font->GetTable(Tag::loca));
   if (glyph_table == NULL || loca_table == NULL) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return false;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw RuntimeException("Font to subset is not valid.");
 #endif
+    return false;
   }
 
   GlyphTableBuilderPtr glyph_table_builder =
@@ -60,11 +59,10 @@
       down_cast<LocaTable::Builder*>
       (font_builder->NewTableBuilder(Tag::loca));
   if (glyph_table_builder == NULL || loca_table_builder == NULL) {
-#if defined (SFNTLY_NO_EXCEPTION)
-    return false;
-#else
+#if !defined (SFNTLY_NO_EXCEPTION)
     throw RuntimeException("Builder for subset is not valid.");
 #endif
+    return false;
   }
   GlyphTable::GlyphBuilderList* glyph_builders =
       glyph_table_builder->GlyphBuilders();
@@ -77,7 +75,7 @@
     glyph.Attach(glyph_table->GetGlyph(old_offset, old_length));
     ReadableFontDataPtr data = glyph->ReadFontData();
     WritableFontDataPtr copy_data;
-    copy_data.Attach(font_builder->GetNewData(data->Length()));
+    copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length()));
     data->CopyTo(copy_data);
     GlyphBuilderPtr glyph_builder;
     glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data));
diff --git a/sfntly/tools/subsetter/subsetter.cc b/sfntly/tools/subsetter/subsetter.cc
index d1b64d9..7d98779 100644
--- a/sfntly/tools/subsetter/subsetter.cc
+++ b/sfntly/tools/subsetter/subsetter.cc
@@ -56,8 +56,8 @@
   font_builder.Attach(font_factory_->NewFontBuilder());
 
   IntegerSet table_tags;
-  for (TableMap::iterator i = font_->Tables()->begin(),
-                          e = font_->Tables()->end(); i != e; ++i) {
+  for (TableMap::const_iterator i = font_->GetTableMap()->begin(),
+                                e = font_->GetTableMap()->end(); i != e; ++i) {
     table_tags.insert(i->first);
   }
   if (!remove_tables_.empty()) {
diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc
index 2e35c20..fb161a6 100644
--- a/test/font_parsing_test.cc
+++ b/test/font_parsing_test.cc
@@ -32,8 +32,6 @@
 bool TestFontParsing() {
   ByteVector input_buffer;
   LoadFile(SAMPLE_TTF_FILE, &input_buffer);
-  ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]),
-                                        input_buffer.size());
 
   FontFactoryPtr factory;
   factory.Attach(FontFactory::GetInstance());
@@ -43,7 +41,7 @@
   FontBuilderPtr font_builder = font_builder_array[0];
   // Memory based
   FontBuilderArray font_builder_array2;
-  factory->LoadFontsForBuilding(ba, &font_builder_array2);
+  factory->LoadFontsForBuilding(&input_buffer, &font_builder_array2);
   FontBuilderPtr font_builder2 = font_builder_array2[0];
 
   for (size_t i = 0; i < SAMPLE_TTF_KNOWN_TAGS; ++i) {
@@ -121,9 +119,7 @@
   FontFactoryPtr factory;
   factory.Attach(FontFactory::GetInstance());
   FontBuilderArray font_builder_array;
-  ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]),
-                                        input_buffer.size());
-  factory->LoadFontsForBuilding(ba, &font_builder_array);
+  factory->LoadFontsForBuilding(&input_buffer, &font_builder_array);
   FontBuilderPtr font_builder = font_builder_array[0];
   FontPtr font;
   font.Attach(font_builder->Build());
diff --git a/test/memory_io_test.cc b/test/memory_io_test.cc
new file mode 100755
index 0000000..b34e1e7
--- /dev/null
+++ b/test/memory_io_test.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include <algorithm>
+
+#include "gtest/gtest.h"
+#include "sfntly/port/memory_input_stream.h"
+#include "sfntly/port/memory_output_stream.h"
+#include "sfntly/port/type.h"
+
+namespace {
+  const char* kTestData =
+"01234567890123456789012345678901234567890123456789"  // 50
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx"  // 100
+"yz";                                                 // 102
+  const size_t kTestBufferLen = 102;
+}
+
+namespace sfntly {
+
+bool TestMemoryInputStream() {
+  ByteVector test_buffer;
+  test_buffer.resize(kTestBufferLen);
+  std::copy(kTestData, kTestData + kTestBufferLen, test_buffer.begin());
+
+  MemoryInputStream is;
+  is.Attach(&(test_buffer[0]), kTestBufferLen);
+  EXPECT_EQ(is.Available(), (int32_t)kTestBufferLen);
+
+  // Read one byte
+  EXPECT_EQ(is.Read(), '0');  // position 1
+  EXPECT_EQ(is.Read(), '1');  // position 2
+  EXPECT_EQ(is.Read(), '2');  // position 3
+
+  // Read byte vector
+  ByteVector b;
+  b.resize(7);
+  EXPECT_EQ(is.Read(&b), 7);  // position 10
+  EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 3, 7), 0);
+
+  b.resize(17);
+  EXPECT_EQ(is.Read(&b, 7, 10), 10);  // position 20
+  EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 3, 17), 0);
+
+  // Test skip
+  b.clear();
+  b.resize(10);
+  EXPECT_EQ(is.Skip(30), 30);  // position 50
+  EXPECT_EQ(is.Read(&b), 10);  // position 60
+  EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 50, 10), 0);
+  b.clear();
+  b.resize(10);
+  EXPECT_EQ(is.Skip(-20), -20);  // position 40
+  EXPECT_EQ(is.Read(&b), 10);  // position 50
+  EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 40, 10), 0);
+
+  EXPECT_EQ(is.Available(), (int32_t)kTestBufferLen - 50);
+  EXPECT_EQ(is.Skip(-60), -50);  // Out of bound, position 0
+  EXPECT_EQ(is.Skip(kTestBufferLen + 10), (int32_t)kTestBufferLen);
+
+  b.clear();
+  b.resize(10);
+  is.Unread(&b);
+  EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + kTestBufferLen - 10, 10), 0);
+
+  return true;
+}
+
+bool TestMemoryOutputStream() {
+  ByteVector test_buffer;
+  test_buffer.resize(kTestBufferLen);
+  std::copy(kTestData, kTestData + kTestBufferLen, test_buffer.begin());
+
+  MemoryOutputStream os;
+  os.Write(&(test_buffer[0]), (int32_t)50, (int32_t)(kTestBufferLen - 50));
+  EXPECT_EQ(os.Size(), kTestBufferLen - 50);
+  EXPECT_EQ(memcmp(os.Get(), &(test_buffer[0]) + 50, kTestBufferLen - 50), 0);
+
+  return true;
+}
+
+}  // namespace sfntly
+
+TEST(MemoryIO, All) {
+  ASSERT_TRUE(sfntly::TestMemoryInputStream());
+  ASSERT_TRUE(sfntly::TestMemoryOutputStream());
+}
diff --git a/test/name_editing_test.cc b/test/name_editing_test.cc
index ce12cd3..260d9d4 100644
--- a/test/name_editing_test.cc
+++ b/test/name_editing_test.cc
@@ -24,9 +24,10 @@
 #include "sfntly/data/memory_byte_array.h"
 #include "sfntly/font.h"
 #include "sfntly/font_factory.h"
+#include "sfntly/port/memory_input_stream.h"
+#include "sfntly/port/memory_output_stream.h"
 #include "sfntly/table/core/name_table.h"
 #include "sfntly/tag.h"
-#include "sfntly/port/memory_output_stream.h"
 #include "test/test_data.h"
 #include "test/test_font_utils.h"
 
@@ -40,11 +41,7 @@
   if (input_buffer.empty()) {
     LoadFile(SAMPLE_TTF_FILE, &input_buffer);
   }
-
-  ByteArrayPtr ba =
-      new MemoryByteArray(&(input_buffer[0]), input_buffer.size());
-
-  factory->LoadFontsForBuilding(ba, font_builders);
+  factory->LoadFontsForBuilding(&input_buffer, font_builders);
 }
 
 bool TestChangeOneName() {
@@ -73,9 +70,10 @@
   // Serialize and reload the serialized font.
   MemoryOutputStream os;
   factory->SerializeFont(font, &os);
+  MemoryInputStream is;
+  is.Attach(os.Get(), os.Size());
   FontArray font_array;
-  ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size());
-  factory->LoadFonts(new_ba, &font_array);
+  factory->LoadFonts(&is, &font_array);
   FontPtr new_font = font_array[0];
 
   // Check the font name.
@@ -121,9 +119,10 @@
   // Serialize and reload the serialized font.
   MemoryOutputStream os;
   factory->SerializeFont(font, &os);
+  MemoryInputStream is;
+  is.Attach(os.Get(), os.Size());
   FontArray font_array;
-  ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size());
-  factory->LoadFonts(new_ba, &font_array);
+  factory->LoadFonts(&is, &font_array);
   FontPtr new_font = font_array[0];
 
   // Check the font name.
@@ -166,9 +165,10 @@
   // Serialize and reload the serialized font.
   MemoryOutputStream os;
   factory->SerializeFont(font, &os);
+  MemoryInputStream is;
+  is.Attach(os.Get(), os.Size());
   FontArray font_array;
-  ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size());
-  factory->LoadFonts(new_ba, &font_array);
+  factory->LoadFonts(&is, &font_array);
   FontPtr new_font = font_array[0];
 
   // Check the font name.
diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc
index 32ba248..c99a3a3 100644
--- a/test/otf_basic_editing_test.cc
+++ b/test/otf_basic_editing_test.cc
@@ -39,6 +39,7 @@
   EXPECT_TRUE(font_builder != NULL);
   TableBuilderMap* builder_map = font_builder->table_builders();
   EXPECT_TRUE(builder_map != NULL);
+  IntegerSet builder_tags;
   for (TableBuilderMap::iterator i = builder_map->begin(),
                                  e = builder_map->end(); i != e; ++i) {
     EXPECT_TRUE(i->second != NULL);
@@ -47,11 +48,11 @@
       int32_t value = ToBE32(i->first);
       memcpy(tag, &value, 4);
       fprintf(stderr, "tag %s does not have valid builder\n", tag);
+    } else {
+      builder_tags.insert(i->first);
     }
   }
 
-  IntegerSet builder_tags;
-  font_builder->TableBuilderTags(&builder_tags);
   FontHeaderTableBuilderPtr header_builder =
       down_cast<FontHeaderTable::Builder*>(
           font_builder->GetTableBuilder(Tag::head));
@@ -61,9 +62,9 @@
   font.Attach(font_builder->Build());
 
   // ensure every table had a builder
-  TableMap* table_map = font->Tables();
-  for (TableMap::iterator i = table_map->begin(), e = table_map->end();
-                          i != e; ++i) {
+  const TableMap* table_map = font->GetTableMap();
+  for (TableMap::const_iterator i = table_map->begin(), e = table_map->end();
+                                i != e; ++i) {
     TablePtr table = (*i).second;
     TableHeaderPtr header = table->header();
     EXPECT_TRUE(builder_tags.find(header->tag()) != builder_tags.end());
diff --git a/test/serialization_test.cc b/test/serialization_test.cc
index 08c8288..3df6d95 100755
--- a/test/serialization_test.cc
+++ b/test/serialization_test.cc
@@ -17,7 +17,8 @@
 #include "gtest/gtest.h"
 #include "sfntly/font.h"
 #include "sfntly/font_factory.h"
-#include "sfntly/data/memory_byte_array.h"
+#include "sfntly/port/memory_input_stream.h"
+#include "sfntly/port/memory_output_stream.h"
 #include "test/test_data.h"
 #include "test/test_font_utils.h"
 #include "test/serialization_test.h"
@@ -43,20 +44,21 @@
 
   factory3.Attach(FontFactory::GetInstance());
   FontArray new_font_array;
-  ByteArrayPtr ba = new MemoryByteArray(os.Get(), os.Size());
-  factory3->LoadFonts(ba, &new_font_array);
+  MemoryInputStream is;
+  is.Attach(os.Get(), os.Size());
+  factory3->LoadFonts(&is, &new_font_array);
   FontPtr serialized = new_font_array[0];
 
   // Check number of tables
   EXPECT_EQ(original->num_tables(), serialized->num_tables());
 
   // Check if same set of tables
-  TableMap* original_tables = original->Tables();
-  TableMap* serialized_tables = serialized->Tables();
+  const TableMap* original_tables = original->GetTableMap();
+  const TableMap* serialized_tables = serialized->GetTableMap();
   EXPECT_EQ(original_tables->size(), serialized_tables->size());
-  TableMap::iterator not_found = serialized_tables->end();
-  for (TableMap::iterator b = original_tables->begin(),
-                          e = original_tables->end(); b != e; ++b) {
+  TableMap::const_iterator not_found = serialized_tables->end();
+  for (TableMap::const_iterator b = original_tables->begin(),
+                                e = original_tables->end(); b != e; ++b) {
     EXPECT_TRUE((serialized_tables->find(b->first) != not_found));
   }
 
@@ -67,7 +69,7 @@
       TablePtr serialized_table = serialized->GetTable(TTF_KNOWN_TAGS[i]);
     EXPECT_EQ(original_table->CalculatedChecksum(),
               serialized_table->CalculatedChecksum());
-    EXPECT_EQ(original_table->Length(), serialized_table->Length());
+    EXPECT_EQ(original_table->DataLength(), serialized_table->DataLength());
 
     if (TTF_KNOWN_TAGS[i] == Tag::hhea) {
       EXPECT_TRUE(VerifyHHEA(original_table, serialized_table));
diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc
index 572f00e..f82a674 100644
--- a/test/subsetter_impl.cc
+++ b/test/subsetter_impl.cc
@@ -28,6 +28,7 @@
 #include "sfntly/table/truetype/loca_table.h"
 #include "sfntly/tag.h"
 #include "sfntly/data/memory_byte_array.h"
+#include "sfntly/port/memory_input_stream.h"
 #include "sfntly/port/memory_output_stream.h"
 
 namespace sfntly {
@@ -81,14 +82,14 @@
 bool SubsetterImpl::LoadFont(const char* font_name,
                              const unsigned char* original_font,
                              size_t font_size) {
-  ByteArrayPtr raw_font =
-      new MemoryByteArray((byte_t*)original_font, font_size);
+  MemoryInputStream mis;
+  mis.Attach(original_font, font_size);
   if (factory_ == NULL) {
     factory_.Attach(FontFactory::GetInstance());
   }
 
   FontArray font_array;
-  factory_->LoadFonts(raw_font, &font_array);
+  factory_->LoadFonts(&mis, &font_array);
   font_ = FindFont(font_name, font_array);
   if (font_ == NULL) {
     return false;
@@ -223,7 +224,7 @@
     IntegerSet comp_glyph_id;
     for (IntegerSet::iterator i = glyph_id_remaining.begin(),
                               e = glyph_id_remaining.end(); i != e; ++i) {
-      if (*i < 0 || *i >= loca_table->NumGlyphs()) {
+      if (*i < 0 || *i >= loca_table->num_glyphs()) {
         // Invalid glyph id, ignore.
         continue;
       }
@@ -285,7 +286,7 @@
 
   // Extract glyphs and setup loca list.
   IntegerList loca_list;
-  loca_list.resize(loca_table->NumGlyphs());
+  loca_list.resize(loca_table->num_glyphs());
   loca_list.push_back(0);
   int32_t last_glyph_id = 0;
   int32_t last_offset = 0;
@@ -302,7 +303,7 @@
     // Add glyph to new glyf table.
     ReadableFontDataPtr data = glyph->ReadFontData();
     WritableFontDataPtr copy_data;
-    copy_data.Attach(font_builder->GetNewData(data->Length()));
+    copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length()));
     data->CopyTo(copy_data);
     GlyphBuilderPtr glyph_builder;
     glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data));
@@ -316,14 +317,14 @@
     loca_list[*i + 1] = last_offset;
     last_glyph_id = *i;
   }
-  for (int32_t j = last_glyph_id + 1; j <= loca_table->NumGlyphs(); ++j) {
+  for (int32_t j = last_glyph_id + 1; j <= loca_table->num_glyphs(); ++j) {
     loca_list[j] = last_offset;
   }
   loca_table_builder->SetLocaList(&loca_list);
 
   // Setup remaining builders.
-  for (TableMap::iterator i = font_->Tables()->begin(),
-                          e = font_->Tables()->end(); i != e; ++i) {
+  for (TableMap::const_iterator i = font_->GetTableMap()->begin(),
+                                e = font_->GetTableMap()->end(); i != e; ++i) {
     // We already build the builder for glyph and loca.
     if (i->first != Tag::glyf && i->first != Tag::loca) {
       font_builder->NewTableBuilder(i->first, i->second->ReadFontData());
diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc
index 99b65fe..d59b52b 100644
--- a/test/test_font_utils.cc
+++ b/test/test_font_utils.cc
@@ -49,17 +49,15 @@
   is.Close();
 }
 
-void LoadFontUsingByteArray(const char* font_path,
+void LoadFontUsingByteVector(const char* font_path,
                             bool fingerprint,
                             FontArray* fonts) {
-  ByteArrayPtr b = new GrowableMemoryByteArray;
   ByteVector bv;
   LoadFile(font_path, &bv);
-  b->Put(0, &bv);
   FontFactoryPtr factory;
   factory.Attach(FontFactory::GetInstance());
   factory->FingerprintFont(fingerprint);
-  factory->LoadFonts(b, fonts);
+  factory->LoadFonts(&bv, fonts);
 }
 
 void LoadFile(const char* input_file_path, ByteVector* input_buffer) {
diff --git a/test/test_font_utils.h b/test/test_font_utils.h
index b8a93b9..57fde7a 100644
--- a/test/test_font_utils.h
+++ b/test/test_font_utils.h
@@ -27,7 +27,7 @@
                         FontBuilderArray* builders);
 void SerializeFont(const char* font_path, FontFactory* factory, Font* font);
 void LoadFont(const char* font_path, FontFactory* factory, FontArray* fonts);
-void LoadFontUsingByteArray(const char* font_path,
+void LoadFontUsingByteVector(const char* font_path,
                             bool fingerprint,
                             FontArray* fonts);
 
diff --git a/test/verify_hhea.cc b/test/verify_hhea.cc
index 491238a..05886d4 100644
--- a/test/verify_hhea.cc
+++ b/test/verify_hhea.cc
@@ -37,7 +37,7 @@
     return false;
   }
 
-  EXPECT_EQ(hhea->Version(), SFNTVERSION_1);
+  EXPECT_EQ(hhea->TableVersion(), SFNTVERSION_1);
   EXPECT_EQ(hhea->Ascender(), HHEA_ASCENDER);
   EXPECT_EQ(hhea->Descender(), HHEA_DESCENDER);
   EXPECT_EQ(hhea->AdvanceWidthMax(), HHEA_ADVANCE_WIDTH_MAX);
diff --git a/test/verify_loca.cc b/test/verify_loca.cc
index 0e36ce8..3090841 100644
--- a/test/verify_loca.cc
+++ b/test/verify_loca.cc
@@ -230,7 +230,7 @@
   }
 
   EXPECT_EQ(loca->NumLocas(), LOCA_NUM_LOCAS);
-  EXPECT_EQ(loca->NumGlyphs(), LOCA_NUM_LOCAS - 1);
+  EXPECT_EQ(loca->num_glyphs(), LOCA_NUM_LOCAS - 1);
 
   for (int32_t i = 0; i < LOCA_NUM_LOCAS - 1; ++i) {
     EXPECT_EQ(loca->GlyphOffset(i), LOCAS[i]);
diff --git a/test/verify_maxp.cc b/test/verify_maxp.cc
index 3bd4490..3b8e183 100644
--- a/test/verify_maxp.cc
+++ b/test/verify_maxp.cc
@@ -42,13 +42,12 @@
     return false;
   }
 
-  EXPECT_EQ(maxp->Version(), SFNTVERSION_1);
+  EXPECT_EQ(maxp->TableVersion(), SFNTVERSION_1);
   EXPECT_EQ(maxp->NumGlyphs(), MAXP_NUM_GLYPHS);
   EXPECT_EQ(maxp->MaxPoints(), MAXP_MAX_POINTS);
   EXPECT_EQ(maxp->MaxContours(), MAXP_MAX_CONTOURS);
   EXPECT_EQ(maxp->MaxCompositePoints(), MAXP_MAX_COMPOSITE_POINTS);
-  // TODO(arthurhsu): maxCompositeContours observed in Microsoft TTF report.
-  //                  Check with stuartg and see if this is a miss.
+  EXPECT_EQ(maxp->MaxCompositeContours(), MAXP_MAX_COMPOSITE_CONTOURS);
   EXPECT_EQ(maxp->MaxZones(), MAXP_MAX_ZONES);
   EXPECT_EQ(maxp->MaxTwilightPoints(), MAXP_MAX_TWILIGHT_POINTS);
   EXPECT_EQ(maxp->MaxStorage(), MAXP_MAX_STORAGE);
diff --git a/test/verify_os2.cc b/test/verify_os2.cc
index 8f6b9ed..4713e44 100644
--- a/test/verify_os2.cc
+++ b/test/verify_os2.cc
@@ -60,7 +60,7 @@
     return false;
   }
 
-  EXPECT_EQ(os2->Version(), OS2_VERSION);
+  EXPECT_EQ(os2->TableVersion(), OS2_VERSION);
   EXPECT_EQ(os2->XAvgCharWidth(), OS2_XAVG_CHAR_WIDTH);
   EXPECT_EQ(os2->UsWeightClass(), OS2_US_WEIGHT_CLASS);
   EXPECT_EQ(os2->UsWidthClass(), OS2_US_WIDTH_CLASS);
@@ -107,7 +107,6 @@
   EXPECT_EQ(os2->UlCodePageRange1(), OS2_UL_CODE_PAGE_RANGE1);
   EXPECT_EQ(os2->UlCodePageRange2(), OS2_UL_CODE_PAGE_RANGE2);
 
-  // TODO(arthurhsu): UlCodePageRange() not tested
   // TODO(arthurhsu): SxHeight() not tested
   // TODO(arthurhsu): SCapHeight() not tested
   // TODO(arthurhsu): UsDefaultChar() not tested