pyglet at 2.0!!!!!!!!!!
This commit is contained in:
parent
7343edc8a8
commit
d67b35e40a
@ -44,10 +44,10 @@ import sys
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
#: The release version
|
#: The release version
|
||||||
version = '2.0.b2'
|
version = '2.0.0'
|
||||||
__version__ = version
|
__version__ = version
|
||||||
|
|
||||||
MIN_PYTHON_VERSION = 3, 7
|
MIN_PYTHON_VERSION = 3, 8
|
||||||
MIN_PYTHON_VERSION_STR = '.'.join([str(v) for v in MIN_PYTHON_VERSION])
|
MIN_PYTHON_VERSION_STR = '.'.join([str(v) for v in MIN_PYTHON_VERSION])
|
||||||
|
|
||||||
if sys.version_info < MIN_PYTHON_VERSION:
|
if sys.version_info < MIN_PYTHON_VERSION:
|
||||||
@ -198,7 +198,7 @@ _option_types = {
|
|||||||
for key in options:
|
for key in options:
|
||||||
"""Read defaults for options from environment"""
|
"""Read defaults for options from environment"""
|
||||||
assert key in _option_types, f"Option '{key}' must have a type set in _option_types."
|
assert key in _option_types, f"Option '{key}' must have a type set in _option_types."
|
||||||
env = f'PYGLET_{key.upper()}'
|
env = 'PYGLET_%s' % key.upper()
|
||||||
try:
|
try:
|
||||||
value = os.environ[env]
|
value = os.environ[env]
|
||||||
if _option_types[key] is tuple:
|
if _option_types[key] is tuple:
|
||||||
@ -265,21 +265,21 @@ def _trace_frame(thread, frame, indent):
|
|||||||
filename = os.path.join('...', filename)
|
filename = os.path.join('...', filename)
|
||||||
_trace_filename_abbreviations[path] = filename
|
_trace_filename_abbreviations[path] = filename
|
||||||
|
|
||||||
location = f'({filename}:{line})'
|
location = '(%s:%d)' % (filename, line)
|
||||||
|
|
||||||
if indent:
|
if indent:
|
||||||
name = f'Called from {name}'
|
name = 'Called from %s' % name
|
||||||
print(f'[{thread}] {indent}{name} {location}')
|
print('[%d] %s%s %s' % (thread, indent, name, location))
|
||||||
|
|
||||||
if _trace_args:
|
if _trace_args:
|
||||||
if is_ctypes:
|
if is_ctypes:
|
||||||
args = [_trace_repr(arg) for arg in frame.f_locals['args']]
|
args = [_trace_repr(arg) for arg in frame.f_locals['args']]
|
||||||
print(f' {indent}args=({", ".join(args)})')
|
print(' %sargs=(%s)' % (indent, ', '.join(args)))
|
||||||
else:
|
else:
|
||||||
for argname in code.co_varnames[:code.co_argcount]:
|
for argname in code.co_varnames[:code.co_argcount]:
|
||||||
try:
|
try:
|
||||||
argvalue = _trace_repr(frame.f_locals[argname])
|
argvalue = _trace_repr(frame.f_locals[argname])
|
||||||
print(f' {indent}{argname}={argvalue}')
|
print(' %s%s=%s' % (indent, argname, argvalue))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -335,7 +335,7 @@ class _ModuleProxy:
|
|||||||
if self._module is not None:
|
if self._module is not None:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
import_name = f'pyglet.{self._module_name}'
|
import_name = 'pyglet.%s' % self._module_name
|
||||||
__import__(import_name)
|
__import__(import_name)
|
||||||
module = sys.modules[import_name]
|
module = sys.modules[import_name]
|
||||||
object.__setattr__(self, '_module', module)
|
object.__setattr__(self, '_module', module)
|
||||||
@ -349,7 +349,7 @@ class _ModuleProxy:
|
|||||||
if self._module is not None:
|
if self._module is not None:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
import_name = f'pyglet.{self._module_name}'
|
import_name = 'pyglet.%s' % self._module_name
|
||||||
__import__(import_name)
|
__import__(import_name)
|
||||||
module = sys.modules[import_name]
|
module = sys.modules[import_name]
|
||||||
object.__setattr__(self, '_module', module)
|
object.__setattr__(self, '_module', module)
|
||||||
|
@ -340,7 +340,9 @@ class ScreenMode:
|
|||||||
self.screen = screen
|
self.screen = screen
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.__class__.__name__}(width={self.width!r}, height={self.height!r}, depth={self.depth!r}, rate={self.rate})'
|
return '%s(width=%r, height=%r, depth=%r, rate=%r)' % (
|
||||||
|
self.__class__.__name__,
|
||||||
|
self.width, self.height, self.depth, self.rate)
|
||||||
|
|
||||||
|
|
||||||
class Canvas:
|
class Canvas:
|
||||||
|
@ -56,7 +56,7 @@ class HeadlessDisplay(Display):
|
|||||||
if num_devices.value > 0:
|
if num_devices.value > 0:
|
||||||
headless_device = pyglet.options['headless_device']
|
headless_device = pyglet.options['headless_device']
|
||||||
if headless_device < 0 or headless_device >= num_devices.value:
|
if headless_device < 0 or headless_device >= num_devices.value:
|
||||||
raise ValueError(f'Invalid EGL devide id: {headless_device}')
|
raise ValueError('Invalid EGL devide id: %d' % headless_device)
|
||||||
devices = (eglext.EGLDeviceEXT * num_devices.value)()
|
devices = (eglext.EGLDeviceEXT * num_devices.value)()
|
||||||
eglext.eglQueryDevicesEXT(num_devices.value, devices, byref(num_devices))
|
eglext.eglQueryDevicesEXT(num_devices.value, devices, byref(num_devices))
|
||||||
self._display_connection = eglext.eglGetPlatformDisplayEXT(
|
self._display_connection = eglext.eglGetPlatformDisplayEXT(
|
||||||
|
@ -134,7 +134,9 @@ class Win32ScreenMode(ScreenMode):
|
|||||||
self.scaling = mode.dmDisplayFixedOutput
|
self.scaling = mode.dmDisplayFixedOutput
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.__class__.__name__}(width={self.width!r}, height={self.height!r}, depth={self.depth!r}, rate={self.rate}, scaling={self.scaling})'
|
return '%s(width=%r, height=%r, depth=%r, rate=%r, scaling=%r)' % (
|
||||||
|
self.__class__.__name__,
|
||||||
|
self.width, self.height, self.depth, self.rate, self.scaling)
|
||||||
|
|
||||||
class Win32Canvas(Canvas):
|
class Win32Canvas(Canvas):
|
||||||
def __init__(self, display, hwnd, hdc):
|
def __init__(self, display, hwnd, hdc):
|
||||||
|
@ -120,11 +120,11 @@ class XlibDisplay(XlibSelectDevice, Display):
|
|||||||
|
|
||||||
self._display = xlib.XOpenDisplay(name)
|
self._display = xlib.XOpenDisplay(name)
|
||||||
if not self._display:
|
if not self._display:
|
||||||
raise NoSuchDisplayException(f'Cannot connect to "{name}"')
|
raise NoSuchDisplayException('Cannot connect to "%s"' % name)
|
||||||
|
|
||||||
screen_count = xlib.XScreenCount(self._display)
|
screen_count = xlib.XScreenCount(self._display)
|
||||||
if x_screen >= screen_count:
|
if x_screen >= screen_count:
|
||||||
raise NoSuchDisplayException(f'Display "{name}" has no screen {x_screen:d}')
|
raise NoSuchDisplayException('Display "%s" has no screen %d' % (name, x_screen))
|
||||||
|
|
||||||
super(XlibDisplay, self).__init__()
|
super(XlibDisplay, self).__init__()
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -274,8 +274,9 @@ class XlibScreen(Screen):
|
|||||||
self.set_mode(self._initial_mode)
|
self.set_mode(self._initial_mode)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"{self.__class__.__name__}(display={self.display!r}, x={self.x}, y={self.y}, " \
|
return 'XlibScreen(display=%r, x=%d, y=%d, ' \
|
||||||
f"width={self.width}, height={self.height}, xinerama={self._xinerama})"
|
'width=%d, height=%d, xinerama=%d)' % \
|
||||||
|
(self.display, self.x, self.y, self.width, self.height, self._xinerama)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ class EventDispatcher:
|
|||||||
# Single magically named function
|
# Single magically named function
|
||||||
name = obj.__name__
|
name = obj.__name__
|
||||||
if name not in self.event_types:
|
if name not in self.event_types:
|
||||||
raise EventException(f'Unknown event "{name}"')
|
raise EventException('Unknown event "%s"' % name)
|
||||||
if inspect.ismethod(obj):
|
if inspect.ismethod(obj):
|
||||||
yield name, WeakMethod(obj, partial(self._remove_handler, name))
|
yield name, WeakMethod(obj, partial(self._remove_handler, name))
|
||||||
else:
|
else:
|
||||||
@ -234,7 +234,7 @@ class EventDispatcher:
|
|||||||
for name, handler in kwargs.items():
|
for name, handler in kwargs.items():
|
||||||
# Function for handling given event (no magic)
|
# Function for handling given event (no magic)
|
||||||
if name not in self.event_types:
|
if name not in self.event_types:
|
||||||
raise EventException(f'Unknown event "{name}"')
|
raise EventException('Unknown event "%s"' % name)
|
||||||
if inspect.ismethod(handler):
|
if inspect.ismethod(handler):
|
||||||
yield name, WeakMethod(handler, partial(self._remove_handler, name))
|
yield name, WeakMethod(handler, partial(self._remove_handler, name))
|
||||||
else:
|
else:
|
||||||
@ -398,7 +398,7 @@ class EventDispatcher:
|
|||||||
"EventDispatcher.register_event_type('event_name')."
|
"EventDispatcher.register_event_type('event_name')."
|
||||||
)
|
)
|
||||||
assert event_type in self.event_types, \
|
assert event_type in self.event_types, \
|
||||||
f"{event_type} not found in {self}.event_types == {self.event_types}"
|
"%r not found in %r.event_types == %r" % (event_type, self, self.event_types)
|
||||||
|
|
||||||
invoked = False
|
invoked = False
|
||||||
|
|
||||||
|
@ -254,17 +254,17 @@ def check_palette(palette):
|
|||||||
for i, t in enumerate(p):
|
for i, t in enumerate(p):
|
||||||
if len(t) not in (3, 4):
|
if len(t) not in (3, 4):
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"palette entry {i}: entries must be 3- or 4-tuples.")
|
"palette entry %d: entries must be 3- or 4-tuples." % i)
|
||||||
if len(t) == 3:
|
if len(t) == 3:
|
||||||
seen_triple = True
|
seen_triple = True
|
||||||
if seen_triple and len(t) == 4:
|
if seen_triple and len(t) == 4:
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"palette entry {i}: all 4-tuples must precede all 3-tuples")
|
"palette entry %d: all 4-tuples must precede all 3-tuples" % i)
|
||||||
for x in t:
|
for x in t:
|
||||||
if int(x) != x or not(0 <= x <= 255):
|
if int(x) != x or not(0 <= x <= 255):
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"palette entry {i}: "
|
"palette entry %d: "
|
||||||
"values must be integer: 0 <= x <= 255")
|
"values must be integer: 0 <= x <= 255" % i)
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
|
||||||
@ -282,10 +282,12 @@ def check_sizes(size, width, height):
|
|||||||
"size argument should be a pair (width, height)")
|
"size argument should be a pair (width, height)")
|
||||||
if width is not None and width != size[0]:
|
if width is not None and width != size[0]:
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"size[0] ({size[0]}) and width ({width}) should match when both are used.")
|
"size[0] (%r) and width (%r) should match when both are used."
|
||||||
|
% (size[0], width))
|
||||||
if height is not None and height != size[1]:
|
if height is not None and height != size[1]:
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"size[1] ({size[1]}) and height ({height}) should match when both are used.")
|
"size[1] (%r) and height (%r) should match when both are used."
|
||||||
|
% (size[1], height))
|
||||||
return size
|
return size
|
||||||
|
|
||||||
|
|
||||||
@ -305,17 +307,17 @@ def check_color(c, greyscale, which):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
c = (c,)
|
c = (c,)
|
||||||
if len(c) != 1:
|
if len(c) != 1:
|
||||||
raise ProtocolError(f"{which} for greyscale must be 1-tuple")
|
raise ProtocolError("%s for greyscale must be 1-tuple" % which)
|
||||||
if not is_natural(c[0]):
|
if not is_natural(c[0]):
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"{which} colour for greyscale must be integer")
|
"%s colour for greyscale must be integer" % which)
|
||||||
else:
|
else:
|
||||||
if not (len(c) == 3 and
|
if not (len(c) == 3 and
|
||||||
is_natural(c[0]) and
|
is_natural(c[0]) and
|
||||||
is_natural(c[1]) and
|
is_natural(c[1]) and
|
||||||
is_natural(c[2])):
|
is_natural(c[2])):
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"{which} colour must be a triple of integers")
|
"%s colour must be a triple of integers" % which)
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
||||||
@ -551,7 +553,8 @@ class Writer:
|
|||||||
valid = is_natural(b) and 1 <= b <= 16
|
valid = is_natural(b) and 1 <= b <= 16
|
||||||
if not valid:
|
if not valid:
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"each bitdepth {bitdepth} must be a positive integer <= 16")
|
"each bitdepth %r must be a positive integer <= 16" %
|
||||||
|
(bitdepth,))
|
||||||
|
|
||||||
# Calculate channels, and
|
# Calculate channels, and
|
||||||
# expand bitdepth to be one element per channel.
|
# expand bitdepth to be one element per channel.
|
||||||
@ -653,7 +656,8 @@ class Writer:
|
|||||||
if wrong_length:
|
if wrong_length:
|
||||||
# Note: row numbers start at 0.
|
# Note: row numbers start at 0.
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"Expected {vpr} values but got {len(row)} values, in row {i}")
|
"Expected %d values but got %d values, in row %d" %
|
||||||
|
(vpr, len(row), i))
|
||||||
yield row
|
yield row
|
||||||
|
|
||||||
if self.interlace:
|
if self.interlace:
|
||||||
@ -664,7 +668,8 @@ class Writer:
|
|||||||
nrows = self.write_passes(outfile, check_rows(rows))
|
nrows = self.write_passes(outfile, check_rows(rows))
|
||||||
if nrows != self.height:
|
if nrows != self.height:
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"rows supplied ({nrows}) does not match height ({self.height})")
|
"rows supplied (%d) does not match height (%d)" %
|
||||||
|
(nrows, self.height))
|
||||||
return nrows
|
return nrows
|
||||||
|
|
||||||
def write_passes(self, outfile, rows):
|
def write_passes(self, outfile, rows):
|
||||||
@ -775,7 +780,8 @@ class Writer:
|
|||||||
if self.rescale:
|
if self.rescale:
|
||||||
write_chunk(
|
write_chunk(
|
||||||
outfile, b'sBIT',
|
outfile, b'sBIT',
|
||||||
struct.pack(f'{self.planes,* [s[0] for s in self.rescale]}B' ))
|
struct.pack('%dB' % self.planes,
|
||||||
|
* [s[0] for s in self.rescale]))
|
||||||
|
|
||||||
# :chunk:order: Without a palette (PLTE chunk),
|
# :chunk:order: Without a palette (PLTE chunk),
|
||||||
# ordering is relatively relaxed.
|
# ordering is relatively relaxed.
|
||||||
@ -991,7 +997,7 @@ def unpack_rows(rows):
|
|||||||
to being a sequence of bytes.
|
to being a sequence of bytes.
|
||||||
"""
|
"""
|
||||||
for row in rows:
|
for row in rows:
|
||||||
fmt = f'!{len(row)}'
|
fmt = '!%dH' % len(row)
|
||||||
yield bytearray(struct.pack(fmt, *row))
|
yield bytearray(struct.pack(fmt, *row))
|
||||||
|
|
||||||
|
|
||||||
@ -1181,7 +1187,8 @@ def from_array(a, mode=None, info={}):
|
|||||||
if bitdepth:
|
if bitdepth:
|
||||||
if info.get("bitdepth") and bitdepth != info['bitdepth']:
|
if info.get("bitdepth") and bitdepth != info['bitdepth']:
|
||||||
raise ProtocolError(
|
raise ProtocolError(
|
||||||
f"bitdepth ({bitdepth}) should match bitdepth of info ({info[bitdepth]}).")
|
"bitdepth (%d) should match bitdepth of info (%d)." %
|
||||||
|
(bitdepth, info['bitdepth']))
|
||||||
info['bitdepth'] = bitdepth
|
info['bitdepth'] = bitdepth
|
||||||
|
|
||||||
# Fill in and/or check entries in *info*.
|
# Fill in and/or check entries in *info*.
|
||||||
@ -1376,17 +1383,19 @@ class Reader:
|
|||||||
data = self.file.read(length)
|
data = self.file.read(length)
|
||||||
if len(data) != length:
|
if len(data) != length:
|
||||||
raise ChunkError(
|
raise ChunkError(
|
||||||
f'Chunk {type} too short for required {length} octets.')
|
'Chunk %s too short for required %i octets.'
|
||||||
|
% (type, length))
|
||||||
checksum = self.file.read(4)
|
checksum = self.file.read(4)
|
||||||
if len(checksum) != 4:
|
if len(checksum) != 4:
|
||||||
raise ChunkError(f'Chunk {type} too short for checksum.')
|
raise ChunkError('Chunk %s too short for checksum.' % type)
|
||||||
verify = zlib.crc32(type)
|
verify = zlib.crc32(type)
|
||||||
verify = zlib.crc32(data, verify)
|
verify = zlib.crc32(data, verify)
|
||||||
verify = struct.pack('!I', verify)
|
verify = struct.pack('!I', verify)
|
||||||
if checksum != verify:
|
if checksum != verify:
|
||||||
(a, ) = struct.unpack('!I', checksum)
|
(a, ) = struct.unpack('!I', checksum)
|
||||||
(b, ) = struct.unpack('!I', verify)
|
(b, ) = struct.unpack('!I', verify)
|
||||||
message = f"Checksum error in {type.decode('ascii')} chunk: 0x{a:08X} != 0x{b:08X}."
|
message = ("Checksum error in %s chunk: 0x%08X != 0x%08X."
|
||||||
|
% (type.decode('ascii'), a, b))
|
||||||
if lenient:
|
if lenient:
|
||||||
warnings.warn(message, RuntimeWarning)
|
warnings.warn(message, RuntimeWarning)
|
||||||
else:
|
else:
|
||||||
@ -1530,7 +1539,7 @@ class Reader:
|
|||||||
return bytearray(bs)
|
return bytearray(bs)
|
||||||
if self.bitdepth == 16:
|
if self.bitdepth == 16:
|
||||||
return array('H',
|
return array('H',
|
||||||
struct.unpack(f'!{(len(bs) // 2)}H' , bs))
|
struct.unpack('!%dH' % (len(bs) // 2), bs))
|
||||||
|
|
||||||
assert self.bitdepth < 8
|
assert self.bitdepth < 8
|
||||||
if width is None:
|
if width is None:
|
||||||
@ -1625,13 +1634,14 @@ class Reader:
|
|||||||
'End of file whilst reading chunk length and type.')
|
'End of file whilst reading chunk length and type.')
|
||||||
length, type = struct.unpack('!I4s', x)
|
length, type = struct.unpack('!I4s', x)
|
||||||
if length > 2 ** 31 - 1:
|
if length > 2 ** 31 - 1:
|
||||||
raise FormatError(f'Chunk {type} is too large: {length}.')
|
raise FormatError('Chunk %s is too large: %d.' % (type, length))
|
||||||
# Check that all bytes are in valid ASCII range.
|
# Check that all bytes are in valid ASCII range.
|
||||||
# https://www.w3.org/TR/2003/REC-PNG-20031110/#5Chunk-layout
|
# https://www.w3.org/TR/2003/REC-PNG-20031110/#5Chunk-layout
|
||||||
type_bytes = set(bytearray(type))
|
type_bytes = set(bytearray(type))
|
||||||
if not(type_bytes <= set(range(65, 91)) | set(range(97, 123))):
|
if not(type_bytes <= set(range(65, 91)) | set(range(97, 123))):
|
||||||
raise FormatError(
|
raise FormatError(
|
||||||
f'Chunk {list(type)} has invalid Chunk Type.')
|
'Chunk %r has invalid Chunk Type.'
|
||||||
|
% list(type))
|
||||||
return length, type
|
return length, type
|
||||||
|
|
||||||
def process_chunk(self, lenient=False):
|
def process_chunk(self, lenient=False):
|
||||||
@ -1663,17 +1673,18 @@ class Reader:
|
|||||||
|
|
||||||
if self.compression != 0:
|
if self.compression != 0:
|
||||||
raise FormatError(
|
raise FormatError(
|
||||||
f"Unknown compression method {self.compression}")
|
"Unknown compression method %d" % self.compression)
|
||||||
if self.filter != 0:
|
if self.filter != 0:
|
||||||
raise FormatError(
|
raise FormatError(
|
||||||
f"Unknown filter method {self.filter},"
|
"Unknown filter method %d,"
|
||||||
" see http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters ."
|
" see http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters ."
|
||||||
)
|
% self.filter)
|
||||||
if self.interlace not in (0, 1):
|
if self.interlace not in (0, 1):
|
||||||
raise FormatError(
|
raise FormatError(
|
||||||
f"Unknown interlace method {self.interlace}, see "
|
"Unknown interlace method %d, see "
|
||||||
"http://www.w3.org/TR/2003/REC-PNG-20031110/#8InterlaceMethods"
|
"http://www.w3.org/TR/2003/REC-PNG-20031110/#8InterlaceMethods"
|
||||||
" .")
|
" ."
|
||||||
|
% self.interlace)
|
||||||
|
|
||||||
# Derived values
|
# Derived values
|
||||||
# http://www.w3.org/TR/PNG/#6Colour-values
|
# http://www.w3.org/TR/PNG/#6Colour-values
|
||||||
@ -1722,7 +1733,7 @@ class Reader:
|
|||||||
"PLTE chunk is required before bKGD chunk.")
|
"PLTE chunk is required before bKGD chunk.")
|
||||||
self.background = struct.unpack('B', data)
|
self.background = struct.unpack('B', data)
|
||||||
else:
|
else:
|
||||||
self.background = struct.unpack(f"!{self.color_planes}",
|
self.background = struct.unpack("!%dH" % self.color_planes,
|
||||||
data)
|
data)
|
||||||
except struct.error:
|
except struct.error:
|
||||||
raise FormatError("bKGD chunk has incorrect length.")
|
raise FormatError("bKGD chunk has incorrect length.")
|
||||||
@ -1741,10 +1752,11 @@ class Reader:
|
|||||||
else:
|
else:
|
||||||
if self.alpha:
|
if self.alpha:
|
||||||
raise FormatError(
|
raise FormatError(
|
||||||
f"tRNS chunk is not valid with colour type {self.color_type}.")
|
"tRNS chunk is not valid with colour type %d." %
|
||||||
|
self.color_type)
|
||||||
try:
|
try:
|
||||||
self.transparent = \
|
self.transparent = \
|
||||||
struct.unpack(f"!{self.color_planes}", data)
|
struct.unpack("!%dH" % self.color_planes, data)
|
||||||
except struct.error:
|
except struct.error:
|
||||||
raise FormatError("tRNS chunk has incorrect length.")
|
raise FormatError("tRNS chunk has incorrect length.")
|
||||||
|
|
||||||
@ -1977,12 +1989,13 @@ class Reader:
|
|||||||
pixels = itertrns(pixels)
|
pixels = itertrns(pixels)
|
||||||
targetbitdepth = None
|
targetbitdepth = None
|
||||||
if self.sbit:
|
if self.sbit:
|
||||||
sbit = struct.unpack(f'{len(self.sbit)}', self.sbit)
|
sbit = struct.unpack('%dB' % len(self.sbit), self.sbit)
|
||||||
targetbitdepth = max(sbit)
|
targetbitdepth = max(sbit)
|
||||||
if targetbitdepth > info['bitdepth']:
|
if targetbitdepth > info['bitdepth']:
|
||||||
raise Error(f'sBIT chunk {sbit!r} exceeds bitdepth {self.bitdepth}')
|
raise Error('sBIT chunk %r exceeds bitdepth %d' %
|
||||||
|
(sbit, self.bitdepth))
|
||||||
if min(sbit) <= 0:
|
if min(sbit) <= 0:
|
||||||
raise Error(f'sBIT chunk {sbit} has a 0-entry')
|
raise Error('sBIT chunk %r has a 0-entry' % sbit)
|
||||||
if targetbitdepth:
|
if targetbitdepth:
|
||||||
shift = info['bitdepth'] - targetbitdepth
|
shift = info['bitdepth'] - targetbitdepth
|
||||||
info['bitdepth'] = targetbitdepth
|
info['bitdepth'] = targetbitdepth
|
||||||
@ -2168,23 +2181,24 @@ def check_bitdepth_colortype(bitdepth, colortype):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if bitdepth not in (1, 2, 4, 8, 16):
|
if bitdepth not in (1, 2, 4, 8, 16):
|
||||||
raise FormatError(f"invalid bit depth {bitdepth}")
|
raise FormatError("invalid bit depth %d" % bitdepth)
|
||||||
if colortype not in (0, 2, 3, 4, 6):
|
if colortype not in (0, 2, 3, 4, 6):
|
||||||
raise FormatError(f"invalid colour type {colortype}")
|
raise FormatError("invalid colour type %d" % colortype)
|
||||||
# Check indexed (palettized) images have 8 or fewer bits
|
# Check indexed (palettized) images have 8 or fewer bits
|
||||||
# per pixel; check only indexed or greyscale images have
|
# per pixel; check only indexed or greyscale images have
|
||||||
# fewer than 8 bits per pixel.
|
# fewer than 8 bits per pixel.
|
||||||
if colortype & 1 and bitdepth > 8:
|
if colortype & 1 and bitdepth > 8:
|
||||||
raise FormatError(
|
raise FormatError(
|
||||||
f"Indexed images (colour type {bitdepth}) cannot"
|
"Indexed images (colour type %d) cannot"
|
||||||
f" have bitdepth > 8 (bit depth {colortype})."
|
" have bitdepth > 8 (bit depth %d)."
|
||||||
" See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 ."
|
" See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 ."
|
||||||
)
|
% (bitdepth, colortype))
|
||||||
if bitdepth < 8 and colortype not in (0, 3):
|
if bitdepth < 8 and colortype not in (0, 3):
|
||||||
raise FormatError(
|
raise FormatError(
|
||||||
f"Illegal combination of bit depth ({bitdepth})"
|
"Illegal combination of bit depth (%d)"
|
||||||
f" and colour type ({colortype})."
|
" and colour type (%d)."
|
||||||
" See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 .")
|
" See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 ."
|
||||||
|
% (bitdepth, colortype))
|
||||||
|
|
||||||
|
|
||||||
def is_natural(x):
|
def is_natural(x):
|
||||||
|
@ -213,7 +213,7 @@ class FreeTypeFont(base.Font):
|
|||||||
def _load_font_face_from_system(self):
|
def _load_font_face_from_system(self):
|
||||||
match = get_fontconfig().find_font(self._name, self.size, self.bold, self.italic)
|
match = get_fontconfig().find_font(self._name, self.size, self.bold, self.italic)
|
||||||
if not match:
|
if not match:
|
||||||
raise base.FontException(f'Could not match font "{self._name}"')
|
raise base.FontException('Could not match font "%s"' % self._name)
|
||||||
self.face = FreeTypeFace.from_fontconfig(match)
|
self.face = FreeTypeFace.from_fontconfig(match)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -258,7 +258,7 @@ class FreeTypeFace:
|
|||||||
return cls(match.face)
|
return cls(match.face)
|
||||||
else:
|
else:
|
||||||
if not match.file:
|
if not match.file:
|
||||||
raise base.FontException(f'No filename for "{match.name}"')
|
raise base.FontException('No filename for "%s"' % match.name)
|
||||||
return cls.from_file(match.file)
|
return cls.from_file(match.file)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -402,16 +402,16 @@ class TruetypeInfo:
|
|||||||
# a fuckwit.
|
# a fuckwit.
|
||||||
header = _read_cmap_format4Header(self._data, offset)
|
header = _read_cmap_format4Header(self._data, offset)
|
||||||
seg_count = header.seg_count_x2 // 2
|
seg_count = header.seg_count_x2 // 2
|
||||||
array_size = struct.calcsize(f'>{seg_count}')
|
array_size = struct.calcsize('>%dH' % seg_count)
|
||||||
end_count = self._read_array(f'>{seg_count}',
|
end_count = self._read_array('>%dH' % seg_count,
|
||||||
offset + header.size)
|
offset + header.size)
|
||||||
start_count = self._read_array(f'>{seg_count}',
|
start_count = self._read_array('>%dH' % seg_count,
|
||||||
offset + header.size + array_size + 2)
|
offset + header.size + array_size + 2)
|
||||||
id_delta = self._read_array(f'>{seg_count}',
|
id_delta = self._read_array('>%dh' % seg_count,
|
||||||
offset + header.size + array_size + 2 + array_size)
|
offset + header.size + array_size + 2 + array_size)
|
||||||
id_range_offset_address = \
|
id_range_offset_address = \
|
||||||
offset + header.size + array_size + 2 + array_size + array_size
|
offset + header.size + array_size + 2 + array_size + array_size
|
||||||
id_range_offset = self._read_array(f'>{seg_count}',
|
id_range_offset = self._read_array('>%dH' % seg_count,
|
||||||
id_range_offset_address)
|
id_range_offset_address)
|
||||||
character_map = {}
|
character_map = {}
|
||||||
for i in range(0, seg_count):
|
for i in range(0, seg_count):
|
||||||
@ -475,7 +475,7 @@ def _read_table(*entries):
|
|||||||
setattr(self, pname, pvalue)
|
setattr(self, pname, pvalue)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '{'+', '.join([f'{pname} = {pvalue}' for pname, pvalue in self.pairs])+'}'
|
return '{'+', '.join(['%s = %s' % (pname, pvalue) for pname, pvalue in self.pairs])+'}'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def array(data, offset, count):
|
def array(data, offset, count):
|
||||||
|
@ -142,9 +142,9 @@ class GDIGlyphRenderer(Win32GlyphRenderer):
|
|||||||
|
|
||||||
if _debug_font:
|
if _debug_font:
|
||||||
_debug('%r.render(%s)' % (self, text))
|
_debug('%r.render(%s)' % (self, text))
|
||||||
_debug(f'abc.abcA = {abc.abcA}')
|
_debug('abc.abcA = %r' % abc.abcA)
|
||||||
_debug(f'abc.abcB = {abc.abcB}')
|
_debug('abc.abcB = %r' % abc.abcB)
|
||||||
_debug(f'abc.abcC = {abc.abcC}')
|
_debug('abc.abcC = %r' % abc.abcC)
|
||||||
_debug('width = %r' % width)
|
_debug('width = %r' % width)
|
||||||
_debug('height = %r' % height)
|
_debug('height = %r' % height)
|
||||||
_debug('lsb = %r' % lsb)
|
_debug('lsb = %r' % lsb)
|
||||||
|
@ -515,7 +515,7 @@ if __name__ == '__main__':
|
|||||||
print('\n'.join(fonts))
|
print('\n'.join(fonts))
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
print(f"Total: {len(font_list())}")
|
print("Total: %s" % len(font_list()))
|
||||||
|
|
||||||
|
|
||||||
# -- CHAPTER 2: WORK WITH FONT DIMENSIONS --
|
# -- CHAPTER 2: WORK WITH FONT DIMENSIONS --
|
||||||
|
@ -120,12 +120,14 @@ class VertexDomain:
|
|||||||
self.buffer_attributes = [] # list of (buffer, attributes)
|
self.buffer_attributes = [] # list of (buffer, attributes)
|
||||||
|
|
||||||
for name, meta in attribute_meta.items():
|
for name, meta in attribute_meta.items():
|
||||||
|
assert meta['format'][0] in _gl_types, f"'{meta['format']}' is not a valid atrribute format for '{name}'."
|
||||||
location = meta['location']
|
location = meta['location']
|
||||||
count = meta['count']
|
count = meta['count']
|
||||||
gl_type = _gl_types[meta['format'][0]]
|
gl_type = _gl_types[meta['format'][0]]
|
||||||
normalize = 'n' in meta['format']
|
normalize = 'n' in meta['format']
|
||||||
attribute = vertexattribute.VertexAttribute(name, location, count, gl_type, normalize)
|
attribute = vertexattribute.VertexAttribute(name, location, count, gl_type, normalize)
|
||||||
self.attributes.append(attribute)
|
self.attributes.append(attribute)
|
||||||
|
|
||||||
# Create buffer:
|
# Create buffer:
|
||||||
attribute.buffer = MappableBufferObject(attribute.stride * self.allocator.capacity)
|
attribute.buffer = MappableBufferObject(attribute.stride * self.allocator.capacity)
|
||||||
attribute.buffer.element_size = attribute.stride
|
attribute.buffer.element_size = attribute.stride
|
||||||
|
@ -79,7 +79,7 @@ def dump_python():
|
|||||||
print('os.getcwd():', os.getcwd())
|
print('os.getcwd():', os.getcwd())
|
||||||
for key, value in os.environ.items():
|
for key, value in os.environ.items():
|
||||||
if key.startswith('PYGLET_'):
|
if key.startswith('PYGLET_'):
|
||||||
print(f"os.environ['{key}']: {value}")
|
print("os.environ['%s']: %s" % (key, value))
|
||||||
|
|
||||||
|
|
||||||
def dump_pyglet():
|
def dump_pyglet():
|
||||||
@ -89,7 +89,7 @@ def dump_pyglet():
|
|||||||
print('pyglet.compat_platform:', pyglet.compat_platform)
|
print('pyglet.compat_platform:', pyglet.compat_platform)
|
||||||
print('pyglet.__file__:', pyglet.__file__)
|
print('pyglet.__file__:', pyglet.__file__)
|
||||||
for key, value in pyglet.options.items():
|
for key, value in pyglet.options.items():
|
||||||
print(f"pyglet.options['{key}'] = {value!r}")
|
print("pyglet.options['%s'] = %r" % (key, value))
|
||||||
|
|
||||||
|
|
||||||
def dump_window():
|
def dump_window():
|
||||||
@ -103,10 +103,10 @@ def dump_window():
|
|||||||
print('display:', repr(display))
|
print('display:', repr(display))
|
||||||
screens = display.get_screens()
|
screens = display.get_screens()
|
||||||
for i, screen in enumerate(screens):
|
for i, screen in enumerate(screens):
|
||||||
print(f'screens[{i}]: {screen!r}')
|
print('screens[%d]: %r' % (i, screen))
|
||||||
window = pyglet.window.Window(visible=False)
|
window = pyglet.window.Window(visible=False)
|
||||||
for key, value in window.config.get_gl_attributes():
|
for key, value in window.config.get_gl_attributes():
|
||||||
print(f"config['{key}'] = {value!r}")
|
print("config['%s'] = %r" % (key, value))
|
||||||
print('context:', repr(window.context))
|
print('context:', repr(window.context))
|
||||||
|
|
||||||
_heading('window.context._info')
|
_heading('window.context._info')
|
||||||
@ -207,9 +207,9 @@ def dump_wintab():
|
|||||||
impl_version = wintab.get_implementation_version()
|
impl_version = wintab.get_implementation_version()
|
||||||
spec_version = wintab.get_spec_version()
|
spec_version = wintab.get_spec_version()
|
||||||
|
|
||||||
print('WinTab: {0} {1}.{2} (Spec {3}.{4})'.format(interface_name,
|
print('WinTab: %s %d.%d (Spec %d.%d)' % (interface_name,
|
||||||
impl_version >> 8, impl_version & 0xff,
|
impl_version >> 8, impl_version & 0xff,
|
||||||
spec_version >> 8, spec_version & 0xff))
|
spec_version >> 8, spec_version & 0xff))
|
||||||
|
|
||||||
|
|
||||||
def _try_dump(heading, func):
|
def _try_dump(heading, func):
|
||||||
|
@ -138,7 +138,7 @@ class LibraryLoader:
|
|||||||
if self.platform.startswith('linux'):
|
if self.platform.startswith('linux'):
|
||||||
for name in names:
|
for name in names:
|
||||||
libname = self.find_library(name)
|
libname = self.find_library(name)
|
||||||
platform_names.append(libname or f'lib{name}.so')
|
platform_names.append(libname or 'lib%s.so' % name)
|
||||||
|
|
||||||
platform_names.extend(names)
|
platform_names.extend(names)
|
||||||
for name in platform_names:
|
for name in platform_names:
|
||||||
@ -165,7 +165,7 @@ class LibraryLoader:
|
|||||||
if _debug_lib:
|
if _debug_lib:
|
||||||
print(f"Unexpected error loading library {name}: {str(o)}")
|
print(f"Unexpected error loading library {name}: {str(o)}")
|
||||||
|
|
||||||
raise ImportError(f'Library "{names[0]}" not found.')
|
raise ImportError('Library "%s" not found.' % names[0])
|
||||||
|
|
||||||
def find_library(self, name):
|
def find_library(self, name):
|
||||||
return ctypes.util.find_library(name)
|
return ctypes.util.find_library(name)
|
||||||
@ -272,7 +272,7 @@ class MachOLibraryLoader(LibraryLoader):
|
|||||||
lib = _TraceLibrary(lib)
|
lib = _TraceLibrary(lib)
|
||||||
return lib
|
return lib
|
||||||
|
|
||||||
raise ImportError(f"Can't find framework {name}.")
|
raise ImportError("Can't find framework %s." % name)
|
||||||
|
|
||||||
|
|
||||||
class LinuxLibraryLoader(LibraryLoader):
|
class LinuxLibraryLoader(LibraryLoader):
|
||||||
|
@ -38,7 +38,7 @@ from ctypes import util
|
|||||||
|
|
||||||
from .cocoatypes import *
|
from .cocoatypes import *
|
||||||
|
|
||||||
__LP64__ = (8 * struct.calcsize("P") == 64)
|
__LP64__ = (8*struct.calcsize("P") == 64)
|
||||||
__i386__ = (platform.machine() == 'i386')
|
__i386__ = (platform.machine() == 'i386')
|
||||||
__arm64__ = (platform.machine() == 'arm64')
|
__arm64__ = (platform.machine() == 'arm64')
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ objc.object_getClassName.argtypes = [c_void_p]
|
|||||||
|
|
||||||
# Ivar object_getInstanceVariable(id obj, const char *name, void **outValue)
|
# Ivar object_getInstanceVariable(id obj, const char *name, void **outValue)
|
||||||
objc.object_getInstanceVariable.restype = c_void_p
|
objc.object_getInstanceVariable.restype = c_void_p
|
||||||
objc.object_getInstanceVariable.argtypes = [c_void_p, c_char_p, c_void_p]
|
objc.object_getInstanceVariable.argtypes=[c_void_p, c_char_p, c_void_p]
|
||||||
|
|
||||||
# id object_getIvar(id object, Ivar ivar)
|
# id object_getIvar(id object, Ivar ivar)
|
||||||
objc.object_getIvar.restype = c_void_p
|
objc.object_getIvar.restype = c_void_p
|
||||||
@ -366,10 +366,8 @@ objc.property_getName.argtypes = [c_void_p]
|
|||||||
objc.protocol_conformsToProtocol.restype = c_bool
|
objc.protocol_conformsToProtocol.restype = c_bool
|
||||||
objc.protocol_conformsToProtocol.argtypes = [c_void_p, c_void_p]
|
objc.protocol_conformsToProtocol.argtypes = [c_void_p, c_void_p]
|
||||||
|
|
||||||
|
|
||||||
class OBJC_METHOD_DESCRIPTION(Structure):
|
class OBJC_METHOD_DESCRIPTION(Structure):
|
||||||
_fields_ = [("name", c_void_p), ("types", c_char_p)]
|
_fields_ = [ ("name", c_void_p), ("types", c_char_p) ]
|
||||||
|
|
||||||
|
|
||||||
# struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *outCount)
|
# struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *outCount)
|
||||||
# You must free() the returned array.
|
# You must free() the returned array.
|
||||||
@ -409,7 +407,6 @@ objc.sel_isEqual.argtypes = [c_void_p, c_void_p]
|
|||||||
objc.sel_registerName.restype = c_void_p
|
objc.sel_registerName.restype = c_void_p
|
||||||
objc.sel_registerName.argtypes = [c_char_p]
|
objc.sel_registerName.argtypes = [c_char_p]
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def ensure_bytes(x):
|
def ensure_bytes(x):
|
||||||
@ -417,25 +414,20 @@ def ensure_bytes(x):
|
|||||||
return x
|
return x
|
||||||
return x.encode('ascii')
|
return x.encode('ascii')
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def get_selector(name):
|
def get_selector(name):
|
||||||
return c_void_p(objc.sel_registerName(ensure_bytes(name)))
|
return c_void_p(objc.sel_registerName(ensure_bytes(name)))
|
||||||
|
|
||||||
|
|
||||||
def get_class(name):
|
def get_class(name):
|
||||||
return c_void_p(objc.objc_getClass(ensure_bytes(name)))
|
return c_void_p(objc.objc_getClass(ensure_bytes(name)))
|
||||||
|
|
||||||
|
|
||||||
def get_object_class(obj):
|
def get_object_class(obj):
|
||||||
return c_void_p(objc.object_getClass(obj))
|
return c_void_p(objc.object_getClass(obj))
|
||||||
|
|
||||||
|
|
||||||
def get_metaclass(name):
|
def get_metaclass(name):
|
||||||
return c_void_p(objc.objc_getMetaClass(ensure_bytes(name)))
|
return c_void_p(objc.objc_getMetaClass(ensure_bytes(name)))
|
||||||
|
|
||||||
|
|
||||||
def get_superclass_of_object(obj):
|
def get_superclass_of_object(obj):
|
||||||
cls = c_void_p(objc.object_getClass(obj))
|
cls = c_void_p(objc.object_getClass(obj))
|
||||||
return c_void_p(objc.class_getSuperclass(cls))
|
return c_void_p(objc.class_getSuperclass(cls))
|
||||||
@ -454,7 +446,6 @@ def x86_should_use_stret(restype):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
# http://www.sealiesoftware.com/blog/archive/2008/11/16/objc_explain_objc_msgSend_fpret.html
|
# http://www.sealiesoftware.com/blog/archive/2008/11/16/objc_explain_objc_msgSend_fpret.html
|
||||||
def should_use_fpret(restype):
|
def should_use_fpret(restype):
|
||||||
"""Determine if objc_msgSend_fpret is required to return a floating point type."""
|
"""Determine if objc_msgSend_fpret is required to return a floating point type."""
|
||||||
@ -468,7 +459,6 @@ def should_use_fpret(restype):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# By default, assumes that restype is c_void_p
|
# By default, assumes that restype is c_void_p
|
||||||
# and that all arguments are wrapped inside c_void_p.
|
# and that all arguments are wrapped inside c_void_p.
|
||||||
# Use the restype and argtypes keyword arguments to
|
# Use the restype and argtypes keyword arguments to
|
||||||
@ -480,7 +470,7 @@ def send_message(receiver, selName, *args, **kwargs):
|
|||||||
receiver = get_class(receiver)
|
receiver = get_class(receiver)
|
||||||
selector = get_selector(selName)
|
selector = get_selector(selName)
|
||||||
restype = kwargs.get('restype', c_void_p)
|
restype = kwargs.get('restype', c_void_p)
|
||||||
# print('send_message', receiver, selName, args, kwargs)
|
#print('send_message', receiver, selName, args, kwargs)
|
||||||
argtypes = kwargs.get('argtypes', [])
|
argtypes = kwargs.get('argtypes', [])
|
||||||
# Choose the correct version of objc_msgSend based on return type.
|
# Choose the correct version of objc_msgSend based on return type.
|
||||||
if should_use_fpret(restype):
|
if should_use_fpret(restype):
|
||||||
@ -499,14 +489,11 @@ def send_message(receiver, selName, *args, **kwargs):
|
|||||||
result = c_void_p(result)
|
result = c_void_p(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class OBJC_SUPER(Structure):
|
class OBJC_SUPER(Structure):
|
||||||
_fields_ = [('receiver', c_void_p), ('class', c_void_p)]
|
_fields_ = [ ('receiver', c_void_p), ('class', c_void_p) ]
|
||||||
|
|
||||||
|
|
||||||
OBJC_SUPER_PTR = POINTER(OBJC_SUPER)
|
OBJC_SUPER_PTR = POINTER(OBJC_SUPER)
|
||||||
|
|
||||||
|
|
||||||
# http://stackoverflow.com/questions/3095360/what-exactly-is-super-in-objective-c
|
# http://stackoverflow.com/questions/3095360/what-exactly-is-super-in-objective-c
|
||||||
#
|
#
|
||||||
# `superclass_name` is optional and can be used to force finding the superclass
|
# `superclass_name` is optional and can be used to force finding the superclass
|
||||||
@ -534,12 +521,10 @@ def send_super(receiver, selName, *args, superclass_name=None, **kwargs):
|
|||||||
result = c_void_p(result)
|
result = c_void_p(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
cfunctype_table = {}
|
cfunctype_table = {}
|
||||||
|
|
||||||
|
|
||||||
def parse_type_encoding(encoding):
|
def parse_type_encoding(encoding):
|
||||||
"""Takes a type encoding string and outputs a list of the separated type codes.
|
"""Takes a type encoding string and outputs a list of the separated type codes.
|
||||||
Currently does not handle unions or bitfields and strips out any field width
|
Currently does not handle unions or bitfields and strips out any field width
|
||||||
@ -551,7 +536,7 @@ def parse_type_encoding(encoding):
|
|||||||
parse_type_encoding('{CGSize=dd}40@0:8{CGSize=dd}16Q32') --> ['{CGSize=dd}', '@', ':', '{CGSize=dd}', 'Q']
|
parse_type_encoding('{CGSize=dd}40@0:8{CGSize=dd}16Q32') --> ['{CGSize=dd}', '@', ':', '{CGSize=dd}', 'Q']
|
||||||
"""
|
"""
|
||||||
type_encodings = []
|
type_encodings = []
|
||||||
brace_count = 0 # number of unclosed curly braces
|
brace_count = 0 # number of unclosed curly braces
|
||||||
bracket_count = 0 # number of unclosed square brackets
|
bracket_count = 0 # number of unclosed square brackets
|
||||||
typecode = b''
|
typecode = b''
|
||||||
for c in encoding:
|
for c in encoding:
|
||||||
@ -570,7 +555,7 @@ def parse_type_encoding(encoding):
|
|||||||
elif c == b'}':
|
elif c == b'}':
|
||||||
typecode += c
|
typecode += c
|
||||||
brace_count -= 1
|
brace_count -= 1
|
||||||
assert (brace_count >= 0)
|
assert(brace_count >= 0)
|
||||||
elif c == b'[':
|
elif c == b'[':
|
||||||
# Check if this marked the end of previous type code.
|
# Check if this marked the end of previous type code.
|
||||||
if typecode and typecode[-1:] != b'^' and brace_count == 0 and bracket_count == 0:
|
if typecode and typecode[-1:] != b'^' and brace_count == 0 and bracket_count == 0:
|
||||||
@ -581,7 +566,7 @@ def parse_type_encoding(encoding):
|
|||||||
elif c == b']':
|
elif c == b']':
|
||||||
typecode += c
|
typecode += c
|
||||||
bracket_count -= 1
|
bracket_count -= 1
|
||||||
assert (bracket_count >= 0)
|
assert(bracket_count >= 0)
|
||||||
elif brace_count or bracket_count:
|
elif brace_count or bracket_count:
|
||||||
# Anything encountered while inside braces or brackets gets stuck on.
|
# Anything encountered while inside braces or brackets gets stuck on.
|
||||||
typecode += c
|
typecode += c
|
||||||
@ -619,12 +604,12 @@ def cfunctype_for_encoding(encoding):
|
|||||||
return cfunctype_table[encoding]
|
return cfunctype_table[encoding]
|
||||||
|
|
||||||
# Otherwise, create a new CFUNCTYPE for the encoding.
|
# Otherwise, create a new CFUNCTYPE for the encoding.
|
||||||
typecodes = {b'c': c_char, b'i': c_int, b's': c_short, b'l': c_long, b'q': c_longlong,
|
typecodes = {b'c':c_char, b'i':c_int, b's':c_short, b'l':c_long, b'q':c_longlong,
|
||||||
b'C': c_ubyte, b'I': c_uint, b'S': c_ushort, b'L': c_ulong, b'Q': c_ulonglong,
|
b'C':c_ubyte, b'I':c_uint, b'S':c_ushort, b'L':c_ulong, b'Q':c_ulonglong,
|
||||||
b'f': c_float, b'd': c_double, b'B': c_bool, b'v': None, b'*': c_char_p,
|
b'f':c_float, b'd':c_double, b'B':c_bool, b'v':None, b'*':c_char_p,
|
||||||
b'@': c_void_p, b'#': c_void_p, b':': c_void_p, NSPointEncoding: NSPoint,
|
b'@':c_void_p, b'#':c_void_p, b':':c_void_p, NSPointEncoding:NSPoint,
|
||||||
NSSizeEncoding: NSSize, NSRectEncoding: NSRect, NSRangeEncoding: NSRange,
|
NSSizeEncoding:NSSize, NSRectEncoding:NSRect, NSRangeEncoding:NSRange,
|
||||||
PyObjectEncoding: py_object}
|
PyObjectEncoding:py_object}
|
||||||
argtypes = []
|
argtypes = []
|
||||||
for code in parse_type_encoding(encoding):
|
for code in parse_type_encoding(encoding):
|
||||||
if code in typecodes:
|
if code in typecodes:
|
||||||
@ -642,7 +627,6 @@ def cfunctype_for_encoding(encoding):
|
|||||||
cfunctype_table[encoding] = cfunctype
|
cfunctype_table[encoding] = cfunctype
|
||||||
return cfunctype
|
return cfunctype
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
# After calling create_subclass, you must first register
|
# After calling create_subclass, you must first register
|
||||||
@ -654,11 +638,9 @@ def create_subclass(superclass, name):
|
|||||||
superclass = get_class(superclass)
|
superclass = get_class(superclass)
|
||||||
return c_void_p(objc.objc_allocateClassPair(superclass, ensure_bytes(name), 0))
|
return c_void_p(objc.objc_allocateClassPair(superclass, ensure_bytes(name), 0))
|
||||||
|
|
||||||
|
|
||||||
def register_subclass(subclass):
|
def register_subclass(subclass):
|
||||||
objc.objc_registerClassPair(subclass)
|
objc.objc_registerClassPair(subclass)
|
||||||
|
|
||||||
|
|
||||||
# types is a string encoding the argument types of the method.
|
# types is a string encoding the argument types of the method.
|
||||||
# The first type code of types is the return type (e.g. 'v' if void)
|
# The first type code of types is the return type (e.g. 'v' if void)
|
||||||
# The second type code must be '@' for id self.
|
# The second type code must be '@' for id self.
|
||||||
@ -666,8 +648,8 @@ def register_subclass(subclass):
|
|||||||
# Additional type codes are for types of other arguments if any.
|
# Additional type codes are for types of other arguments if any.
|
||||||
def add_method(cls, selName, method, types):
|
def add_method(cls, selName, method, types):
|
||||||
type_encodings = parse_type_encoding(types)
|
type_encodings = parse_type_encoding(types)
|
||||||
assert (type_encodings[1] == b'@') # ensure id self typecode
|
assert(type_encodings[1] == b'@') # ensure id self typecode
|
||||||
assert (type_encodings[2] == b':') # ensure SEL cmd typecode
|
assert(type_encodings[2] == b':') # ensure SEL cmd typecode
|
||||||
selector = get_selector(selName)
|
selector = get_selector(selName)
|
||||||
cfunctype = cfunctype_for_encoding(types)
|
cfunctype = cfunctype_for_encoding(types)
|
||||||
imp = cfunctype(method)
|
imp = cfunctype(method)
|
||||||
@ -675,22 +657,18 @@ def add_method(cls, selName, method, types):
|
|||||||
objc.class_addMethod(cls, selector, imp, types)
|
objc.class_addMethod(cls, selector, imp, types)
|
||||||
return imp
|
return imp
|
||||||
|
|
||||||
|
|
||||||
def add_ivar(cls, name, vartype):
|
def add_ivar(cls, name, vartype):
|
||||||
return objc.class_addIvar(cls, ensure_bytes(name), sizeof(vartype), alignment(vartype), encoding_for_ctype(vartype))
|
return objc.class_addIvar(cls, ensure_bytes(name), sizeof(vartype), alignment(vartype), encoding_for_ctype(vartype))
|
||||||
|
|
||||||
|
|
||||||
def set_instance_variable(obj, varname, value, vartype):
|
def set_instance_variable(obj, varname, value, vartype):
|
||||||
objc.object_setInstanceVariable.argtypes = [c_void_p, c_char_p, vartype]
|
objc.object_setInstanceVariable.argtypes = [c_void_p, c_char_p, vartype]
|
||||||
objc.object_setInstanceVariable(obj, ensure_bytes(varname), value)
|
objc.object_setInstanceVariable(obj, ensure_bytes(varname), value)
|
||||||
|
|
||||||
|
|
||||||
def get_instance_variable(obj, varname, vartype):
|
def get_instance_variable(obj, varname, vartype):
|
||||||
variable = vartype()
|
variable = vartype()
|
||||||
objc.object_getInstanceVariable(obj, ensure_bytes(varname), byref(variable))
|
objc.object_getInstanceVariable(obj, ensure_bytes(varname), byref(variable))
|
||||||
return variable.value
|
return variable.value
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
class ObjCMethod:
|
class ObjCMethod:
|
||||||
@ -699,13 +677,13 @@ class ObjCMethod:
|
|||||||
# Note, need to map 'c' to c_byte rather than c_char, because otherwise
|
# Note, need to map 'c' to c_byte rather than c_char, because otherwise
|
||||||
# ctypes converts the value into a one-character string which is generally
|
# ctypes converts the value into a one-character string which is generally
|
||||||
# not what we want at all, especially when the 'c' represents a bool var.
|
# not what we want at all, especially when the 'c' represents a bool var.
|
||||||
typecodes = {b'c': c_byte, b'i': c_int, b's': c_short, b'l': c_long, b'q': c_longlong,
|
typecodes = {b'c':c_byte, b'i':c_int, b's':c_short, b'l':c_long, b'q':c_longlong,
|
||||||
b'C': c_ubyte, b'I': c_uint, b'S': c_ushort, b'L': c_ulong, b'Q': c_ulonglong,
|
b'C':c_ubyte, b'I':c_uint, b'S':c_ushort, b'L':c_ulong, b'Q':c_ulonglong,
|
||||||
b'f': c_float, b'd': c_double, b'B': c_bool, b'v': None, b'Vv': None, b'*': c_char_p,
|
b'f':c_float, b'd':c_double, b'B':c_bool, b'v':None, b'Vv':None, b'*':c_char_p,
|
||||||
b'@': c_void_p, b'#': c_void_p, b':': c_void_p, b'^v': c_void_p, b'?': c_void_p,
|
b'@':c_void_p, b'#':c_void_p, b':':c_void_p, b'^v':c_void_p, b'?':c_void_p,
|
||||||
NSPointEncoding: NSPoint, NSSizeEncoding: NSSize, NSRectEncoding: NSRect,
|
NSPointEncoding:NSPoint, NSSizeEncoding:NSSize, NSRectEncoding:NSRect,
|
||||||
NSRangeEncoding: NSRange,
|
NSRangeEncoding:NSRange,
|
||||||
PyObjectEncoding: py_object}
|
PyObjectEncoding:py_object}
|
||||||
|
|
||||||
cfunctype_table = {}
|
cfunctype_table = {}
|
||||||
|
|
||||||
@ -728,7 +706,7 @@ class ObjCMethod:
|
|||||||
try:
|
try:
|
||||||
self.argtypes = [self.ctype_for_encoding(t) for t in self.argument_types]
|
self.argtypes = [self.ctype_for_encoding(t) for t in self.argument_types]
|
||||||
except:
|
except:
|
||||||
# print(f'no argtypes encoding for {self.name} ({self.argument_types})')
|
#print('no argtypes encoding for %s (%s)' % (self.name, self.argument_types))
|
||||||
self.argtypes = None
|
self.argtypes = None
|
||||||
# Get types for the return type.
|
# Get types for the return type.
|
||||||
try:
|
try:
|
||||||
@ -739,7 +717,7 @@ class ObjCMethod:
|
|||||||
else:
|
else:
|
||||||
self.restype = self.ctype_for_encoding(self.return_type)
|
self.restype = self.ctype_for_encoding(self.return_type)
|
||||||
except:
|
except:
|
||||||
# print(f'no restype encoding for {self.name} ({self.return_type})')
|
#print('no restype encoding for %s (%s)' % (self.name, self.return_type))
|
||||||
self.restype = None
|
self.restype = None
|
||||||
self.func = None
|
self.func = None
|
||||||
|
|
||||||
@ -808,7 +786,6 @@ class ObjCMethod:
|
|||||||
'encoding = ' + str(self.encoding))
|
'encoding = ' + str(self.encoding))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
class ObjCBoundMethod:
|
class ObjCBoundMethod:
|
||||||
@ -827,7 +804,6 @@ class ObjCBoundMethod:
|
|||||||
"""Call the method with the given arguments."""
|
"""Call the method with the given arguments."""
|
||||||
return self.method(self.objc_id, *args)
|
return self.method(self.objc_id, *args)
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
class ObjCClass:
|
class ObjCClass:
|
||||||
@ -865,9 +841,9 @@ class ObjCClass:
|
|||||||
objc_class = super(ObjCClass, cls).__new__(cls)
|
objc_class = super(ObjCClass, cls).__new__(cls)
|
||||||
objc_class.ptr = ptr
|
objc_class.ptr = ptr
|
||||||
objc_class.name = name
|
objc_class.name = name
|
||||||
objc_class.instance_methods = {} # mapping of name -> instance method
|
objc_class.instance_methods = {} # mapping of name -> instance method
|
||||||
objc_class.class_methods = {} # mapping of name -> class method
|
objc_class.class_methods = {} # mapping of name -> class method
|
||||||
objc_class._as_parameter_ = ptr # for ctypes argument passing
|
objc_class._as_parameter_ = ptr # for ctypes argument passing
|
||||||
|
|
||||||
# Store the new class in dictionary of registered classes.
|
# Store the new class in dictionary of registered classes.
|
||||||
cls._registered_classes[name] = objc_class
|
cls._registered_classes[name] = objc_class
|
||||||
@ -951,7 +927,6 @@ class ObjCClass:
|
|||||||
# Otherwise, raise an exception.
|
# Otherwise, raise an exception.
|
||||||
raise AttributeError('ObjCClass %s has no attribute %s' % (self.name, name))
|
raise AttributeError('ObjCClass %s has no attribute %s' % (self.name, name))
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
class ObjCInstance:
|
class ObjCInstance:
|
||||||
@ -1033,7 +1008,6 @@ class ObjCInstance:
|
|||||||
# Otherwise raise an exception.
|
# Otherwise raise an exception.
|
||||||
raise AttributeError('ObjCInstance %s has no attribute %s' % (self.objc_class.name, name))
|
raise AttributeError('ObjCInstance %s has no attribute %s' % (self.objc_class.name, name))
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def convert_method_arguments(encoding, args):
|
def convert_method_arguments(encoding, args):
|
||||||
@ -1050,7 +1024,6 @@ def convert_method_arguments(encoding, args):
|
|||||||
new_args.append(a)
|
new_args.append(a)
|
||||||
return new_args
|
return new_args
|
||||||
|
|
||||||
|
|
||||||
# ObjCSubclass is used to define an Objective-C subclass of an existing
|
# ObjCSubclass is used to define an Objective-C subclass of an existing
|
||||||
# class registered with the runtime. When you create an instance of
|
# class registered with the runtime. When you create an instance of
|
||||||
# ObjCSubclass, it registers the new subclass with the Objective-C
|
# ObjCSubclass, it registers the new subclass with the Objective-C
|
||||||
@ -1147,12 +1120,10 @@ class ObjCSubclass:
|
|||||||
typecodes = parse_type_encoding(encoding)
|
typecodes = parse_type_encoding(encoding)
|
||||||
typecodes.insert(1, b'@:')
|
typecodes.insert(1, b'@:')
|
||||||
encoding = b''.join(typecodes)
|
encoding = b''.join(typecodes)
|
||||||
|
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
name = f.__name__.replace('_', ':')
|
name = f.__name__.replace('_', ':')
|
||||||
self.add_method(f, name, encoding)
|
self.add_method(f, name, encoding)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
def method(self, encoding):
|
def method(self, encoding):
|
||||||
@ -1162,7 +1133,6 @@ class ObjCSubclass:
|
|||||||
typecodes = parse_type_encoding(encoding)
|
typecodes = parse_type_encoding(encoding)
|
||||||
typecodes.insert(1, b'@:')
|
typecodes.insert(1, b'@:')
|
||||||
encoding = b''.join(typecodes)
|
encoding = b''.join(typecodes)
|
||||||
|
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
def objc_method(objc_self, objc_cmd, *args):
|
def objc_method(objc_self, objc_cmd, *args):
|
||||||
py_self = ObjCInstance(objc_self)
|
py_self = ObjCInstance(objc_self)
|
||||||
@ -1174,11 +1144,9 @@ class ObjCSubclass:
|
|||||||
elif isinstance(result, ObjCInstance):
|
elif isinstance(result, ObjCInstance):
|
||||||
result = result.ptr.value
|
result = result.ptr.value
|
||||||
return result
|
return result
|
||||||
|
|
||||||
name = f.__name__.replace('_', ':')
|
name = f.__name__.replace('_', ':')
|
||||||
self.add_method(objc_method, name, encoding)
|
self.add_method(objc_method, name, encoding)
|
||||||
return objc_method
|
return objc_method
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
def classmethod(self, encoding):
|
def classmethod(self, encoding):
|
||||||
@ -1188,7 +1156,6 @@ class ObjCSubclass:
|
|||||||
typecodes = parse_type_encoding(encoding)
|
typecodes = parse_type_encoding(encoding)
|
||||||
typecodes.insert(1, b'@:')
|
typecodes.insert(1, b'@:')
|
||||||
encoding = b''.join(typecodes)
|
encoding = b''.join(typecodes)
|
||||||
|
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
def objc_class_method(objc_cls, objc_cmd, *args):
|
def objc_class_method(objc_cls, objc_cmd, *args):
|
||||||
py_cls = ObjCClass(objc_cls)
|
py_cls = ObjCClass(objc_cls)
|
||||||
@ -1200,14 +1167,11 @@ class ObjCSubclass:
|
|||||||
elif isinstance(result, ObjCInstance):
|
elif isinstance(result, ObjCInstance):
|
||||||
result = result.ptr.value
|
result = result.ptr.value
|
||||||
return result
|
return result
|
||||||
|
|
||||||
name = f.__name__.replace('_', ':')
|
name = f.__name__.replace('_', ':')
|
||||||
self.add_class_method(objc_class_method, name, encoding)
|
self.add_class_method(objc_class_method, name, encoding)
|
||||||
return objc_class_method
|
return objc_class_method
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
# Instances of DeallocationObserver are associated with every
|
# Instances of DeallocationObserver are associated with every
|
||||||
|
@ -87,7 +87,7 @@ def get_audio_driver():
|
|||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
if _debug:
|
if _debug:
|
||||||
print(f'Error importing driver {driver_name}:')
|
print('Error importing driver %s:' % driver_name)
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
else:
|
else:
|
||||||
|
@ -210,7 +210,7 @@ class PulseAudioPlayer(AbstractAudioPlayer):
|
|||||||
def _write_to_stream(self, nbytes=None):
|
def _write_to_stream(self, nbytes=None):
|
||||||
if nbytes is None:
|
if nbytes is None:
|
||||||
nbytes = self.stream.writable_size
|
nbytes = self.stream.writable_size
|
||||||
assert _debug(f'PulseAudioPlayer: Requested to write {nbytes} bytes to stream')
|
assert _debug('PulseAudioPlayer: Requested to write %d bytes to stream' % nbytes)
|
||||||
|
|
||||||
seek_mode = pa.PA_SEEK_RELATIVE
|
seek_mode = pa.PA_SEEK_RELATIVE
|
||||||
if self._clear_write:
|
if self._clear_write:
|
||||||
|
@ -101,7 +101,7 @@ class MediaThread:
|
|||||||
Time to wait, in seconds.
|
Time to wait, in seconds.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
assert _debug(f'MediaThread.sleep({timeout!r})')
|
assert _debug('MediaThread.sleep(%r)' % timeout)
|
||||||
with self._condition:
|
with self._condition:
|
||||||
if not self._stopped:
|
if not self._stopped:
|
||||||
self._condition.wait(timeout)
|
self._condition.wait(timeout)
|
||||||
|
@ -184,16 +184,16 @@ def get_settings_path(name):
|
|||||||
if 'APPDATA' in os.environ:
|
if 'APPDATA' in os.environ:
|
||||||
return os.path.join(os.environ['APPDATA'], name)
|
return os.path.join(os.environ['APPDATA'], name)
|
||||||
else:
|
else:
|
||||||
return os.path.expanduser(f'~/{name}')
|
return os.path.expanduser('~/%s' % name)
|
||||||
elif pyglet.compat_platform == 'darwin':
|
elif pyglet.compat_platform == 'darwin':
|
||||||
return os.path.expanduser(f'~/Library/Application Support/{name}')
|
return os.path.expanduser('~/Library/Application Support/%s' % name)
|
||||||
elif pyglet.compat_platform.startswith('linux'):
|
elif pyglet.compat_platform.startswith('linux'):
|
||||||
if 'XDG_CONFIG_HOME' in os.environ:
|
if 'XDG_CONFIG_HOME' in os.environ:
|
||||||
return os.path.join(os.environ['XDG_CONFIG_HOME'], name)
|
return os.path.join(os.environ['XDG_CONFIG_HOME'], name)
|
||||||
else:
|
else:
|
||||||
return os.path.expanduser(f'~/.config/{name}')
|
return os.path.expanduser('~/.config/%s' % name)
|
||||||
else:
|
else:
|
||||||
return os.path.expanduser(f'~/.{name}')
|
return os.path.expanduser('~/.%s' % name)
|
||||||
|
|
||||||
|
|
||||||
def get_data_path(name):
|
def get_data_path(name):
|
||||||
@ -225,16 +225,16 @@ def get_data_path(name):
|
|||||||
if 'APPDATA' in os.environ:
|
if 'APPDATA' in os.environ:
|
||||||
return os.path.join(os.environ['APPDATA'], name)
|
return os.path.join(os.environ['APPDATA'], name)
|
||||||
else:
|
else:
|
||||||
return os.path.expanduser(f'~/{name}')
|
return os.path.expanduser('~/%s' % name)
|
||||||
elif pyglet.compat_platform == 'darwin':
|
elif pyglet.compat_platform == 'darwin':
|
||||||
return os.path.expanduser(f'~/Library/Application Support/{name}')
|
return os.path.expanduser('~/Library/Application Support/%s' % name)
|
||||||
elif pyglet.compat_platform.startswith('linux'):
|
elif pyglet.compat_platform.startswith('linux'):
|
||||||
if 'XDG_DATA_HOME' in os.environ:
|
if 'XDG_DATA_HOME' in os.environ:
|
||||||
return os.path.join(os.environ['XDG_DATA_HOME'], name)
|
return os.path.join(os.environ['XDG_DATA_HOME'], name)
|
||||||
else:
|
else:
|
||||||
return os.path.expanduser(f'~/.local/share/{name}')
|
return os.path.expanduser('~/.local/share/%s' % name)
|
||||||
else:
|
else:
|
||||||
return os.path.expanduser(f'~/.{name}')
|
return os.path.expanduser('~/.%s' % name)
|
||||||
|
|
||||||
|
|
||||||
class Location:
|
class Location:
|
||||||
|
@ -63,7 +63,7 @@ properties determine the sprite's :py:attr:`~pyglet.sprite.Sprite.rotation`,
|
|||||||
:py:attr:`~pyglet.sprite.Sprite.scale` and
|
:py:attr:`~pyglet.sprite.Sprite.scale` and
|
||||||
:py:attr:`~pyglet.sprite.Sprite.opacity`.
|
:py:attr:`~pyglet.sprite.Sprite.opacity`.
|
||||||
|
|
||||||
By default sprite coordinates are restricted to integer values to avoid
|
By default, sprite coordinates are restricted to integer values to avoid
|
||||||
sub-pixel artifacts. If you require to use floats, for example for smoother
|
sub-pixel artifacts. If you require to use floats, for example for smoother
|
||||||
animations, you can set the ``subpixel`` parameter to ``True`` when creating
|
animations, you can set the ``subpixel`` parameter to ``True`` when creating
|
||||||
the sprite (:since: pyglet 1.2).
|
the sprite (:since: pyglet 1.2).
|
||||||
@ -256,7 +256,7 @@ class SpriteGroup(graphics.Group):
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (other.__class__ is self.__class__ and
|
return (other.__class__ is self.__class__ and
|
||||||
self.program is other.program and
|
self.program is other.program and
|
||||||
self.parent is other.parent and
|
self.parent == other.parent and
|
||||||
self.texture.target == other.texture.target and
|
self.texture.target == other.texture.target and
|
||||||
self.texture.id == other.texture.id and
|
self.texture.id == other.texture.id and
|
||||||
self.blend_src == other.blend_src and
|
self.blend_src == other.blend_src and
|
||||||
|
@ -148,7 +148,7 @@ def get_decoder(filename, mimetype=None):
|
|||||||
from pyglet.text.formats import attributed
|
from pyglet.text.formats import attributed
|
||||||
return attributed.AttributedTextDecoder()
|
return attributed.AttributedTextDecoder()
|
||||||
else:
|
else:
|
||||||
raise DocumentDecodeException(f'Unknown format "{mimetype}"')
|
raise DocumentDecodeException('Unknown format "%s"' % mimetype)
|
||||||
|
|
||||||
|
|
||||||
def load(filename, file=None, mimetype=None):
|
def load(filename, file=None, mimetype=None):
|
||||||
|
@ -487,7 +487,7 @@ class AbstractDocument(event.EventDispatcher):
|
|||||||
for element in self._elements:
|
for element in self._elements:
|
||||||
if element._position == position:
|
if element._position == position:
|
||||||
return element
|
return element
|
||||||
raise RuntimeError(f'No element at position {position}')
|
raise RuntimeError('No element at position %d' % position)
|
||||||
|
|
||||||
def set_style(self, start, end, attributes):
|
def set_style(self, start, end, attributes):
|
||||||
"""Set text style of some or all of the document.
|
"""Set text style of some or all of the document.
|
||||||
|
@ -236,7 +236,7 @@ class OrderedListBuilder(ListBuilder):
|
|||||||
mark = '?'
|
mark = '?'
|
||||||
if self.numbering == 'A':
|
if self.numbering == 'A':
|
||||||
mark = mark.upper()
|
mark = mark.upper()
|
||||||
return f'{self.prefix}{mark}{self.suffix}'
|
return '%s%s%s' % (self.prefix, mark, self.suffix)
|
||||||
elif self.numbering in 'iI':
|
elif self.numbering in 'iI':
|
||||||
try:
|
try:
|
||||||
mark = _int_to_roman(value)
|
mark = _int_to_roman(value)
|
||||||
@ -244,9 +244,9 @@ class OrderedListBuilder(ListBuilder):
|
|||||||
mark = '?'
|
mark = '?'
|
||||||
if self.numbering == 'i':
|
if self.numbering == 'i':
|
||||||
mark = mark.lower()
|
mark = mark.lower()
|
||||||
return f'{self.prefix}{mark}{self.suffix}'
|
return '%s%s%s' % (self.prefix, mark, self.suffix)
|
||||||
else:
|
else:
|
||||||
return f'{self.prefix}{value}{self.suffix}'
|
return '%s%d%s' % (self.prefix, value, self.suffix)
|
||||||
|
|
||||||
|
|
||||||
class StructuredTextDecoder(pyglet.text.DocumentDecoder):
|
class StructuredTextDecoder(pyglet.text.DocumentDecoder):
|
||||||
|
@ -180,7 +180,7 @@ def _parse_distance(distance, dpi):
|
|||||||
return int(distance)
|
return int(distance)
|
||||||
|
|
||||||
match = _distance_re.match(distance)
|
match = _distance_re.match(distance)
|
||||||
assert match, f'Could not parse distance {distance}'
|
assert match, 'Could not parse distance %s' % distance
|
||||||
if not match:
|
if not match:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ def _parse_distance(distance, dpi):
|
|||||||
elif unit == 'cm':
|
elif unit == 'cm':
|
||||||
return int(value * dpi * 0.393700787)
|
return int(value * dpi * 0.393700787)
|
||||||
else:
|
else:
|
||||||
assert False, f'Unknown distance unit {unit}'
|
assert False, 'Unknown distance unit %s' % unit
|
||||||
|
|
||||||
|
|
||||||
class _Line:
|
class _Line:
|
||||||
@ -225,7 +225,7 @@ class _Line:
|
|||||||
self.boxes = []
|
self.boxes = []
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'_Line({self.boxes})'
|
return '_Line(%r)' % self.boxes
|
||||||
|
|
||||||
def add_box(self, box):
|
def add_box(self, box):
|
||||||
self.boxes.append(box)
|
self.boxes.append(box)
|
||||||
@ -460,7 +460,7 @@ class _GlyphBox(_AbstractBox):
|
|||||||
return position
|
return position
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'_GlyphBox({self.glyphs})'
|
return '_GlyphBox(%r)' % self.glyphs
|
||||||
|
|
||||||
|
|
||||||
class _InlineElementBox(_AbstractBox):
|
class _InlineElementBox(_AbstractBox):
|
||||||
@ -495,7 +495,7 @@ class _InlineElementBox(_AbstractBox):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'_InlineElementBox({self.element})'
|
return '_InlineElementBox(%r)' % self.element
|
||||||
|
|
||||||
|
|
||||||
class _InvalidRange:
|
class _InvalidRange:
|
||||||
@ -1131,8 +1131,8 @@ class TextLayout:
|
|||||||
dz = z - self._z
|
dz = z - self._z
|
||||||
for vertex_list in self._vertex_lists:
|
for vertex_list in self._vertex_lists:
|
||||||
vertices = vertex_list.position[:]
|
vertices = vertex_list.position[:]
|
||||||
vertices[::2] = [x + dx for x in vertices[::2]]
|
vertices[::3] = [x + dx for x in vertices[::3]]
|
||||||
vertices[1::2] = [y + dy for y in vertices[1::2]]
|
vertices[1::3] = [y + dy for y in vertices[1::3]]
|
||||||
vertices[2::3] = [z + dz for z in vertices[2::3]]
|
vertices[2::3] = [z + dz for z in vertices[2::3]]
|
||||||
vertex_list.position[:] = vertices
|
vertex_list.position[:] = vertices
|
||||||
self._x = x
|
self._x = x
|
||||||
@ -2046,8 +2046,6 @@ class IncrementalTextLayout(TextLayout, EventDispatcher):
|
|||||||
self._update_scissor_area()
|
self._update_scissor_area()
|
||||||
|
|
||||||
def _update_scissor_area(self):
|
def _update_scissor_area(self):
|
||||||
if not self.document.text:
|
|
||||||
return
|
|
||||||
area = self._get_left(), self._get_bottom(self._get_lines()), self._width, self._height
|
area = self._get_left(), self._get_bottom(self._get_lines()), self._width, self._height
|
||||||
for group in self.group_cache.values():
|
for group in self.group_cache.values():
|
||||||
group.scissor_area = area
|
group.scissor_area = area
|
||||||
@ -2127,6 +2125,7 @@ class IncrementalTextLayout(TextLayout, EventDispatcher):
|
|||||||
self.invalid_flow.is_invalid() or
|
self.invalid_flow.is_invalid() or
|
||||||
self.invalid_lines.is_invalid())
|
self.invalid_lines.is_invalid())
|
||||||
|
|
||||||
|
len_groups = len(self.group_cache)
|
||||||
# Special care if there is no text:
|
# Special care if there is no text:
|
||||||
if not self.glyphs:
|
if not self.glyphs:
|
||||||
for line in self.lines:
|
for line in self.lines:
|
||||||
@ -2145,6 +2144,11 @@ class IncrementalTextLayout(TextLayout, EventDispatcher):
|
|||||||
self._update_visible_lines()
|
self._update_visible_lines()
|
||||||
self._update_vertex_lists()
|
self._update_vertex_lists()
|
||||||
|
|
||||||
|
# Update group cache areas if the count has changed. Usually if it starts with no text.
|
||||||
|
# Group cache is only cleared in a regular TextLayout. May need revisiting if that changes.
|
||||||
|
if len_groups != len(self.group_cache):
|
||||||
|
self._update_scissor_area()
|
||||||
|
|
||||||
if trigger_update_event:
|
if trigger_update_event:
|
||||||
self.dispatch_event('on_layout_update')
|
self.dispatch_event('on_layout_update')
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class _Run:
|
|||||||
self.count = count
|
self.count = count
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'Run({self.value}, {self.count})'
|
return 'Run(%r, %d)' % (self.value, self.count)
|
||||||
|
|
||||||
|
|
||||||
class RunList:
|
class RunList:
|
||||||
|
Loading…
Reference in New Issue
Block a user