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.
Files changed (267) hide show
  1. pyglet/__init__.py +67 -61
  2. pyglet/__init__.pyi +15 -8
  3. pyglet/app/__init__.py +22 -13
  4. pyglet/app/async_app.py +212 -0
  5. pyglet/app/base.py +2 -1
  6. pyglet/app/{xlib.py → linux.py} +3 -3
  7. pyglet/config/__init__.py +101 -0
  8. pyglet/config/gl/__init__.py +30 -0
  9. pyglet/config/gl/egl.py +120 -0
  10. pyglet/config/gl/macos.py +262 -0
  11. pyglet/config/gl/windows.py +267 -0
  12. pyglet/config/gl/x11.py +142 -0
  13. pyglet/customtypes.py +43 -2
  14. pyglet/display/__init__.py +8 -6
  15. pyglet/display/base.py +3 -63
  16. pyglet/display/cocoa.py +12 -17
  17. pyglet/display/emscripten.py +39 -0
  18. pyglet/display/headless.py +23 -30
  19. pyglet/display/wayland.py +157 -0
  20. pyglet/display/win32.py +5 -21
  21. pyglet/display/xlib.py +19 -27
  22. pyglet/display/xlib_vidmoderestore.py +2 -2
  23. pyglet/enums.py +183 -0
  24. pyglet/event.py +0 -1
  25. pyglet/experimental/geoshader_sprite.py +15 -13
  26. pyglet/experimental/hidraw.py +6 -15
  27. pyglet/experimental/multitexture_sprite.py +31 -19
  28. pyglet/experimental/particles.py +13 -35
  29. pyglet/font/__init__.py +251 -85
  30. pyglet/font/base.py +116 -61
  31. pyglet/font/dwrite/__init__.py +349 -204
  32. pyglet/font/dwrite/dwrite_lib.py +27 -5
  33. pyglet/font/fontconfig.py +14 -6
  34. pyglet/font/freetype.py +138 -87
  35. pyglet/font/freetype_lib.py +19 -0
  36. pyglet/font/group.py +179 -0
  37. pyglet/font/harfbuzz/__init__.py +3 -3
  38. pyglet/font/pyodide_js.py +310 -0
  39. pyglet/font/quartz.py +319 -126
  40. pyglet/font/ttf.py +45 -3
  41. pyglet/font/user.py +14 -19
  42. pyglet/font/win32.py +45 -21
  43. pyglet/graphics/__init__.py +8 -787
  44. pyglet/graphics/allocation.py +115 -1
  45. pyglet/graphics/api/__init__.py +77 -0
  46. pyglet/graphics/api/base.py +299 -0
  47. pyglet/graphics/api/gl/__init__.py +58 -0
  48. pyglet/graphics/api/gl/base.py +24 -0
  49. pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
  50. pyglet/graphics/api/gl/cocoa/context.py +76 -0
  51. pyglet/graphics/api/gl/context.py +391 -0
  52. pyglet/graphics/api/gl/default_shaders.py +0 -0
  53. pyglet/graphics/api/gl/draw.py +627 -0
  54. pyglet/graphics/api/gl/egl/__init__.py +0 -0
  55. pyglet/graphics/api/gl/egl/context.py +92 -0
  56. pyglet/graphics/api/gl/enums.py +76 -0
  57. pyglet/graphics/api/gl/framebuffer.py +315 -0
  58. pyglet/graphics/api/gl/gl.py +5463 -0
  59. pyglet/graphics/api/gl/gl_info.py +188 -0
  60. pyglet/graphics/api/gl/global_opengl.py +226 -0
  61. pyglet/{gl → graphics/api/gl}/lib.py +34 -18
  62. pyglet/graphics/api/gl/shader.py +1476 -0
  63. pyglet/graphics/api/gl/shapes.py +55 -0
  64. pyglet/graphics/api/gl/sprite.py +102 -0
  65. pyglet/graphics/api/gl/state.py +219 -0
  66. pyglet/graphics/api/gl/text.py +190 -0
  67. pyglet/graphics/api/gl/texture.py +1526 -0
  68. pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
  69. pyglet/graphics/api/gl/vertexdomain.py +751 -0
  70. pyglet/graphics/api/gl/win32/__init__.py +0 -0
  71. pyglet/graphics/api/gl/win32/context.py +108 -0
  72. pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
  73. pyglet/graphics/api/gl/xlib/__init__.py +0 -0
  74. pyglet/graphics/api/gl/xlib/context.py +174 -0
  75. pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
  76. pyglet/graphics/api/gl1/__init__.py +0 -0
  77. pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
  78. pyglet/graphics/api/gl2/__init__.py +0 -0
  79. pyglet/graphics/api/gl2/buffer.py +320 -0
  80. pyglet/graphics/api/gl2/draw.py +600 -0
  81. pyglet/graphics/api/gl2/global_opengl.py +122 -0
  82. pyglet/graphics/api/gl2/shader.py +200 -0
  83. pyglet/graphics/api/gl2/shapes.py +51 -0
  84. pyglet/graphics/api/gl2/sprite.py +79 -0
  85. pyglet/graphics/api/gl2/text.py +175 -0
  86. pyglet/graphics/api/gl2/vertexdomain.py +364 -0
  87. pyglet/graphics/api/webgl/__init__.py +233 -0
  88. pyglet/graphics/api/webgl/buffer.py +302 -0
  89. pyglet/graphics/api/webgl/context.py +234 -0
  90. pyglet/graphics/api/webgl/draw.py +590 -0
  91. pyglet/graphics/api/webgl/enums.py +76 -0
  92. pyglet/graphics/api/webgl/framebuffer.py +360 -0
  93. pyglet/graphics/api/webgl/gl.py +1537 -0
  94. pyglet/graphics/api/webgl/gl_info.py +130 -0
  95. pyglet/graphics/api/webgl/shader.py +1346 -0
  96. pyglet/graphics/api/webgl/shapes.py +92 -0
  97. pyglet/graphics/api/webgl/sprite.py +102 -0
  98. pyglet/graphics/api/webgl/state.py +227 -0
  99. pyglet/graphics/api/webgl/text.py +187 -0
  100. pyglet/graphics/api/webgl/texture.py +1227 -0
  101. pyglet/graphics/api/webgl/vertexarray.py +54 -0
  102. pyglet/graphics/api/webgl/vertexdomain.py +616 -0
  103. pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
  104. pyglet/{image → graphics}/atlas.py +33 -32
  105. pyglet/graphics/base.py +10 -0
  106. pyglet/graphics/buffer.py +245 -0
  107. pyglet/graphics/draw.py +578 -0
  108. pyglet/graphics/framebuffer.py +26 -0
  109. pyglet/graphics/instance.py +178 -69
  110. pyglet/graphics/shader.py +267 -1553
  111. pyglet/graphics/state.py +83 -0
  112. pyglet/graphics/texture.py +703 -0
  113. pyglet/graphics/vertexdomain.py +695 -538
  114. pyglet/gui/ninepatch.py +10 -10
  115. pyglet/gui/widgets.py +120 -10
  116. pyglet/image/__init__.py +20 -1973
  117. pyglet/image/animation.py +12 -12
  118. pyglet/image/base.py +730 -0
  119. pyglet/image/codecs/__init__.py +9 -0
  120. pyglet/image/codecs/bmp.py +53 -30
  121. pyglet/image/codecs/dds.py +53 -31
  122. pyglet/image/codecs/gdiplus.py +38 -14
  123. pyglet/image/codecs/gdkpixbuf2.py +0 -2
  124. pyglet/image/codecs/js_image.py +99 -0
  125. pyglet/image/codecs/ktx2.py +161 -0
  126. pyglet/image/codecs/pil.py +1 -1
  127. pyglet/image/codecs/png.py +1 -1
  128. pyglet/image/codecs/wic.py +11 -2
  129. pyglet/info.py +26 -24
  130. pyglet/input/__init__.py +8 -0
  131. pyglet/input/base.py +163 -105
  132. pyglet/input/controller.py +13 -19
  133. pyglet/input/controller_db.py +39 -24
  134. pyglet/input/emscripten/__init__.py +18 -0
  135. pyglet/input/emscripten/gamepad_js.py +397 -0
  136. pyglet/input/linux/__init__.py +11 -5
  137. pyglet/input/linux/evdev.py +10 -11
  138. pyglet/input/linux/x11_xinput.py +2 -2
  139. pyglet/input/linux/x11_xinput_tablet.py +1 -1
  140. pyglet/input/macos/__init__.py +7 -2
  141. pyglet/input/macos/darwin_gc.py +559 -0
  142. pyglet/input/win32/__init__.py +1 -1
  143. pyglet/input/win32/directinput.py +34 -29
  144. pyglet/input/win32/xinput.py +11 -61
  145. pyglet/lib.py +3 -3
  146. pyglet/libs/__init__.py +1 -1
  147. pyglet/{gl → libs/darwin}/agl.py +1 -1
  148. pyglet/libs/darwin/cocoapy/__init__.py +2 -2
  149. pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
  150. pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
  151. pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
  152. pyglet/libs/darwin/cocoapy/runtime.py +81 -45
  153. pyglet/libs/darwin/coreaudio.py +4 -4
  154. pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
  155. pyglet/libs/darwin/quartzkey.py +1 -3
  156. pyglet/libs/egl/__init__.py +2 -0
  157. pyglet/libs/egl/egl_lib.py +576 -0
  158. pyglet/libs/egl/eglext.py +51 -5
  159. pyglet/libs/linux/__init__.py +0 -0
  160. pyglet/libs/linux/egl/__init__.py +0 -0
  161. pyglet/libs/linux/egl/eglext.py +22 -0
  162. pyglet/libs/linux/glx/__init__.py +0 -0
  163. pyglet/{gl → libs/linux/glx}/glx.py +13 -14
  164. pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
  165. pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
  166. pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
  167. pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
  168. pyglet/libs/linux/wayland/__init__.py +0 -0
  169. pyglet/libs/linux/wayland/client.py +1068 -0
  170. pyglet/libs/linux/wayland/lib_wayland.py +207 -0
  171. pyglet/libs/linux/wayland/wayland_egl.py +38 -0
  172. pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
  173. pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
  174. pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
  175. pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
  176. pyglet/libs/linux/x11/xrandr.py +0 -0
  177. pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
  178. pyglet/libs/shared/__init__.py +0 -0
  179. pyglet/libs/shared/spirv/__init__.py +0 -0
  180. pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
  181. pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
  182. pyglet/libs/win32/__init__.py +28 -8
  183. pyglet/libs/win32/constants.py +59 -48
  184. pyglet/libs/win32/context_managers.py +20 -3
  185. pyglet/libs/win32/dinput.py +105 -88
  186. pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
  187. pyglet/libs/win32/types.py +58 -23
  188. pyglet/{gl → libs/win32}/wgl.py +32 -25
  189. pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
  190. pyglet/media/__init__.py +9 -10
  191. pyglet/media/codecs/__init__.py +12 -1
  192. pyglet/media/codecs/base.py +99 -96
  193. pyglet/media/codecs/ffmpeg.py +2 -2
  194. pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
  195. pyglet/media/codecs/webaudio_pyodide.py +111 -0
  196. pyglet/media/drivers/__init__.py +9 -4
  197. pyglet/media/drivers/base.py +4 -4
  198. pyglet/media/drivers/openal/__init__.py +1 -1
  199. pyglet/media/drivers/openal/adaptation.py +3 -3
  200. pyglet/media/drivers/pulse/__init__.py +1 -1
  201. pyglet/media/drivers/pulse/adaptation.py +3 -3
  202. pyglet/media/drivers/pyodide_js/__init__.py +8 -0
  203. pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
  204. pyglet/media/drivers/xaudio2/adaptation.py +3 -3
  205. pyglet/media/player.py +276 -193
  206. pyglet/media/player_worker_thread.py +1 -1
  207. pyglet/model/__init__.py +39 -29
  208. pyglet/model/codecs/base.py +4 -4
  209. pyglet/model/codecs/gltf.py +3 -3
  210. pyglet/model/codecs/obj.py +71 -43
  211. pyglet/resource.py +129 -78
  212. pyglet/shapes.py +154 -194
  213. pyglet/sprite.py +47 -164
  214. pyglet/text/__init__.py +44 -54
  215. pyglet/text/caret.py +12 -7
  216. pyglet/text/document.py +19 -17
  217. pyglet/text/formats/html.py +2 -2
  218. pyglet/text/formats/structured.py +10 -40
  219. pyglet/text/layout/__init__.py +20 -13
  220. pyglet/text/layout/base.py +176 -287
  221. pyglet/text/layout/incremental.py +9 -10
  222. pyglet/text/layout/scrolling.py +7 -95
  223. pyglet/window/__init__.py +183 -172
  224. pyglet/window/cocoa/__init__.py +62 -51
  225. pyglet/window/cocoa/pyglet_delegate.py +2 -25
  226. pyglet/window/cocoa/pyglet_view.py +9 -8
  227. pyglet/window/dialog/__init__.py +184 -0
  228. pyglet/window/dialog/base.py +99 -0
  229. pyglet/window/dialog/darwin.py +121 -0
  230. pyglet/window/dialog/linux.py +72 -0
  231. pyglet/window/dialog/windows.py +194 -0
  232. pyglet/window/emscripten/__init__.py +779 -0
  233. pyglet/window/headless/__init__.py +44 -28
  234. pyglet/window/key.py +2 -0
  235. pyglet/window/mouse.py +2 -2
  236. pyglet/window/wayland/__init__.py +377 -0
  237. pyglet/window/win32/__init__.py +101 -46
  238. pyglet/window/xlib/__init__.py +104 -66
  239. {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
  240. pyglet-3.0.dev1.dist-info/RECORD +322 -0
  241. {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
  242. pyglet/gl/__init__.py +0 -208
  243. pyglet/gl/base.py +0 -499
  244. pyglet/gl/cocoa.py +0 -309
  245. pyglet/gl/gl.py +0 -4625
  246. pyglet/gl/gl.pyi +0 -2320
  247. pyglet/gl/gl_compat.pyi +0 -3097
  248. pyglet/gl/gl_info.py +0 -190
  249. pyglet/gl/headless.py +0 -166
  250. pyglet/gl/wgl_info.py +0 -36
  251. pyglet/gl/wglext_nv.py +0 -1096
  252. pyglet/gl/win32.py +0 -268
  253. pyglet/gl/xlib.py +0 -295
  254. pyglet/image/buffer.py +0 -274
  255. pyglet/image/codecs/s3tc.py +0 -354
  256. pyglet/libs/x11/xrandr.py +0 -166
  257. pyglet-2.1.13.dist-info/RECORD +0 -234
  258. /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
  259. /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
  260. /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
  261. /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
  262. /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
  263. /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
  264. /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
  265. /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
  266. /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
  267. {pyglet-2.1.13.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, str]]:
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().get_data("RGBA"))
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", italic: bool = False, stretch: bool = False, dpi: int = 96, locale: str | None = None,
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
- italic:
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, weight: str = "normal", italic: bool = False,
192
- stretch: bool = False, dpi: int = 96, locale: str | None = None) -> None:
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
- italic:
213
- If ``True``, this font will be used when ``italic`` is enabled for the font name.
207
+ style:
208
+ The font style, as a string. Defaults to "normal".
214
209
  stretch:
215
- If ``True``, this font will be used when ``stretch`` is enabled for the font name.
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, italic, stretch, dpi, locale)
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.italic,
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["debug_font"]
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.italic:
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", italic: bool = False, stretch: bool = False,
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 if weight in (None, True, False) else "bold" in 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", italic: bool=False, stretch: bool=False,
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 stretching.") # noqa: B028
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, bold, italic, stretch, dpi)
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
- style = 0
410
- if bold:
411
- style |= FontStyleBold
412
- if italic:
413
- style |= FontStyleItalic
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), style, unit, ctypes.byref(self._gdipfont))
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
- ctypes.byref(cls._private_collection))
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.