#[no_mangle] pubunsafeextern"C"fn _hb_harfrust_shaper_face_data_create_rs(
face: *mut hb_face_t,
) -> *mut c_void { let face_index = hb_face_get_index(face); let face_blob = hb_face_reference_blob(face); let blob_length = hb_blob_get_length(face_blob); let blob_data = hb_blob_get_data(face_blob, null_mut()); if blob_data.is_null() { return null_mut();
} let face_data = std::slice::from_raw_parts(blob_data as *const u8, blob_length as usize);
let font_ref = match FontRef::from_index(face_data, face_index) {
Ok(f) => f,
Err(_) => return null_mut(),
}; let shaper_data = ShaperData::new(&font_ref);
let hr_face_data = Box::new(HBHarfRustFaceData {
face_blob,
font_ref,
shaper_data,
});
Box::into_raw(hr_face_data) as *mut c_void
}
#[no_mangle] pubunsafeextern"C"fn _hb_harfrust_shaper_face_data_destroy_rs(data: *mut c_void) { let data = data as *mut HBHarfRustFaceData; let hr_face_data = Box::from_raw(data); let blob = hr_face_data.face_blob;
hb_blob_destroy(blob);
}
let font_ref = &(*face_data).font_ref; let shaper_instance = Box::new(font_to_shaper_instance(font, font_ref));
let shaper_instance_ref = &*(&*shaper_instance as *const _); let shaper = (*face_data)
.shaper_data
.shaper(font_ref)
.instance(Some(shaper_instance_ref))
.build();
let hr_font_data = Box::new(HBHarfRustFontData {
shaper_instance,
shaper: transmute::<harfrust::Shaper<'_>, harfrust::Shaper<'_>>(shaper),
}); let hr_font_data_ptr = Box::into_raw(hr_font_data);
hr_font_data_ptr as *mut c_void
}
#[no_mangle] pubunsafeextern"C"fn _hb_harfrust_shaper_font_data_destroy_rs(data: *mut c_void) { let data = data as *mut HBHarfRustFontData; let _hr_font_data = Box::from_raw(data);
}
fn hb_language_to_hr_language(language: hb_language_t) -> Option<harfrust::Language> { let language_str = unsafe { hb_language_to_string(language) }; if language_str.is_null() { return None;
} let language_str = unsafe { std::ffi::CStr::from_ptr(language_str) }; let language_str = language_str.to_str().unwrap_or_default();
Some(harfrust::Language::from_str(language_str).unwrap())
}
#[no_mangle] pubunsafeextern"C"fn _hb_harfrust_buffer_create_rs() -> *mut c_void { let hr_buffer = Box::new(harfrust::UnicodeBuffer::new()); Box::into_raw(hr_buffer) as *mut c_void
}
#[no_mangle] pubunsafeextern"C"fn _hb_harfrust_buffer_destroy_rs(data: *mut c_void) { let data = data as *mut harfrust::UnicodeBuffer; let _hr_buffer = Box::from_raw(data);
}
let script = harfrust::Script::from_iso15924_tag(Tag::from_u32(script)); let language = hb_language_to_hr_language(language); let direction = match direction {
hb_direction_t_HB_DIRECTION_LTR => harfrust::Direction::LeftToRight,
hb_direction_t_HB_DIRECTION_RTL => harfrust::Direction::RightToLeft,
hb_direction_t_HB_DIRECTION_TTB => harfrust::Direction::TopToBottom,
hb_direction_t_HB_DIRECTION_BTT => harfrust::Direction::BottomToTop,
_ => harfrust::Direction::Invalid,
};
let shaper = &(*font_data).shaper;
let hr_shape_plan = harfrust::ShapePlan::new(shaper, direction, script, language.as_ref(), &[]); let hr_shape_plan = Box::new(hr_shape_plan); Box::into_raw(hr_shape_plan) as *mut c_void
}
#[no_mangle] pubunsafeextern"C"fn _hb_harfrust_shape_plan_destroy_rs(data: *mut c_void) { let data = data as *mut harfrust::ShapePlan; let _hr_shape_plan = Box::from_raw(data);
}
let hr_buffer_box = hr_buffer_box as *mut harfrust::UnicodeBuffer; letmut hr_buffer_box = Box::from_raw(hr_buffer_box); letmut hr_buffer = *hr_buffer_box;
// Set buffer properties let cluster_level = hb_buffer_get_cluster_level(buffer); let cluster_level = match cluster_level {
hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES => {
harfrust::BufferClusterLevel::MonotoneGraphemes
}
hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS => {
harfrust::BufferClusterLevel::MonotoneCharacters
}
hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_CHARACTERS => {
harfrust::BufferClusterLevel::Characters
}
hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES => {
harfrust::BufferClusterLevel::Graphemes
}
_ => harfrust::BufferClusterLevel::default(),
};
hr_buffer.set_cluster_level(cluster_level); let flags = hb_buffer_get_flags(buffer);
hr_buffer.set_flags(harfrust::BufferFlags::from_bits_truncate(flags)); let not_found_variation_selector_glyph =
hb_buffer_get_not_found_variation_selector_glyph(buffer); if not_found_variation_selector_glyph != u32::MAX {
hr_buffer.set_not_found_variation_selector_glyph(not_found_variation_selector_glyph);
}
// Segment properties: let script = hb_buffer_get_script(buffer); let language = hb_buffer_get_language(buffer); let direction = hb_buffer_get_direction(buffer); // Convert to HarfRust types let script = harfrust::Script::from_iso15924_tag(Tag::from_u32(script))
.unwrap_or(harfrust::script::UNKNOWN); let language = hb_language_to_hr_language(language); let direction = match direction {
hb_direction_t_HB_DIRECTION_LTR => harfrust::Direction::LeftToRight,
hb_direction_t_HB_DIRECTION_RTL => harfrust::Direction::RightToLeft,
hb_direction_t_HB_DIRECTION_TTB => harfrust::Direction::TopToBottom,
hb_direction_t_HB_DIRECTION_BTT => harfrust::Direction::BottomToTop,
_ => harfrust::Direction::Invalid,
}; // Set properties on the buffer
hr_buffer.set_script(script); iflet Some(lang) = language {
hr_buffer.set_language(lang);
}
hr_buffer.set_direction(direction);
// Populate buffer let count = hb_buffer_get_length(buffer); let infos = hb_buffer_get_glyph_infos(buffer, null_mut());
hr_buffer.reserve(count as usize);
for i in0..count { let info = &*infos.add(i as usize); let unicode = info.codepoint; let cluster = info.cluster;
hr_buffer.add(char::from_u32_unchecked(unicode), cluster);
}
let pre_context = std::slice::from_raw_parts(pre_context, pre_context_length as usize);
hr_buffer.set_pre_context(str::from_utf8(pre_context).unwrap()); let post_context = std::slice::from_raw_parts(post_context, post_context_length as usize);
hr_buffer.set_post_context(str::from_utf8(post_context).unwrap());
let ptem = hb_font_get_ptem(font); let ptem = if ptem > 0.0 { Some(ptem) } else { None };
let shaper = if ptem.is_some() {
(*face_data)
.shaper_data
.shaper(font_ref)
.instance(Some(&(*font_data).shaper_instance))
.point_size(ptem)
.build()
} else {
(*font_data).shaper.clone()
};
let features = if features.is_null() {
Vec::new()
} else { let features = std::slice::from_raw_parts(features, num_features as usize);
features
.iter()
.map(|f| { let tag = f.tag; let value = f.value; let start = f.start; let end = f.end;
harfrust::Feature {
tag: Tag::from_u32(tag),
value,
start,
end,
}
})
.collect::<Vec<_>>()
};
let glyphs = if shape_plan.is_null() {
shaper.shape(hr_buffer, &features)
} else { let shape_plan = shape_plan as *const harfrust::ShapePlan;
shaper.shape_with_plan(shape_plan.as_ref().unwrap(), hr_buffer, &features)
};
let count = glyphs.len();
hb_buffer_set_length(buffer, 0u32);
hb_buffer_set_content_type(
buffer,
hb_buffer_content_type_t_HB_BUFFER_CONTENT_TYPE_GLYPHS,
);
hb_buffer_set_length(buffer, count as u32); letmut count_out: u32 = 0; let infos = hb_buffer_get_glyph_infos(buffer, &mut count_out); let positions = hb_buffer_get_glyph_positions(buffer, null_mut()); if count != count_out as usize { returnfalseas hb_bool_t;
}
letmut x_scale: i32 = 0; letmut y_scale: i32 = 0;
hb_font_get_scale(font, &mut x_scale, &mut y_scale); let upem = shaper.units_per_em(); let upem = if upem > 0 { upem } else { 1000 }; let x_mult = if x_scale < 0 {
-((-x_scale as i64) << 16)
} else {
(x_scale as i64) << 16
} / upem as i64; let y_mult = if y_scale < 0 {
-((-y_scale as i64) << 16)
} else {
(y_scale as i64) << 16
} / upem as i64;
let em_mult =
|v: i32, mult: i64| -> hb_position_t { ((v as i64 * mult + 32768) >> 16) as hb_position_t };
for (i, (hr_info, hr_pos)) in glyphs
.glyph_infos()
.iter()
.zip(glyphs.glyph_positions())
.enumerate()
{ let info = &mut *infos.add(i); let pos = &mut *positions.add(i);
info.codepoint = hr_info.glyph_id;
info.cluster = hr_info.cluster;
info.mask = 0; if hr_info.unsafe_to_break() {
info.mask |= hb_glyph_flags_t_HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
} if hr_info.unsafe_to_concat() {
info.mask |= hb_glyph_flags_t_HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
} if hr_info.safe_to_insert_tatweel() {
info.mask |= hb_glyph_flags_t_HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL;
}
pos.x_advance = em_mult(hr_pos.x_advance, x_mult);
pos.y_advance = em_mult(hr_pos.y_advance, y_mult);
pos.x_offset = em_mult(hr_pos.x_offset, x_mult);
pos.y_offset = em_mult(hr_pos.y_offset, y_mult);
}
let hr_buffer = glyphs.clear();
*hr_buffer_box = hr_buffer; // Move the buffer back into the box let _ = Box::into_raw(hr_buffer_box); // Prevent double free
trueas hb_bool_t
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-09-30)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.