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 | |