Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

277
vendor/rustybuzz/examples/shape.rs vendored Normal file
View File

@@ -0,0 +1,277 @@
use std::path::PathBuf;
use std::str::FromStr;
const HELP: &str = "\
USAGE:
shape [OPTIONS] <FONT-FILE> [TEXT]
OPTIONS:
-h, --help Show help options
--version Show version number
--font-file PATH Set font file-name
--face-index INDEX Set face index [default: 0]
--font-ptem NUMBER Set font point-size
--variations LIST Set comma-separated list of font variations
--text TEXT Set input text
--text-file PATH Set input text file
-u, --unicodes LIST Set comma-separated list of input Unicode codepoints
Examples: 'U+0056,U+0057'
--direction DIRECTION Set text direction
[possible values: ltr, rtl, ttb, btt]
--language LANG Set text language [default: LC_CTYPE]
--script TAG Set text script as ISO-15924 tag
--utf8-clusters Use UTF-8 byte indices, not char indices
--cluster-level N Cluster merging level [default: 0]
[possible values: 0, 1, 2]
--features LIST Set comma-separated list of font features
--no-glyph-names Output glyph indices instead of names
--no-positions Do not output glyph positions
--no-advances Do not output glyph advances
--no-clusters Do not output cluster indices
--show-extents Output glyph extents
--show-flags Output glyph flags
--single-par Treat the input string as a single paragraph
--ned No Extra Data; Do not output clusters or advances
ARGS:
<FONT-FILE> A font file
[TEXT] An optional text
";
struct Args {
help: bool,
version: bool,
font_file: Option<PathBuf>,
face_index: u32,
font_ptem: Option<f32>,
variations: Vec<rustybuzz::Variation>,
text: Option<String>,
text_file: Option<PathBuf>,
unicodes: Option<String>,
direction: Option<rustybuzz::Direction>,
language: rustybuzz::Language,
script: Option<rustybuzz::Script>,
utf8_clusters: bool,
cluster_level: rustybuzz::BufferClusterLevel,
features: Vec<rustybuzz::Feature>,
no_glyph_names: bool,
no_positions: bool,
no_advances: bool,
no_clusters: bool,
show_extents: bool,
show_flags: bool,
single_par: bool,
ned: bool,
free: Vec<String>,
}
fn parse_args() -> Result<Args, pico_args::Error> {
let mut args = pico_args::Arguments::from_env();
let args = Args {
help: args.contains(["-h", "--help"]),
version: args.contains("--version"),
font_file: args.opt_value_from_str("--font-file")?,
face_index: args.opt_value_from_str("--face-index")?.unwrap_or(0),
font_ptem: args.opt_value_from_str("--font-ptem")?,
variations: args
.opt_value_from_fn("--variations", parse_variations)?
.unwrap_or_default(),
text: args.opt_value_from_str("--text")?,
text_file: args.opt_value_from_str("--text-file")?,
unicodes: args.opt_value_from_fn(["-u", "--unicodes"], parse_unicodes)?,
direction: args.opt_value_from_str("--direction")?,
language: args
.opt_value_from_str("--language")?
.unwrap_or(system_language()),
script: args.opt_value_from_str("--script")?,
utf8_clusters: args.contains("--utf8-clusters"),
cluster_level: args
.opt_value_from_fn("--cluster-level", parse_cluster)?
.unwrap_or_default(),
features: args
.opt_value_from_fn("--features", parse_features)?
.unwrap_or_default(),
no_glyph_names: args.contains("--no-glyph-names"),
no_positions: args.contains("--no-positions"),
no_advances: args.contains("--no-advances"),
no_clusters: args.contains("--no-clusters"),
show_extents: args.contains("--show-extents"),
show_flags: args.contains("--show-flags"),
single_par: args.contains("--single-par"),
ned: args.contains("--ned"),
free: args
.finish()
.iter()
.map(|s| s.to_string_lossy().to_string())
.collect(),
};
Ok(args)
}
fn main() {
let args = match parse_args() {
Ok(v) => v,
Err(e) => {
eprintln!("Error: {}.", e);
std::process::exit(1);
}
};
if args.version {
println!("{}", env!("CARGO_PKG_VERSION"));
return;
}
if args.help {
print!("{}", HELP);
return;
}
let mut font_set_as_free_arg = false;
let font_path = if let Some(path) = args.font_file {
path.clone()
} else if !args.free.is_empty() {
font_set_as_free_arg = true;
PathBuf::from(&args.free[0])
} else {
eprintln!("Error: font is not set.");
std::process::exit(1);
};
if !font_path.exists() {
eprintln!("Error: '{}' does not exist.", font_path.display());
std::process::exit(1);
}
let font_data = std::fs::read(font_path).unwrap();
let mut face = rustybuzz::Face::from_slice(&font_data, args.face_index).unwrap();
face.set_points_per_em(args.font_ptem);
if !args.variations.is_empty() {
face.set_variations(&args.variations);
}
let text = if let Some(path) = args.text_file {
std::fs::read_to_string(path).unwrap()
} else if args.free.len() == 2 && font_set_as_free_arg {
args.free[1].clone()
} else if args.free.len() == 1 && !font_set_as_free_arg {
args.free[0].clone()
} else if let Some(ref text) = args.unicodes {
text.clone()
} else if let Some(ref text) = args.text {
text.clone()
} else {
eprintln!("Error: text is not set.");
std::process::exit(1);
};
let lines = if args.single_par {
vec![text.as_str()]
} else {
text.split("\n").filter(|s| !s.is_empty()).collect()
};
for text in lines {
let mut buffer = rustybuzz::UnicodeBuffer::new();
buffer.push_str(&text);
if let Some(d) = args.direction {
buffer.set_direction(d);
}
buffer.set_language(args.language.clone());
if let Some(script) = args.script {
buffer.set_script(script);
}
buffer.set_cluster_level(args.cluster_level);
if !args.utf8_clusters {
buffer.reset_clusters();
}
let glyph_buffer = rustybuzz::shape(&face, &args.features, buffer);
let mut format_flags = rustybuzz::SerializeFlags::default();
if args.no_glyph_names {
format_flags |= rustybuzz::SerializeFlags::NO_GLYPH_NAMES;
}
if args.no_clusters || args.ned {
format_flags |= rustybuzz::SerializeFlags::NO_CLUSTERS;
}
if args.no_positions {
format_flags |= rustybuzz::SerializeFlags::NO_POSITIONS;
}
if args.no_advances || args.ned {
format_flags |= rustybuzz::SerializeFlags::NO_ADVANCES;
}
if args.show_extents {
format_flags |= rustybuzz::SerializeFlags::GLYPH_EXTENTS;
}
if args.show_flags {
format_flags |= rustybuzz::SerializeFlags::GLYPH_FLAGS;
}
println!("{}", glyph_buffer.serialize(&face, format_flags));
}
}
fn parse_unicodes(s: &str) -> Result<String, String> {
let mut text = String::new();
for u in s.split(',') {
let u = u32::from_str_radix(&u[2..], 16)
.map_err(|_| format!("'{}' is not a valid codepoint", u))?;
let c = char::try_from(u).map_err(|_| format!("{} is not a valid codepoint", u))?;
text.push(c);
}
Ok(text)
}
fn parse_features(s: &str) -> Result<Vec<rustybuzz::Feature>, String> {
let mut features = Vec::new();
for f in s.split(',') {
features.push(rustybuzz::Feature::from_str(&f)?);
}
Ok(features)
}
fn parse_variations(s: &str) -> Result<Vec<rustybuzz::Variation>, String> {
let mut variations = Vec::new();
for v in s.split(',') {
variations.push(rustybuzz::Variation::from_str(&v)?);
}
Ok(variations)
}
fn parse_cluster(s: &str) -> Result<rustybuzz::BufferClusterLevel, String> {
match s {
"0" => Ok(rustybuzz::BufferClusterLevel::MonotoneGraphemes),
"1" => Ok(rustybuzz::BufferClusterLevel::MonotoneCharacters),
"2" => Ok(rustybuzz::BufferClusterLevel::Characters),
_ => Err(format!("invalid cluster level")),
}
}
fn system_language() -> rustybuzz::Language {
unsafe {
libc::setlocale(libc::LC_ALL, b"\0" as *const _ as *const i8);
let s = libc::setlocale(libc::LC_CTYPE, std::ptr::null());
let s = std::ffi::CStr::from_ptr(s);
let s = s.to_str().expect("locale must be ASCII");
rustybuzz::Language::from_str(s).unwrap()
}
}