shape.rs (12229B)
1 #![allow(non_upper_case_globals)] 2 3 use super::hb::*; 4 5 use std::ffi::c_void; 6 use std::mem::transmute; 7 use std::ptr::null_mut; 8 use std::str::FromStr; 9 10 use harfrust::{FontRef, NormalizedCoord, Shaper, ShaperData, ShaperInstance, Tag}; 11 12 pub struct HBHarfRustFaceData<'a> { 13 face_blob: *mut hb_blob_t, 14 font_ref: FontRef<'a>, 15 shaper_data: ShaperData, 16 } 17 18 #[no_mangle] 19 pub unsafe extern "C" fn _hb_harfrust_shaper_face_data_create_rs( 20 face: *mut hb_face_t, 21 ) -> *mut c_void { 22 let face_index = hb_face_get_index(face); 23 let face_blob = hb_face_reference_blob(face); 24 let blob_length = hb_blob_get_length(face_blob); 25 let blob_data = hb_blob_get_data(face_blob, null_mut()); 26 if blob_data.is_null() { 27 return null_mut(); 28 } 29 let face_data = std::slice::from_raw_parts(blob_data as *const u8, blob_length as usize); 30 31 let font_ref = match FontRef::from_index(face_data, face_index) { 32 Ok(f) => f, 33 Err(_) => return null_mut(), 34 }; 35 let shaper_data = ShaperData::new(&font_ref); 36 37 let hr_face_data = Box::new(HBHarfRustFaceData { 38 face_blob, 39 font_ref, 40 shaper_data, 41 }); 42 43 Box::into_raw(hr_face_data) as *mut c_void 44 } 45 46 #[no_mangle] 47 pub unsafe extern "C" fn _hb_harfrust_shaper_face_data_destroy_rs(data: *mut c_void) { 48 let data = data as *mut HBHarfRustFaceData; 49 let hr_face_data = Box::from_raw(data); 50 let blob = hr_face_data.face_blob; 51 hb_blob_destroy(blob); 52 } 53 54 pub struct HBHarfRustFontData { 55 shaper_instance: Box<ShaperInstance>, 56 shaper: Shaper<'static>, 57 } 58 59 fn font_to_shaper_instance(font: *mut hb_font_t, font_ref: &FontRef<'_>) -> ShaperInstance { 60 let mut num_coords: u32 = 0; 61 let coords = unsafe { hb_font_get_var_coords_normalized(font, &mut num_coords) }; 62 let coords = if coords.is_null() { 63 &[] 64 } else { 65 unsafe { std::slice::from_raw_parts(coords, num_coords as usize) } 66 }; 67 let coords = coords.iter().map(|&v| NormalizedCoord::from_bits(v as i16)); 68 ShaperInstance::from_coords(font_ref, coords) 69 } 70 71 #[no_mangle] 72 pub unsafe extern "C" fn _hb_harfrust_shaper_font_data_create_rs( 73 font: *mut hb_font_t, 74 face_data: *const c_void, 75 ) -> *mut c_void { 76 let face_data = face_data as *const HBHarfRustFaceData; 77 78 let font_ref = &(*face_data).font_ref; 79 let shaper_instance = Box::new(font_to_shaper_instance(font, font_ref)); 80 81 let shaper_instance_ref = &*(&*shaper_instance as *const _); 82 let shaper = (*face_data) 83 .shaper_data 84 .shaper(font_ref) 85 .instance(Some(shaper_instance_ref)) 86 .build(); 87 88 let hr_font_data = Box::new(HBHarfRustFontData { 89 shaper_instance, 90 shaper: transmute::<harfrust::Shaper<'_>, harfrust::Shaper<'_>>(shaper), 91 }); 92 let hr_font_data_ptr = Box::into_raw(hr_font_data); 93 94 hr_font_data_ptr as *mut c_void 95 } 96 97 #[no_mangle] 98 pub unsafe extern "C" fn _hb_harfrust_shaper_font_data_destroy_rs(data: *mut c_void) { 99 let data = data as *mut HBHarfRustFontData; 100 let _hr_font_data = Box::from_raw(data); 101 } 102 103 fn hb_language_to_hr_language(language: hb_language_t) -> Option<harfrust::Language> { 104 let language_str = unsafe { hb_language_to_string(language) }; 105 if language_str.is_null() { 106 return None; 107 } 108 let language_str = unsafe { std::ffi::CStr::from_ptr(language_str) }; 109 let language_str = language_str.to_str().unwrap_or_default(); 110 Some(harfrust::Language::from_str(language_str).unwrap()) 111 } 112 113 #[no_mangle] 114 pub unsafe extern "C" fn _hb_harfrust_buffer_create_rs() -> *mut c_void { 115 let hr_buffer = Box::new(harfrust::UnicodeBuffer::new()); 116 Box::into_raw(hr_buffer) as *mut c_void 117 } 118 119 #[no_mangle] 120 pub unsafe extern "C" fn _hb_harfrust_buffer_destroy_rs(data: *mut c_void) { 121 let data = data as *mut harfrust::UnicodeBuffer; 122 let _hr_buffer = Box::from_raw(data); 123 } 124 125 #[no_mangle] 126 pub unsafe extern "C" fn _hb_harfrust_shape_plan_create_rs( 127 font_data: *const c_void, 128 script: hb_script_t, 129 language: hb_language_t, 130 direction: hb_direction_t, 131 ) -> *mut c_void { 132 let font_data = font_data as *const HBHarfRustFontData; 133 134 let script = harfrust::Script::from_iso15924_tag(Tag::from_u32(script)); 135 let language = hb_language_to_hr_language(language); 136 let direction = match direction { 137 hb_direction_t_HB_DIRECTION_LTR => harfrust::Direction::LeftToRight, 138 hb_direction_t_HB_DIRECTION_RTL => harfrust::Direction::RightToLeft, 139 hb_direction_t_HB_DIRECTION_TTB => harfrust::Direction::TopToBottom, 140 hb_direction_t_HB_DIRECTION_BTT => harfrust::Direction::BottomToTop, 141 _ => harfrust::Direction::Invalid, 142 }; 143 144 let shaper = &(*font_data).shaper; 145 146 let hr_shape_plan = harfrust::ShapePlan::new(shaper, direction, script, language.as_ref(), &[]); 147 let hr_shape_plan = Box::new(hr_shape_plan); 148 Box::into_raw(hr_shape_plan) as *mut c_void 149 } 150 151 #[no_mangle] 152 pub unsafe extern "C" fn _hb_harfrust_shape_plan_destroy_rs(data: *mut c_void) { 153 let data = data as *mut harfrust::ShapePlan; 154 let _hr_shape_plan = Box::from_raw(data); 155 } 156 157 #[no_mangle] 158 pub unsafe extern "C" fn _hb_harfrust_shape_rs( 159 font_data: *const c_void, 160 face_data: *const c_void, 161 shape_plan: *const c_void, 162 hr_buffer_box: *const c_void, 163 font: *mut hb_font_t, 164 buffer: *mut hb_buffer_t, 165 pre_context: *const u8, 166 pre_context_length: u32, 167 post_context: *const u8, 168 post_context_length: u32, 169 features: *const hb_feature_t, 170 num_features: u32, 171 ) -> hb_bool_t { 172 let font_data = font_data as *const HBHarfRustFontData; 173 let face_data = face_data as *const HBHarfRustFaceData; 174 175 let font_ref = &(*face_data).font_ref; 176 177 let hr_buffer_box = hr_buffer_box as *mut harfrust::UnicodeBuffer; 178 let mut hr_buffer_box = Box::from_raw(hr_buffer_box); 179 let mut hr_buffer = *hr_buffer_box; 180 181 // Set buffer properties 182 let cluster_level = hb_buffer_get_cluster_level(buffer); 183 let cluster_level = match cluster_level { 184 hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES => { 185 harfrust::BufferClusterLevel::MonotoneGraphemes 186 } 187 hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS => { 188 harfrust::BufferClusterLevel::MonotoneCharacters 189 } 190 hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_CHARACTERS => { 191 harfrust::BufferClusterLevel::Characters 192 } 193 hb_buffer_cluster_level_t_HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES => { 194 harfrust::BufferClusterLevel::Graphemes 195 } 196 _ => harfrust::BufferClusterLevel::default(), 197 }; 198 hr_buffer.set_cluster_level(cluster_level); 199 let flags = hb_buffer_get_flags(buffer); 200 hr_buffer.set_flags(harfrust::BufferFlags::from_bits_truncate(flags)); 201 let not_found_variation_selector_glyph = 202 hb_buffer_get_not_found_variation_selector_glyph(buffer); 203 if not_found_variation_selector_glyph != u32::MAX { 204 hr_buffer.set_not_found_variation_selector_glyph(not_found_variation_selector_glyph); 205 } 206 207 // Segment properties: 208 let script = hb_buffer_get_script(buffer); 209 let language = hb_buffer_get_language(buffer); 210 let direction = hb_buffer_get_direction(buffer); 211 // Convert to HarfRust types 212 let script = harfrust::Script::from_iso15924_tag(Tag::from_u32(script)) 213 .unwrap_or(harfrust::script::UNKNOWN); 214 let language = hb_language_to_hr_language(language); 215 let direction = match direction { 216 hb_direction_t_HB_DIRECTION_LTR => harfrust::Direction::LeftToRight, 217 hb_direction_t_HB_DIRECTION_RTL => harfrust::Direction::RightToLeft, 218 hb_direction_t_HB_DIRECTION_TTB => harfrust::Direction::TopToBottom, 219 hb_direction_t_HB_DIRECTION_BTT => harfrust::Direction::BottomToTop, 220 _ => harfrust::Direction::Invalid, 221 }; 222 // Set properties on the buffer 223 hr_buffer.set_script(script); 224 if let Some(lang) = language { 225 hr_buffer.set_language(lang); 226 } 227 hr_buffer.set_direction(direction); 228 229 // Populate buffer 230 let count = hb_buffer_get_length(buffer); 231 let infos = hb_buffer_get_glyph_infos(buffer, null_mut()); 232 233 hr_buffer.reserve(count as usize); 234 235 for i in 0..count { 236 let info = &*infos.add(i as usize); 237 let unicode = info.codepoint; 238 let cluster = info.cluster; 239 hr_buffer.add(char::from_u32_unchecked(unicode), cluster); 240 } 241 242 let pre_context = std::slice::from_raw_parts(pre_context, pre_context_length as usize); 243 hr_buffer.set_pre_context(str::from_utf8(pre_context).unwrap()); 244 let post_context = std::slice::from_raw_parts(post_context, post_context_length as usize); 245 hr_buffer.set_post_context(str::from_utf8(post_context).unwrap()); 246 247 let ptem = hb_font_get_ptem(font); 248 let ptem = if ptem > 0.0 { Some(ptem) } else { None }; 249 250 let shaper = if ptem.is_some() { 251 (*face_data) 252 .shaper_data 253 .shaper(font_ref) 254 .instance(Some(&(*font_data).shaper_instance)) 255 .point_size(ptem) 256 .build() 257 } else { 258 (*font_data).shaper.clone() 259 }; 260 261 let features = if features.is_null() { 262 Vec::new() 263 } else { 264 let features = std::slice::from_raw_parts(features, num_features as usize); 265 features 266 .iter() 267 .map(|f| { 268 let tag = f.tag; 269 let value = f.value; 270 let start = f.start; 271 let end = f.end; 272 harfrust::Feature { 273 tag: Tag::from_u32(tag), 274 value, 275 start, 276 end, 277 } 278 }) 279 .collect::<Vec<_>>() 280 }; 281 282 let glyphs = if shape_plan.is_null() { 283 shaper.shape(hr_buffer, &features) 284 } else { 285 let shape_plan = shape_plan as *const harfrust::ShapePlan; 286 shaper.shape_with_plan(shape_plan.as_ref().unwrap(), hr_buffer, &features) 287 }; 288 289 let count = glyphs.len(); 290 hb_buffer_set_length(buffer, 0u32); 291 hb_buffer_set_content_type( 292 buffer, 293 hb_buffer_content_type_t_HB_BUFFER_CONTENT_TYPE_GLYPHS, 294 ); 295 hb_buffer_set_length(buffer, count as u32); 296 let mut count_out: u32 = 0; 297 let infos = hb_buffer_get_glyph_infos(buffer, &mut count_out); 298 let positions = hb_buffer_get_glyph_positions(buffer, null_mut()); 299 if count != count_out as usize { 300 return false as hb_bool_t; 301 } 302 303 let mut x_scale: i32 = 0; 304 let mut y_scale: i32 = 0; 305 hb_font_get_scale(font, &mut x_scale, &mut y_scale); 306 let upem = shaper.units_per_em(); 307 let upem = if upem > 0 { upem } else { 1000 }; 308 let x_mult = if x_scale < 0 { 309 -((-x_scale as i64) << 16) 310 } else { 311 (x_scale as i64) << 16 312 } / upem as i64; 313 let y_mult = if y_scale < 0 { 314 -((-y_scale as i64) << 16) 315 } else { 316 (y_scale as i64) << 16 317 } / upem as i64; 318 319 let em_mult = 320 |v: i32, mult: i64| -> hb_position_t { ((v as i64 * mult + 32768) >> 16) as hb_position_t }; 321 322 for (i, (hr_info, hr_pos)) in glyphs 323 .glyph_infos() 324 .iter() 325 .zip(glyphs.glyph_positions()) 326 .enumerate() 327 { 328 let info = &mut *infos.add(i); 329 let pos = &mut *positions.add(i); 330 info.codepoint = hr_info.glyph_id; 331 info.cluster = hr_info.cluster; 332 info.mask = 0; 333 if hr_info.unsafe_to_break() { 334 info.mask |= hb_glyph_flags_t_HB_GLYPH_FLAG_UNSAFE_TO_BREAK; 335 } 336 if hr_info.unsafe_to_concat() { 337 info.mask |= hb_glyph_flags_t_HB_GLYPH_FLAG_UNSAFE_TO_CONCAT; 338 } 339 if hr_info.safe_to_insert_tatweel() { 340 info.mask |= hb_glyph_flags_t_HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL; 341 } 342 pos.x_advance = em_mult(hr_pos.x_advance, x_mult); 343 pos.y_advance = em_mult(hr_pos.y_advance, y_mult); 344 pos.x_offset = em_mult(hr_pos.x_offset, x_mult); 345 pos.y_offset = em_mult(hr_pos.y_offset, y_mult); 346 } 347 348 let hr_buffer = glyphs.clear(); 349 *hr_buffer_box = hr_buffer; // Move the buffer back into the box 350 let _ = Box::into_raw(hr_buffer_box); // Prevent double free 351 352 true as hb_bool_t 353 }