### Build and install Ragel and Colm Source: https://github.com/harfbuzz/rustybuzz/blob/main/docs/ragel.md Build the Colm dependency followed by the Ragel development branch from source. ```sh # build `colm` first git clone https://github.com/adrian-thurston/colm cd colm ./autogen.sh ./configure --prefix=/path/to/colm/install # prefer a custom path to /usr/local make make install cd .. git clone https://github.com/adrian-thurston/ragel ./autogen.sh # --with-colm takes the same path we used above ./configure --prefix=/path/to/ragel/install --with-colm=/path/to/colm/install make make install ``` -------------------------------- ### Install Ragel dependencies on macOS Source: https://github.com/harfbuzz/rustybuzz/blob/main/docs/ragel.md Install required build tools using Homebrew. ```sh brew install automake autoconf libtool ``` -------------------------------- ### Complete Rustybuzz Shaping Workflow Source: https://context7.com/harfbuzz/rustybuzz/llms.txt A comprehensive example showing font loading, feature parsing, buffer preparation, text shaping, and outputting glyph positions for rendering. Handles script detection and direction. ```rust use rustybuzz::{ Face, UnicodeBuffer, GlyphBuffer, Feature, Direction, BufferFlags, SerializeFlags, shape }; use std::str::FromStr; fn shape_text( font_path: &str, text: &str, features: &[&str], ) -> Result> { // Load font let font_data = std::fs::read(font_path)?; let face = Face::from_slice(&font_data, 0) .ok_or("Failed to parse font")?; // Parse features let features: Vec = features .iter() .filter_map(|f| Feature::from_str(f).ok()) .collect(); // Prepare buffer let mut buffer = UnicodeBuffer::new(); buffer.push_str(text); buffer.set_flags( BufferFlags::BEGINNING_OF_TEXT | BufferFlags::END_OF_TEXT ); // Auto-detect script and direction buffer.guess_segment_properties(); // Shape let glyph_buffer = shape(&face, &features, buffer); // Collect results for rendering let mut output = String::new(); let mut x_cursor = 0i32; let mut y_cursor = 0i32; for (info, pos) in glyph_buffer.glyph_infos() .iter() .zip(glyph_buffer.glyph_positions()) { let glyph_x = x_cursor + pos.x_offset; let glyph_y = y_cursor + pos.y_offset; output.push_str(&format!( "Draw glyph {} at ({}, {})\n", info.glyph_id, glyph_x, glyph_y )); x_cursor += pos.x_advance; y_cursor += pos.y_advance; } Ok(output) } // Usage fn main() { let result = shape_text( "fonts/NotoSans-Regular.ttf", "Hello, Typography!", &["kern", "liga", "calt"] ).unwrap(); println!("{}", result); } ``` -------------------------------- ### Prepare Text with UnicodeBuffer Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Initialize and configure a UnicodeBuffer with text, direction, script, language, and flags. Handles context for partial shaping. ```rust use rustybuzz::{UnicodeBuffer, Direction, BufferFlags}; use std::str::FromStr; // Create a new buffer and add text let mut buffer = UnicodeBuffer::new(); buffer.push_str("Hello, World!"); // Configure text properties buffer.set_direction(Direction::LeftToRight); buffer.set_script(rustybuzz::script::LATIN); buffer.set_language(rustybuzz::Language::from_str("en").unwrap()); // For Arabic text (right-to-left) let mut arabic_buffer = UnicodeBuffer::new(); arabic_buffer.push_str("مرحبا"); arabic_buffer.set_direction(Direction::RightToLeft); arabic_buffer.set_script(rustybuzz::script::ARABIC); // Set buffer flags for special handling buffer.set_flags( BufferFlags::BEGINNING_OF_TEXT | BufferFlags::END_OF_TEXT ); // Add characters with explicit cluster indices let mut custom_buffer = UnicodeBuffer::new(); custom_buffer.add('H', 0); custom_buffer.add('i', 1); // Set context for partial text shaping buffer.set_pre_context("Previous "); buffer.set_post_context(" following text"); ``` -------------------------------- ### Run Rustybuzz Benchmarks Source: https://github.com/harfbuzz/rustybuzz/blob/main/benches/README.md Executes the benchmark suite using the nightly Cargo toolchain with pkg-config disabled. ```bash HARFBUZZ_SYS_NO_PKG_CONFIG="" cargo +nightly bench ``` -------------------------------- ### Convert Ragel scripts to Rust Source: https://github.com/harfbuzz/rustybuzz/blob/main/docs/ragel.md Execute the ragel-rust binary to generate Rust source files from .rl scripts. ```sh /path/to/ragel/install/bin/ragel-rust -e -F1 src/hb/ot_shape_complex_indic_machine.rl # or any other .rl file ``` -------------------------------- ### Generate Rust Table Source: https://github.com/harfbuzz/rustybuzz/blob/main/scripts/README.md Use this command to generate the `ot_shaper_use_table.rs` file from the `gen-universal-table.py` script. ```sh python3 gen-universal-table.py > ../src/hb/ot_shaper_use_table.rs ``` -------------------------------- ### Generate and Format Rust Vowel Constraints Source: https://github.com/harfbuzz/rustybuzz/blob/main/scripts/README.md This command generates the `vowel_constraints.rs` file using `gen-vowel-constraints.py` and then formats it using `rustfmt`. ```sh python3 ./gen-vowel-constraints.py > ../src/complex/vowel_constraints.rs rustfmt ../src/complex/vowel_constraints.rs ``` -------------------------------- ### Add autogenerated file header Source: https://github.com/harfbuzz/rustybuzz/blob/main/docs/ragel.md Manual header to include in generated files since Ragel does not preserve comments. ```c // This file is autogenerated. Do not edit it! // // See docs/ragel.md for details. ``` -------------------------------- ### Count Lines of Code with tokei Source: https://github.com/harfbuzz/rustybuzz/blob/main/README.md Use the `tokei` command-line tool to count the lines of code in the rustybuzz project, excluding specific generated or machine-related files. This provides an estimate of the 'real' code size. ```shell tokei --exclude hb/unicode_norm.rs --exclude hb/ot_shaper_vowel_constraints.rs \ --exclude '*_machine.rs' --exclude '*_table.rs' src ``` -------------------------------- ### Configure OpenType Features in Rustybuzz Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Demonstrates parsing features from strings and creating them programmatically with specific character ranges. ```rust use rustybuzz::Feature; use ttf_parser::Tag; use std::str::FromStr; // Parse features from strings let kern = Feature::from_str("kern").unwrap(); // kern=1 (enabled) let no_liga = Feature::from_str("-liga").unwrap(); // liga=0 (disabled) let smcp = Feature::from_str("smcp=1").unwrap(); // Small caps on let ss02 = Feature::from_str("ss02=1").unwrap(); // Stylistic set 2 // Create features programmatically with ranges let feature = Feature::new( Tag::from_bytes(b"kern"), // Feature tag 1, // Value (1 = on, 0 = off) .., // Range: entire text ); // Apply feature to specific character range let partial_feature = Feature::new( Tag::from_bytes(b"smcp"), 1, 3..=7, // Only characters 3-7 ); // Features with index ranges (string parsing) let ranged = Feature::from_str("kern[5:]").unwrap(); // From index 5 let ranged2 = Feature::from_str("kern[:10]").unwrap(); // Up to index 10 let ranged3 = Feature::from_str("kern[3:8]").unwrap(); // Range 3-8 // Common OpenType features: // kern - Kerning // liga - Standard Ligatures (fi, fl, etc.) // clig - Contextual Ligatures // dlig - Discretionary Ligatures // smcp - Small Capitals // c2sc - Capitals to Small Capitals // onum - Oldstyle Figures // lnum - Lining Figures // tnum - Tabular Figures // pnum - Proportional Figures // ss01-ss20 - Stylistic Sets // calt - Contextual Alternates // swsh - Swash // frac - Fractions ``` -------------------------------- ### Build harfbuzz for test generation Source: https://github.com/harfbuzz/rustybuzz/blob/main/docs/backporting.md Use meson to build the specific version of harfbuzz corresponding to the commit being ported. ```sh git clone https://github.com/harfbuzz/harfbuzz cd harfbuzz git checkout HASH # put the required hash here meson builddir --reconfigure # `--reconfigure` is needed only on the first run ninja -Cbuilddir ``` -------------------------------- ### Optimize Repeated Shaping with ShapePlan Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Uses ShapePlan to reuse shaping configurations across multiple strings, improving performance. ```rust use rustybuzz::{Face, UnicodeBuffer, ShapePlan, Feature, Direction, shape_with_plan}; use std::str::FromStr; let font_data = std::fs::read("font.ttf").unwrap(); let face = Face::from_slice(&font_data, 0).unwrap(); // Create a reusable shape plan let features = [ Feature::from_str("kern").unwrap(), Feature::from_str("liga").unwrap(), ]; let plan = ShapePlan::new( &face, Direction::LeftToRight, Some(rustybuzz::script::LATIN), Some(&rustybuzz::Language::from_str("en").unwrap()), &features, ); // Shape multiple strings efficiently using the same plan let texts = ["Hello", "World", "OpenType", "Shaping"]; for text in texts { let mut buffer = UnicodeBuffer::new(); buffer.push_str(text); buffer.set_direction(Direction::LeftToRight); buffer.set_script(rustybuzz::script::LATIN); let glyph_buffer = shape_with_plan(&face, &plan, buffer); println!("Text: {} -> {} glyphs", text, glyph_buffer.len()); } ``` -------------------------------- ### Configure Script and Language in Rustybuzz Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Specify the script and language for script-specific shaping rules. Scripts can be set using predefined constants or parsed from ISO 15924 tags. Languages are set using BCP 47 tags and affect features like 'locl'. ```rust use rustybuzz::{UnicodeBuffer, Language, Script, script}; use std::str::FromStr; let mut buffer = UnicodeBuffer::new(); buffer.push_str("Hello"); // Set script using predefined constants buffer.set_script(script::LATIN); // Other common scripts // script::ARABIC - Arabic // script::HEBREW - Hebrew // script::DEVANAGARI - Hindi, Sanskrit // script::THAI - Thai // script::HAN - Chinese // script::HIRAGANA - Japanese Hiragana // script::HANGUL - Korean // Parse script from ISO 15924 tag let arabic_script = Script::from_iso15924_tag( ttf_parser::Tag::from_bytes(b"Arab") ).unwrap(); // Set language using BCP 47 tags buffer.set_language(Language::from_str("en").unwrap()); // Language affects OpenType 'locl' feature behavior let mut turkish_buffer = UnicodeBuffer::new(); turkish_buffer.push_str("i"); turkish_buffer.set_language(Language::from_str("tr").unwrap()); // Turkish turkish_buffer.set_script(script::LATIN); // Serbian Cyrillic vs Russian let mut serbian = UnicodeBuffer::new(); serbian.push_str("б"); serbian.set_language(Language::from_str("sr").unwrap()); serbian.set_script(script::CYRILLIC); ``` -------------------------------- ### Load and Configure Font Face Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Load a font face from file data and configure its properties like variations and pixel density. Supports variable fonts and Apple Advanced Typography. ```rust use rustybuzz::Face; // Load a font face from font file data let font_data = std::fs::read("path/to/font.ttf").unwrap(); let face = Face::from_slice(&font_data, 0).unwrap(); // Get font metrics let units_per_em = face.units_per_em(); // Configure for variable fonts - set variation axes let variations = [ rustybuzz::Variation::from_str("wght=700").unwrap(), // Bold weight rustybuzz::Variation::from_str("wdth=75").unwrap(), // Condensed width ]; face.set_variations(&variations); // Set optical sizing for Apple fonts (points per em) face.set_points_per_em(Some(12.0)); // Set pixels per em for raster glyph processing face.set_pixels_per_em(Some((16, 16))); ``` -------------------------------- ### Generate rustybuzz shaping tests Source: https://github.com/harfbuzz/rustybuzz/blob/main/docs/backporting.md Execute the test generation script using the path to the local harfbuzz repository. ```sh # Pass harfbuzz clone dir, not `harfbuzz/src` one. cd rustybuzz/scripts ./gen-shaping-tests.py /path/to/harfbuzz ``` -------------------------------- ### GlyphInfo Flags for Text Layout Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Use GlyphInfo flags like unsafe_to_break and unsafe_to_concat for advanced text layout operations. Ensure the BufferFlags::PRODUCE_UNSAFE_TO_CONCAT flag is set before shaping. ```rust use rustybuzz::{Face, UnicodeBuffer, BufferFlags, shape}; let font_data = std::fs::read("font.ttf").unwrap(); let face = Face::from_slice(&font_data, 0).unwrap(); // Enable glyph flag production let mut buffer = UnicodeBuffer::new(); buffer.push_str("Hello world"); buffer.set_flags(BufferFlags::PRODUCE_UNSAFE_TO_CONCAT); let glyph_buffer = shape(&face, &[], buffer); for info in glyph_buffer.glyph_infos() { // Basic glyph data let glyph_id = info.glyph_id; // Font glyph index (u32, but <= u16::MAX) let cluster = info.cluster; // Original character index // Line breaking optimization flags if info.unsafe_to_break() { // If breaking here, both sides need re-shaping println!("Cluster {} is unsafe to break", cluster); } if info.unsafe_to_concat() { // Text changes on one side may affect the other println!("Cluster {} is unsafe to concatenate", cluster); } // For Arabic/Mongolian elongation (tatweel insertion) if info.safe_to_insert_tatweel() { println!("Safe to insert tatweel before cluster {}", cluster); } } ``` -------------------------------- ### Access and Serialize GlyphBuffer Results Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Retrieves glyph information and positioning data from a GlyphBuffer, and demonstrates serialization for debugging. ```rust use rustybuzz::{Face, UnicodeBuffer, SerializeFlags, shape}; let font_data = std::fs::read("font.ttf").unwrap(); let face = Face::from_slice(&font_data, 0).unwrap(); let mut buffer = UnicodeBuffer::new(); buffer.push_str("ffi"); // Text with potential ligatures let glyph_buffer = shape(&face, &[], buffer); // Get glyph information let infos = glyph_buffer.glyph_infos(); let positions = glyph_buffer.glyph_positions(); for (i, (info, pos)) in infos.iter().zip(positions).enumerate() { // glyph_id: The font's glyph index // cluster: Maps back to original character index println!("Glyph {}: id={}, cluster={}", i, info.glyph_id, info.cluster); // Position data for rendering println!(" x_advance={}, y_advance={}", pos.x_advance, pos.y_advance); println!(" x_offset={}, y_offset={}", pos.x_offset, pos.y_offset); // Check glyph flags for line breaking optimization if info.unsafe_to_break() { println!(" WARNING: Unsafe to break at this cluster"); } } // Serialize for debugging (HarfBuzz-compatible format) let output = glyph_buffer.serialize(&face, SerializeFlags::default()); println!("Serialized: {}", output); // Output: "f_f_i=0+1500|..." (glyph_name=cluster+advance) // Serialize with different options let detailed = glyph_buffer.serialize( &face, SerializeFlags::GLYPH_EXTENTS | SerializeFlags::GLYPH_FLAGS ); // Reuse the buffer for another shaping operation let unicode_buffer = glyph_buffer.clear(); ``` -------------------------------- ### Advanced Shaping Control with BufferFlags Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Fine-tune shaping behavior using BufferFlags. Options include controlling default ignorable characters, dotted circle insertion, verification, and flags for line breaking optimization. ```rust use rustybuzz::{UnicodeBuffer, BufferFlags}; let mut buffer = UnicodeBuffer::new(); buffer.push_str("Sample text"); // Set flags for complete paragraph buffer.set_flags( BufferFlags::BEGINNING_OF_TEXT | BufferFlags::END_OF_TEXT ); // Control default ignorable character handling buffer.set_flags( BufferFlags::PRESERVE_DEFAULT_IGNORABLES // Show ZWJ, ZWNJ, etc. ); // Or remove them entirely buffer.set_flags( BufferFlags::REMOVE_DEFAULT_IGNORABLES ); // Don't insert dotted circle for invalid sequences buffer.set_flags( BufferFlags::DO_NOT_INSERT_DOTTED_CIRCLE ); // Enable verification of shaping results buffer.set_flags(BufferFlags::VERIFY); // Produce flags for line breaking optimization buffer.set_flags( BufferFlags::PRODUCE_UNSAFE_TO_CONCAT | BufferFlags::PRODUCE_SAFE_TO_INSERT_TATWEEL // For Arabic elongation ); ``` -------------------------------- ### BufferClusterLevel for Cluster Mapping Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Control how input characters map to output glyph clusters using BufferClusterLevel. Options include MonotoneGraphemes (default), MonotoneCharacters, and Characters. Reset clusters after configuration. ```rust use rustybuzz::{UnicodeBuffer, BufferClusterLevel}; let mut buffer = UnicodeBuffer::new(); buffer.push_str("ffi"); // May form ligature // Default: Grapheme clusters (recommended for most uses) buffer.set_cluster_level(BufferClusterLevel::MonotoneGraphemes); // Ligature "ffi" -> cluster 0 for all components // Monotone characters: each character gets unique cluster buffer.set_cluster_level(BufferClusterLevel::MonotoneCharacters); // Ligature "ffi" -> cluster 0 (from first char) // Characters: most detailed, non-monotone buffer.set_cluster_level(BufferClusterLevel::Characters); // May reorder clusters based on shaping // Reset clusters to character indices after configuration buffer.reset_clusters(); ``` -------------------------------- ### Perform Basic Text Shaping Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Shape text using the `shape` function with a font face and Unicode buffer. Access glyph information and positioning after shaping. ```rust use rustybuzz::{Face, UnicodeBuffer, Feature, shape}; use std::str::FromStr; let font_data = std::fs::read("font.ttf").unwrap(); let face = Face::from_slice(&font_data, 0).unwrap(); // Basic shaping without features let mut buffer = UnicodeBuffer::new(); buffer.push_str("Hello"); let glyph_buffer = shape(&face, &[], buffer); // Access shaping results for (info, pos) in glyph_buffer.glyph_infos().iter() .zip(glyph_buffer.glyph_positions()) { println!( "Glyph: {}, Cluster: {}, Advance: ({}, {}), Offset: ({}, {})", info.glyph_id, info.cluster, pos.x_advance, pos.y_advance, pos.x_offset, pos.y_offset ); } ``` -------------------------------- ### Configure Variable Font Axes in Rustybuzz Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Control variable font styling by setting axes like weight, width, and slant using the Variation struct. Variations can be parsed from strings or created programmatically. ```rust use rustybuzz::{Face, Variation}; use std::str::FromStr; let font_data = std::fs::read("variable-font.ttf").unwrap(); let mut face = Face::from_slice(&font_data, 0).unwrap(); // Parse variations from strings let weight = Variation::from_str("wght=700").unwrap(); // Bold let width = Variation::from_str("wdth=75").unwrap(); // Condensed let slant = Variation::from_str("slnt=-12").unwrap(); // Italic // Apply multiple variations face.set_variations(&[weight, width, slant]); // Common variation axes: // wght - Weight (100-900, thin to black) // wdth - Width (50-200, condensed to expanded) // slnt - Slant (-90 to 90, italic angle) // ital - Italic (0 or 1) // opsz - Optical Size (6-144pt) // Create variation programmatically let variation = Variation { tag: ttf_parser::Tag::from_bytes(b"wght"), value: 600.0, // Semi-bold }; face.set_variations(&[variation]); ``` -------------------------------- ### Configure Text Direction in Rustybuzz Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Set the text flow direction using the Direction enum. Supports horizontal (LTR, RTL) and vertical (TTB, BTT) modes. Direction can also be parsed from strings or guessed from script properties. ```rust use rustybuzz::{UnicodeBuffer, Direction}; use std::str::FromStr; // Horizontal directions let mut ltr_buffer = UnicodeBuffer::new(); ltr_buffer.push_str("English text"); ltr_buffer.set_direction(Direction::LeftToRight); let mut rtl_buffer = UnicodeBuffer::new(); rtl_buffer.push_str("עברית"); // Hebrew rtl_buffer.set_direction(Direction::RightToLeft); // Vertical directions (for CJK, Mongolian, etc.) let mut ttb_buffer = UnicodeBuffer::new(); ttb_buffer.push_str("縦書き"); // Japanese vertical ttb_buffer.set_direction(Direction::TopToBottom); let mut btt_buffer = UnicodeBuffer::new(); btt_buffer.set_direction(Direction::BottomToTop); // Parse direction from string let dir = Direction::from_str("rtl").unwrap(); let dir2 = Direction::from_str("ltr").unwrap(); // Let rustybuzz guess from script (automatically handled in shape()) let mut buffer = UnicodeBuffer::new(); buffer.push_str("مرحبا"); buffer.guess_segment_properties(); // Sets RTL for Arabic ``` -------------------------------- ### Shape Text with OpenType Features Source: https://context7.com/harfbuzz/rustybuzz/llms.txt Shape text with specific OpenType features enabled or disabled. Features like kerning, ligatures, and stylistic sets can be applied. ```rust use rustybuzz::{Face, UnicodeBuffer, Feature, shape}; use std::str::FromStr; let font_data = std::fs::read("font.ttf").unwrap(); let face = Face::from_slice(&font_data, 0).unwrap(); // Shaping with OpenType features let features = [ Feature::from_str("kern").unwrap(), // Enable kerning Feature::from_str("liga").unwrap(), // Enable ligatures Feature::from_str("-calt").unwrap(), // Disable contextual alternates Feature::from_str("smcp").unwrap(), // Small caps Feature::from_str("ss01=1").unwrap(), // Stylistic set 1 ]; let mut buffer = UnicodeBuffer::new(); buffer.push_str("office"); let glyph_buffer = shape(&face, &features, buffer); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.