pyglet 2.1.2__py3-none-any.whl → 2.1.4__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 +21 -9
- pyglet/__init__.pyi +3 -1
- pyglet/app/cocoa.py +6 -3
- pyglet/app/xlib.py +1 -1
- pyglet/display/cocoa.py +2 -2
- pyglet/display/win32.py +17 -18
- pyglet/display/xlib.py +2 -2
- pyglet/display/xlib_vidmoderestore.py +1 -1
- pyglet/extlibs/earcut.py +2 -2
- pyglet/font/__init__.py +3 -3
- pyglet/font/base.py +118 -51
- pyglet/font/dwrite/__init__.py +1381 -0
- pyglet/font/dwrite/d2d1_lib.py +637 -0
- pyglet/font/dwrite/d2d1_types_lib.py +60 -0
- pyglet/font/dwrite/dwrite_lib.py +1577 -0
- pyglet/font/fontconfig.py +79 -16
- pyglet/font/freetype.py +252 -77
- pyglet/font/freetype_lib.py +234 -125
- pyglet/font/harfbuzz/__init__.py +275 -0
- pyglet/font/harfbuzz/harfbuzz_lib.py +212 -0
- pyglet/font/quartz.py +432 -112
- pyglet/font/user.py +18 -11
- pyglet/font/win32.py +9 -1
- pyglet/gl/wgl.py +94 -87
- pyglet/gl/wglext_arb.py +472 -218
- pyglet/gl/wglext_nv.py +410 -188
- pyglet/gui/frame.py +4 -4
- pyglet/gui/widgets.py +6 -1
- pyglet/image/__init__.py +0 -2
- pyglet/image/codecs/bmp.py +3 -5
- pyglet/image/codecs/dds.py +1 -1
- pyglet/image/codecs/gdiplus.py +28 -9
- pyglet/image/codecs/wic.py +198 -489
- pyglet/image/codecs/wincodec_lib.py +413 -0
- pyglet/input/base.py +3 -2
- pyglet/input/linux/x11_xinput.py +3 -3
- pyglet/input/linux/x11_xinput_tablet.py +2 -2
- pyglet/input/macos/darwin_hid.py +28 -2
- pyglet/input/win32/directinput.py +3 -2
- pyglet/input/win32/wintab.py +1 -1
- pyglet/input/win32/xinput.py +10 -9
- pyglet/lib.py +14 -2
- pyglet/libs/darwin/cocoapy/cocoalibs.py +74 -3
- pyglet/libs/darwin/coreaudio.py +0 -2
- pyglet/libs/win32/__init__.py +4 -2
- pyglet/libs/win32/com.py +65 -12
- pyglet/libs/win32/constants.py +1 -0
- pyglet/libs/win32/dinput.py +1 -9
- pyglet/libs/win32/types.py +72 -8
- pyglet/math.py +5 -5
- pyglet/media/codecs/coreaudio.py +1 -0
- pyglet/media/codecs/wmf.py +93 -72
- pyglet/media/devices/win32.py +5 -4
- pyglet/media/drivers/directsound/lib_dsound.py +4 -4
- pyglet/media/drivers/xaudio2/interface.py +21 -17
- pyglet/media/drivers/xaudio2/lib_xaudio2.py +42 -25
- pyglet/model/__init__.py +78 -57
- pyglet/shapes.py +1 -1
- pyglet/text/document.py +7 -53
- pyglet/text/formats/attributed.py +3 -1
- pyglet/text/formats/plaintext.py +1 -1
- pyglet/text/formats/structured.py +1 -1
- pyglet/text/layout/base.py +76 -68
- pyglet/text/layout/incremental.py +38 -8
- pyglet/text/layout/scrolling.py +1 -1
- pyglet/text/runlist.py +2 -114
- pyglet/window/__init__.py +11 -8
- pyglet/window/win32/__init__.py +1 -3
- pyglet/window/xlib/__init__.py +2 -2
- {pyglet-2.1.2.dist-info → pyglet-2.1.4.dist-info}/METADATA +2 -3
- {pyglet-2.1.2.dist-info → pyglet-2.1.4.dist-info}/RECORD +73 -67
- pyglet/font/directwrite.py +0 -2798
- {pyglet-2.1.2.dist-info → pyglet-2.1.4.dist-info}/LICENSE +0 -0
- {pyglet-2.1.2.dist-info → pyglet-2.1.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
from ctypes import c_void_p, c_uint16, c_uint32, string_at, create_string_buffer, py_object, cast, POINTER
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from pyglet.font.base import GlyphPosition
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from pyglet.font.freetype import FreeTypeFont
|
|
12
|
+
from pyglet.font.dwrite import Win32DirectWriteFont
|
|
13
|
+
from pyglet.font.quartz import QuartzFont
|
|
14
|
+
from pyglet.font.base import Font, Glyph
|
|
15
|
+
|
|
16
|
+
from .harfbuzz_lib import hb_lib
|
|
17
|
+
_available = False
|
|
18
|
+
|
|
19
|
+
if hb_lib:
|
|
20
|
+
_available = True
|
|
21
|
+
|
|
22
|
+
from .harfbuzz_lib import HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def harfbuzz_available() -> bool:
|
|
26
|
+
"""Return if the Harfbuzz library is available to use."""
|
|
27
|
+
return _available
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
_hb_cache: dict[tuple[str, str, bool, str | bool], _HarfbuzzResources] = {}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _add_utf16_buffer(text: str, buffer: c_void_p) -> None:
|
|
34
|
+
txt_utf16 = text.encode("utf-16-le") # HarfBuzz expects little-endian UTF-16
|
|
35
|
+
length = len(txt_utf16) // 2
|
|
36
|
+
txt_array = (c_uint16 * length).from_buffer_copy(txt_utf16)
|
|
37
|
+
hb_lib.hb_buffer_add_utf16(buffer, txt_array, length, 0, length)
|
|
38
|
+
|
|
39
|
+
def _add_utf32_buffer(text: str, buffer: c_void_p) -> None:
|
|
40
|
+
txt_utf32 = text.encode("utf-32-le")
|
|
41
|
+
char_ct = (len(txt_utf32) // 4)
|
|
42
|
+
txt_array = (c_uint32 * char_ct).from_buffer_copy(txt_utf32)
|
|
43
|
+
hb_lib.hb_buffer_add_utf32(buffer, txt_array,char_ct, 0, char_ct)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Set which unicode python is using for the strings.
|
|
47
|
+
if sys.maxunicode == 0x10FFFF: # UTF-32
|
|
48
|
+
set_buffer_string = _add_utf32_buffer
|
|
49
|
+
elif sys.maxunicode == 0xFFFF: # UTF-16
|
|
50
|
+
set_buffer_string = _add_utf16_buffer
|
|
51
|
+
|
|
52
|
+
def get_resource_from_ct_font(font: QuartzFont):
|
|
53
|
+
"""Get a harfbuzz resource object from a CoreText (Mac) font."""
|
|
54
|
+
key = (font.name, font.weight, font.italic, font.stretch)
|
|
55
|
+
if key in _hb_cache:
|
|
56
|
+
return _hb_cache[key]
|
|
57
|
+
|
|
58
|
+
resource = _HarfbuzzResources()
|
|
59
|
+
hb_face = font._get_hb_face()
|
|
60
|
+
resource.load_from_tabled_face(hb_face)
|
|
61
|
+
_hb_cache[key] = resource
|
|
62
|
+
return resource
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_resource_from_dw_font(font: Win32DirectWriteFont) -> _HarfbuzzResources:
|
|
66
|
+
"""Get a harfbuzz resource object from a DirectWrite (Windows) font."""
|
|
67
|
+
key = (font.name, font.weight, font.italic, font.stretch)
|
|
68
|
+
if key in _hb_cache:
|
|
69
|
+
return _hb_cache[key]
|
|
70
|
+
|
|
71
|
+
data = font.get_font_data()
|
|
72
|
+
if data:
|
|
73
|
+
resource = _HarfbuzzResources()
|
|
74
|
+
resource.load_from_memory(data)
|
|
75
|
+
_hb_cache[key] = resource
|
|
76
|
+
return resource
|
|
77
|
+
|
|
78
|
+
raise Exception("Font data could not be read.")
|
|
79
|
+
|
|
80
|
+
def get_resource_from_ft_font(font: FreeTypeFont) -> _HarfbuzzResources:
|
|
81
|
+
"""Get a harfbuzz resource object from a FreeType (Linux) font."""
|
|
82
|
+
key = (font.name, font.weight, font.italic, font.stretch)
|
|
83
|
+
if key in _hb_cache:
|
|
84
|
+
return _hb_cache[key]
|
|
85
|
+
|
|
86
|
+
stream = font.face.ft_face.contents.stream.contents
|
|
87
|
+
data = string_at(stream.base, stream.size)
|
|
88
|
+
resource = _HarfbuzzResources()
|
|
89
|
+
resource.load_from_memory(data)
|
|
90
|
+
_hb_cache[key] = resource
|
|
91
|
+
return resource
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def get_resource_from_path(font_path: str):
|
|
95
|
+
with open(font_path, "rb") as f:
|
|
96
|
+
data = f.read()
|
|
97
|
+
|
|
98
|
+
resource = _HarfbuzzResources()
|
|
99
|
+
resource.load_from_memory(data)
|
|
100
|
+
return resource
|
|
101
|
+
|
|
102
|
+
def _get_fallback_glyph_shape(font: Font, text: str) -> tuple[list[Glyph], list[GlyphPosition]]:
|
|
103
|
+
glyphs = []
|
|
104
|
+
offsets = []
|
|
105
|
+
pystr_len = len(text)
|
|
106
|
+
for fallback in font.fallbacks:
|
|
107
|
+
glyph_info = fallback.hb_resource.shape_text(text, fallback.pixel_size)
|
|
108
|
+
|
|
109
|
+
indices = [glyph_data["codepoint"] for glyph_data in glyph_info]
|
|
110
|
+
fallback.render_glyph_indices(indices)
|
|
111
|
+
|
|
112
|
+
for glyph_data in glyph_info:
|
|
113
|
+
glyph = fallback.glyphs[glyph_data["codepoint"]]
|
|
114
|
+
glyphs.append(glyph)
|
|
115
|
+
offset = GlyphPosition(glyph_data["x_advance"]-glyph.advance, glyph_data["y_advance"],
|
|
116
|
+
glyph_data["x_offset"], glyph_data["y_offset"])
|
|
117
|
+
offsets.append(offset)
|
|
118
|
+
|
|
119
|
+
diff = pystr_len - len(glyphs)
|
|
120
|
+
if diff > 0:
|
|
121
|
+
for i in range(diff):
|
|
122
|
+
glyphs.append(font._zero_glyph)
|
|
123
|
+
offsets.append(GlyphPosition(0, 0, 0, 0))
|
|
124
|
+
|
|
125
|
+
return glyphs, offsets
|
|
126
|
+
|
|
127
|
+
def get_harfbuzz_shaped_glyphs(font: Font, text: str) -> tuple[list[Glyph], list[GlyphPosition]]:
|
|
128
|
+
glyph_info = font.hb_resource.shape_text(text, font.pixel_size)
|
|
129
|
+
clusters = [glyph_data["cluster"] for glyph_data in glyph_info]
|
|
130
|
+
cluster_map = defaultdict(list)
|
|
131
|
+
|
|
132
|
+
# Find any clusters that have empty indices.
|
|
133
|
+
empty_clusters = {}
|
|
134
|
+
indices = []
|
|
135
|
+
for glyph_data in glyph_info:
|
|
136
|
+
# If any clusters have no codepoint, determine the size to pass to fallback.
|
|
137
|
+
cluster_num = glyph_data["cluster"]
|
|
138
|
+
glyph_index = glyph_data["codepoint"]
|
|
139
|
+
if glyph_index == 0 and cluster_num not in empty_clusters:
|
|
140
|
+
empty_clusters[cluster_num] = clusters.count(cluster_num)
|
|
141
|
+
|
|
142
|
+
if cluster_num not in cluster_map:
|
|
143
|
+
cluster_map[cluster_num] = []
|
|
144
|
+
|
|
145
|
+
cluster_map[cluster_num].append(glyph_data)
|
|
146
|
+
indices.append(glyph_index)
|
|
147
|
+
|
|
148
|
+
font.render_glyph_indices(indices)
|
|
149
|
+
|
|
150
|
+
# If a cluster is missing and had 0 indices.
|
|
151
|
+
missing_glyphs = {}
|
|
152
|
+
for cluster_id, cluster_ct in empty_clusters.items():
|
|
153
|
+
missing_text = text[cluster_id:cluster_id + cluster_ct]
|
|
154
|
+
if missing_text not in font.glyphs:
|
|
155
|
+
if missing_text == '\n':
|
|
156
|
+
fb_glyph_info = ([font._zero_glyph], [GlyphPosition(0, 0, 0, 0)])
|
|
157
|
+
else:
|
|
158
|
+
# Get glyphs from fallback, since we need the fallback to actually render it.
|
|
159
|
+
fb_glyph_info = _get_fallback_glyph_shape(font, missing_text)
|
|
160
|
+
font.glyphs[missing_text] = fb_glyph_info # Cache by string to prevent future fallback paths.
|
|
161
|
+
missing_glyphs[cluster_id] = font.glyphs[missing_text]
|
|
162
|
+
|
|
163
|
+
glyphs = []
|
|
164
|
+
offsets = []
|
|
165
|
+
for i in range(len(text)):
|
|
166
|
+
cluster_glyph_info = cluster_map[i]
|
|
167
|
+
|
|
168
|
+
# Cluster has data, check if it's part of the missing glyphs.
|
|
169
|
+
if i in missing_glyphs:
|
|
170
|
+
_glyphs, _offsets = missing_glyphs[i]
|
|
171
|
+
glyphs.extend(_glyphs)
|
|
172
|
+
offsets.extend(_offsets)
|
|
173
|
+
|
|
174
|
+
# If this cluster is missing, add some zero glyphs until count matches.
|
|
175
|
+
elif len(cluster_glyph_info) == 0:
|
|
176
|
+
while len(glyphs) - 1 < i:
|
|
177
|
+
glyphs.append(font._zero_glyph)
|
|
178
|
+
offsets.append(GlyphPosition(0, 0, 0, 0))
|
|
179
|
+
else:
|
|
180
|
+
for glyph_info in cluster_glyph_info:
|
|
181
|
+
glyph = font.glyphs[glyph_info["codepoint"]]
|
|
182
|
+
glyphs.append(glyph)
|
|
183
|
+
|
|
184
|
+
offsets.append(
|
|
185
|
+
GlyphPosition(glyph_info["x_advance"] - glyph.advance, glyph_info["y_advance"],
|
|
186
|
+
glyph_info["x_offset"], glyph_info["y_offset"])
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return glyphs, offsets
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class _HarfbuzzResources:
|
|
193
|
+
def __init__(self) -> None:
|
|
194
|
+
self.blob = None
|
|
195
|
+
self.face = None
|
|
196
|
+
self.font = None
|
|
197
|
+
|
|
198
|
+
def load_from_tabled_face(self, hb_face: c_void_p) -> None:
|
|
199
|
+
self.blob = None
|
|
200
|
+
self.face = hb_face
|
|
201
|
+
self.font = hb_lib.hb_font_create(self.face)
|
|
202
|
+
|
|
203
|
+
def load_from_memory(self, data: bytes) -> None:
|
|
204
|
+
data_len = len(data)
|
|
205
|
+
data_buf = create_string_buffer(data, data_len)
|
|
206
|
+
self.blob = hb_lib.hb_blob_create(data_buf, data_len, HB_MEMORY_MODE_READONLY, None, None)
|
|
207
|
+
self.face = hb_lib.hb_face_create(self.blob, 0)
|
|
208
|
+
self.font = hb_lib.hb_font_create(self.face)
|
|
209
|
+
|
|
210
|
+
def shape_text(self, text: str, pixel_size: int, direction: int=HB_DIRECTION_LTR):
|
|
211
|
+
"""Shapes the given string using the provided hb_font.
|
|
212
|
+
Returns a list of dictionaries for each glyph containing:
|
|
213
|
+
- codepoint: the glyph index
|
|
214
|
+
- cluster: the index into the original string
|
|
215
|
+
- x_advance, y_advance: the advances (including kerning adjustments)
|
|
216
|
+
- x_offset, y_offset: the offsets (shaped adjustments)
|
|
217
|
+
"""
|
|
218
|
+
# Create a new buffer.
|
|
219
|
+
buf = hb_lib.hb_buffer_create()
|
|
220
|
+
|
|
221
|
+
# hb_lib.hb_buffer_set_cluster_level(buf, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
|
|
222
|
+
set_buffer_string(text, buf)
|
|
223
|
+
|
|
224
|
+
scale = int(pixel_size * 64)
|
|
225
|
+
hb_lib.hb_font_set_scale(self.font, scale, scale)
|
|
226
|
+
|
|
227
|
+
hb_lib.hb_buffer_guess_segment_properties(buf)
|
|
228
|
+
|
|
229
|
+
# Set text direction (LTR, RTL, etc.).
|
|
230
|
+
hb_lib.hb_buffer_set_direction(buf, direction)
|
|
231
|
+
|
|
232
|
+
# Perform shaping.
|
|
233
|
+
hb_lib.hb_shape(self.font, buf, None, 0)
|
|
234
|
+
|
|
235
|
+
# Retrieve the number of glyphs.
|
|
236
|
+
length = hb_lib.hb_buffer_get_length(buf)
|
|
237
|
+
|
|
238
|
+
# Get pointers to the glyph info and position arrays.
|
|
239
|
+
infos = hb_lib.hb_buffer_get_glyph_infos(buf, None)
|
|
240
|
+
positions = hb_lib.hb_buffer_get_glyph_positions(buf, None)
|
|
241
|
+
|
|
242
|
+
# Collect glyph metrics.
|
|
243
|
+
glyphs = []
|
|
244
|
+
for i in range(length):
|
|
245
|
+
info = infos[i]
|
|
246
|
+
pos = positions[i]
|
|
247
|
+
glyphs.append({
|
|
248
|
+
"codepoint": info.codepoint,
|
|
249
|
+
"cluster": info.cluster,
|
|
250
|
+
"x_advance": pos.x_advance / 64.0,
|
|
251
|
+
"y_advance": pos.y_advance / 64.0,
|
|
252
|
+
"x_offset": pos.x_offset / 64.0,
|
|
253
|
+
"y_offset": pos.y_offset / 64.0,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
# Clean up the buffer.
|
|
257
|
+
hb_lib.hb_buffer_destroy(buf)
|
|
258
|
+
|
|
259
|
+
return glyphs
|
|
260
|
+
|
|
261
|
+
def __del__(self):
|
|
262
|
+
self.destroy()
|
|
263
|
+
|
|
264
|
+
def destroy(self):
|
|
265
|
+
if self.font:
|
|
266
|
+
hb_lib.hb_font_destroy(self.font)
|
|
267
|
+
self.font = None
|
|
268
|
+
|
|
269
|
+
if self.face:
|
|
270
|
+
hb_lib.hb_face_destroy(self.face)
|
|
271
|
+
self.face = None
|
|
272
|
+
|
|
273
|
+
if self.blob:
|
|
274
|
+
hb_lib.hb_blob_destroy(self.blob)
|
|
275
|
+
self.blob = None
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
from ctypes import (
|
|
5
|
+
CFUNCTYPE,
|
|
6
|
+
POINTER,
|
|
7
|
+
Structure,
|
|
8
|
+
Union,
|
|
9
|
+
c_char_p,
|
|
10
|
+
c_int,
|
|
11
|
+
c_int8,
|
|
12
|
+
c_int16,
|
|
13
|
+
c_int32,
|
|
14
|
+
c_size_t,
|
|
15
|
+
c_uint,
|
|
16
|
+
c_uint8,
|
|
17
|
+
c_uint16,
|
|
18
|
+
c_uint32,
|
|
19
|
+
c_void_p,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
import pyglet
|
|
23
|
+
|
|
24
|
+
# Harfbuzz DLL depends on libglib and libintl (for Windows)
|
|
25
|
+
hb_lib = None
|
|
26
|
+
with contextlib.suppress(ImportError):
|
|
27
|
+
hb_lib = pyglet.lib.load_library("harfbuzz", win32='libharfbuzz-0.dll', darwin='libharfbuzz.0.dylib')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
HB_MEMORY_MODE_READONLY = 0 # for read-only font data
|
|
31
|
+
|
|
32
|
+
HB_DIRECTION_INVALID = 0
|
|
33
|
+
HB_DIRECTION_LTR = 4
|
|
34
|
+
HB_DIRECTION_RTL = 5
|
|
35
|
+
HB_DIRECTION_TTB = 6
|
|
36
|
+
HB_DIRECTION_BTT = 7
|
|
37
|
+
|
|
38
|
+
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0
|
|
39
|
+
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1
|
|
40
|
+
HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2
|
|
41
|
+
HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
|
|
42
|
+
|
|
43
|
+
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001
|
|
44
|
+
HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002
|
|
45
|
+
HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL = 0x00000004
|
|
46
|
+
|
|
47
|
+
HB_GLYPH_FLAG_DEFINED = 0x00000007 # OR of all defined flags
|
|
48
|
+
|
|
49
|
+
hb_buffer_cluster_level_t = c_uint
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class hb_var_int_t(Union):
|
|
53
|
+
_fields_ = [
|
|
54
|
+
("u32", c_uint32),
|
|
55
|
+
("i32", c_int32),
|
|
56
|
+
("u16", c_uint16 * 2),
|
|
57
|
+
("i16", c_int16 * 2),
|
|
58
|
+
("u8", c_uint8 * 4),
|
|
59
|
+
("i8", c_int8 * 4),
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
hb_codepoint_t = c_uint32
|
|
64
|
+
hb_mask_t = c_uint32
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class hb_glyph_info_t(Structure):
|
|
68
|
+
_fields_ = [
|
|
69
|
+
("codepoint", hb_codepoint_t), # glyph index
|
|
70
|
+
("mask", hb_mask_t),
|
|
71
|
+
("cluster", c_uint32), # index in the original text
|
|
72
|
+
("var1", hb_var_int_t),
|
|
73
|
+
("var2", hb_var_int_t)
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
def __repr__(self) -> str:
|
|
77
|
+
return f"hb_glyph_info_t(codepoint={self.codepoint}, cluster={self.cluster}, flag={self.mask & HB_GLYPH_FLAG_DEFINED})"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
hb_position_t = c_int32
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# The glyph position structure contains advances and offsets.
|
|
84
|
+
class hb_glyph_position_t(Structure):
|
|
85
|
+
_fields_ = [
|
|
86
|
+
("x_advance", hb_position_t), # includes kerning
|
|
87
|
+
("y_advance", hb_position_t),
|
|
88
|
+
("x_offset", hb_position_t), # adjustments to the glyph's drawing position
|
|
89
|
+
("y_offset", hb_position_t),
|
|
90
|
+
('var', hb_var_int_t), # Private, do not use, but must be included for proper reading.
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if hb_lib:
|
|
95
|
+
hb_lib.hb_blob_create.argtypes = [
|
|
96
|
+
c_char_p, # pointer to the font data const char *data
|
|
97
|
+
c_size_t, # length of the data
|
|
98
|
+
c_uint, # memory mode (e.g., HB_MEMORY_MODE_READONLY) hb_memory_mode_t
|
|
99
|
+
c_void_p, # user data (None here) void *user_data
|
|
100
|
+
c_void_p # destroy callback (None here) hb_destroy_func_t
|
|
101
|
+
]
|
|
102
|
+
hb_lib.hb_blob_create.restype = c_void_p
|
|
103
|
+
|
|
104
|
+
hb_blob_t = c_void_p
|
|
105
|
+
hb_lib.hb_face_create.argtypes = [
|
|
106
|
+
c_void_p, # hb_blob_t *blob
|
|
107
|
+
c_uint # font index in the blob (usually 0) index
|
|
108
|
+
]
|
|
109
|
+
hb_lib.hb_face_create.restype = c_void_p
|
|
110
|
+
|
|
111
|
+
hb_reference_table_func_t = CFUNCTYPE(c_void_p, c_void_p, c_uint32, c_void_p)
|
|
112
|
+
hb_destroy_func_t = CFUNCTYPE(None, c_void_p)
|
|
113
|
+
|
|
114
|
+
hb_lib.hb_face_create_for_tables.argtypes = [
|
|
115
|
+
hb_reference_table_func_t, # table func
|
|
116
|
+
c_void_p, # user data ptr
|
|
117
|
+
hb_destroy_func_t # free memory function
|
|
118
|
+
]
|
|
119
|
+
hb_lib.hb_face_create_for_tables.restype = c_void_p
|
|
120
|
+
|
|
121
|
+
hb_lib.hb_font_create.argtypes = [c_void_p] # hb_face_t *face
|
|
122
|
+
hb_lib.hb_font_create.restype = c_void_p
|
|
123
|
+
|
|
124
|
+
hb_lib.hb_face_get_upem.argtypes = [c_void_p] # hb_face_t *face
|
|
125
|
+
hb_lib.hb_face_get_upem.restype = c_uint
|
|
126
|
+
|
|
127
|
+
hb_lib.hb_font_set_scale.argtypes = [
|
|
128
|
+
c_void_p, # b_font_t *font
|
|
129
|
+
c_int, # x_scale
|
|
130
|
+
c_int # y_scale
|
|
131
|
+
]
|
|
132
|
+
hb_lib.hb_font_set_scale.restype = None
|
|
133
|
+
|
|
134
|
+
hb_lib.hb_buffer_create.argtypes = []
|
|
135
|
+
hb_lib.hb_buffer_create.restype = c_void_p
|
|
136
|
+
|
|
137
|
+
hb_lib.hb_buffer_add_utf8.argtypes = [
|
|
138
|
+
c_void_p, # b_buffer_t *buffer
|
|
139
|
+
c_char_p, # UTF-8 text const char *text
|
|
140
|
+
c_int, # text length (number of bytes)
|
|
141
|
+
c_uint, # item offset (usually 0)
|
|
142
|
+
c_int # item length (often the same as text_length)
|
|
143
|
+
]
|
|
144
|
+
hb_lib.hb_buffer_add_utf8.restype = None
|
|
145
|
+
|
|
146
|
+
hb_lib.hb_buffer_set_cluster_level.argtypes = [c_void_p, hb_buffer_cluster_level_t]
|
|
147
|
+
hb_lib.hb_buffer_set_cluster_level.restype = None
|
|
148
|
+
|
|
149
|
+
hb_lib.hb_buffer_add_utf16.argtypes = [
|
|
150
|
+
c_void_p, # hb_buffer_t *buffer
|
|
151
|
+
POINTER(c_uint16), # UTF-16 text onst char *text
|
|
152
|
+
c_int, # text length (number of bytes)
|
|
153
|
+
c_uint, # item offset (usually 0)
|
|
154
|
+
c_int # item length (often the same as text_length)
|
|
155
|
+
]
|
|
156
|
+
hb_lib.hb_buffer_add_utf16.restype = None
|
|
157
|
+
|
|
158
|
+
hb_lib.hb_buffer_add_utf32.argtypes = [
|
|
159
|
+
c_void_p, # hb_buffer_t *buffer
|
|
160
|
+
POINTER(c_uint32), # UTF-32 text const char *text
|
|
161
|
+
c_int, # text length (number of bytes)
|
|
162
|
+
c_uint, # item offset (usually 0)
|
|
163
|
+
c_int # item length (often the same as text_length)
|
|
164
|
+
]
|
|
165
|
+
hb_lib.hb_buffer_add_utf32.restype = None
|
|
166
|
+
|
|
167
|
+
hb_lib.hb_buffer_set_direction.argtypes = [
|
|
168
|
+
c_void_p, # hb_buffer_t *buffer
|
|
169
|
+
c_int # direction (e.g., HB_DIRECTION_LTR) hb_direction_t
|
|
170
|
+
]
|
|
171
|
+
hb_lib.hb_buffer_set_direction.restype = None
|
|
172
|
+
|
|
173
|
+
hb_lib.hb_shape.argtypes = [
|
|
174
|
+
c_void_p, # hb_font_t *font
|
|
175
|
+
c_void_p, # hb_buffer_t *buffer
|
|
176
|
+
c_void_p, # hb_feature_t *features (None if not used)
|
|
177
|
+
c_uint # number of features (0 if features is None)
|
|
178
|
+
]
|
|
179
|
+
hb_lib.hb_shape.restype = None
|
|
180
|
+
|
|
181
|
+
hb_lib.hb_buffer_guess_segment_properties.argtypes = [c_void_p]
|
|
182
|
+
hb_lib.hb_buffer_guess_segment_properties.restype = None
|
|
183
|
+
|
|
184
|
+
hb_lib.hb_buffer_get_length.argtypes = [c_void_p] # hb_buffer_t *buffer
|
|
185
|
+
hb_lib.hb_buffer_get_length.restype = c_uint
|
|
186
|
+
|
|
187
|
+
hb_lib.hb_buffer_get_glyph_infos.argtypes = [
|
|
188
|
+
c_void_p, # hb_buffer_t *buffer,
|
|
189
|
+
POINTER(c_uint) # pointer for length (can be None)
|
|
190
|
+
]
|
|
191
|
+
hb_lib.hb_buffer_get_glyph_infos.restype = POINTER(hb_glyph_info_t)
|
|
192
|
+
|
|
193
|
+
hb_lib.hb_buffer_get_glyph_positions.argtypes = [
|
|
194
|
+
c_void_p, # hb_buffer_t *buffer
|
|
195
|
+
POINTER(c_uint) # pointer for length (can be None)
|
|
196
|
+
]
|
|
197
|
+
hb_lib.hb_buffer_get_glyph_positions.restype = POINTER(hb_glyph_position_t)
|
|
198
|
+
|
|
199
|
+
hb_lib.hb_blob_destroy.argtypes = [c_void_p] # b_blob_t *blob)
|
|
200
|
+
hb_lib.hb_blob_destroy.restype = None
|
|
201
|
+
|
|
202
|
+
hb_lib.hb_face_destroy.argtypes = [c_void_p] # hb_face_t *face
|
|
203
|
+
hb_lib.hb_face_destroy.restype = None
|
|
204
|
+
|
|
205
|
+
hb_lib.hb_font_destroy.argtypes = [c_void_p] # hb_font_t *font
|
|
206
|
+
hb_lib.hb_font_destroy.restype = None
|
|
207
|
+
|
|
208
|
+
hb_lib.hb_buffer_destroy.argtypes = [c_void_p] # hb_buffer_t *buffer
|
|
209
|
+
hb_lib.hb_buffer_destroy.restype = None
|
|
210
|
+
|
|
211
|
+
hb_lib.hb_buffer_normalize_glyphs.argtypes = [c_void_p]
|
|
212
|
+
hb_lib.hb_buffer_normalize_glyphs.restype = None
|