pyglet 2.1.12__py3-none-any.whl → 3.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyglet/__init__.py +67 -61
- pyglet/__init__.pyi +15 -8
- pyglet/app/__init__.py +22 -13
- pyglet/app/async_app.py +212 -0
- pyglet/app/base.py +2 -1
- pyglet/app/{xlib.py → linux.py} +3 -3
- pyglet/config/__init__.py +101 -0
- pyglet/config/gl/__init__.py +30 -0
- pyglet/config/gl/egl.py +120 -0
- pyglet/config/gl/macos.py +262 -0
- pyglet/config/gl/windows.py +267 -0
- pyglet/config/gl/x11.py +142 -0
- pyglet/customtypes.py +43 -2
- pyglet/display/__init__.py +8 -6
- pyglet/display/base.py +3 -63
- pyglet/display/cocoa.py +12 -17
- pyglet/display/emscripten.py +39 -0
- pyglet/display/headless.py +23 -30
- pyglet/display/wayland.py +157 -0
- pyglet/display/win32.py +4 -17
- pyglet/display/xlib.py +19 -27
- pyglet/display/xlib_vidmoderestore.py +2 -2
- pyglet/enums.py +183 -0
- pyglet/event.py +0 -1
- pyglet/experimental/geoshader_sprite.py +15 -13
- pyglet/experimental/hidraw.py +6 -15
- pyglet/experimental/multitexture_sprite.py +31 -19
- pyglet/experimental/particles.py +13 -35
- pyglet/font/__init__.py +251 -85
- pyglet/font/base.py +116 -61
- pyglet/font/dwrite/__init__.py +349 -204
- pyglet/font/dwrite/dwrite_lib.py +27 -5
- pyglet/font/fontconfig.py +14 -6
- pyglet/font/freetype.py +138 -87
- pyglet/font/freetype_lib.py +19 -0
- pyglet/font/group.py +179 -0
- pyglet/font/harfbuzz/__init__.py +3 -3
- pyglet/font/pyodide_js.py +310 -0
- pyglet/font/quartz.py +319 -126
- pyglet/font/ttf.py +45 -3
- pyglet/font/user.py +14 -19
- pyglet/font/win32.py +45 -21
- pyglet/graphics/__init__.py +8 -787
- pyglet/graphics/allocation.py +115 -1
- pyglet/graphics/api/__init__.py +77 -0
- pyglet/graphics/api/base.py +299 -0
- pyglet/graphics/api/gl/__init__.py +58 -0
- pyglet/graphics/api/gl/base.py +24 -0
- pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
- pyglet/graphics/api/gl/cocoa/context.py +76 -0
- pyglet/graphics/api/gl/context.py +391 -0
- pyglet/graphics/api/gl/default_shaders.py +0 -0
- pyglet/graphics/api/gl/draw.py +627 -0
- pyglet/graphics/api/gl/egl/__init__.py +0 -0
- pyglet/graphics/api/gl/egl/context.py +92 -0
- pyglet/graphics/api/gl/enums.py +76 -0
- pyglet/graphics/api/gl/framebuffer.py +315 -0
- pyglet/graphics/api/gl/gl.py +5463 -0
- pyglet/graphics/api/gl/gl_info.py +188 -0
- pyglet/graphics/api/gl/global_opengl.py +226 -0
- pyglet/{gl → graphics/api/gl}/lib.py +34 -18
- pyglet/graphics/api/gl/shader.py +1476 -0
- pyglet/graphics/api/gl/shapes.py +55 -0
- pyglet/graphics/api/gl/sprite.py +102 -0
- pyglet/graphics/api/gl/state.py +219 -0
- pyglet/graphics/api/gl/text.py +190 -0
- pyglet/graphics/api/gl/texture.py +1526 -0
- pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
- pyglet/graphics/api/gl/vertexdomain.py +751 -0
- pyglet/graphics/api/gl/win32/__init__.py +0 -0
- pyglet/graphics/api/gl/win32/context.py +108 -0
- pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
- pyglet/graphics/api/gl/xlib/__init__.py +0 -0
- pyglet/graphics/api/gl/xlib/context.py +174 -0
- pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
- pyglet/graphics/api/gl1/__init__.py +0 -0
- pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
- pyglet/graphics/api/gl2/__init__.py +0 -0
- pyglet/graphics/api/gl2/buffer.py +320 -0
- pyglet/graphics/api/gl2/draw.py +600 -0
- pyglet/graphics/api/gl2/global_opengl.py +122 -0
- pyglet/graphics/api/gl2/shader.py +200 -0
- pyglet/graphics/api/gl2/shapes.py +51 -0
- pyglet/graphics/api/gl2/sprite.py +79 -0
- pyglet/graphics/api/gl2/text.py +175 -0
- pyglet/graphics/api/gl2/vertexdomain.py +364 -0
- pyglet/graphics/api/webgl/__init__.py +233 -0
- pyglet/graphics/api/webgl/buffer.py +302 -0
- pyglet/graphics/api/webgl/context.py +234 -0
- pyglet/graphics/api/webgl/draw.py +590 -0
- pyglet/graphics/api/webgl/enums.py +76 -0
- pyglet/graphics/api/webgl/framebuffer.py +360 -0
- pyglet/graphics/api/webgl/gl.py +1537 -0
- pyglet/graphics/api/webgl/gl_info.py +130 -0
- pyglet/graphics/api/webgl/shader.py +1346 -0
- pyglet/graphics/api/webgl/shapes.py +92 -0
- pyglet/graphics/api/webgl/sprite.py +102 -0
- pyglet/graphics/api/webgl/state.py +227 -0
- pyglet/graphics/api/webgl/text.py +187 -0
- pyglet/graphics/api/webgl/texture.py +1227 -0
- pyglet/graphics/api/webgl/vertexarray.py +54 -0
- pyglet/graphics/api/webgl/vertexdomain.py +616 -0
- pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
- pyglet/{image → graphics}/atlas.py +33 -32
- pyglet/graphics/base.py +10 -0
- pyglet/graphics/buffer.py +245 -0
- pyglet/graphics/draw.py +578 -0
- pyglet/graphics/framebuffer.py +26 -0
- pyglet/graphics/instance.py +178 -69
- pyglet/graphics/shader.py +267 -1553
- pyglet/graphics/state.py +83 -0
- pyglet/graphics/texture.py +703 -0
- pyglet/graphics/vertexdomain.py +695 -538
- pyglet/gui/ninepatch.py +10 -10
- pyglet/gui/widgets.py +120 -10
- pyglet/image/__init__.py +20 -1973
- pyglet/image/animation.py +12 -12
- pyglet/image/base.py +730 -0
- pyglet/image/codecs/__init__.py +9 -0
- pyglet/image/codecs/bmp.py +53 -30
- pyglet/image/codecs/dds.py +53 -31
- pyglet/image/codecs/gdiplus.py +38 -14
- pyglet/image/codecs/gdkpixbuf2.py +0 -2
- pyglet/image/codecs/js_image.py +99 -0
- pyglet/image/codecs/ktx2.py +161 -0
- pyglet/image/codecs/pil.py +1 -1
- pyglet/image/codecs/png.py +1 -1
- pyglet/image/codecs/wic.py +11 -2
- pyglet/info.py +26 -24
- pyglet/input/__init__.py +8 -0
- pyglet/input/base.py +163 -105
- pyglet/input/controller.py +13 -19
- pyglet/input/controller_db.py +39 -24
- pyglet/input/emscripten/__init__.py +18 -0
- pyglet/input/emscripten/gamepad_js.py +397 -0
- pyglet/input/linux/__init__.py +11 -5
- pyglet/input/linux/evdev.py +10 -11
- pyglet/input/linux/x11_xinput.py +2 -2
- pyglet/input/linux/x11_xinput_tablet.py +1 -1
- pyglet/input/macos/__init__.py +7 -2
- pyglet/input/macos/darwin_gc.py +559 -0
- pyglet/input/win32/__init__.py +1 -1
- pyglet/input/win32/directinput.py +34 -29
- pyglet/input/win32/xinput.py +11 -61
- pyglet/lib.py +3 -3
- pyglet/libs/__init__.py +1 -1
- pyglet/{gl → libs/darwin}/agl.py +1 -1
- pyglet/libs/darwin/cocoapy/__init__.py +2 -2
- pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
- pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
- pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
- pyglet/libs/darwin/cocoapy/runtime.py +81 -45
- pyglet/libs/darwin/coreaudio.py +4 -4
- pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
- pyglet/libs/darwin/quartzkey.py +1 -3
- pyglet/libs/egl/__init__.py +2 -0
- pyglet/libs/egl/egl_lib.py +576 -0
- pyglet/libs/egl/eglext.py +51 -5
- pyglet/libs/linux/__init__.py +0 -0
- pyglet/libs/linux/egl/__init__.py +0 -0
- pyglet/libs/linux/egl/eglext.py +22 -0
- pyglet/libs/linux/glx/__init__.py +0 -0
- pyglet/{gl → libs/linux/glx}/glx.py +13 -14
- pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
- pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
- pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
- pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
- pyglet/libs/linux/wayland/__init__.py +0 -0
- pyglet/libs/linux/wayland/client.py +1068 -0
- pyglet/libs/linux/wayland/lib_wayland.py +207 -0
- pyglet/libs/linux/wayland/wayland_egl.py +38 -0
- pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
- pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
- pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
- pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
- pyglet/libs/linux/x11/xrandr.py +0 -0
- pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
- pyglet/libs/shared/__init__.py +0 -0
- pyglet/libs/shared/spirv/__init__.py +0 -0
- pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
- pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
- pyglet/libs/win32/__init__.py +27 -5
- pyglet/libs/win32/constants.py +59 -48
- pyglet/libs/win32/context_managers.py +20 -3
- pyglet/libs/win32/dinput.py +105 -88
- pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
- pyglet/libs/win32/types.py +58 -23
- pyglet/{gl → libs/win32}/wgl.py +32 -25
- pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
- pyglet/media/__init__.py +9 -10
- pyglet/media/codecs/__init__.py +12 -1
- pyglet/media/codecs/base.py +99 -96
- pyglet/media/codecs/ffmpeg.py +2 -2
- pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
- pyglet/media/codecs/webaudio_pyodide.py +111 -0
- pyglet/media/drivers/__init__.py +9 -4
- pyglet/media/drivers/base.py +4 -4
- pyglet/media/drivers/openal/__init__.py +1 -1
- pyglet/media/drivers/openal/adaptation.py +3 -3
- pyglet/media/drivers/pulse/__init__.py +1 -1
- pyglet/media/drivers/pulse/adaptation.py +3 -3
- pyglet/media/drivers/pyodide_js/__init__.py +8 -0
- pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
- pyglet/media/drivers/xaudio2/adaptation.py +3 -3
- pyglet/media/player.py +276 -193
- pyglet/media/player_worker_thread.py +1 -1
- pyglet/model/__init__.py +39 -29
- pyglet/model/codecs/base.py +4 -4
- pyglet/model/codecs/gltf.py +3 -3
- pyglet/model/codecs/obj.py +71 -43
- pyglet/resource.py +129 -78
- pyglet/shapes.py +147 -177
- pyglet/sprite.py +47 -164
- pyglet/text/__init__.py +44 -54
- pyglet/text/caret.py +12 -7
- pyglet/text/document.py +19 -17
- pyglet/text/formats/html.py +2 -2
- pyglet/text/formats/structured.py +10 -40
- pyglet/text/layout/__init__.py +20 -13
- pyglet/text/layout/base.py +176 -287
- pyglet/text/layout/incremental.py +9 -10
- pyglet/text/layout/scrolling.py +7 -95
- pyglet/window/__init__.py +183 -172
- pyglet/window/cocoa/__init__.py +62 -51
- pyglet/window/cocoa/pyglet_delegate.py +2 -25
- pyglet/window/cocoa/pyglet_view.py +9 -8
- pyglet/window/dialog/__init__.py +184 -0
- pyglet/window/dialog/base.py +99 -0
- pyglet/window/dialog/darwin.py +121 -0
- pyglet/window/dialog/linux.py +72 -0
- pyglet/window/dialog/windows.py +194 -0
- pyglet/window/emscripten/__init__.py +779 -0
- pyglet/window/headless/__init__.py +44 -28
- pyglet/window/key.py +2 -0
- pyglet/window/mouse.py +2 -2
- pyglet/window/wayland/__init__.py +377 -0
- pyglet/window/win32/__init__.py +101 -46
- pyglet/window/xlib/__init__.py +104 -66
- {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
- pyglet-3.0.dev1.dist-info/RECORD +322 -0
- {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
- pyglet/gl/__init__.py +0 -208
- pyglet/gl/base.py +0 -499
- pyglet/gl/cocoa.py +0 -309
- pyglet/gl/gl.py +0 -4625
- pyglet/gl/gl.pyi +0 -2320
- pyglet/gl/gl_compat.pyi +0 -3097
- pyglet/gl/gl_info.py +0 -190
- pyglet/gl/headless.py +0 -166
- pyglet/gl/wgl_info.py +0 -36
- pyglet/gl/wglext_nv.py +0 -1096
- pyglet/gl/win32.py +0 -268
- pyglet/gl/xlib.py +0 -295
- pyglet/image/buffer.py +0 -274
- pyglet/image/codecs/s3tc.py +0 -354
- pyglet/libs/x11/xrandr.py +0 -166
- pyglet-2.1.12.dist-info/RECORD +0 -234
- /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
- /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
- /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
- /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
- /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
- {pyglet-2.1.12.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
pyglet/font/ttf.py
CHANGED
|
@@ -14,8 +14,11 @@ import codecs
|
|
|
14
14
|
import mmap
|
|
15
15
|
import os
|
|
16
16
|
import struct
|
|
17
|
+
from io import BytesIO
|
|
17
18
|
from typing import Any
|
|
18
19
|
|
|
20
|
+
from pyglet.font.base import FontException
|
|
21
|
+
|
|
19
22
|
|
|
20
23
|
class TruetypeInfo:
|
|
21
24
|
"""Information about a single Truetype face.
|
|
@@ -94,6 +97,9 @@ class TruetypeInfo:
|
|
|
94
97
|
|
|
95
98
|
self._closed = False
|
|
96
99
|
|
|
100
|
+
self._read_tables()
|
|
101
|
+
|
|
102
|
+
def _read_tables(self) -> None:
|
|
97
103
|
offsets = _read_offset_table(self._data, 0)
|
|
98
104
|
self._tables = {}
|
|
99
105
|
for table in _read_table_directory_entry.array(self._data, offsets.size, offsets.num_tables):
|
|
@@ -107,6 +113,8 @@ class TruetypeInfo:
|
|
|
107
113
|
self._character_map = None
|
|
108
114
|
self._glyph_map = None
|
|
109
115
|
self._font_selection_flags = None
|
|
116
|
+
self._weight_class = None
|
|
117
|
+
self._width_class = None
|
|
110
118
|
|
|
111
119
|
self.header = _read_head_table(self._data, self._tables["head"].offset)
|
|
112
120
|
self.horizontal_header = _read_horizontal_header(self._data, self._tables["hhea"].offset)
|
|
@@ -118,6 +126,18 @@ class TruetypeInfo:
|
|
|
118
126
|
self._font_selection_flags = OS2_table.fs_selection
|
|
119
127
|
return self._font_selection_flags
|
|
120
128
|
|
|
129
|
+
def get_weight_class(self) -> int:
|
|
130
|
+
if not self._weight_class:
|
|
131
|
+
OS2_table = _read_OS2_table(self._data, self._tables["OS/2"].offset)
|
|
132
|
+
self._weight_class = OS2_table.us_weight_class
|
|
133
|
+
return self._weight_class
|
|
134
|
+
|
|
135
|
+
def get_width_class(self) -> int:
|
|
136
|
+
if not self._width_class:
|
|
137
|
+
OS2_table = _read_OS2_table(self._data, self._tables["OS/2"].offset)
|
|
138
|
+
self._width_class = OS2_table.us_width_class
|
|
139
|
+
return self._width_class
|
|
140
|
+
|
|
121
141
|
def is_bold(self) -> bool:
|
|
122
142
|
"""Returns True iff the font describes itself as bold."""
|
|
123
143
|
return bool(self.get_font_selection_flags() & 0x20)
|
|
@@ -126,15 +146,14 @@ class TruetypeInfo:
|
|
|
126
146
|
"""Returns True iff the font describes itself as italic."""
|
|
127
147
|
return bool(self.get_font_selection_flags() & 0x1)
|
|
128
148
|
|
|
129
|
-
def get_names(self) -> dict[tuple[int, int], tuple[int, int,
|
|
149
|
+
def get_names(self) -> dict[tuple[int, int], tuple[int, int, bytes]]:
|
|
130
150
|
"""Returns a dictionary of names defined in the file.
|
|
131
151
|
|
|
132
152
|
The key of each item is a tuple of ``platform_id``, ``name_id``,
|
|
133
153
|
where each ID is the number as described in the Truetype format.
|
|
134
154
|
|
|
135
155
|
The value of each item is a tuple of
|
|
136
|
-
``encoding_id``, ``language_id``, ``value``, where ``value`` is
|
|
137
|
-
an encoded string.
|
|
156
|
+
``encoding_id``, ``language_id``, ``value``, where ``value`` is an encoded string.
|
|
138
157
|
"""
|
|
139
158
|
if self._names:
|
|
140
159
|
return self._names
|
|
@@ -415,6 +434,29 @@ class TruetypeInfo:
|
|
|
415
434
|
if not self._closed:
|
|
416
435
|
self.close()
|
|
417
436
|
|
|
437
|
+
class TruetypeInfoBytes(TruetypeInfo):
|
|
438
|
+
"""A subclass of TruetypeInfo that uses bytes, not mmap as mmap is not supported in Emscripten."""
|
|
439
|
+
|
|
440
|
+
def __init__(self, data: bytes) -> None: # noqa, noqa: RUF100
|
|
441
|
+
"""Read the given TrueType file.
|
|
442
|
+
|
|
443
|
+
Args:
|
|
444
|
+
data:
|
|
445
|
+
Bytes data containing a font file.
|
|
446
|
+
|
|
447
|
+
An exception will be raised if the data cannot be read.
|
|
448
|
+
"""
|
|
449
|
+
self._closed = False
|
|
450
|
+
self._data = data
|
|
451
|
+
|
|
452
|
+
try:
|
|
453
|
+
self._read_tables()
|
|
454
|
+
except Exception as err:
|
|
455
|
+
msg = "Failed to read the font tables. Ensure this data contains a TrueType or OpenType Font."
|
|
456
|
+
raise FontException(msg) from err
|
|
457
|
+
|
|
458
|
+
def close(self) -> None:
|
|
459
|
+
self._closed = True
|
|
418
460
|
|
|
419
461
|
def _read_table(*entries: str):
|
|
420
462
|
""" Generic table constructor used for table formats listed at
|
pyglet/font/user.py
CHANGED
|
@@ -85,7 +85,7 @@ class UserDefinedGlyphRenderer(base.GlyphRenderer):
|
|
|
85
85
|
def render(self, image_data: ImageData) -> Glyph:
|
|
86
86
|
if self._font._scaling: # noqa: SLF001
|
|
87
87
|
image_original = Image.frombytes("RGBA", (image_data.width, image_data.height),
|
|
88
|
-
image_data.get_image_data().
|
|
88
|
+
image_data.get_image_data().get_bytes("RGBA"))
|
|
89
89
|
scale_ratio = self._font.size / self._font._base_size
|
|
90
90
|
image_resized = image_original.resize((int(image_data.width * scale_ratio),
|
|
91
91
|
int(image_data.height * scale_ratio)), Resampling.NEAREST)
|
|
@@ -108,7 +108,7 @@ class UserDefinedFontBase(base.Font):
|
|
|
108
108
|
|
|
109
109
|
def __init__(
|
|
110
110
|
self, name: str, default_char: str, size: int, ascent: int | None = None, descent: int | None = None,
|
|
111
|
-
weight: str = "normal",
|
|
111
|
+
weight: str = "normal", style: str = "normal", stretch: str = "normal", dpi: int = 96, locale: str | None = None,
|
|
112
112
|
) -> None:
|
|
113
113
|
"""Initialize a user defined font.
|
|
114
114
|
|
|
@@ -126,7 +126,7 @@ class UserDefinedFontBase(base.Font):
|
|
|
126
126
|
Maximum descent below the baseline, in pixels. Usually negative.
|
|
127
127
|
weight:
|
|
128
128
|
The font weight, as a string. Defaults to "normal".
|
|
129
|
-
|
|
129
|
+
style:
|
|
130
130
|
If True, this font will be used when ``italic`` is enabled for the font name.
|
|
131
131
|
stretch:
|
|
132
132
|
If True, this font will be used when ``stretch`` is enabled for the font name.
|
|
@@ -136,16 +136,10 @@ class UserDefinedFontBase(base.Font):
|
|
|
136
136
|
locale:
|
|
137
137
|
Used to specify the locale of this font.
|
|
138
138
|
"""
|
|
139
|
-
super().__init__()
|
|
140
|
-
self._name = name
|
|
139
|
+
super().__init__(name, size, weight, style, stretch, dpi)
|
|
141
140
|
self.default_char = default_char
|
|
142
141
|
self.ascent = ascent
|
|
143
142
|
self.descent = descent
|
|
144
|
-
self.size = size
|
|
145
|
-
self.weight = weight
|
|
146
|
-
self.italic = italic
|
|
147
|
-
self.stretch = stretch
|
|
148
|
-
self.dpi = dpi
|
|
149
143
|
self.locale = locale
|
|
150
144
|
|
|
151
145
|
self._base_size = 0
|
|
@@ -188,8 +182,9 @@ class UserDefinedMappingFont(UserDefinedFontBase):
|
|
|
188
182
|
_glyph_renderer: UserDefinedGlyphRenderer
|
|
189
183
|
|
|
190
184
|
def __init__(self, name: str, default_char: str, size: int, mappings: DictLikeObject,
|
|
191
|
-
ascent: int | None = None, descent: int | None = None,
|
|
192
|
-
|
|
185
|
+
ascent: int | None = None, descent: int | None = None,
|
|
186
|
+
weight: str = "normal", style: str = "normal", stretch: str = "normal",
|
|
187
|
+
dpi: int = 96, locale: str | None = None) -> None:
|
|
193
188
|
"""Initialize the default parameters of your font.
|
|
194
189
|
|
|
195
190
|
Args:
|
|
@@ -209,10 +204,10 @@ class UserDefinedMappingFont(UserDefinedFontBase):
|
|
|
209
204
|
Maximum descent below the baseline, in pixels. Usually negative.
|
|
210
205
|
weight:
|
|
211
206
|
The font weight, as a string. Defaults to "normal".
|
|
212
|
-
|
|
213
|
-
|
|
207
|
+
style:
|
|
208
|
+
The font style, as a string. Defaults to "normal".
|
|
214
209
|
stretch:
|
|
215
|
-
|
|
210
|
+
The font stretch, as a string. Defaults to "normal".
|
|
216
211
|
dpi:
|
|
217
212
|
The assumed resolution of the display device, for the purposes of determining the pixel size of the
|
|
218
213
|
font. Use a default of 96 for standard sizing.
|
|
@@ -231,7 +226,7 @@ class UserDefinedMappingFont(UserDefinedFontBase):
|
|
|
231
226
|
if descent is None:
|
|
232
227
|
descent = 0
|
|
233
228
|
|
|
234
|
-
super().__init__(name, default_char, size, ascent, descent, weight,
|
|
229
|
+
super().__init__(name, default_char, size, ascent, descent, weight, style, stretch, dpi, locale)
|
|
235
230
|
|
|
236
231
|
def enable_scaling(self, base_size: int) -> None:
|
|
237
232
|
"""Enables scaling the font size.
|
|
@@ -241,11 +236,11 @@ class UserDefinedMappingFont(UserDefinedFontBase):
|
|
|
241
236
|
The base size is used to calculate the ratio between new sizes and the original.
|
|
242
237
|
"""
|
|
243
238
|
super().enable_scaling(base_size)
|
|
244
|
-
glyphs, offsets = self.get_glyphs(self.default_char)
|
|
239
|
+
glyphs, offsets = self.get_glyphs(self.default_char, False)
|
|
245
240
|
self.ascent = glyphs[0].height
|
|
246
241
|
self.descent = 0
|
|
247
242
|
|
|
248
|
-
def get_glyphs(self, text: str) -> tuple[list[Glyph], list[GlyphPosition]]:
|
|
243
|
+
def get_glyphs(self, text: str, shaping: bool = False) -> tuple[list[Glyph], list[GlyphPosition]]:
|
|
249
244
|
"""Create and return a list of Glyphs for `text`.
|
|
250
245
|
|
|
251
246
|
If any characters do not have a known glyph representation in this font, a substitution will be made with
|
|
@@ -284,7 +279,7 @@ def get_scaled_user_font(font_base: UserDefinedMappingFont, size: int) -> UserDe
|
|
|
284
279
|
The new font size. This will be scaled based on the ratio between the base size and the new size.
|
|
285
280
|
"""
|
|
286
281
|
new_font = UserDefinedMappingFont(font_base.name, font_base.default_char, size, font_base.mappings,
|
|
287
|
-
font_base.ascent, font_base.descent, font_base.weight, font_base.
|
|
282
|
+
font_base.ascent, font_base.descent, font_base.weight, font_base.style,
|
|
288
283
|
font_base.stretch, font_base.dpi, font_base.locale)
|
|
289
284
|
|
|
290
285
|
new_font.enable_scaling(font_base.size)
|
pyglet/font/win32.py
CHANGED
|
@@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, ClassVar, Sequence
|
|
|
8
8
|
|
|
9
9
|
import pyglet
|
|
10
10
|
import pyglet.image
|
|
11
|
-
from pyglet.font import base
|
|
11
|
+
from pyglet.font import base, FontManager
|
|
12
12
|
from pyglet.image.codecs.gdiplus import BitmapData, ImageLockModeRead, PixelFormat32bppARGB, Rect, gdiplus
|
|
13
13
|
from pyglet.libs.win32 import _gdi32 as gdi32
|
|
14
14
|
from pyglet.libs.win32 import _user32 as user32
|
|
@@ -20,6 +20,7 @@ if TYPE_CHECKING:
|
|
|
20
20
|
from pyglet.font.base import Glyph
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
|
|
23
24
|
DriverStringOptionsCmapLookup = 1
|
|
24
25
|
DriverStringOptionsRealizedAdvance = 4
|
|
25
26
|
TextRenderingHintSingleBitPerPixelGridFit = 1
|
|
@@ -45,7 +46,7 @@ StringFormatFlagsNoClip = 0x00004000
|
|
|
45
46
|
FontFamilyNotFound = 14
|
|
46
47
|
|
|
47
48
|
|
|
48
|
-
_debug_font = pyglet.options
|
|
49
|
+
_debug_font = pyglet.options.debug_font
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
class Rectf(ctypes.Structure):
|
|
@@ -221,7 +222,7 @@ class GDIPlusGlyphRenderer(base.GlyphRenderer):
|
|
|
221
222
|
# This hack bumps up the width if the font is italic;
|
|
222
223
|
# this compensates for some common fonts. It's also a stupid
|
|
223
224
|
# waste of texture memory.
|
|
224
|
-
if self.font.
|
|
225
|
+
if self.font.style:
|
|
225
226
|
width += width // 2
|
|
226
227
|
# Do not enlarge more than the _rect width.
|
|
227
228
|
width = min(width, self._rect.Width)
|
|
@@ -270,12 +271,15 @@ class Win32Font(base.Font):
|
|
|
270
271
|
def __init__(
|
|
271
272
|
self,
|
|
272
273
|
name: str, size: float,
|
|
273
|
-
weight: str = "normal",
|
|
274
|
+
weight: str = "normal",
|
|
275
|
+
style: str = "normal",
|
|
276
|
+
stretch: str = "normal",
|
|
274
277
|
dpi: int | None = None,
|
|
275
278
|
) -> None:
|
|
276
|
-
super().__init__()
|
|
279
|
+
super().__init__(name, size, weight, style, stretch, dpi)
|
|
277
280
|
|
|
278
|
-
bold = weight
|
|
281
|
+
bold = weight != "normal"
|
|
282
|
+
italic = style != "normal"
|
|
279
283
|
|
|
280
284
|
self.logfont = self.get_logfont(name, size, bold, italic, dpi)
|
|
281
285
|
self.hfont = gdi32.CreateFontIndirectW(ctypes.byref(self.logfont))
|
|
@@ -341,6 +345,15 @@ def _get_font_families(font_collection: ctypes.c_void_p) -> Sequence[ctypes.c_vo
|
|
|
341
345
|
|
|
342
346
|
return gpfamilies
|
|
343
347
|
|
|
348
|
+
def _get_font_family_names(font_collection: ctypes.c_void_p) -> set[str]:
|
|
349
|
+
names = set()
|
|
350
|
+
font_name = ctypes.create_unicode_buffer(32)
|
|
351
|
+
for gpfamily in _get_font_families(font_collection):
|
|
352
|
+
gdiplus.GdipGetFamilyName(gpfamily, font_name, "\0")
|
|
353
|
+
names.add(font_name.value)
|
|
354
|
+
|
|
355
|
+
return names
|
|
356
|
+
|
|
344
357
|
def _font_exists_in_collection(font_collection: ctypes.c_void_p, name: str) -> bool:
|
|
345
358
|
font_name = ctypes.create_unicode_buffer(32)
|
|
346
359
|
for gpfamily in _get_font_families(font_collection):
|
|
@@ -359,17 +372,15 @@ class GDIPlusFont(Win32Font):
|
|
|
359
372
|
|
|
360
373
|
_default_name = "Arial"
|
|
361
374
|
|
|
362
|
-
def __init__(self, name: str, size: float, weight: str = "normal",
|
|
375
|
+
def __init__(self, name: str, size: float, weight: str = "normal", style: str = "normal", stretch: str= "normal",
|
|
363
376
|
dpi: int | None=None) -> None:
|
|
364
377
|
if not name:
|
|
365
378
|
name = self._default_name
|
|
366
379
|
|
|
367
|
-
if stretch:
|
|
368
|
-
warnings.warn("The current font render does not support
|
|
369
|
-
|
|
370
|
-
bold = weight if weight in (None, True, False) else "bold" in weight
|
|
380
|
+
if stretch != "normal":
|
|
381
|
+
warnings.warn("The current font render does not support the stretch argument.")
|
|
371
382
|
|
|
372
|
-
super().__init__(name, size,
|
|
383
|
+
super().__init__(name, size, weight, style, stretch, dpi)
|
|
373
384
|
|
|
374
385
|
self._name = name
|
|
375
386
|
|
|
@@ -406,13 +417,13 @@ class GDIPlusFont(Win32Font):
|
|
|
406
417
|
size = (size * dpi) // 72
|
|
407
418
|
self.dpi = dpi
|
|
408
419
|
|
|
409
|
-
|
|
410
|
-
if
|
|
411
|
-
|
|
412
|
-
if
|
|
413
|
-
|
|
420
|
+
gdip_style = 0
|
|
421
|
+
if weight != "normal":
|
|
422
|
+
gdip_style |= FontStyleBold
|
|
423
|
+
if style != "normal":
|
|
424
|
+
gdip_style |= FontStyleItalic
|
|
414
425
|
self._gdipfont = ctypes.c_void_p()
|
|
415
|
-
gdiplus.GdipCreateFont(family, ctypes.c_float(size),
|
|
426
|
+
gdiplus.GdipCreateFont(family, ctypes.c_float(size), gdip_style, unit, ctypes.byref(self._gdipfont))
|
|
416
427
|
gdiplus.GdipDeleteFontFamily(family)
|
|
417
428
|
|
|
418
429
|
@property
|
|
@@ -424,7 +435,7 @@ class GDIPlusFont(Win32Font):
|
|
|
424
435
|
gdiplus.GdipDeleteFont(self._gdipfont)
|
|
425
436
|
|
|
426
437
|
@classmethod
|
|
427
|
-
def add_font_data(cls: type[GDIPlusFont], data: bytes) -> None:
|
|
438
|
+
def add_font_data(cls: type[GDIPlusFont], data: bytes, manager: FontManager) -> None:
|
|
428
439
|
numfonts = ctypes.c_uint32()
|
|
429
440
|
_handle = gdi32.AddFontMemResourceEx(data, len(data), 0, ctypes.byref(numfonts))
|
|
430
441
|
|
|
@@ -433,11 +444,24 @@ class GDIPlusFont(Win32Font):
|
|
|
433
444
|
raise ctypes.WinError()
|
|
434
445
|
|
|
435
446
|
if not cls._private_collection:
|
|
447
|
+
_loaded_families = set()
|
|
436
448
|
cls._private_collection = ctypes.c_void_p()
|
|
437
|
-
gdiplus.GdipNewPrivateFontCollection(
|
|
438
|
-
|
|
449
|
+
gdiplus.GdipNewPrivateFontCollection(ctypes.byref(cls._private_collection))
|
|
450
|
+
else:
|
|
451
|
+
_loaded_families = _get_font_family_names(cls._private_collection)
|
|
452
|
+
|
|
439
453
|
gdiplus.GdipPrivateAddMemoryFont(cls._private_collection, data, len(data))
|
|
440
454
|
|
|
455
|
+
current_families = _get_font_family_names(cls._private_collection)
|
|
456
|
+
|
|
457
|
+
new_font = current_families - _loaded_families
|
|
458
|
+
if len(new_font) > 0:
|
|
459
|
+
font_name = list(new_font)[0]
|
|
460
|
+
manager._add_loaded_font({(font_name, "normal", "normal", "normal")})
|
|
461
|
+
|
|
462
|
+
# Loaded a variant?
|
|
463
|
+
|
|
464
|
+
|
|
441
465
|
@classmethod
|
|
442
466
|
def have_font(cls: type[GDIPlusFont], name: str) -> bool:
|
|
443
467
|
# Enumerate the private collection fonts first, as those are most likely to be used.
|