Add support for loading WOFF file format
diff --git a/Lib/fontTools/ttLib/sfnt.py b/Lib/fontTools/ttLib/sfnt.py
index 7ba40f4..7943e1e 100644
--- a/Lib/fontTools/ttLib/sfnt.py
+++ b/Lib/fontTools/ttLib/sfnt.py
@@ -22,14 +22,14 @@
 	def __init__(self, file, checkChecksums=1, fontNumber=-1):
 		self.file = file
 		self.checkChecksums = checkChecksums
-		data = self.file.read(sfntDirectorySize)
-		if len(data) <> sfntDirectorySize:
-			from fontTools import ttLib
-			raise ttLib.TTLibError, "Not a TrueType or OpenType font (not enough data)"
-		sstruct.unpack(sfntDirectoryFormat, data, self)
+
+		self.flavor = None
+		self.flavorData = None
+		self.DirectoryEntry = SFNTDirectoryEntry
+		self.sfntVersion = self.file.read(4)
+		self.file.seek(0)
 		if self.sfntVersion == "ttcf":
-			assert ttcHeaderSize == sfntDirectorySize
-			sstruct.unpack(ttcHeaderFormat, data, self)
+			sstruct.unpack(ttcHeaderFormat, self.file.read(ttcHeaderSize), self)
 			assert self.Version == 0x00010000 or self.Version == 0x00020000, "unrecognized TTC version 0x%08x" % self.Version
 			if not 0 <= fontNumber < self.numFonts:
 				from fontTools import ttLib
@@ -38,14 +38,20 @@
 			if self.Version == 0x00020000:
 				pass # ignoring version 2.0 signatures
 			self.file.seek(offsetTable[fontNumber])
-			data = self.file.read(sfntDirectorySize)
-			sstruct.unpack(sfntDirectoryFormat, data, self)
+			sstruct.unpack(sfntDirectoryFormat, self.file.read(sfntDirectorySize), self)
+		elif self.sfntVersion == "wOFF":
+			self.flavor = "woff"
+			self.DirectoryEntry = WOFFDirectoryEntry
+			sstruct.unpack(woffDirectoryFormat, self.file.read(woffDirectorySize), self)
+		else:
+			sstruct.unpack(sfntDirectoryFormat, self.file.read(sfntDirectorySize), self)
+
 		if self.sfntVersion not in ("\000\001\000\000", "OTTO", "true"):
 			from fontTools import ttLib
 			raise ttLib.TTLibError, "Not a TrueType or OpenType font (bad sfntVersion)"
 		self.tables = {}
 		for i in range(self.numTables):
-			entry = SFNTDirectoryEntry()
+			entry = self.DirectoryEntry()
 			entry.fromFile(self.file)
 			if entry.length > 0:
 				self.tables[entry.tag] = entry
@@ -55,7 +61,11 @@
 				# Besides, at least one font has been sighted which actually
 				# *has* a zero-length table.
 				pass
-	
+
+		# Load flavor data if any
+		if self.flavor == "woff":
+			self.flavorData = WOFFFlavorData(self)
+
 	def has_key(self, tag):
 		return self.tables.has_key(tag)
 	
@@ -65,8 +75,7 @@
 	def __getitem__(self, tag):
 		"""Fetch the raw table data."""
 		entry = self.tables[tag]
-		self.file.seek(entry.offset)
-		data = self.file.read(entry.length)
+		data = entry.loadData (self.file)
 		if self.checkChecksums:
 			if tag == 'head':
 				# Beh: we have to special-case the 'head' table.
@@ -214,23 +223,105 @@
 
 sfntDirectoryEntrySize = sstruct.calcsize(sfntDirectoryEntryFormat)
 
-class SFNTDirectoryEntry:
+woffDirectoryFormat = """
+		> # big endian
+		signature:      4s   # "wOFF"
+		sfntVersion:    4s
+		length:         L    # total woff file size
+		numTables:      H    # number of tables
+		reserved:       H    # set to 0
+		totalSfntSize:  L    # uncompressed size
+		majorVersion:   H    # major version of WOFF file
+		minorVersion:   H    # minor version of WOFF file
+		metaOffset:     L    # offset to metadata block
+		metaLength:     L    # length of compressed metadata
+		metaOrigLength: L    # length of uncompressed metadata
+		privOffset:     L    # offset to private data block
+		privLength:     L    # length of private data block
+"""
+
+woffDirectorySize = sstruct.calcsize(woffDirectoryFormat)
+
+woffDirectoryEntryFormat = """
+		> # big endian
+		tag:            4s
+		offset:         L
+		length:         L    # compressed length
+		origLength:     L    # original length
+		checksum:       L    # original checksum
+"""
+
+woffDirectoryEntrySize = sstruct.calcsize(woffDirectoryEntryFormat)
+
+
+class DirectoryEntry:
 	
 	def fromFile(self, file):
-		sstruct.unpack(sfntDirectoryEntryFormat, 
-				file.read(sfntDirectoryEntrySize), self)
+		sstruct.unpack(self.format, file.read(self.formatSize), self)
 	
 	def fromString(self, str):
-		sstruct.unpack(sfntDirectoryEntryFormat, str, self)
+		sstruct.unpack(self.format, str, self)
 	
 	def toString(self):
-		return sstruct.pack(sfntDirectoryEntryFormat, self)
+		return sstruct.pack(self.format, self)
 	
 	def __repr__(self):
 		if hasattr(self, "tag"):
-			return "<SFNTDirectoryEntry '%s' at %x>" % (self.tag, id(self))
+			return "<%s '%s' at %x>" % (self.__class__.__name__, self.tag, id(self))
 		else:
-			return "<SFNTDirectoryEntry at %x>" % id(self)
+			return "<%s at %x>" % (self.__class__.__name__, id(self))
+
+	def loadData(self, file):
+		file.seek(self.offset)
+		data = file.read(self.length)
+		assert len(data) == self.length
+		return self.decodeData (data)
+
+	def decodeData(self, rawData):
+		return rawData
+
+class SFNTDirectoryEntry(DirectoryEntry):
+
+	format = sfntDirectoryEntryFormat
+	formatSize = sfntDirectoryEntrySize
+
+class WOFFDirectoryEntry(DirectoryEntry):
+
+	format = woffDirectoryEntryFormat
+	formatSize = woffDirectoryEntrySize
+
+	def decodeData(self, rawData):
+		import zlib
+		if self.length == self.origLength:
+			data = rawData
+		else:
+			assert self.length < self.origLength
+			data = zlib.decompress(rawData)
+			assert len (data) == self.origLength
+		return data
+
+class WOFFFlavorData():
+
+	def __init__(self, reader=None):
+		self.majorVersion = None
+		self.minorVersion = None
+		self.metaData = None
+		self.privData = None
+		if reader:
+			self.majorVersion = reader.majorVersion
+			self.minorVersion = reader.minorVersion
+			if reader.metaLength:
+				reader.file.seek(reader.metaOffset)
+				rawData = read.file.read(reader.metaLength)
+				assert len(rawData) == reader.metaLength
+				data = zlib.decompress(rawData)
+				assert len(data) == reader.metaOrigLength
+				self.metaData = data
+			if reader.privLength:
+				reader.file.seek(reader.privOffset)
+				data = read.file.read(reader.privLength)
+				assert len(data) == reader.privLength
+				self.privData = data
 
 
 def calcChecksum(data):