M_E_T_A_.py :  » GUI » TTX-FontTools » fonttools-2.3 » Lib » fontTools » ttLib » tables » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » TTX FontTools 
TTX FontTools » fonttools 2.3 » Lib » fontTools » ttLib » tables » M_E_T_A_.py
import DefaultTable
import struct, sstruct
from fontTools.misc.textTools import safeEval
import string
from types import FloatType,ListType,StringType,TupleType
import sys
METAHeaderFormat = """
    >  # big endian
    tableVersionMajor:      H
    tableVersionMinor:      H
    metaEntriesVersionMajor:  H
    metaEntriesVersionMinor:  H
    unicodeVersion:        L
    metaFlags:          H
    nMetaRecs:          H
"""
# This record is followed by nMetaRecs of METAGlyphRecordFormat.
# This in turn is followd by as many METAStringRecordFormat entries
# as specified by the METAGlyphRecordFormat entries
# this is followed by the strings specifried in the  METAStringRecordFormat
METAGlyphRecordFormat = """
    >  # big endian
    glyphID:      H
    nMetaEntry:      H
"""
# This record is followd by a variable data length field:
#   USHORT or ULONG  hdrOffset  
# Offset from start of META table to the beginning
# of this glyphs array of ns Metadata string entries.
# Size determined by metaFlags field    
# METAGlyphRecordFormat entries must be sorted by glyph ID
 
METAStringRecordFormat = """
    >  # big endian
    labelID:      H
    stringLen:      H
"""
# This record is followd by a variable data length field:
#   USHORT or ULONG  stringOffset  
# METAStringRecordFormat entries must be sorted in order of labelID
# There may be more than one entry with the same labelID
# There may be more than one strign with the same content.

# Strings shall be Unicode UTF-8 encoded, and null-terminated.

METALabelDict = {
  0 : "MojikumiX4051", # An integer in the range 1-20
  1 : "UNIUnifiedBaseChars",
  2 : "BaseFontName",
  3 : "Language",
  4 : "CreationDate",
  5 : "FoundryName",
  6 : "FoundryCopyright",
  7 : "OwnerURI",
  8 : "WritingScript",
  10 : "StrokeCount",
  11 : "IndexingRadical",
}


def getLabelString(labelID):
  try:
    label = METALabelDict[labelID]
  except KeyError:
    label = "Unknown label"
  return str(label)


class table_M_E_T_A_(DefaultTable.DefaultTable):
  
  dependencies = []
  
  def decompile(self, data, ttFont):
    dummy, newData = sstruct.unpack2(METAHeaderFormat, data, self)
    self.glyphRecords = []
    for i in range(self.nMetaRecs):
      glyphRecord, newData = sstruct.unpack2(METAGlyphRecordFormat, newData, GlyphRecord())
      if self.metaFlags == 0:
        [glyphRecord.offset] = struct.unpack(">H", newData[:2])
        newData = newData[2:]
      elif self.metaFlags == 1:
        [glyphRecord.offset] = struct.unpack(">H", newData[:4])
        newData = newData[4:]
      else:
        assert 0, "The metaFlags field in the META table header has a value other than 0 or 1 :" + str(self.metaFlags)
      glyphRecord.stringRecs = []
      newData = data[glyphRecord.offset:]
      for j in range(glyphRecord.nMetaEntry):
        stringRec, newData = sstruct.unpack2(METAStringRecordFormat, newData, StringRecord())
        if self.metaFlags == 0:
          [stringRec.offset] = struct.unpack(">H", newData[:2])
          newData = newData[2:]
        else:
          [stringRec.offset] = struct.unpack(">H", newData[:4])
          newData = newData[4:]
        stringRec.string = data[stringRec.offset:stringRec.offset + stringRec.stringLen]
        glyphRecord.stringRecs.append(stringRec)
      self.glyphRecords.append(glyphRecord)  
      
  def compile(self, ttFont):
    offsetOK = 0
    self.nMetaRecs = len(self.glyphRecords)
    count = 0
    while ( offsetOK != 1):
      count = count + 1
      if count > 4:
        pdb_set_trace()
      metaData = sstruct.pack(METAHeaderFormat, self)
      stringRecsOffset = len(metaData) + self.nMetaRecs * (6 + 2*(self.metaFlags & 1))
      stringRecSize = (6 + 2*(self.metaFlags & 1))
      for glyphRec in self.glyphRecords:
        glyphRec.offset = stringRecsOffset
        if (glyphRec.offset > 65535) and ((self.metaFlags & 1) == 0):
          self.metaFlags = self.metaFlags + 1
          offsetOK = -1
          break
        metaData = metaData + glyphRec.compile(self)
        stringRecsOffset = stringRecsOffset + (glyphRec.nMetaEntry * stringRecSize) 
        # this will be the String Record offset for the next GlyphRecord.
      if   offsetOK == -1:
        offsetOK = 0
        continue
      
      # metaData now contains the header and all of the GlyphRecords. Its length should bw
      # the offset to the first StringRecord.
      stringOffset = stringRecsOffset
      for glyphRec in self.glyphRecords:
        assert (glyphRec.offset == len(metaData)), "Glyph record offset did not compile correctly! for rec:" + str(glyphRec)
        for stringRec in glyphRec.stringRecs:
          stringRec.offset = stringOffset
          if (stringRec.offset > 65535) and ((self.metaFlags & 1) == 0):
            self.metaFlags = self.metaFlags + 1
            offsetOK = -1
            break
          metaData = metaData + stringRec.compile(self)
          stringOffset = stringOffset + stringRec.stringLen
      if   offsetOK == -1:
        offsetOK = 0
        continue
        
      if ((self.metaFlags & 1) == 1) and (stringOffset < 65536):
        self.metaFlags = self.metaFlags - 1
        continue
      else:
        offsetOK = 1
          
                
      # metaData now contains the header and all of the GlyphRecords and all of the String Records.
      # Its length should be the offset to the first string datum.
      for glyphRec in self.glyphRecords:
        for stringRec in glyphRec.stringRecs:
          assert (stringRec.offset == len(metaData)), "String offset did not compile correctly! for string:" + str(stringRec.string)
          metaData = metaData + stringRec.string
    
    return metaData
  
  def toXML(self, writer, ttFont):
    writer.comment("Lengths and number of entries in this table will be recalculated by the compiler")
    writer.newline()
    formatstring, names, fixes = sstruct.getformat(METAHeaderFormat)
    for name in names:
      value = getattr(self, name)
      writer.simpletag(name, value=value)
      writer.newline()
    for glyphRec in self.glyphRecords:
      glyphRec.toXML(writer, ttFont)
    
  def fromXML(self, (name, attrs, content), ttFont):
    if name == "GlyphRecord":
      if not hasattr(self, "glyphRecords"):
        self.glyphRecords = []
      glyphRec = GlyphRecord()
      self.glyphRecords.append(glyphRec)
      for element in content:
        if isinstance(element, StringType):
          continue
        glyphRec.fromXML(element, ttFont)
      glyphRec.offset = -1
      glyphRec.nMetaEntry = len(glyphRec.stringRecs)
    else:      
      value = attrs["value"]
      try:
        value = safeEval(value)
      except OverflowError:
        value = long(value)
      setattr(self, name, value)


class GlyphRecord:
  def __init__(self):
    self.glyphID = -1
    self.nMetaEntry = -1
    self.offset = -1
    self.stringRecs = []
    
  def toXML(self, writer, ttFont):
    writer.begintag("GlyphRecord")
    writer.newline()
    writer.simpletag("glyphID", value=self.glyphID)
    writer.newline()
    writer.simpletag("nMetaEntry", value=self.nMetaEntry)
    writer.newline()
    for stringRec in self.stringRecs:
      stringRec.toXML(writer, ttFont)
    writer.endtag("GlyphRecord")
    writer.newline()


  def fromXML(self, (name, attrs, content), ttFont):
    if name == "StringRecord":
      stringRec = StringRecord()
      self.stringRecs.append(stringRec)
      for element in content:
        if isinstance(element, StringType):
          continue
        stringRec.fromXML(element, ttFont)
      stringRec.stringLen = len(stringRec.string)
    else:      
      value = attrs["value"]
      try:
        value = safeEval(value)
      except OverflowError:
        value = long(value)
      setattr(self, name, value)

  def compile(self, parentTable):
    data = sstruct.pack(METAGlyphRecordFormat, self)
    if parentTable.metaFlags == 0:
      datum = struct.pack(">H", self.offset)
    elif parentTable.metaFlags == 1:
      datum = struct.pack(">L", self.offset)
    data = data + datum
    return data


  def __cmp__(self, other):
    """Compare method, so a list of NameRecords can be sorted
    according to the spec by just sorting it..."""
    return cmp(self.glyphID, other.glyphID)
  
  def __repr__(self):
    return "GlyphRecord[ glyphID: " + str(self.glyphID) + ", nMetaEntry: " + str(self.nMetaEntry) + ", offset: " + str(self.offset) + " ]"


def mapXMLToUTF8(string):
  uString = u""
  strLen = len(string)
  i = 0
  while i < strLen:
    prefixLen = 0
    if  (string[i:i+3] == "&#x"):
      prefixLen = 3
    elif  (string[i:i+7] == "&amp;#x"):
      prefixLen = 7
    if prefixLen:
      i = i+prefixLen
      j= i
      while string[i] != ";":
        i = i+1
      valStr = string[j:i]
      
      uString = uString + unichr(eval('0x' + valStr))
    else:
      uString = uString + unichr(ord(string[i]))
    i = i +1
      
  return uString.encode('utf8')


def mapUTF8toXML(string):
  uString = string.decode('utf8')
  string = ""
  for uChar in uString:
    i = ord(uChar)
    if (i < 0x80) and (i > 0x1F):
      string = string + chr(i)
    else:
      string = string + "&#x" + hex(i)[2:] + ";"
  return string


class StringRecord:
  def __init__(self):
    self.labelID = -1
    self.string = ""
    self.stringLen = -1
    self.offset = -1

  def toXML(self, writer, ttFont):
    writer.begintag("StringRecord")
    writer.newline()
    writer.simpletag("labelID", value=self.labelID)
    writer.comment(getLabelString(self.labelID))
    writer.newline()
    writer.newline()
    writer.simpletag("string", value=mapUTF8toXML(self.string))
    writer.newline()
    writer.endtag("StringRecord")
    writer.newline()

  def fromXML(self, (name, attrs, content), ttFont):
    value = attrs["value"]
    if name == "string":
      self.string = mapXMLToUTF8(value)
    else:
      try:
        value = safeEval(value)
      except OverflowError:
        value = long(value)
      setattr(self, name, value)

  def compile(self, parentTable):
    data = sstruct.pack(METAStringRecordFormat, self)
    if parentTable.metaFlags == 0:
      datum = struct.pack(">H", self.offset)
    elif parentTable.metaFlags == 1:
      datum = struct.pack(">L", self.offset)
    data = data + datum
    return data

  def __cmp__(self, other):
    """Compare method, so a list of NameRecords can be sorted
    according to the spec by just sorting it..."""
    return cmp(self.labelID, other.labelID)
  
  def __repr__(self):
    return "StringRecord [ labelID: " + str(self.labelID) + " aka " + getLabelString(self.labelID) \
      + ", offset: " + str(self.offset) + ", length: " + str(self.stringLen) + ", string: " +self.string + " ]"

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.