Skip to content

Port xetex_layout to Rust #1138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 107 commits into from
Aug 7, 2025
Merged
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
878b443
Start porting xetex-layout
CraftSpider Oct 2, 2023
7691184
Fix build on linux
CraftSpider Oct 3, 2023
590f23f
Port a lot to Rust
CraftSpider Oct 5, 2023
b04bfd0
Port 99% of XeTeXFont and XeTeXLayoutEngine to Rust
CraftSpider Feb 5, 2024
d9e87ff
Start porting FontMgr - tex_outputs should pass!
CraftSpider Feb 5, 2024
d2b17d1
Impl {append,prepend}_to_list
CraftSpider Feb 5, 2024
4555e6a
Continue port. FontManagerBackend functionality mostly implemented fo…
CraftSpider Feb 7, 2024
b9a3d50
Minor cleanup, work on type errors.
CraftSpider Feb 7, 2024
b0240d6
Encapsulate Fc unsafe a bit - use a `Pattern` type for most situations.
CraftSpider Feb 7, 2024
c4af8d6
More cleanups, put unicode in the right place
CraftSpider Feb 7, 2024
cbfa6ae
Stop compiling the C++ code. Remove unnecessary functions.
CraftSpider Feb 7, 2024
527b471
Set up symbol versioning
CraftSpider Feb 9, 2024
5406477
Try fixing symbol name setup
CraftSpider Feb 9, 2024
a3ffbf8
Start work on making mac run
CraftSpider Feb 10, 2024
e673f64
Hopefully make new_path_index work on mac
CraftSpider Feb 10, 2024
2b5f6ee
Continue work on porting Mac to CoreText.
CraftSpider Feb 20, 2024
170f845
Mac stuff!
CraftSpider Mar 20, 2024
0fd8de1
Make findFontByName work on Mac
CraftSpider Mar 21, 2024
ac4f6bb
Setup linkage for mac externs
CraftSpider Mar 21, 2024
99f6adc
Remove probably bad CFRelease
CraftSpider Mar 21, 2024
c4c8c20
Clearer array pointer creation
CraftSpider Mar 21, 2024
ac02683
Fix build
CraftSpider Mar 21, 2024
15fb535
Fix another keys location
CraftSpider Mar 21, 2024
0daca1d
More debugging
CraftSpider Mar 21, 2024
792846e
Add null checks
CraftSpider Mar 21, 2024
0649529
Try fix for heap corruption
CraftSpider Mar 22, 2024
f12746d
Fixup freetype - move unsafe into the freetype bindings, with safe in…
CraftSpider Mar 22, 2024
7719c63
Fix panic on bad engine creation
CraftSpider Mar 22, 2024
dcc9fdf
Fix build
CraftSpider Mar 22, 2024
f7153aa
Fix otf_basic and remove font_ref from engine
CraftSpider Mar 23, 2024
b3d713c
Fixup mac use of fc
CraftSpider Mar 23, 2024
ffcbcca
Remove unused import
CraftSpider Mar 23, 2024
fe7eb67
Fix clippy
CraftSpider Mar 23, 2024
90da329
Hopefully fix mac
CraftSpider Mar 23, 2024
2fcaacd
Partway through changes
CraftSpider Mar 23, 2024
326abf2
Use less unsafe in string manip
CraftSpider Mar 24, 2024
3430365
Start encapsulating harfbuzz
CraftSpider Mar 24, 2024
c1c2357
Port FontFuncs
CraftSpider Mar 24, 2024
c8e1fe1
HB builds on Windows - now just to fix the bugs
CraftSpider Mar 25, 2024
ae34a52
Cleanup C files, simplify Rust code that no longer needs C-isms
CraftSpider Mar 25, 2024
f8368a2
Add some asserts
CraftSpider Mar 25, 2024
a04f169
Fix mac build errors
CraftSpider Mar 26, 2024
40b8c7b
Remove support for MACOS <= 10.6
CraftSpider Mar 26, 2024
2453207
Remove outdated comment
CraftSpider Mar 27, 2024
81428c1
Fix getIndFeature/countFeatures
CraftSpider Mar 27, 2024
eb4e740
Remove outdated comment
CraftSpider Mar 27, 2024
48bbe26
Fix AFM handling and char bug, a little more safety
CraftSpider Mar 28, 2024
951a2de
Minor cleanups
CraftSpider Mar 30, 2024
8cacc17
fix2d/d2fix cleanup
CraftSpider Mar 30, 2024
5fb77a6
Change shaper in engine.rs to CString
CraftSpider Mar 31, 2024
6183061
Step 1 of graphite2 API cleanup
CraftSpider Apr 1, 2024
ebd3dab
Start on gr_seg
CraftSpider Apr 1, 2024
7ddf2c3
Finish porting graphite2 to safe interface
CraftSpider Apr 1, 2024
0f887ed
Engine takes ownership, not reference
CraftSpider Apr 5, 2024
bf5a1ac
Start on graphite test
CraftSpider Apr 7, 2024
c8b969a
Work on graphite engine
CraftSpider Apr 8, 2024
c69507f
Graphite test working - still need to add feature enablement example
CraftSpider Apr 8, 2024
aaefad8
Add Graphite feature test and fix feature selection by 4-letter code.
CraftSpider Apr 9, 2024
8d38222
Clippy cleanup
CraftSpider Apr 9, 2024
1477e99
Start work on making Mac safe also - basically copying Servo's way of…
CraftSpider Apr 11, 2024
99b6050
Fix raw->rs font ref handling
CraftSpider Apr 12, 2024
40403a3
Fix CFArray handling
CraftSpider Apr 12, 2024
444f636
Fix mac build issues
CraftSpider Apr 12, 2024
de68c82
Fix clippy on non-mac
CraftSpider Apr 12, 2024
2083a42
Remove an allocation - print some useful info on destroy
CraftSpider Apr 15, 2024
adc3779
Don't cross allocators/deallocators
CraftSpider Apr 16, 2024
c8eb957
Fix up font maps - even less unsafe
CraftSpider Apr 18, 2024
0612243
Encapsulate Fc API
CraftSpider Apr 18, 2024
38905b3
Encapsulate ICU API
CraftSpider Apr 18, 2024
b5a1ae4
Fix mac build
CraftSpider Apr 18, 2024
91e7b41
Fix clippy
CraftSpider Apr 18, 2024
f4a67ec
Move more thread_local values into the font manager
CraftSpider Apr 18, 2024
f4b2c2e
Remove FcBackend thread locals
CraftSpider Apr 18, 2024
e516fcc
Move graphite breaking thread_locals into the engine
CraftSpider Apr 18, 2024
c41aa52
Update tectonic_xetex_layout
CraftSpider Apr 18, 2024
b4c3ea3
Fix mac build
CraftSpider Apr 18, 2024
0b3a7be
Add safety documentation to bridge_graphite2, and improve soundness.
CraftSpider Apr 18, 2024
10c095f
Improve Harfbuzz soundness - start on safety documentation.
CraftSpider Apr 23, 2024
19e1c86
Fix Harfbuzz, add safety documentation.
CraftSpider Apr 24, 2024
2d7691b
Shorten some method names, make Harfbuzz OpenType API nicer, and avoi…
CraftSpider Apr 25, 2024
64a8e8c
Clippy fixes. A little more usize.
CraftSpider Apr 25, 2024
1165aa5
Rename XeTeXFontBase/XeTeXLayoutEngineBase as they don't need to be t…
CraftSpider Apr 25, 2024
2950560
Move fontconfig to its own crate
CraftSpider Apr 27, 2024
6937f75
Separate out no_mangle functions, remove pure Rust stuff from c_api m…
CraftSpider Apr 27, 2024
739e956
Minor cleanup
CraftSpider Apr 27, 2024
49cd10a
Fix mac build hopefully
CraftSpider Apr 27, 2024
d29676c
Fix fontconfig build script/dep handling
CraftSpider Apr 28, 2024
1f008d9
Fixup build scripts
CraftSpider Apr 28, 2024
04f3ac3
Try to fix include paths
CraftSpider Apr 29, 2024
bfd81a7
Add ICU dep and export its headers in engine_xetex
CraftSpider Apr 29, 2024
6e22aec
Fix mac compile more, clippy
CraftSpider Apr 29, 2024
8a8b16c
Fix compile error hopefully, remove never-used debug code
CraftSpider Aug 10, 2024
d08873a
Remove cstr. Update docs.
CraftSpider Feb 21, 2025
57656eb
Allow using current bridge state from Rust, use Rust APIs for inputs
CraftSpider Feb 21, 2025
a7cd4b1
Fix clippy
CraftSpider Feb 22, 2025
255bff6
Replace Rust usage of ICU and unreleased vcpkg with `enrede`
CraftSpider Jun 18, 2025
118059f
Fix for freetype changes in master
CraftSpider Jul 16, 2025
f041386
Fix cranko/cargo
CraftSpider Jul 24, 2025
46a3f65
Fix clippy (allow missing_docs is temporary)
CraftSpider Aug 2, 2025
5582878
Fix for changes in master
CraftSpider Aug 6, 2025
27a044b
Add freetype includes to xetex
CraftSpider Aug 6, 2025
1618f20
Add Cargo.lock
CraftSpider Aug 6, 2025
8a8290f
Fix up privacy, add documentation, and make a couple of improvements …
CraftSpider Aug 6, 2025
9de2e4a
Fix clippy
CraftSpider Aug 7, 2025
a18b72c
Use Result in more places
CraftSpider Aug 7, 2025
b803f2c
Fix doctests on cross
CraftSpider Aug 7, 2025
bc933fa
Fix doctests on cross pt 2
CraftSpider Aug 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/build-and-test/action.yml
Original file line number Diff line number Diff line change
@@ -52,11 +52,11 @@ runs:
- name: "cargo build for ${{ inputs.target }}"
shell: bash
run: |
${{ inputs.executable }} build --all --target ${{ inputs.target }} --release ${{ steps.set-feature-flags.outputs.cargo-features }} $CARGO_VERBOSE
${{ inputs.executable }} build --workspace --target ${{ inputs.target }} --release ${{ steps.set-feature-flags.outputs.cargo-features }} $CARGO_VERBOSE
- name: "cargo test"
shell: bash
run: |
${{ inputs.executable }} test --all --target ${{ inputs.target }} ${{ inputs.test-flags }} --release ${{ steps.set-feature-flags.outputs.cargo-features }} $CARGO_VERBOSE
${{ inputs.executable }} test --workspace --target ${{ inputs.target }} ${{ inputs.test-flags }} --release ${{ steps.set-feature-flags.outputs.cargo-features }} $CARGO_VERBOSE
- name: "Package test failure files"
id: package-tests
if: ${{ failure() }}
17 changes: 9 additions & 8 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: "Build and Test"

on: [workflow_call]
on: [ workflow_call ]

jobs:
clippy:
@@ -68,12 +68,12 @@ jobs:
run: |
artifact_dir="appimage"
mkdir -p "$artifact_dir"

if [[ $SOURCE_BRANCH == master ]] ; then
export TECTONIC_APPIMAGE_TAG=continuous
export UPDATE_INFORMATION="gh-releases-zsync|tectonic-typesetting|tectonic|continuous|tectonic-*.AppImage.zsync"
fi

./dist/appimage/build.sh
cp dist/appimage/tectonic-*.AppImage* "$artifact_dir"
env:
@@ -141,7 +141,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
toolchain: ["beta", "nightly"]
toolchain: [ "beta", "nightly" ]
fail-fast: false
steps:
- name: Checkout repository
@@ -166,7 +166,7 @@ jobs:
linux-feature-tests:
strategy:
matrix:
features: ["_all_", "_none_", "geturl-curl serialization"]
features: [ "_all_", "_none_", "geturl-curl serialization" ]
fail-fast: false
runs-on: ubuntu-latest
steps:
@@ -193,8 +193,8 @@ jobs:
pkg-config:
strategy:
matrix:
image: [ubuntu-latest, windows-latest, macos-latest]
install-all-deps: [true, false]
image: [ ubuntu-latest, windows-latest, macos-latest ]
install-all-deps: [ true, false ]
include:
# By default, all items have toolchain: stable, and don't publish
- toolchain: stable
@@ -327,12 +327,13 @@ jobs:
echo "CROSS_ROOTLESS_CONTAINER_ENGINE=1" >> "$GITHUB_ENV"
echo "DOCKER_OPTS=--privileged -e HOST_UID=${HOST_UID} -e HOST_GID=${HOST_GID}" >> "$GITHUB_ENV"
# TODO: Add font files to the cross images so we can include fontconfig_bridge in tests
# TODO: Figure out why doctests are broken so we can drop all-targets
- name: "Build and Test"
uses: ./.github/actions/build-and-test
with:
target: ${{ matrix.target }}
publish: 'true'
executable: 'cross'
test-flags: '--exclude tectonic_bridge_fontconfig'
test-flags: '--all-targets --exclude tectonic_bridge_fontconfig'
package-flags: '--command-name=cross --reroot=.'

52 changes: 52 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 18 additions & 2 deletions crates/bridge_core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -194,6 +194,8 @@ impl<T: IoProvider> DriverHooks for MinimalDriver<T> {
// Function defined in the C support code:
extern "C" {
fn _ttbc_get_error_message() -> *const libc::c_char;
#[allow(improper_ctypes)]
fn _ttbc_get_core_state() -> *mut CoreBridgeState<'static>;
}

lazy_static::lazy_static! {
@@ -377,6 +379,18 @@ impl<'a> CoreBridgeState<'a> {
}
}

/// Get the current global bridge state. Uses a mutex to ensure unique access, and panics
/// if no global state is set.
pub fn with_global_state<T, F: for<'b> FnOnce(&mut CoreBridgeState<'b>) -> T>(f: F) -> T {
/// Ensures we only enter the state once at a time, globally
static GLOBAL: Mutex<()> = Mutex::new(());
let _lock = GLOBAL.lock().unwrap();
// SAFETY: Pointer is either null or valid, set by the engine on entrance
let state = unsafe { _ttbc_get_core_state().as_mut() }
.expect("Currently within an engine context in C");
f(state)
}

fn input_open_name_format(
&mut self,
name: &str,
@@ -637,7 +651,8 @@ impl<'a> CoreBridgeState<'a> {
InputId::new(self.input_handles.len())
}

fn input_get_size(&mut self, handle: InputId) -> usize {
/// Get the size of an input. Prints a warning and returns 0 on error
pub fn input_get_size(&mut self, handle: InputId) -> usize {
let rhandle: &mut InputHandle = self.get_input(handle);

match rhandle.get_size() {
@@ -671,7 +686,8 @@ impl<'a> CoreBridgeState<'a> {
rhandle.try_seek(pos)
}

fn input_read(&mut self, handle: InputId, buf: &mut [u8]) -> Result<()> {
/// Read from an input
pub fn input_read(&mut self, handle: InputId, buf: &mut [u8]) -> Result<()> {
let rhandle: &mut InputHandle = self.get_input(handle);
rhandle.read_exact(buf).map_err(Error::from)
}
7 changes: 7 additions & 0 deletions crates/bridge_core/support/support.c
Original file line number Diff line number Diff line change
@@ -113,6 +113,13 @@ _ttbc_get_error_message(void)
}


ttbc_state_t *
_ttbc_get_core_state(void)
{
return tectonic_global_bridge_core;
}


jmp_buf *
ttbc_global_engine_enter(ttbc_state_t *api)
{
4 changes: 4 additions & 0 deletions crates/engine_xetex/Cargo.toml
Original file line number Diff line number Diff line change
@@ -23,9 +23,11 @@ links = "tectonic_engine_xetex"
[dependencies]
libc = "^0.2"
tectonic_bridge_core = { path = "../bridge_core", version = "0.0.0-dev.0" }
tectonic_bridge_freetype2 = { path = "../bridge_freetype2", version = "0.0.0-dev.0" }
tectonic_bridge_flate = { path = "../bridge_flate", version = "0.0.0-dev.0" }
tectonic_bridge_graphite2 = { path = "../bridge_graphite2", version = "0.0.0-dev.0" }
tectonic_bridge_harfbuzz = { path = "../bridge_harfbuzz", version = "0.0.0-dev.0" }
tectonic_bridge_icu = { path = "../bridge_icu", version = "0.0.0-dev.0" }
tectonic_errors = { path = "../errors", version = "0.0.0-dev.0" }
tectonic_pdf_io = { path = "../pdf_io", version = "0.0.0-dev.0" }
tectonic_xetex_layout = { path = "../xetex_layout", version = "0.0.0-dev.0" }
@@ -42,9 +44,11 @@ external-harfbuzz = [

[package.metadata.internal_dep_versions]
tectonic_bridge_core = "4e16bf963700aae59772a6fb223981ceaa9b5f57"
tectonic_bridge_freetype2 = "fe112797308ca8aa0478cd31851ab75bc5afd43c"
tectonic_bridge_flate = "5933308152efb6ba206b4dc01ab6814063b835c0"
tectonic_bridge_graphite2 = "2c1ffcd702a662c003bd3d7d0ca4d169784cb6ad"
tectonic_bridge_harfbuzz = "2c1ffcd702a662c003bd3d7d0ca4d169784cb6ad"
tectonic_bridge_icu = "thiscommit:2023-09-17:6uIZ4lA"
tectonic_cfg_support = "9d5feb40c7ac6958ee3c50604af9271eb2db2b20"
tectonic_errors = "317ae79ceaa2593fb56090e37bf1f5cc24213dd9"
tectonic_pdf_io = "9a8b975e76c7a27f140d0974ec3442f2347e18ad"
20 changes: 20 additions & 0 deletions crates/engine_xetex/build.rs
Original file line number Diff line number Diff line change
@@ -18,7 +18,10 @@ fn main() {
let flate_include_dir = env::var("DEP_TECTONIC_BRIDGE_FLATE_INCLUDE").unwrap();
let graphite2_include_path = env::var("DEP_GRAPHITE2_INCLUDE_PATH").unwrap();
let graphite2_static = !env::var("DEP_GRAPHITE2_DEFINE_STATIC").unwrap().is_empty();
let freetype_include_path = env::var("DEP_FREETYPE2_INCLUDE_PATH").unwrap();
let harfbuzz_include_path = env::var("DEP_HARFBUZZ_INCLUDE_PATH").unwrap();
let fontconfig_include_path = env::var("DEP_FONTCONFIG_INCLUDE_PATH");
let icu_include_path = env::var("DEP_ICUUC_INCLUDE_PATH").unwrap();

// If we want to profile, the default assumption is that we must force the
// compiler to include frame pointers. We whitelist platforms that are
@@ -76,11 +79,28 @@ fn main() {
cxx_cfg.include(item);
}

for item in freetype_include_path.split(';') {
c_cfg.include(item);
cxx_cfg.include(item);
}

for item in graphite2_include_path.split(';') {
c_cfg.include(item);
cxx_cfg.include(item);
}

for item in icu_include_path.split(';') {
c_cfg.include(item);
cxx_cfg.include(item);
}

if let Ok(fc_includes) = fontconfig_include_path {
for item in fc_includes.split(';') {
c_cfg.include(item);
cxx_cfg.include(item);
}
}

if graphite2_static {
c_cfg.define("GRAPHITE2_STATIC", "1");
cxx_cfg.define("GRAPHITE2_STATIC", "1");
3 changes: 3 additions & 0 deletions crates/engine_xetex/src/lib.rs
Original file line number Diff line number Diff line change
@@ -256,6 +256,9 @@ mod linkage {

#[allow(unused_imports)]
use tectonic_xetex_layout as clipyrenamehack2;

#[allow(unused_imports)]
use tectonic_bridge_icu as clipyrenamehack3;
}

/// Does our resulting executable link correctly?
Loading
Loading