text: # ----------------------------------------------------------------------------
  # fos.lib.pyglet
  # Copyright (c) 2006-2008 Alex Holkner
  # All rights reserved.
  # 
  # Redistribution and use in source and binary forms, with or without
  # modification, are permitted provided that the following conditions 
  # are met:
  #
  #  * Redistributions of source code must retain the above copyright
  #    notice, this list of conditions and the following disclaimer.
  #  * Redistributions in binary form must reproduce the above copyright 
  #    notice, this list of conditions and the following disclaimer in
  #    the documentation and/or other materials provided with the
  #    distribution.
  #  * Neither the name of fos.lib.pyglet nor the names of its
  #    contributors may be used to endorse or promote products
  #    derived from this software without specific prior written
  #    permission.
  #
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  # POSSIBILITY OF SUCH DAMAGE.
  # ----------------------------------------------------------------------------
  
  '''
  '''
  
  __docformat__ = 'restructuredtext'
  __version__ = '$Id$'
  
  from ctypes import *
  from base import FontException
  import fos.lib.pyglet.lib
  
  _libfreetype = fos.lib.pyglet.lib.load_library('freetype')
  
  _font_data = {}
  
  def _get_function(name, argtypes, rtype):
      try:
          func = getattr(_libfreetype, name)
          func.argtypes = argtypes
          func.restype = rtype
          return func
      except AttributeError, e:
              raise ImportError(e)
  
  FT_Done_FreeType = _get_function('FT_Done_FreeType', [c_void_p], None)
  FT_Done_Face = _get_function('FT_Done_Face', [c_void_p], None)
  
  
  class FT_LibraryRec(Structure):
      _fields_ = [
          ('dummy', c_int),
      ]
  
      def __del__(self):
          global _library
          try:
              FT_Done_FreeType(byref(self))
              _library = None
          except:
              pass
  FT_Library = POINTER(FT_LibraryRec)
  
  class FT_Glyph_Metrics(Structure):
      _fields_ = [
          ('width', c_long),
          ('height', c_long),
          ('horiBearingX', c_long),
          ('horiBearingY', c_long),
          ('horiAdvance', c_long),
          ('vertBearingX', c_long),
          ('vertBearingY', c_long),
          ('vertAdvance', c_long),
      ]
  
      def dump(self):
          for (name, type) in self._fields_:
              print 'FT_Glyph_Metrics', name, `getattr(self, name)`
  
  class FT_Generic(Structure):
      _fields_ = [('data', c_void_p), ('finalizer', c_void_p)]
  
  class FT_BBox(Structure):
      _fields_ = [('xMin', c_long), ('yMin', c_long), ('xMax', c_long),
          ('yMax', c_long)]
  
  class FT_Vector(Structure):
      _fields_ = [('x', c_long), ('y', c_long)]
  
  class FT_Bitmap(Structure):
      _fields_ = [
          ('rows', c_int),
          ('width', c_int),
          ('pitch', c_int),
          # declaring buffer as c_char_p confuses ctypes, poor dear
          ('buffer', POINTER(c_ubyte)),
          ('num_grays', c_short),
          ('pixel_mode', c_ubyte),
          ('palette_mode', c_char),
          ('palette', c_void_p),
      ]
  
  class FT_Outline(Structure):
      _fields_ = [
          ('n_contours', c_short),      # number of contours in glyph
          ('n_points', c_short),        # number of points in the glyph
          ('points', POINTER(FT_Vector)),  # the outline's points
          ('tags', c_char_p),            # the points flags
          ('contours', POINTER(c_short)),  # the contour end points
          ('flags', c_int),             # outline masks
      ]
  
  class FT_GlyphSlotRec(Structure):
      _fields_ = [
          ('library', FT_Library),
          ('face', c_void_p),
          ('next', c_void_p),
          ('reserved', c_uint),
          ('generic', FT_Generic),
  
          ('metrics', FT_Glyph_Metrics),
          ('linearHoriAdvance', c_long),
          ('linearVertAdvance', c_long),
          ('advance', FT_Vector),
  
          ('format', c_int),
  
          ('bitmap', FT_Bitmap),
          ('bitmap_left', c_int),
          ('bitmap_top', c_int),
  
          ('outline', FT_Outline),
          ('num_subglyphs', c_uint),
          ('subglyphs', c_void_p),
  
          ('control_data', c_void_p),
          ('control_len', c_long),
  
          ('lsb_delta', c_long),
          ('rsb_delta', c_long),
          ('other', c_void_p),
          ('internal', c_void_p),
      ]
  FT_GlyphSlot = POINTER(FT_GlyphSlotRec)
  
  class FT_Size_Metrics(Structure):
      _fields_ = [
          ('x_ppem', c_ushort),    # horizontal pixels per EM
          ('y_ppem', c_ushort),    # vertical pixels per EM
  
          ('x_scale', c_long),     # two scales used to convert font units
          ('y_scale', c_long),     # to 26.6 frac. pixel coordinates
  
          ('ascender', c_long),    # ascender in 26.6 frac. pixels
          ('descender', c_long),   # descender in 26.6 frac. pixels
          ('height', c_long),      # text height in 26.6 frac. pixels
          ('max_advance', c_long), # max horizontal advance, in 26.6 pixels
      ]
  
  class FT_SizeRec(Structure):
      _fields_ = [
          ('face', c_void_p),
          ('generic', FT_Generic),
          ('metrics', FT_Size_Metrics),
          ('internal', c_void_p),
      ]
  FT_Size = POINTER(FT_SizeRec)
  
  class FT_Bitmap_Size(Structure):
      _fields_ = [
          ('height', c_ushort),
          ('width', c_ushort),
          ('size', c_long),
          ('x_ppem', c_long),
          ('y_ppem', c_long),
      ]
  
  # face_flags values
  FT_FACE_FLAG_SCALABLE          = 1 <<  0
  FT_FACE_FLAG_FIXED_SIZES       = 1 <<  1
  FT_FACE_FLAG_FIXED_WIDTH       = 1 <<  2
  FT_FACE_FLAG_SFNT              = 1 <<  3
  FT_FACE_FLAG_HORIZONTAL        = 1 <<  4
  FT_FACE_FLAG_VERTICAL          = 1 <<  5
  FT_FACE_FLAG_KERNING           = 1 <<  6
  FT_FACE_FLAG_FAST_GLYPHS       = 1 <<  7
  FT_FACE_FLAG_MULTIPLE_MASTERS  = 1 <<  8
  FT_FACE_FLAG_GLYPH_NAMES       = 1 <<  9
  FT_FACE_FLAG_EXTERNAL_STREAM   = 1 << 10
  FT_FACE_FLAG_HINTER            = 1 << 11
  
  class FT_FaceRec(Structure):
      _fields_ = [
            ('num_faces', c_long),
            ('face_index', c_long),
  
            ('face_flags', c_long),
            ('style_flags', c_long),
  
            ('num_glyphs', c_long),
            ('family_name', c_char_p),
            ('style_name', c_char_p),
  
            ('num_fixed_sizes', c_int),
            ('available_sizes', POINTER(FT_Bitmap_Size)),
  
            ('num_charmaps', c_int),
            ('charmaps', c_void_p),
  
            ('generic', FT_Generic),
  
            ('bbox', FT_BBox),
  
            ('units_per_EM', c_ushort),
            ('ascender', c_short),
            ('descender', c_short),
            ('height', c_short),
  
            ('max_advance_width', c_short),
            ('max_advance_height', c_short),
  
            ('underline_position', c_short),
            ('underline_thickness', c_short),
  
            ('glyph', FT_GlyphSlot),
            ('size', FT_Size),
            ('charmap', c_void_p),
  
            ('driver', c_void_p),
            ('memory', c_void_p),
            ('stream', c_void_p),
  
            ('sizes_list_head', c_void_p),
            ('sizes_list_tail', c_void_p),
  
            ('autohint', FT_Generic),
            ('extensions', c_void_p),
            ('internal', c_void_p),
      ]
  
      def dump(self):
          for (name, type) in self._fields_:
              print 'FT_FaceRec', name, `getattr(self, name)`
  
      def has_kerning(self):
          return self.face_flags & FT_FACE_FLAG_KERNING
  
  FT_Face = POINTER(FT_FaceRec)
  
  class Error(Exception):
      def __init__(self, message, errcode):
          self.message = message
          self.errcode = errcode
  
      def __str__(self):
          return '%s: %s (%s)'%(self.__class__.__name__, self.message,
              self._ft_errors.get(self.errcode, 'unknown error'))
      _ft_errors = {
          0x00: "no error" ,
          0x01: "cannot open resource" ,
          0x02: "unknown file format" ,
          0x03: "broken file" ,
          0x04: "invalid FreeType version" ,
          0x05: "module version is too low" ,
          0x06: "invalid argument" ,
          0x07: "unimplemented feature" ,
          0x08: "broken table" ,
          0x09: "broken offset within table" ,
          0x10: "invalid glyph index" ,
          0x11: "invalid character code" ,
          0x12: "unsupported glyph image format" ,
          0x13: "cannot render this glyph format" ,
          0x14: "invalid outline" ,
          0x15: "invalid composite glyph" ,
          0x16: "too many hints" ,
          0x17: "invalid pixel size" ,
          0x20: "invalid object handle" ,
          0x21: "invalid library handle" ,
          0x22: "invalid module handle" ,
          0x23: "invalid face handle" ,
          0x24: "invalid size handle" ,
          0x25: "invalid glyph slot handle" ,
          0x26: "invalid charmap handle" ,
          0x27: "invalid cache manager handle" ,
          0x28: "invalid stream handle" ,
          0x30: "too many modules" ,
          0x31: "too many extensions" ,
          0x40: "out of memory" ,
          0x41: "unlisted object" ,
          0x51: "cannot open stream" ,
          0x52: "invalid stream seek" ,
          0x53: "invalid stream skip" ,
          0x54: "invalid stream read" ,
          0x55: "invalid stream operation" ,
          0x56: "invalid frame operation" ,
          0x57: "nested frame access" ,
          0x58: "invalid frame read" ,
          0x60: "raster uninitialized" ,
          0x61: "raster corrupted" ,
          0x62: "raster overflow" ,
          0x63: "negative height while rastering" ,
          0x70: "too many registered caches" ,
          0x80: "invalid opcode" ,
          0x81: "too few arguments" ,
          0x82: "stack overflow" ,
          0x83: "code overflow" ,
          0x84: "bad argument" ,
          0x85: "division by zero" ,
          0x86: "invalid reference" ,
          0x87: "found debug opcode" ,
          0x88: "found ENDF opcode in execution stream" ,
          0x89: "nested DEFS" ,
          0x8A: "invalid code range" ,
          0x8B: "execution context too long" ,
          0x8C: "too many function definitions" ,
          0x8D: "too many instruction definitions" ,
          0x8E: "SFNT font table missing" ,
          0x8F: "horizontal header (hhea, table missing" ,
          0x90: "locations (loca, table missing" ,
          0x91: "name table missing" ,
          0x92: "character map (cmap, table missing" ,
          0x93: "horizontal metrics (hmtx, table missing" ,
          0x94: "PostScript (post, table missing" ,
          0x95: "invalid horizontal metrics" ,
          0x96: "invalid character map (cmap, format" ,
          0x97: "invalid ppem value" ,
          0x98: "invalid vertical metrics" ,
          0x99: "could not find context" ,
          0x9A: "invalid PostScript (post, table format" ,
          0x9B: "invalid PostScript (post, table" ,
          0xA0: "opcode syntax error" ,
          0xA1: "argument stack underflow" ,
          0xA2: "ignore" ,
          0xB0: "`STARTFONT' field missing" ,
          0xB1: "`FONT' field missing" ,
          0xB2: "`SIZE' field missing" ,
          0xB3: "`CHARS' field missing" ,
          0xB4: "`STARTCHAR' field missing" ,
          0xB5: "`ENCODING' field missing" ,
          0xB6: "`BBX' field missing" ,
          0xB7: "`BBX' too big" ,
      }
  
  FT_LOAD_RENDER = 0x4
  
  FT_F26Dot6 = c_long
  
  FT_Init_FreeType = _get_function('FT_Init_FreeType',
      [POINTER(FT_Library)], c_int)
  FT_New_Memory_Face = _get_function('FT_New_Memory_Face',
      [FT_Library, POINTER(c_byte), c_long, c_long, POINTER(FT_Face)], c_int)
  FT_New_Face = _get_function('FT_New_Face',
      [FT_Library, c_char_p, c_long, POINTER(FT_Face)], c_int)
  FT_Set_Pixel_Sizes = _get_function('FT_Set_Pixel_Sizes',
      [FT_Face, c_uint, c_uint], c_int)
  FT_Set_Char_Size = _get_function('FT_Set_Char_Size',
      [FT_Face, FT_F26Dot6, FT_F26Dot6, c_uint, c_uint], c_int)
  FT_Load_Glyph = _get_function('FT_Load_Glyph',
      [FT_Face, c_uint, c_int32], c_int)
  FT_Get_Char_Index = _get_function('FT_Get_Char_Index',
      [FT_Face, c_ulong], c_uint)
  FT_Load_Char = _get_function('FT_Load_Char',
      [FT_Face, c_ulong, c_int], c_int)
  FT_Get_Kerning = _get_function('FT_Get_Kerning',
      [FT_Face, c_uint, c_uint, c_uint, POINTER(FT_Vector)], c_int)
  
  # SFNT interface
  
  class FT_SfntName(Structure):
      _fields_ = [
          ('platform_id', c_ushort),
          ('encoding_id', c_ushort),
          ('language_id', c_ushort),
          ('name_id', c_ushort),
          ('string', POINTER(c_byte)),
          ('string_len', c_uint)
      ]
  
  FT_Get_Sfnt_Name_Count = _get_function('FT_Get_Sfnt_Name_Count',
      [FT_Face], c_uint)
  FT_Get_Sfnt_Name = _get_function('FT_Get_Sfnt_Name',
      [FT_Face, c_uint, POINTER(FT_SfntName)], c_int)
  
  TT_PLATFORM_MICROSOFT = 3
  TT_MS_ID_UNICODE_CS = 1
  TT_NAME_ID_COPYRIGHT          = 0
  TT_NAME_ID_FONT_FAMILY        = 1
  TT_NAME_ID_FONT_SUBFAMILY     = 2
  TT_NAME_ID_UNIQUE_ID          = 3
  TT_NAME_ID_FULL_NAME          = 4
  TT_NAME_ID_VERSION_STRING     = 5
  TT_NAME_ID_PS_NAME            = 6
  TT_NAME_ID_TRADEMARK          = 7
  TT_NAME_ID_MANUFACTURER       = 8
  TT_NAME_ID_DESIGNER           = 9
  TT_NAME_ID_DESCRIPTION        = 10
  TT_NAME_ID_VENDOR_URL         = 11
  TT_NAME_ID_DESIGNER_URL       = 12
  TT_NAME_ID_LICENSE            = 13
  TT_NAME_ID_LICENSE_URL        = 14
  TT_NAME_ID_PREFERRED_FAMILY   = 16
  TT_NAME_ID_PREFERRED_SUBFAMILY= 17
  TT_NAME_ID_MAC_FULL_NAME      = 18
  TT_NAME_ID_CID_FINDFONT_NAME  = 20
  
  _library = None
  def ft_get_library():
      global _library
      if not _library:
          _library = FT_Library()
          error = FT_Init_FreeType(byref(_library))
          if error:
              raise FontException(
                  'an error occurred during library initialization', error)
      return _library
  