| 1 | use super::hb_font_t; |
| 2 | use super::ot_shape::{hb_ot_shape_context_t, shape_internal}; |
| 3 | use super::ot_shape_plan::hb_ot_shape_plan_t; |
| 4 | use crate::{script, Feature, GlyphBuffer, UnicodeBuffer}; |
| 5 | |
| 6 | /// Shapes the buffer content using provided font and features. |
| 7 | /// |
| 8 | /// Consumes the buffer. You can then run [`GlyphBuffer::clear`] to get the [`UnicodeBuffer`] back |
| 9 | /// without allocating a new one. |
| 10 | /// |
| 11 | /// If you plan to shape multiple strings using the same [`Face`] prefer [`shape_with_plan`]. |
| 12 | /// This is because [`ShapePlan`] initialization is pretty slow and should preferably be called |
| 13 | /// once for each [`Face`]. |
| 14 | pub fn shape(face: &hb_font_t, features: &[Feature], mut buffer: UnicodeBuffer) -> GlyphBuffer { |
| 15 | buffer.0.guess_segment_properties(); |
| 16 | let plan: hb_ot_shape_plan_t = hb_ot_shape_plan_t::new( |
| 17 | face, |
| 18 | buffer.0.direction, |
| 19 | buffer.0.script, |
| 20 | buffer.0.language.as_ref(), |
| 21 | features, |
| 22 | ); |
| 23 | shape_with_plan(face, &plan, buffer) |
| 24 | } |
| 25 | |
| 26 | /// Shapes the buffer content using the provided font and plan. |
| 27 | /// |
| 28 | /// Consumes the buffer. You can then run [`GlyphBuffer::clear`] to get the [`UnicodeBuffer`] back |
| 29 | /// without allocating a new one. |
| 30 | /// |
| 31 | /// It is up to the caller to ensure that the shape plan matches the properties of the provided |
| 32 | /// buffer, otherwise the shaping result will likely be incorrect. |
| 33 | /// |
| 34 | /// # Panics |
| 35 | /// |
| 36 | /// Will panic when debugging assertions are enabled if the buffer and plan have mismatched |
| 37 | /// properties. |
| 38 | pub fn shape_with_plan( |
| 39 | face: &hb_font_t, |
| 40 | plan: &hb_ot_shape_plan_t, |
| 41 | buffer: UnicodeBuffer, |
| 42 | ) -> GlyphBuffer { |
| 43 | let mut buffer = buffer.0; |
| 44 | buffer.guess_segment_properties(); |
| 45 | |
| 46 | buffer.enter(); |
| 47 | |
| 48 | debug_assert_eq!(buffer.direction, plan.direction); |
| 49 | debug_assert_eq!( |
| 50 | buffer.script.unwrap_or(script::UNKNOWN), |
| 51 | plan.script.unwrap_or(script::UNKNOWN) |
| 52 | ); |
| 53 | |
| 54 | if buffer.len > 0 { |
| 55 | // Save the original direction, we use it later. |
| 56 | let target_direction = buffer.direction; |
| 57 | |
| 58 | #[cfg (feature = "wasm-shaper" )] |
| 59 | { |
| 60 | super::shape_wasm::shape_with_wasm(face, plan, &mut buffer).unwrap_or_else(|| { |
| 61 | shape_internal(&mut hb_ot_shape_context_t { |
| 62 | plan, |
| 63 | face, |
| 64 | buffer: &mut buffer, |
| 65 | target_direction, |
| 66 | }); |
| 67 | }); |
| 68 | } |
| 69 | #[cfg (not(feature = "wasm-shaper" ))] |
| 70 | { |
| 71 | shape_internal(&mut hb_ot_shape_context_t { |
| 72 | plan, |
| 73 | face, |
| 74 | buffer: &mut buffer, |
| 75 | target_direction, |
| 76 | }); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | GlyphBuffer(buffer) |
| 81 | } |
| 82 | |