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.
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 +4 -17
  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 +27 -5
  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 +147 -177
  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.12.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.12.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.12.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.12.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
pyglet/font/base.py CHANGED
@@ -7,12 +7,23 @@ classes as a documented interface to the concrete classes.
7
7
  from __future__ import annotations
8
8
 
9
9
  import abc
10
- import unicodedata
11
10
  from dataclasses import dataclass
12
- from typing import Any, BinaryIO, ClassVar
11
+ from typing import Any, BinaryIO, ClassVar, TYPE_CHECKING
12
+
13
+ import unicodedata
13
14
 
14
- from pyglet import image
15
- from pyglet.gl import GL_LINEAR, GL_RGBA, GL_TEXTURE_2D
15
+ from pyglet.enums import (
16
+ TextureFilter,
17
+ Weight,
18
+ Stretch,
19
+ Style,
20
+ )
21
+ from pyglet.graphics import atlas
22
+ from pyglet.graphics.texture import Texture, TextureRegion
23
+ from pyglet.image import ImageData
24
+
25
+ if TYPE_CHECKING:
26
+ from pyglet.font import FontManager
16
27
 
17
28
  _OTHER_GRAPHEME_EXTEND = {
18
29
  chr(x) for x in [0x09be, 0x09d7, 0x0be3, 0x0b57, 0x0bbe, 0x0bd7, 0x0cc2,
@@ -114,7 +125,7 @@ class GlyphPosition:
114
125
  y_offset: int # How much the current glyph moves on the Y-axis when drawn. Does not advance.
115
126
 
116
127
 
117
- class Glyph(image.TextureRegion):
128
+ class Glyph(TextureRegion):
118
129
  """A single glyph located within a larger texture.
119
130
 
120
131
  Glyphs are drawn most efficiently using the higher level APIs.
@@ -151,42 +162,40 @@ class Glyph(image.TextureRegion):
151
162
  -baseline + self.height)
152
163
 
153
164
 
154
- class GlyphTexture(image.Texture):
165
+ class GlyphTexture(Texture):
155
166
  """A texture containing a glyph."""
156
167
  region_class = Glyph
157
168
 
158
169
 
159
- class GlyphTextureAtlas(image.atlas.TextureAtlas):
170
+ class GlyphTextureAtlas(atlas.TextureAtlas):
160
171
  """A texture atlas containing many glyphs."""
161
172
  texture_class = GlyphTexture
162
173
 
163
- def __init__(self, width: int = 2048, height: int = 2048, fmt: int = GL_RGBA, min_filter: int = GL_LINEAR, # noqa: D107
164
- mag_filter: int = GL_LINEAR) -> None:
174
+ def __init__(self, width: int = 2048, height: int = 2048, filters: TextureFilter = TextureFilter.LINEAR) -> None:
165
175
  super().__init__(width, height)
166
- self.texture = self.texture_class.create(width, height, GL_TEXTURE_2D, fmt, min_filter, mag_filter, fmt=fmt)
167
- self.allocator = image.atlas.Allocator(width, height)
176
+ self.texture = self.texture_class.create(width, height, filters=filters)
177
+ self.allocator = atlas.Allocator(width, height)
168
178
 
169
- def add(self, img: image.AbstractImage, border: int = 0) -> Glyph:
179
+ def add(self, img: ImageData, border: int = 0) -> Glyph:
170
180
  return super().add(img, border)
171
181
 
172
182
 
173
- class GlyphTextureBin(image.atlas.TextureBin):
183
+ class GlyphTextureBin(atlas.TextureBin):
174
184
  """Same as a TextureBin but allows you to specify filter of Glyphs."""
175
185
 
176
- def add(self, img: image.AbstractImage, fmt: int = GL_RGBA, min_filter: int = GL_LINEAR,
177
- mag_filter: int = GL_LINEAR, border: int = 0) -> Glyph:
178
- for atlas in list(self.atlases):
186
+ def add(self, img: ImageData, filters: TextureFilter, border: int = 0) -> Glyph:
187
+ for glyph_atlas in list(self.atlases):
179
188
  try:
180
- return atlas.add(img, border)
181
- except image.atlas.AllocatorException: # noqa: PERF203
189
+ return glyph_atlas.add(img, border)
190
+ except atlas.AllocatorException: # noqa: PERF203
182
191
  # Remove atlases that are no longer useful (so that their textures
183
192
  # can later be freed if the images inside them get collected).
184
193
  if img.width < 64 and img.height < 64:
185
- self.atlases.remove(atlas)
194
+ self.atlases.remove(glyph_atlas)
186
195
 
187
- atlas = GlyphTextureAtlas(self.texture_width, self.texture_height, fmt, min_filter, mag_filter)
188
- self.atlases.append(atlas)
189
- return atlas.add(img, border)
196
+ glyph_atlas = GlyphTextureAtlas(self.texture_width, self.texture_height, filters)
197
+ self.atlases.append(glyph_atlas)
198
+ return glyph_atlas.add(img, border)
190
199
 
191
200
 
192
201
  class GlyphRenderer(abc.ABC):
@@ -217,7 +226,7 @@ class GlyphRenderer(abc.ABC):
217
226
 
218
227
  This is to fill in for potential substitutions since font system requires 1 glyph per character in a string.
219
228
  """
220
- image_data = image.ImageData(1, 1, 'RGBA', bytes([0, 0, 0, 0]))
229
+ image_data = ImageData(1, 1, 'RGBA', bytes([0, 0, 0, 0]))
221
230
  glyph = self.font.create_glyph(image_data)
222
231
  glyph.set_bearings(-self.font.descent, 0, -1)
223
232
  return glyph
@@ -248,15 +257,12 @@ class Font:
248
257
  pre-calculate how many glyphs can be saved into a single texture atlas. Increase this if you plan to
249
258
  support more than this standard scenario. Performance is increased the less textures are used. However,
250
259
  it does consume more video memory.
251
- texture_internalformat:
252
- Determines how textures are stored in internal format. By default, ``GL_RGBA``.
253
- texture_min_filter:
254
- The default minification filter for glyph textures. By default, ``GL_LINEAR``. Can be changed to
255
- ``GL_NEAREST`` to prevent aliasing with pixelated fonts.
256
- texture_mag_filter:
257
- The default magnification filter for glyph textures. By default, ``GL_LINEAR``. Can be changed to
258
- ``GL_NEAREST`` to prevent aliasing with pixelated fonts.
260
+ default_descriptor:
261
+ The default Texture description of the atlas and font.
259
262
  """
263
+ #: :meta private:
264
+ texture_bin: None | GlyphTextureBin
265
+
260
266
  #: :meta private:
261
267
  glyphs: dict[str | int | tuple[Any, int], Glyph]
262
268
  # Glyphs can be cached in various ways:
@@ -270,9 +276,7 @@ class Font:
270
276
  optimize_fit: int = True
271
277
  glyph_fit: int = 100
272
278
 
273
- texture_internalformat: int = GL_RGBA
274
- texture_min_filter: int = GL_LINEAR
275
- texture_mag_filter: int = GL_LINEAR
279
+ filters = TextureFilter.LINEAR
276
280
 
277
281
  # These should also be set by subclass when known
278
282
  ascent: int = 0
@@ -286,9 +290,6 @@ class Font:
286
290
  # The default type of texture bins. Should not be overridden by users.
287
291
  texture_class: ClassVar[type[GlyphTextureBin]] = GlyphTextureBin
288
292
 
289
- # A list of fallback fonts to use when an existing glyph is not found.
290
- fallbacks: list[Font]
291
-
292
293
  _glyph_renderer: GlyphRenderer | None
293
294
  _missing_glyph: Glyph | None
294
295
  _zero_glyph: Glyph | None
@@ -296,8 +297,42 @@ class Font:
296
297
  # The size of the font in pixels.
297
298
  pixel_size: float
298
299
 
299
- def __init__(self) -> None:
300
- """Initialize a font that can be used with Pyglet."""
300
+ def __init__(self, name: str, size: float, weight: str | Weight, style: str | Style, stretch: str | Stretch,
301
+ dpi: int | None) -> None:
302
+ """Initialize a font that can be used with Pyglet.
303
+
304
+ Args:
305
+ name:
306
+ Font family, for example, "Times New Roman". If a list of names
307
+ is provided, the first one matching a known font is used. If no
308
+ font can be matched to the name(s), a default font is used. The default font
309
+ will be platform dependent.
310
+ size:
311
+ Size of the font, in points. The returned font may be an exact
312
+ match or the closest available.
313
+ weight:
314
+ If set, a specific weight variant is returned if one exists for the given font
315
+ family and size. The weight is provided as a string. For example: "bold" or "light".
316
+ style:
317
+ If True, an italic variant is returned, if one exists for the given family and size. For some Font
318
+ renderers, italics may have an "oblique" variation which can be specified as a string.
319
+ stretch:
320
+ If True, a stretch variant is returned, if one exists for the given family and size. Currently only
321
+ supported by Windows through the ``DirectWrite`` font renderer. For example, "condensed" or "expanded".
322
+ dpi: int
323
+ The assumed resolution of the display device, for the purposes of
324
+ determining the pixel size of the font. Defaults to 96.
325
+ """
326
+ self._name = name
327
+ self.size = size
328
+ self.weight = weight
329
+ self.style = style
330
+ self.stretch = stretch
331
+ self.dpi = dpi
332
+
333
+ # From DPI to DIP (Device Independent Pixels)
334
+ self.pixel_size = (self.size * self.dpi) // 72
335
+
301
336
  self.texture_bin = None
302
337
  self.hb_resource = None
303
338
  self._glyph_renderer = None
@@ -308,7 +343,6 @@ class Font:
308
343
  # Represents a zero width glyph.
309
344
  self._zero_glyph = None
310
345
  self.glyphs = {}
311
- self.fallbacks = []
312
346
 
313
347
  def _initialize_renderer(self) -> None:
314
348
  """Initialize the glyph renderer and cache it on the Font.
@@ -320,21 +354,14 @@ class Font:
320
354
  self._missing_glyph = self._glyph_renderer.render(" ")
321
355
  self._zero_glyph = self._glyph_renderer.create_zero_glyph()
322
356
 
323
- def add_fallback(self, font: Font) -> None:
324
- assert font not in self.fallbacks, "Font is already added."
325
- self.fallbacks.append(font)
326
-
327
- def remove_fallback(self, font: Font) -> None:
328
- assert font not in self.fallbacks, "Font has not been added."
329
- self.fallbacks.remove(font)
330
-
331
357
  @property
332
- @abc.abstractmethod
333
358
  def name(self) -> str:
334
359
  """Return the Family Name of the font as a string."""
360
+ return self._name
335
361
 
336
362
  @classmethod
337
- def add_font_data(cls: type[Font], data: BinaryIO) -> None:
363
+ @abc.abstractmethod
364
+ def add_font_data(cls: type[Font], data: BinaryIO, manager: FontManager) -> None:
338
365
  """Add font data to the font loader.
339
366
 
340
367
  This is a class method and affects all fonts loaded. Data must be
@@ -347,6 +374,7 @@ class Font:
347
374
  """
348
375
 
349
376
  @classmethod
377
+ @abc.abstractmethod
350
378
  def have_font(cls: type[Font], name: str) -> bool:
351
379
  """Determine if a font with the given name is installed.
352
380
 
@@ -354,9 +382,8 @@ class Font:
354
382
  name:
355
383
  Name of a font to search for.
356
384
  """
357
- return True
358
385
 
359
- def create_glyph(self, img: image.AbstractImage, fmt: int | None = None) -> Glyph:
386
+ def create_glyph(self, img: ImageData) -> Glyph:
360
387
  """Create a glyph using the given image.
361
388
 
362
389
  This is used internally by `Font` subclasses to add glyph data
@@ -368,18 +395,17 @@ class Font:
368
395
  Args:
369
396
  img:
370
397
  The image to write to the font texture.
371
- fmt:
372
- Override for the format and internalformat of the atlas texture. None will use default.
398
+ descriptor:
399
+ Override for the atlas texture's descriptor. None will use default.
373
400
  """
374
401
  if self.texture_bin is None:
375
402
  if self.optimize_fit:
376
403
  self.texture_width, self.texture_height = self._get_optimal_atlas_size(img)
377
404
  self.texture_bin = GlyphTextureBin(self.texture_width, self.texture_height)
378
405
 
379
- return self.texture_bin.add(
380
- img, fmt or self.texture_internalformat, self.texture_min_filter, self.texture_mag_filter, border=1)
406
+ return self.texture_bin.add(img, self.filters, border=1)
381
407
 
382
- def _get_optimal_atlas_size(self, image_data: image.AbstractImage) -> tuple[int, int]:
408
+ def _get_optimal_atlas_size(self, image_data: ImageData) -> tuple[int, int]:
383
409
  """Retrieves the optimal atlas size to fit ``image_data`` with ``glyph_fit`` number of glyphs."""
384
410
  # A texture glyph sheet should be able to handle all standard keyboard characters in one sheet.
385
411
  # 26 Alpha upper, 26 lower, 10 numbers, 33 symbols, space = around 96 characters. (Glyph Fit)
@@ -405,7 +431,7 @@ class Font:
405
431
 
406
432
  return atlas_size
407
433
 
408
- def get_glyphs(self, text: str) -> tuple[list[Glyph], list[GlyphPosition]]:
434
+ def get_glyphs(self, text: str, shaping: bool = False) -> tuple[list[Glyph], list[GlyphPosition]]:
409
435
  """Create and return a list of Glyphs for `text`.
410
436
 
411
437
  If any characters do not have a known glyph representation in this
@@ -414,14 +440,16 @@ class Font:
414
440
  Args:
415
441
  text:
416
442
  Text to render.
443
+ shaping:
444
+ If the text will be shaped using the global option. If ``False``, no text shaping will occur and
445
+ positioning will instead be based on glyph dimensions.
417
446
  """
418
447
  glyph_renderer = None
419
448
 
420
449
  glyphs = [] # glyphs that are committed.
421
450
  offsets = []
422
451
  for c in get_grapheme_clusters(str(text)):
423
- # Get the glyph for 'c'. Hide tabs (Windows and Linux render
424
- # boxes)
452
+ # Get the glyph for 'c'. Hide tabs (Windows and Linux render boxes)
425
453
  if c == "\t":
426
454
  c = " " # noqa: PLW2901
427
455
  if c not in self.glyphs:
@@ -496,4 +524,31 @@ class Font:
496
524
  return glyphs
497
525
 
498
526
  def __repr__(self) -> str:
499
- return f"{self.__class__.__name__}('{self.name}')"
527
+ return f"{self.__class__.__name__}('name={self.name}, size={self.size})')"
528
+
529
+
530
+ # Font Table Mappings
531
+ _weight_class_to_weight = {
532
+ 100: Weight.THIN,
533
+ 200: Weight.EXTRALIGHT, # Ultralight
534
+ 300: Weight.LIGHT,
535
+ 400: Weight.NORMAL, # REGULAR
536
+ 500: Weight.MEDIUM,
537
+ 600: Weight.SEMIBOLD, # DEMIBOLD
538
+ 700: Weight.BOLD,
539
+ 800: Weight.EXTRABOLD, # ULTRABOLD
540
+ 900: Weight.BLACK, # HEAVY
541
+ 950: Weight.EXTRABLACK,
542
+ }
543
+
544
+ _width_class_to_stretch = {
545
+ 1: Stretch.ULTRACONDENSED,
546
+ 2: Stretch.EXTRACONDENSED,
547
+ 3: Stretch.CONDENSED,
548
+ 4: Stretch.SEMICONDENSED,
549
+ 5: Stretch.NORMAL,
550
+ 6: Stretch.SEMIEXPANDED,
551
+ 7: Stretch.EXPANDED,
552
+ 8: Stretch.EXTRAEXPANDED,
553
+ 9: Stretch.ULTRAEXPANDED,
554
+ }