Skip to main content

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

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyyudit-0.1.1-0-py3-none-win_amd64.whl (420.4 kB view details)

Uploaded Python 3Windows x86-64

pyyudit-0.1.1-0-py3-none-manylinux_2_17_x86_64.whl (711.9 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

pyyudit-0.1.1-0-py3-none-macosx_11_0_arm64.whl (566.2 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

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

Hashes for pyyudit-0.1.1-0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 1bf80775238418c0e312ff394f72a03835ef90567b1f3faffc4ceb0c94f7853b
MD5 f7354851abed761312144565b247479d
BLAKE2b-256 c4f8d288a46e179a070f4a7332dc67938576a739b74d950815b9810afb1ae079

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyyudit-0.1.1-0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for pyyudit-0.1.1-0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 b668aa79a93b5652bde21460f00640587c9759897f3362746b4418d5f80a2656
MD5 a80c8dba13912eb39b27307a090fd132
BLAKE2b-256 e8eb2b94682c0942fa3667b2f24fb692a71511978a371a4c6048e174c4836e99

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyyudit-0.1.1-0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyyudit-0.1.1-0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1e99ee898c14758f21149908bf6ce506623267ef9533b819bbc4d73a2e0872d1
MD5 622bb7284eeda75778524d9e85659dd4
BLAKE2b-256 7a0800da7550a74967d712393f294e22cbe093e4e4358ebc5324fd440940e84d

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.0

3 files

0.2.0

3 files

This release

0.1.1 This release

3 files

0.1.0

4 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page