[harfrust] Cache Shaper object (#5454)

diff --git a/src/hb-harfrust.cc b/src/hb-harfrust.cc
index 38c9c89..6859f4a 100644
--- a/src/hb-harfrust.cc
+++ b/src/hb-harfrust.cc
@@ -92,7 +92,6 @@
 
 extern "C" void *
 _hb_harfrust_shape_plan_create_rs (const void *font_data,
-				   const void *face_data,
 				   hb_script_t script,
 				   hb_language_t language,
 				   hb_direction_t direction);
@@ -154,7 +153,7 @@
     hr_shape_plan = hb_shape_plan_get_user_data (shape_plan, &hb_object_key);
     if (unlikely (!hr_shape_plan))
     {
-      hr_shape_plan = _hb_harfrust_shape_plan_create_rs (font_data, face_data,
+      hr_shape_plan = _hb_harfrust_shape_plan_create_rs (font_data,
 							 shape_plan->key.props.script,
 							 shape_plan->key.props.language,
 							 shape_plan->key.props.direction);
diff --git a/src/rust/shape.rs b/src/rust/shape.rs
index 820c295..d7b348f 100644
--- a/src/rust/shape.rs
+++ b/src/rust/shape.rs
@@ -3,10 +3,11 @@
 use super::hb::*;
 
 use std::ffi::c_void;
+use std::mem::transmute;
 use std::ptr::null_mut;
 use std::str::FromStr;
 
-use harfrust::{FontRef, NormalizedCoord, ShaperData, ShaperInstance, Tag};
+use harfrust::{FontRef, NormalizedCoord, Shaper, ShaperData, ShaperInstance, Tag};
 
 pub struct HBHarfRustFaceData<'a> {
     face_blob: *mut hb_blob_t,
@@ -51,7 +52,8 @@
 }
 
 pub struct HBHarfRustFontData {
-    shaper_instance: ShaperInstance,
+    shaper_instance: Box<ShaperInstance>,
+    shaper: Shaper<'static>,
 }
 
 fn font_to_shaper_instance(font: *mut hb_font_t, font_ref: &FontRef<'_>) -> ShaperInstance {
@@ -74,9 +76,19 @@
     let face_data = face_data as *const HBHarfRustFaceData;
 
     let font_ref = &(*face_data).font_ref;
-    let shaper_instance = font_to_shaper_instance(font, font_ref);
+    let shaper_instance = Box::new(font_to_shaper_instance(font, font_ref));
 
-    let hr_font_data = Box::new(HBHarfRustFontData { shaper_instance });
+    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
@@ -113,15 +125,11 @@
 #[no_mangle]
 pub unsafe extern "C" fn _hb_harfrust_shape_plan_create_rs(
     font_data: *const c_void,
-    face_data: *const c_void,
     script: hb_script_t,
     language: hb_language_t,
     direction: hb_direction_t,
 ) -> *mut c_void {
     let font_data = font_data as *const HBHarfRustFontData;
-    let face_data = face_data as *const HBHarfRustFaceData;
-
-    let font_ref = &(*face_data).font_ref;
 
     let script = harfrust::Script::from_iso15924_tag(Tag::from_u32(script));
     let language = hb_language_to_hr_language(language);
@@ -133,14 +141,9 @@
         _ => harfrust::Direction::Invalid,
     };
 
-    let shaper = (*face_data)
-        .shaper_data
-        .shaper(font_ref)
-        .instance(Some(&(*font_data).shaper_instance))
-        .build();
+    let shaper = &(*font_data).shaper;
 
-    let hr_shape_plan =
-        harfrust::ShapePlan::new(&shaper, direction, script, language.as_ref(), &[]);
+    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
 }
@@ -233,12 +236,16 @@
     let ptem = hb_font_get_ptem(font);
     let ptem = if ptem > 0.0 { Some(ptem) } else { None };
 
-    let shaper = (*face_data)
-        .shaper_data
-        .shaper(font_ref)
-        .instance(Some(&(*font_data).shaper_instance))
-        .point_size(ptem)
-        .build();
+    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()