You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
428 lines
14 KiB
Python
428 lines
14 KiB
Python
# ----------------------------------------------------------------------------
|
|
# 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 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: freetype_lib.py 2084 2008-05-27 12:42:19Z Alex.Holkner $'
|
|
|
|
from ctypes import *
|
|
|
|
import pyglet.lib
|
|
|
|
_libfreetype = 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
|