pyglet 2.1.13__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 +5 -21
- 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 +28 -8
- 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 +154 -194
- 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.13.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
- pyglet-3.0.dev1.dist-info/RECORD +322 -0
- {pyglet-2.1.13.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.13.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.13.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
pyglet/font/dwrite/dwrite_lib.py
CHANGED
|
@@ -168,6 +168,28 @@ DWRITE_FONT_FACE_TYPE_UNKNOWN = 6
|
|
|
168
168
|
DWRITE_FONT_FACE_TYPE_RAW_CFF = 7
|
|
169
169
|
DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION = 8
|
|
170
170
|
|
|
171
|
+
DWRITE_FONT_PROPERTY_ID = UINT
|
|
172
|
+
DWRITE_FONT_PROPERTY_ID_NONE = 0
|
|
173
|
+
DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME = 1
|
|
174
|
+
DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FAMILY_NAME = 2
|
|
175
|
+
DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FACE_NAME = 3
|
|
176
|
+
DWRITE_FONT_PROPERTY_ID_FULL_NAME = 4
|
|
177
|
+
DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME = 5
|
|
178
|
+
DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME = 6
|
|
179
|
+
DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG = 7
|
|
180
|
+
DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG = 8
|
|
181
|
+
DWRITE_FONT_PROPERTY_ID_SEMANTIC_TAG = 9
|
|
182
|
+
DWRITE_FONT_PROPERTY_ID_WEIGHT = 10
|
|
183
|
+
DWRITE_FONT_PROPERTY_ID_STRETCH = 11
|
|
184
|
+
DWRITE_FONT_PROPERTY_ID_STYLE = 12
|
|
185
|
+
DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME = 13
|
|
186
|
+
DWRITE_FONT_PROPERTY_ID_TOTAL = 14
|
|
187
|
+
DWRITE_FONT_PROPERTY_ID_TOTAL_RS3 = 15
|
|
188
|
+
DWRITE_FONT_PROPERTY_ID_PREFERRED_FAMILY_NAME = 16
|
|
189
|
+
DWRITE_FONT_PROPERTY_ID_FAMILY_NAME = 17
|
|
190
|
+
DWRITE_FONT_PROPERTY_ID_FACE_NAME = 18
|
|
191
|
+
|
|
192
|
+
|
|
171
193
|
def repr_func(self):
|
|
172
194
|
field_values = []
|
|
173
195
|
for field_value in self._fields_:
|
|
@@ -368,7 +390,7 @@ class IDWriteFontFace(com.pIUnknown):
|
|
|
368
390
|
("GetIndex",
|
|
369
391
|
com.METHOD(UINT32)),
|
|
370
392
|
("GetSimulations",
|
|
371
|
-
com.
|
|
393
|
+
com.METHOD(UINT32)),
|
|
372
394
|
("IsSymbolFont",
|
|
373
395
|
com.METHOD(BOOL)),
|
|
374
396
|
("GetMetrics",
|
|
@@ -682,7 +704,7 @@ class IDWriteFont(com.pIUnknown):
|
|
|
682
704
|
("GetInformationalStrings",
|
|
683
705
|
com.STDMETHOD(DWRITE_INFORMATIONAL_STRING_ID, POINTER(IDWriteLocalizedStrings), POINTER(BOOL))),
|
|
684
706
|
("GetSimulations",
|
|
685
|
-
com.
|
|
707
|
+
com.METHOD(UINT32)),
|
|
686
708
|
("GetMetrics",
|
|
687
709
|
com.STDMETHOD()),
|
|
688
710
|
("HasCharacter",
|
|
@@ -1155,11 +1177,11 @@ class IDWriteFontSet(com.pIUnknown):
|
|
|
1155
1177
|
("FindFontFace",
|
|
1156
1178
|
com.STDMETHOD()),
|
|
1157
1179
|
("GetPropertyValues__",
|
|
1158
|
-
com.STDMETHOD()),
|
|
1180
|
+
com.STDMETHOD(UINT32, DWRITE_FONT_PROPERTY_ID, POINTER(BOOL), POINTER(IDWriteLocalizedStrings))),
|
|
1159
1181
|
("GetPropertyValues_",
|
|
1160
|
-
com.STDMETHOD()),
|
|
1182
|
+
com.STDMETHOD(DWRITE_FONT_PROPERTY_ID, c_wchar_p, c_void_p)),
|
|
1161
1183
|
("GetPropertyValues",
|
|
1162
|
-
com.STDMETHOD()),
|
|
1184
|
+
com.STDMETHOD(DWRITE_FONT_PROPERTY_ID, c_void_p)),
|
|
1163
1185
|
("GetPropertyOccurrenceCount",
|
|
1164
1186
|
com.STDMETHOD()),
|
|
1165
1187
|
("GetMatchingFonts_",
|
pyglet/font/fontconfig.py
CHANGED
|
@@ -5,6 +5,7 @@ from collections import OrderedDict
|
|
|
5
5
|
from ctypes import CDLL, Structure, Union, byref, c_char_p, c_double, c_int, c_uint, c_void_p, POINTER
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
+
from pyglet.enums import Style
|
|
8
9
|
from pyglet.font.base import FontException
|
|
9
10
|
from pyglet.lib import load_library
|
|
10
11
|
from pyglet.util import asbytes, asstr
|
|
@@ -200,7 +201,9 @@ class FontConfig:
|
|
|
200
201
|
return result.weight, result.italic, result.stretch
|
|
201
202
|
|
|
202
203
|
def find_font(self, name: str, size: float = 12, weight: str = "normal",
|
|
203
|
-
italic:
|
|
204
|
+
italic: str = "normal", stretch: str = "normal") -> FontConfigSearchResult:
|
|
205
|
+
assert isinstance(weight, str)
|
|
206
|
+
assert isinstance(italic, str)
|
|
204
207
|
if result := self._get_from_search_cache(name, size, weight, italic, stretch):
|
|
205
208
|
return result
|
|
206
209
|
|
|
@@ -239,7 +242,7 @@ class FontConfig:
|
|
|
239
242
|
self._search_cache.popitem(last=False)[1].dispose()
|
|
240
243
|
|
|
241
244
|
def _get_from_search_cache(self, name: str, size: float, weight: str,
|
|
242
|
-
italic:
|
|
245
|
+
italic: str, stretch: str) -> FontConfigSearchResult | None:
|
|
243
246
|
result = self._search_cache.get((name, size, weight, italic, stretch), None)
|
|
244
247
|
|
|
245
248
|
if result and result.is_valid:
|
|
@@ -295,8 +298,13 @@ class FontConfigPattern:
|
|
|
295
298
|
self._pattern = None
|
|
296
299
|
|
|
297
300
|
@staticmethod
|
|
298
|
-
def _italic_to_slant(italic:
|
|
299
|
-
|
|
301
|
+
def _italic_to_slant(italic: str) -> int:
|
|
302
|
+
if italic == Style.ITALIC:
|
|
303
|
+
return FC_SLANT_ITALIC
|
|
304
|
+
if italic == Style.OBLIQUE:
|
|
305
|
+
return FC_SLANT_OBLIQUE
|
|
306
|
+
|
|
307
|
+
return FC_SLANT_ROMAN
|
|
300
308
|
|
|
301
309
|
def _set_string(self, name: bytes, value: str) -> None:
|
|
302
310
|
assert self._pattern
|
|
@@ -377,7 +385,7 @@ class FontConfigPattern:
|
|
|
377
385
|
|
|
378
386
|
class FontConfigSearchPattern(FontConfigPattern):
|
|
379
387
|
size: float | None
|
|
380
|
-
italic:
|
|
388
|
+
italic: str
|
|
381
389
|
weight: str
|
|
382
390
|
name: str | None
|
|
383
391
|
stretch: str
|
|
@@ -387,7 +395,7 @@ class FontConfigSearchPattern(FontConfigPattern):
|
|
|
387
395
|
|
|
388
396
|
self.name = None
|
|
389
397
|
self.weight = "normal"
|
|
390
|
-
self.italic =
|
|
398
|
+
self.italic = "normal"
|
|
391
399
|
self.size = None
|
|
392
400
|
self.stretch = 'normal'
|
|
393
401
|
|
pyglet/font/freetype.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
|
-
from ctypes import POINTER, byref, c_ubyte, cast, memmove
|
|
5
|
-
from typing import NamedTuple, Sequence
|
|
4
|
+
from ctypes import POINTER, byref, c_ubyte, cast, memmove, string_at, Array
|
|
5
|
+
from typing import NamedTuple, Sequence, TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
import pyglet
|
|
8
8
|
from pyglet import image
|
|
@@ -26,13 +26,31 @@ from pyglet.font.freetype_lib import (
|
|
|
26
26
|
FT_Set_Char_Size,
|
|
27
27
|
f26p6_to_float,
|
|
28
28
|
float_to_f26p6,
|
|
29
|
-
ft_get_library,
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
ft_get_library,
|
|
30
|
+
FT_LOAD_TARGET_MONO,
|
|
31
|
+
FT_LOAD_COLOR,
|
|
32
|
+
FT_FACE_FLAG_SCALABLE,
|
|
33
|
+
FT_FACE_FLAG_FIXED_SIZES,
|
|
34
|
+
FT_FACE_FLAG_COLOR,
|
|
35
|
+
FT_Select_Size,
|
|
36
|
+
FT_PIXEL_MODE_BGRA,
|
|
37
|
+
FT_Get_Char_Index,
|
|
38
|
+
FT_LOAD_NO_BITMAP,
|
|
39
|
+
FT_Load_Char,
|
|
40
|
+
FT_FACE_FLAG_SFNT,
|
|
41
|
+
FT_SfntName,
|
|
42
|
+
FT_Get_Sfnt_Name_Count,
|
|
43
|
+
FT_Get_Sfnt_Name,
|
|
44
|
+
TT_NAME_ID_FULL_NAME,
|
|
45
|
+
TT_NAME_ID_FONT_FAMILY,
|
|
32
46
|
)
|
|
33
47
|
from pyglet.font.harfbuzz import harfbuzz_available, get_resource_from_ft_font, get_harfbuzz_shaped_glyphs
|
|
34
|
-
from pyglet.util import asbytes, asstr
|
|
48
|
+
from pyglet.util import asbytes, asstr, debug_print
|
|
35
49
|
|
|
50
|
+
_debug_font = debug_print("debug_font")
|
|
51
|
+
|
|
52
|
+
if TYPE_CHECKING:
|
|
53
|
+
from pyglet.font import FontManager
|
|
36
54
|
|
|
37
55
|
class FreeTypeGlyphRenderer(base.GlyphRenderer):
|
|
38
56
|
def __init__(self, font: FreeTypeFont) -> None:
|
|
@@ -70,7 +88,12 @@ class FreeTypeGlyphRenderer(base.GlyphRenderer):
|
|
|
70
88
|
self._mode = self._glyph_slot.bitmap.pixel_mode
|
|
71
89
|
self._pitch = self._glyph_slot.bitmap.pitch
|
|
72
90
|
|
|
73
|
-
|
|
91
|
+
# Hack! Adjust baseline position depending backends for now.
|
|
92
|
+
if pyglet.options.backend == "vulkan":
|
|
93
|
+
self._baseline = self._glyph_slot.bitmap_top - self.font.descent - self.font.ascent
|
|
94
|
+
else:
|
|
95
|
+
self._baseline = self._height - self._glyph_slot.bitmap_top
|
|
96
|
+
|
|
74
97
|
self._lsb = self._glyph_slot.bitmap_left
|
|
75
98
|
self._advance_x = int(f26p6_to_float(self._glyph_slot.advance.x))
|
|
76
99
|
|
|
@@ -137,6 +160,34 @@ class FreeTypeGlyphRenderer(base.GlyphRenderer):
|
|
|
137
160
|
self._data = data
|
|
138
161
|
self._pitch = self._width
|
|
139
162
|
|
|
163
|
+
def _expand_to_rgba(self, data: bytes, src_format: str, dst_format: str) -> bytes:
|
|
164
|
+
"""Expands data type to RGBA with putting values into A.
|
|
165
|
+
|
|
166
|
+
Will re-evaluate on a better system later.
|
|
167
|
+
"""
|
|
168
|
+
src_len = len(src_format)
|
|
169
|
+
dst_len = len(dst_format)
|
|
170
|
+
|
|
171
|
+
if src_len >= dst_len:
|
|
172
|
+
return data
|
|
173
|
+
|
|
174
|
+
expanded_data = bytearray(len(data) // src_len * dst_len)
|
|
175
|
+
mapping = {c: i for i, c in enumerate(src_format)}
|
|
176
|
+
|
|
177
|
+
for i in range(len(data) // src_len):
|
|
178
|
+
default_value = data[i * src_len + 0] if src_len > 0 else 0
|
|
179
|
+
|
|
180
|
+
for j, c in enumerate(dst_format):
|
|
181
|
+
if c in mapping:
|
|
182
|
+
expanded_data[i * dst_len + j] = 255
|
|
183
|
+
elif c == 'A':
|
|
184
|
+
# Default alpha to fully opaque
|
|
185
|
+
expanded_data[i * dst_len + j] = default_value
|
|
186
|
+
else:
|
|
187
|
+
expanded_data[i * dst_len + j] = 255
|
|
188
|
+
|
|
189
|
+
return bytes(expanded_data)
|
|
190
|
+
|
|
140
191
|
def _create_glyph(self) -> base.Glyph:
|
|
141
192
|
# Textures should be a minimum of 1x1.
|
|
142
193
|
if self._width == 0 and self._height == 0:
|
|
@@ -190,21 +241,22 @@ class FreeTypeFontMetrics(NamedTuple):
|
|
|
190
241
|
|
|
191
242
|
|
|
192
243
|
class MemoryFaceStore:
|
|
193
|
-
_dict: dict[tuple[str, str,
|
|
244
|
+
_dict: dict[tuple[str, str, str, str], FreeTypeMemoryFace]
|
|
194
245
|
|
|
195
246
|
def __init__(self) -> None:
|
|
196
247
|
self._dict = {}
|
|
197
248
|
|
|
198
249
|
def add(self, face: FreeTypeMemoryFace) -> None:
|
|
199
|
-
self._dict[face.name
|
|
250
|
+
self._dict[face.name, face.weight, face.style, face.stretch] = face
|
|
200
251
|
|
|
201
252
|
def contains(self, name: str) -> bool:
|
|
202
|
-
|
|
203
|
-
|
|
253
|
+
return len([fn_name for fn_name, _, _, _ in self._dict if name.lower() == fn_name.lower()]) > 0
|
|
254
|
+
|
|
255
|
+
def get(self, name: str, weight: str, style: str, stretch: str) -> FreeTypeMemoryFace | None:
|
|
256
|
+
return self._dict.get((name, weight, style, stretch), None)
|
|
204
257
|
|
|
205
|
-
def
|
|
206
|
-
|
|
207
|
-
return self._dict.get((lname, weight, italic), None)
|
|
258
|
+
def all_keys(self) -> list[tuple[str, str, str, str]]:
|
|
259
|
+
return list(self._dict.keys())
|
|
208
260
|
|
|
209
261
|
|
|
210
262
|
class FreeTypeFont(base.Font):
|
|
@@ -214,18 +266,12 @@ class FreeTypeFont(base.Font):
|
|
|
214
266
|
# Map font (name, weight, italic) to FreeTypeMemoryFace
|
|
215
267
|
_memory_faces = MemoryFaceStore()
|
|
216
268
|
face: FreeTypeFace
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
self.size = size
|
|
224
|
-
self.weight = weight
|
|
225
|
-
self.italic = italic
|
|
226
|
-
self.stretch = stretch
|
|
227
|
-
self.dpi = dpi or 96
|
|
228
|
-
self.pixel_size = (self.size * self.dpi) // 72
|
|
269
|
+
|
|
270
|
+
def __init__(self, name: str, size: float,
|
|
271
|
+
weight: str = "normal",
|
|
272
|
+
style: str = "normal",
|
|
273
|
+
stretch: str = "normal", dpi: int | None = None) -> None:
|
|
274
|
+
super().__init__(name, size, weight, style, stretch, dpi)
|
|
229
275
|
|
|
230
276
|
self._load_font_face()
|
|
231
277
|
self.metrics = self.face.get_font_metrics(self.size, self.dpi)
|
|
@@ -245,42 +291,22 @@ class FreeTypeFont(base.Font):
|
|
|
245
291
|
def descent(self) -> int:
|
|
246
292
|
return self.metrics.descent
|
|
247
293
|
|
|
248
|
-
def add_fallback(self, font):
|
|
249
|
-
self.fallbacks.append(font)
|
|
250
|
-
|
|
251
|
-
def _get_slot_from_fallbacks(self, character: str) -> FT_GlyphSlot | None:
|
|
252
|
-
"""Checks all fallback fonts in order to find a valid glyph index."""
|
|
253
|
-
# Check if fallback has this glyph, if so.
|
|
254
|
-
for fallback_font in self.fallbacks:
|
|
255
|
-
fb_index = fallback_font.face.get_character_index(character)
|
|
256
|
-
if fb_index:
|
|
257
|
-
fallback_font.face.set_char_size(self.size, self.dpi)
|
|
258
|
-
return fallback_font.get_glyph_slot(character)
|
|
259
|
-
|
|
260
|
-
return None
|
|
261
|
-
|
|
262
294
|
def get_glyph_slot_index(self, glyph_index: int) -> FT_GlyphSlot:
|
|
263
295
|
self.face.set_char_size(self.size, self.dpi)
|
|
264
296
|
return self.face.get_glyph_slot(glyph_index)
|
|
265
297
|
|
|
266
298
|
def get_glyph_slot(self, character: str) -> FT_GlyphSlot:
|
|
267
299
|
glyph_index = self.face.get_character_index(character)
|
|
268
|
-
# Glyph index does not exist, so check fallback fonts.
|
|
269
|
-
if glyph_index == 0 and (self.name not in self.fallbacks):
|
|
270
|
-
glyph_slot = self._get_slot_from_fallbacks(character)
|
|
271
|
-
if glyph_slot is not None:
|
|
272
|
-
return glyph_slot
|
|
273
|
-
|
|
274
300
|
self.face.set_char_size(self.size, self.dpi)
|
|
275
301
|
return self.face.get_glyph_slot(glyph_index)
|
|
276
302
|
|
|
277
303
|
def _load_font_face(self) -> None:
|
|
278
|
-
self.face = self._memory_faces.get(self._name, self.weight, self.
|
|
304
|
+
self.face = self._memory_faces.get(self._name, self.weight, self.style, self.stretch)
|
|
279
305
|
if self.face is None:
|
|
280
306
|
self._load_font_face_from_system()
|
|
281
307
|
|
|
282
308
|
def _load_font_face_from_system(self) -> None:
|
|
283
|
-
match = get_fontconfig().find_font(self._name, self.size, self.weight, self.
|
|
309
|
+
match = get_fontconfig().find_font(self._name, self.size, self.weight, self.style, self.stretch)
|
|
284
310
|
if not match:
|
|
285
311
|
msg = f"Could not match font '{self._name}'"
|
|
286
312
|
raise base.FontException(msg)
|
|
@@ -295,7 +321,7 @@ class FreeTypeFont(base.Font):
|
|
|
295
321
|
return get_fontconfig().have_font(name)
|
|
296
322
|
|
|
297
323
|
@classmethod
|
|
298
|
-
def add_font_data(cls: type[FreeTypeFont], data: bytes) -> None:
|
|
324
|
+
def add_font_data(cls: type[FreeTypeFont], data: bytes, manager: FontManager) -> None:
|
|
299
325
|
font_data = (FT_Byte * len(data))()
|
|
300
326
|
memmove(font_data, data, len(data))
|
|
301
327
|
|
|
@@ -308,7 +334,10 @@ class FreeTypeFont(base.Font):
|
|
|
308
334
|
face = FreeTypeMemoryFace(font_data, i)
|
|
309
335
|
cls._memory_faces.add(face)
|
|
310
336
|
|
|
311
|
-
|
|
337
|
+
all_fonts = cls._memory_faces.all_keys()
|
|
338
|
+
manager._add_loaded_font(set(all_fonts)) # noqa: SLF001
|
|
339
|
+
|
|
340
|
+
def render_glyph_indices(self, indices: Sequence[int]) -> None:
|
|
312
341
|
# Process any glyphs that have not been rendered.
|
|
313
342
|
self._initialize_renderer()
|
|
314
343
|
|
|
@@ -321,7 +350,7 @@ class FreeTypeFont(base.Font):
|
|
|
321
350
|
for glyph_indice in missing:
|
|
322
351
|
self.glyphs[glyph_indice] = self._glyph_renderer.render_index(glyph_indice)
|
|
323
352
|
|
|
324
|
-
def get_glyphs(self, text: str) -> tuple[list[base.Glyph], list[base.GlyphPosition]]:
|
|
353
|
+
def get_glyphs(self, text: str, shaping: bool) -> tuple[list[base.Glyph], list[base.GlyphPosition]]:
|
|
325
354
|
"""Create and return a list of Glyphs for `text`.
|
|
326
355
|
|
|
327
356
|
If any characters do not have a known glyph representation in this
|
|
@@ -330,22 +359,24 @@ class FreeTypeFont(base.Font):
|
|
|
330
359
|
Args:
|
|
331
360
|
text:
|
|
332
361
|
Text to render.
|
|
362
|
+
shaping:
|
|
363
|
+
If the text will be shaped using the global option.
|
|
333
364
|
"""
|
|
334
365
|
self._initialize_renderer()
|
|
335
|
-
|
|
366
|
+
|
|
367
|
+
if shaping and pyglet.options.text_shaping == "harfbuzz" and harfbuzz_available():
|
|
336
368
|
return get_harfbuzz_shaped_glyphs(self, text)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return glyphs, [GlyphPosition(0, 0, 0, 0)] * len(text)
|
|
369
|
+
|
|
370
|
+
glyphs = [] # glyphs that are committed.
|
|
371
|
+
for idx, c in enumerate(text):
|
|
372
|
+
# Get the glyph for 'c'. Hide tabs (Windows and Linux render boxes)
|
|
373
|
+
if c == "\t":
|
|
374
|
+
c = " " # noqa: PLW2901
|
|
375
|
+
if c not in self.glyphs:
|
|
376
|
+
self.glyphs[c] = self._glyph_renderer.render(c)
|
|
377
|
+
glyphs.append(self.glyphs[c])
|
|
378
|
+
|
|
379
|
+
return glyphs, [GlyphPosition(0, 0, 0, 0)] * len(text)
|
|
349
380
|
|
|
350
381
|
def get_text_size(self, text: str) -> tuple[int, int]:
|
|
351
382
|
width = 0
|
|
@@ -387,9 +418,11 @@ class FreeTypeFace:
|
|
|
387
418
|
self._get_best_name()
|
|
388
419
|
|
|
389
420
|
self._italic = self.style_flags & FT_STYLE_FLAG_ITALIC != 0
|
|
421
|
+
self._style = "italic" if self._italic else "normal"
|
|
390
422
|
bold = self.style_flags & FT_STYLE_FLAG_BOLD != 0
|
|
391
423
|
if bold:
|
|
392
424
|
self._weight = "bold"
|
|
425
|
+
self._stretch = "normal"
|
|
393
426
|
else:
|
|
394
427
|
# Sometimes it may have a weight, but FT_STYLE_FLAG_BOLD is not accurate. Check the font config.
|
|
395
428
|
config = get_fontconfig()
|
|
@@ -413,11 +446,11 @@ class FreeTypeFace:
|
|
|
413
446
|
if match.face is not None:
|
|
414
447
|
FT_Reference_Face(match.face)
|
|
415
448
|
return cls(match.face)
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
449
|
+
|
|
450
|
+
if not match.file:
|
|
451
|
+
msg = f'No filename for "{match.name}"'
|
|
452
|
+
raise base.FontException(msg)
|
|
453
|
+
return cls.from_file(match.file)
|
|
421
454
|
|
|
422
455
|
@property
|
|
423
456
|
def name(self) -> str:
|
|
@@ -447,6 +480,14 @@ class FreeTypeFace:
|
|
|
447
480
|
def italic(self) -> bool:
|
|
448
481
|
return self._italic
|
|
449
482
|
|
|
483
|
+
@property
|
|
484
|
+
def stretch(self) -> str:
|
|
485
|
+
return self._stretch
|
|
486
|
+
|
|
487
|
+
@property
|
|
488
|
+
def style(self) -> str:
|
|
489
|
+
return self._style
|
|
490
|
+
|
|
450
491
|
@property
|
|
451
492
|
def face_flags(self) -> int:
|
|
452
493
|
return self.ft_face.contents.face_flags
|
|
@@ -514,36 +555,46 @@ class FreeTypeFace:
|
|
|
514
555
|
i = self.get_character_index("X")
|
|
515
556
|
self.get_glyph_slot(i)
|
|
516
557
|
ascent = self.ft_face.contents.available_sizes.contents.height
|
|
517
|
-
return FreeTypeFontMetrics(ascent=ascent,
|
|
518
|
-
descent=-ascent // 4) # arbitrary.
|
|
558
|
+
return FreeTypeFontMetrics(ascent=ascent, descent=-ascent // 4) # arbitrary.
|
|
519
559
|
|
|
520
560
|
def _get_best_name(self) -> None:
|
|
521
561
|
self._name = asstr(self.ft_face.contents.family_name)
|
|
522
|
-
self._get_font_family_from_ttf()
|
|
523
562
|
|
|
524
|
-
def _get_font_family_from_ttf(self) -> None:
|
|
525
563
|
# Replace Freetype's generic family name with TTF/OpenType specific
|
|
526
564
|
# name if we can find one; there are some instances where Freetype
|
|
527
565
|
# gets it wrong.
|
|
566
|
+
if (ttf_name := self._get_ttf_string(TT_NAME_ID_FONT_FAMILY)) and ttf_name != self._name:
|
|
567
|
+
assert _debug_font(f"FreeType name: {self._name} does not match header name: {ttf_name}")
|
|
528
568
|
|
|
529
|
-
|
|
530
|
-
|
|
569
|
+
def _get_ttf_string(self, name_id: int) -> str | None:
|
|
570
|
+
"""Return the value from the TTF/OTF/AAT font table for the specified TT_NAME_ID."""
|
|
531
571
|
if self.face_flags & FT_FACE_FLAG_SFNT:
|
|
532
|
-
|
|
533
|
-
for i in range(
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
#
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
572
|
+
name_count = FT_Get_Sfnt_Name_Count(self.ft_face)
|
|
573
|
+
for i in range(name_count):
|
|
574
|
+
name = FT_SfntName()
|
|
575
|
+
FT_Get_Sfnt_Name(self.ft_face, i, name)
|
|
576
|
+
if name.platform_id == name_id:
|
|
577
|
+
raw = string_at(name.string, name.string_len)
|
|
578
|
+
|
|
579
|
+
# First try decoding with UTF-16BE (used by Windows name table)
|
|
580
|
+
try:
|
|
581
|
+
full_name = raw.decode("utf-16-be")
|
|
582
|
+
except UnicodeDecodeError:
|
|
583
|
+
full_name = raw.decode("latin1", errors="replace")
|
|
584
|
+
|
|
585
|
+
return full_name
|
|
586
|
+
|
|
587
|
+
return None
|
|
588
|
+
|
|
589
|
+
def _get_full_name(self) -> str | None:
|
|
590
|
+
"""Checks the font naming table."""
|
|
591
|
+
return self._get_ttf_string(TT_NAME_ID_FULL_NAME)
|
|
592
|
+
|
|
593
|
+
|
|
543
594
|
|
|
544
595
|
|
|
545
596
|
class FreeTypeMemoryFace(FreeTypeFace):
|
|
546
|
-
def __init__(self, data:
|
|
597
|
+
def __init__(self, data: Array, face_index: int = 0) -> None:
|
|
547
598
|
self.font_data = data
|
|
548
599
|
ft_library = ft_get_library()
|
|
549
600
|
ft_face = FT_Face()
|
pyglet/font/freetype_lib.py
CHANGED
|
@@ -672,7 +672,9 @@ FT_Get_Sfnt_Name = _get_function_with_error_handling("FT_Get_Sfnt_Name",
|
|
|
672
672
|
[FT_Face, FT_UInt, POINTER(FT_SfntName)], FT_Error)
|
|
673
673
|
|
|
674
674
|
TT_PLATFORM_MICROSOFT = 3
|
|
675
|
+
|
|
675
676
|
TT_MS_ID_UNICODE_CS = 1
|
|
677
|
+
|
|
676
678
|
TT_NAME_ID_COPYRIGHT = 0
|
|
677
679
|
TT_NAME_ID_FONT_FAMILY = 1
|
|
678
680
|
TT_NAME_ID_FONT_SUBFAMILY = 2
|
|
@@ -681,6 +683,8 @@ TT_NAME_ID_FULL_NAME = 4
|
|
|
681
683
|
TT_NAME_ID_VERSION_STRING = 5
|
|
682
684
|
TT_NAME_ID_PS_NAME = 6
|
|
683
685
|
TT_NAME_ID_TRADEMARK = 7
|
|
686
|
+
|
|
687
|
+
# From OpenType:
|
|
684
688
|
TT_NAME_ID_MANUFACTURER = 8
|
|
685
689
|
TT_NAME_ID_DESIGNER = 9
|
|
686
690
|
TT_NAME_ID_DESCRIPTION = 10
|
|
@@ -688,11 +692,26 @@ TT_NAME_ID_VENDOR_URL = 11
|
|
|
688
692
|
TT_NAME_ID_DESIGNER_URL = 12
|
|
689
693
|
TT_NAME_ID_LICENSE = 13
|
|
690
694
|
TT_NAME_ID_LICENSE_URL = 14
|
|
695
|
+
# 15 is reserved.
|
|
691
696
|
TT_NAME_ID_PREFERRED_FAMILY = 16
|
|
692
697
|
TT_NAME_ID_PREFERRED_SUBFAMILY = 17
|
|
693
698
|
TT_NAME_ID_MAC_FULL_NAME = 18
|
|
699
|
+
TT_NAME_ID_SAMPLE_TEXT = 19
|
|
700
|
+
|
|
701
|
+
# OpenType 1.3
|
|
694
702
|
TT_NAME_ID_CID_FINDFONT_NAME = 20
|
|
695
703
|
|
|
704
|
+
# OpenType 1.5
|
|
705
|
+
TT_NAME_ID_WWS_FAMILY = 21
|
|
706
|
+
TT_NAME_ID_WWS_SUBFAMILY = 22
|
|
707
|
+
|
|
708
|
+
# OpenType 1.7
|
|
709
|
+
TT_NAME_ID_LIGHT_BACKGROUND = 23
|
|
710
|
+
TT_NAME_ID_DARK_BACKGROUND = 24
|
|
711
|
+
|
|
712
|
+
# OpenType 1.8
|
|
713
|
+
TT_NAME_ID_VARIATIONS_PREFIX = 25
|
|
714
|
+
|
|
696
715
|
_library = None
|
|
697
716
|
|
|
698
717
|
|