nfntLib.py :  » GUI » TTX-FontTools » fonttools-2.3 » Lib » fontTools » 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 » nfntLib.py
import struct, sstruct
import string
import types


# FontRec header
nfntHeaderFormat = """
  >  # big endian
  fontType:    h     # font type
  firstChar:   h     # ASCII code of first character
  lastChar:    h     # ASCII code of last character
  widMax:      h     # maximum character width
  kernMax:     h     # negative of maximum character kern
  nDescent:    h     # negative of descent
  fRectWidth:  h     # width of font rectangle
  fRectHeight: h     # height of font rectangle
  owTLoc:      H     # offset to offset/width table (in words from _this_ point)
  ascent:      h     # ascent
  descent:     h     # descent
  leading:     h     # leading
  rowWords:    h     # row width of bit image / 2
"""
headerSize = sstruct.calcsize(nfntHeaderFormat)
assert headerSize == 26


class NFNT:
  
  def __init__(self, data=None):
    if data is not None:
      self.decompile(data)
  
  def decompile(self, data):
    # header; FontRec
    sstruct.unpack(nfntHeaderFormat, data[:headerSize], self)
    
    #assert self.fRectHeight == (self.ascent + self.descent)
    
    # rest
    tableSize = 2 * (self.lastChar - self.firstChar + 3)
    bitmapSize = 2 * self.rowWords * self.fRectHeight
    
    self.bits = data[headerSize:headerSize + bitmapSize]
    
    # XXX deal with self.nDescent being a positive number
    assert (headerSize + bitmapSize + tableSize - 16) / 2 == self.owTLoc  # ugh...
    
    locTable = data[headerSize + bitmapSize:headerSize + bitmapSize + tableSize]
    if len(locTable) <> tableSize:
      raise ValueError, 'invalid NFNT format'
    
    owTable = data[headerSize + bitmapSize + tableSize:headerSize + bitmapSize + 2 * tableSize]
    if len(owTable) <> tableSize:
      raise ValueError, 'invalid NFNT format'
    
    # fill tables
    self.offsetTable = []
    self.widthTable = []
    self.locTable = []
    for i in range(0, tableSize, 2):
      self.offsetTable.append(ord(owTable[i]))
      self.widthTable.append(ord(owTable[i+1]))
      loc, = struct.unpack("h", locTable[i:i+2])
      self.locTable.append(loc)
  
  def compile(self):
    header = sstruct.pack(nfntHeaderFormat, self)
    nEntries = len(self.widthTable)
    owTable = [None] * nEntries
    locTable = [None] * nEntries
    for i in range(nEntries):
      owTable[i] = chr(self.offsetTable[i]) + chr(self.widthTable[i])
      locTable[i] = struct.pack("h", self.locTable[i])
    owTable = string.join(owTable, "")
    locTable = string.join(locTable, "")
    assert len(locTable) == len(owTable) == 2 * (self.lastChar - self.firstChar + 3)
    return header + self.bits + locTable + owTable
  
  def unpackGlyphs(self):
    import numpy
    nGlyphs = len(self.locTable) - 1
    self.glyphs = [None] * nGlyphs
    
    rowBytes = self.rowWords * 2
    imageWidth = self.rowWords * 16
    imageHeight = self.fRectHeight
    bits = self.bits
    bitImage = numpy.zeros((imageWidth, imageHeight), numpy.int8)
    
    for y in range(imageHeight):
      for xByte in range(rowBytes):
        byte = bits[y * rowBytes + xByte]
        for xBit in range(8):
          x = 8 * xByte + xBit
          bit = (ord(byte) >> (7 - xBit)) & 0x01
          bitImage[x, y] = bit
    
    for i in range(nGlyphs):
      width = self.widthTable[i]
      offset = self.offsetTable[i]
      if width == 255 and offset == 255:
        self.glyphs[i] = None
      else:
        imageL = self.locTable[i]
        imageR = self.locTable[i+1]
        imageWidth = imageR - imageL
        offset = offset + self.kernMax
        self.glyphs[i] = glyph = Glyph(width, offset, bitImage[imageL:imageR])
  
  def packGlyphs(self):
    import numpy
    imageWidth = 0
    kernMax = 0
    imageHeight = None
    widMax = 0
    fRectWidth = 0
    for glyph in self.glyphs:
      if glyph is None:
        continue
      if imageHeight is None:
        imageHeight = glyph.pixels.shape[1]
      else:
        assert imageHeight == glyph.pixels.shape[1]
      imageWidth = imageWidth + glyph.pixels.shape[0]
      kernMax = min(kernMax, glyph.offset)
      widMax = max(widMax, glyph.width)
      fRectWidth = max(fRectWidth, glyph.pixels.shape[0] + glyph.offset)
    
    fRectWidth = fRectWidth - kernMax
    imageWidth = 16 * ((imageWidth - 1) / 16 + 1)
    rowBytes = imageWidth / 8
    rowWords = rowBytes / 2
    bitImage = numpy.zeros((imageWidth, imageHeight), numpy.int8)
    locTable = []
    widthTable = []
    offsetTable = []
    loc = 0
    for glyph in self.glyphs:
      locTable.append(loc)
      if glyph is None:
        widthTable.append(255)
        offsetTable.append(255)
        continue
      widthTable.append(glyph.width)
      offsetTable.append(glyph.offset - kernMax)
      imageWidth = glyph.pixels.shape[0]
      bitImage[loc:loc+imageWidth] = glyph.pixels
      loc = loc + imageWidth
    
    locTable.append(loc)
    widthTable.append(255)
    offsetTable.append(255)
    
    bits = []
    for y in range(imageHeight):
      for xByte in range(rowBytes):
        byte = 0
        for x in range(8):
          byte = byte | ((bitImage[8 * xByte + x, y] & 0x01) << (7 - x))
        bits.append(chr(byte))
    bits = string.join(bits, "")
    
    # assign values
    self.fontType = 0x9000
    self.lastChar = self.firstChar + len(self.glyphs) - 2
    self.widMax = widMax
    self.kernMax = kernMax
    self.descent = imageHeight - self.ascent
    self.nDescent = -self.descent
    self.fRectWidth = fRectWidth
    self.fRectHeight = imageHeight
    self.rowWords = rowWords
    
    tableSize = 2 * (self.lastChar - self.firstChar + 3)
    self.owTLoc = (headerSize + len(bits) + tableSize - 16) / 2
    
    self.bits = bits
    self.locTable = locTable
    self.widthTable = widthTable
    self.offsetTable = offsetTable
  
  def getMissing(self):
    return self.glyphs[-1]
  
  def __getitem__(self, charNum):
    if charNum > self.lastChar or charNum < 0:
      raise IndexError, "no such character"
    index = charNum - self.firstChar
    if index < 0:
      return None
    return self.glyphs[index]
  
  def __setitem__(self, charNum, glyph):
    if charNum > self.lastChar or charNum < 0:
      raise IndexError, "no such character"
    index = charNum - self.firstChar
    if index < 0:
      raise IndexError, "no such character"
    self.glyphs[index] = glyph
  
  def __len__(self):
    return len(self.locTable) - 2 + self.firstChar
  
  #
  # XXX old cruft
  #
  
  def createQdBitImage(self):
    import Qd
    self.bitImage = Qd.BitMap(self.bits, 2 * self.rowWords, (0, 0, self.rowWords * 16, self.fRectHeight))
  
  def drawstring(self, astring, destbits, xOffset=0, yOffset=0):
    drawchar = self.drawchar
    for ch in astring:
      xOffset = drawchar(ch, destbits, xOffset, yOffset)
    return xOffset
  
  def drawchar(self, ch, destbits, xOffset, yOffset=0):
    import Qd
    width, bounds, destbounds = self.getcharbounds(ch)
    destbounds = Qd.OffsetRect(destbounds, xOffset, yOffset)
    Qd.CopyBits(self.bitImage, destbits, bounds, destbounds, 1, None)
    return xOffset + width
  
  def stringwidth(self, astring):
    charwidth = self.charwidth
    width = 0
    for ch in astring:
      width = width + charwidth(ch)
    return width
  
  def charwidth(self, ch):
    cindex = ord(ch) - self.firstChar
    if cindex > self.lastChar or   \
        (self.offsetTable[cindex] == 255 and self.widthTable[cindex] == 255):
      cindex = -2    # missing char
    return self.widthTable[cindex]
  
  def getcharbounds(self, ch):
    cindex = ord(ch) - self.firstChar
    if cindex > self.lastChar or   \
        (self.offsetTable[cindex] == 255 and self.widthTable[cindex] == 255):
      return self.getcharboundsindex(-2)  # missing char
    return self.getcharboundsindex(cindex)
  
  def getcharboundsindex(self, cindex):
    offset = self.offsetTable[cindex]
    width = self.widthTable[cindex]
    if offset == 255 and width == 255:
      raise ValueError, "character not defined"
    location0 = self.locTable[cindex]
    location1 = self.locTable[cindex + 1]
    srcbounds = (location0, 0, location1, self.fRectHeight)
    destbounds = (  offset + self.kernMax, 
          0, 
          offset + self.kernMax + location1 - location0, 
          self.fRectHeight  )
    return width, srcbounds, destbounds


class Glyph:
  
  def __init__(self, width, offset, pixels=None, pixelDepth=1):
    self.width = width
    self.offset = offset
    self.pixelDepth = pixelDepth
    self.pixels = pixels


def dataFromFile(pathOrFSSpec, nameOrID="", resType='NFNT'):
  from Carbon import Res
  import macfs
  if type(pathOrFSSpec) == types.StringType:
    fss = macfs.FSSpec(pathOrFSSpec)
  else:
    fss = pathOrFSSpec
  resref = Res.FSpOpenResFile(fss, 1)  # readonly
  try:
    Res.UseResFile(resref)
    if not nameOrID:
      # just take the first in the file
      res = Res.Get1IndResource(resType, 1)
    elif type(nameOrID) == types.IntType:
      res = Res.Get1Resource(resType, nameOrID)
    else:
      res = Res.Get1NamedResource(resType, nameOrID)
    theID, theType, name = res.GetResInfo()
    data = res.data
  finally:
    Res.CloseResFile(resref)
  return data


def fromFile(pathOrFSSpec, nameOrID="", resType='NFNT'):
  data = dataFromFile(pathOrFSSpec, nameOrID, resType)
  return NFNT(data)


if __name__ == "__main__":
  import macfs
  fss, ok = macfs.StandardGetFile('FFIL')
  if ok:
    data = dataFromFile(fss)
    font = NFNT(data)
    font.unpackGlyphs()
    font.packGlyphs()
    data2 = font.compile()
    print "xxxxx", data == data2, len(data) == len(data2)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.