pyyudit
Cross-platform Python binding to Yudit's Unicode shaping engine, with per-step trace output.
What is this?
pyyudit extracts the shaping engine from the Yudit Unicode editor into a standalone shared library and wraps it with Python ctypes bindings. It provides:
- Indic script shaping — Devanagari, Bengali, Gujarati, Gurmukhi, Oriya, Telugu, Kannada, Malayalam, Sinhala
- Arabic/Syriac joining
- Thai, Lao, Tibetan text processing
- Hangul Jamo composition
- OpenType GSUB/GPOS feature application
- Full BiDi (bidirectional text) support
- Per-step trace — see every decompose → reorder → gsub → gpos step
Architecture
pyyudit (Python)
├── YuditFont — load font from bytes/path
│ ├── shape() — one-shot shaping
│ └── shape_trace() — shaping with full trace
├── _binding.py — ctypes declarations for C API
├── _loader.py — cross-platform native lib discovery
└── _lib/ — bundled native library (DLL/SO/dylib)
yudit_shaper (C/C++)
├── yudit_shaper.h/cpp — C API wrapper
├── stoolkit/ — Yudit core (BiDi, Unicode, glyphs, paragraphs)
├── swindow/ — Font handling (SFontTTF) + SScriptProcessor
└── CMakeLists.txt — build system
Installation
From source (with native build)
# Prerequisites: CMake 3.15+, C++ compiler
git clone https://github.com/Kushim-Jiang/pyyudit.git
cd pyyudit
# Download Yudit source (for the shaping engine)
curl -L https://www.yudit.org/download/yudit-3.1.0.tar.gz | tar xz
# Build the native library
python scripts/build_native.py
# Install the Python package
pip install -e ".[dev]"
Cross-platform wheel
# Build wheel (includes the native library)
pip install hatchling build
python -m build
pip install dist/pyyudit-0.1.0-py3-none-any.whl
Usage
import pyyudit
# One-shot shaping
font_bytes = open("NotoSansDevanagari.ttf", "rb").read()
glyphs = pyyudit.shape(font_bytes, "नमस्ते")
for g in glyphs:
print(f"gid={g.g} cluster={g.cl} adv={g.ax}")
# With full trace
with pyyudit.YuditFont.from_path("NotoSansDevanagari.ttf") as f:
result = f.shape_trace("नमस्ते")
for stage in result.stages:
print(f"{stage.m}: {len(stage.glyphs)} glyphs")
if stage.effective:
print(" (buffer changed)")
# Reusable font object
font = pyyudit.YuditFont.from_path("NotoSansArabic.ttf")
result = font.shape("مرحبا")
print(f"Advance: {result.advance_x} units")
font.close()
Trace stages
The trace captures every step of Yudit's shaping pipeline:
| Stage | Description |
|---|---|
input |
Original codepoints before shaping |
decompose |
Unicode decomposition (vowel splits etc.) |
reorder |
Indic consonant/vowel reordering |
gindex |
Glyph index lookup from cmap |
half |
Half-form substitution (GSUB) |
pres |
Pre-base substitution (GSUB) |
abvs |
Above-base substitution (GSUB) |
blws |
Below-base substitution (GSUB) |
psts |
Post-base substitution (GSUB) |
haln |
Halant/virama substitution (GSUB) |
abvm |
Above-base mark positioning (GPOS) |
blwm |
Below-base mark positioning (GPOS) |
clean |
Post-GSUB cleanup |
final |
Final positioning |
shaped |
Final shaped glyph buffer |
Pure-Python helpers
These work without the native library:
from pyyudit import upem_from_ttf, has_table, read_font_bytes
data = read_font_bytes("font.ttf")
upem = upem_from_ttf(data)
has_gsub = has_table(data, "GSUB")
Configuration
# Set explicit library path
pyyudit.configure("/path/to/libyudit_shaper.so")
# Or via environment variable
# export PYYUDIT_LIBRARY_PATH=/path/to/libyudit_shaper.so
# Check availability
print(pyyudit.is_available())
print(pyyudit.library_info())
Supported scripts
Yudit's shaping engine supports these scripts (with OpenType features):
| Script | Tag | GSUB features | GPOS features |
|---|---|---|---|
| Devanagari | deva |
nukt akhn rphf blwf half vatu pres abvs blws psts haln | abvm blwm dist |
| Bengali | beng |
init nukt akhn rphf blwf half pstf vatu pres abvs blws psts | abvm blwm dist |
| Gujarati | gujr |
nukt akhn rphf blwf half pstf vatu pres abvs blws psts haln | abvm blwm dist |
| Gurmukhi | guru |
nukt blwf pstf vatu pres abvs blws psts haln | abvm blwm dist |
| Oriya | orya |
nukt akhn rphf blwf half pstf vatu pres blws abvs psts haln | abvm blwm dist |
| Tamil | taml |
akhn half pres abvs blws psts haln | abvm blwm dist |
| Telugu | telu |
akhn blwf abvs blws psts haln | abvm blwm dist |
| Kannada | knda |
nukt akhn rphf blwf half pstf vatu pres blws abvs psts haln | abvm blwm dist |
| Malayalam | mlym |
nukt akhn rphf blwf half pstf vatu pres blws abvs psts haln | abvm blwm dist |
| Sinhala | sinh |
nukt akhn rphf blwf half pstf vatu pres blws abvs psts haln | abvm blwm dist |
| Thai | thai |
ccmp | kern mark mkmk |
| Lao | lao |
ccmp blws abvs | kern mark mkmk |
| Tibetan | tibt |
ccmp blws abvs | blwm abvm kern |
| Jamo | jamo |
ccmp ljmo vjmo tjmo | — |
License
- pyyudit Python code: MIT
- Yudit shaping engine: GPL-2.0-or-later (Gaspar Sinai)
- See COPYING.TXT for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyyudit-0.1.1-0-py3-none-win_amd64.whl.
File metadata
- Download URL: pyyudit-0.1.1-0-py3-none-win_amd64.whl
- Upload date:
- Size: 420.4 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bf80775238418c0e312ff394f72a03835ef90567b1f3faffc4ceb0c94f7853b
|
|
| MD5 |
f7354851abed761312144565b247479d
|
|
| BLAKE2b-256 |
c4f8d288a46e179a070f4a7332dc67938576a739b74d950815b9810afb1ae079
|
Provenance
The following attestation bundles were made for pyyudit-0.1.1-0-py3-none-win_amd64.whl:
Publisher:
build.yml on Kushim-Jiang/pyyudit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyyudit-0.1.1-0-py3-none-win_amd64.whl -
Subject digest:
1bf80775238418c0e312ff394f72a03835ef90567b1f3faffc4ceb0c94f7853b - Sigstore transparency entry: 2804995030
- Sigstore integration time:
-
Permalink:
Kushim-Jiang/pyyudit@05e2c8f7138ad2f9de22aeaf024c41f17329930d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Kushim-Jiang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@05e2c8f7138ad2f9de22aeaf024c41f17329930d -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyyudit-0.1.1-0-py3-none-manylinux_2_17_x86_64.whl.
File metadata
- Download URL: pyyudit-0.1.1-0-py3-none-manylinux_2_17_x86_64.whl
- Upload date:
- Size: 711.9 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b668aa79a93b5652bde21460f00640587c9759897f3362746b4418d5f80a2656
|
|
| MD5 |
a80c8dba13912eb39b27307a090fd132
|
|
| BLAKE2b-256 |
e8eb2b94682c0942fa3667b2f24fb692a71511978a371a4c6048e174c4836e99
|
Provenance
The following attestation bundles were made for pyyudit-0.1.1-0-py3-none-manylinux_2_17_x86_64.whl:
Publisher:
build.yml on Kushim-Jiang/pyyudit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyyudit-0.1.1-0-py3-none-manylinux_2_17_x86_64.whl -
Subject digest:
b668aa79a93b5652bde21460f00640587c9759897f3362746b4418d5f80a2656 - Sigstore transparency entry: 2804995306
- Sigstore integration time:
-
Permalink:
Kushim-Jiang/pyyudit@05e2c8f7138ad2f9de22aeaf024c41f17329930d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Kushim-Jiang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@05e2c8f7138ad2f9de22aeaf024c41f17329930d -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyyudit-0.1.1-0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: pyyudit-0.1.1-0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 566.2 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e99ee898c14758f21149908bf6ce506623267ef9533b819bbc4d73a2e0872d1
|
|
| MD5 |
622bb7284eeda75778524d9e85659dd4
|
|
| BLAKE2b-256 |
7a0800da7550a74967d712393f294e22cbe093e4e4358ebc5324fd440940e84d
|
Provenance
The following attestation bundles were made for pyyudit-0.1.1-0-py3-none-macosx_11_0_arm64.whl:
Publisher:
build.yml on Kushim-Jiang/pyyudit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyyudit-0.1.1-0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
1e99ee898c14758f21149908bf6ce506623267ef9533b819bbc4d73a2e0872d1 - Sigstore transparency entry: 2804995156
- Sigstore integration time:
-
Permalink:
Kushim-Jiang/pyyudit@05e2c8f7138ad2f9de22aeaf024c41f17329930d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Kushim-Jiang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@05e2c8f7138ad2f9de22aeaf024c41f17329930d -
Trigger Event:
push
-
Statement type: