skia_safe/modules/paragraph/
paragraph_style.rs1use std::fmt;
2
3use skia_bindings as sb;
4
5use super::{FontFamilies, TextAlign, TextDirection, TextStyle};
6use crate::{
7 FontStyle,
8 interop::{self, AsStr, FromStrs, SetStr},
9 modules::paragraph::TextHeightBehavior,
10 prelude::*,
11 scalar,
12};
13
14pub type StrutStyle = Handle<sb::skia_textlayout_StrutStyle>;
15unsafe_send_sync!(StrutStyle);
16
17impl NativeDrop for sb::skia_textlayout_StrutStyle {
18 fn drop(&mut self) {
19 unsafe { sb::C_StrutStyle_destruct(self) }
20 }
21}
22
23impl NativeClone for sb::skia_textlayout_StrutStyle {
24 fn clone(&self) -> Self {
25 construct(|ss| unsafe { sb::C_StrutStyle_CopyConstruct(ss, self) })
26 }
27}
28
29impl NativePartialEq for sb::skia_textlayout_StrutStyle {
30 fn eq(&self, rhs: &Self) -> bool {
31 unsafe { sb::C_StrutStyle_equals(self, rhs) }
32 }
33}
34
35impl Default for StrutStyle {
36 fn default() -> Self {
37 Self::new()
38 }
39}
40
41impl fmt::Debug for StrutStyle {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 f.debug_struct("StrutStyle")
44 .field("font_families", &self.font_families())
45 .field("font_style", &self.font_style())
46 .field("font_size", &self.font_size())
47 .field("height", &self.height())
48 .field("leading", &self.leading())
49 .field("strut_enabled", &self.strut_enabled())
50 .field("force_strut_height", &self.force_strut_height())
51 .field("height_override", &self.height_override())
52 .field("half_leading", &self.half_leading())
53 .finish()
54 }
55}
56
57impl StrutStyle {
58 pub fn new() -> Self {
59 StrutStyle::construct(|ss| unsafe { sb::C_StrutStyle_Construct(ss) })
60 }
61
62 pub fn font_families(&self) -> FontFamilies {
63 unsafe {
64 let mut count = 0;
65 let ptr = sb::C_StrutStyle_getFontFamilies(self.native(), &mut count);
66 FontFamilies(safer::from_raw_parts(ptr, count))
67 }
68 }
69
70 pub fn set_font_families(&mut self, families: &[impl AsRef<str>]) -> &mut Self {
71 let families: Vec<interop::String> = FromStrs::from_strs(families);
72 let families = families.native();
73 unsafe {
74 sb::C_StrutStyle_setFontFamilies(self.native_mut(), families.as_ptr(), families.len());
75 }
76 self
77 }
78
79 pub fn font_style(&self) -> FontStyle {
80 FontStyle::from_native_c(self.native().fFontStyle)
81 }
82
83 pub fn set_font_style(&mut self, font_style: FontStyle) -> &mut Self {
84 self.native_mut().fFontStyle = font_style.into_native();
85 self
86 }
87
88 pub fn font_size(&self) -> scalar {
89 self.native().fFontSize
90 }
91
92 pub fn set_font_size(&mut self, font_size: scalar) -> &mut Self {
93 self.native_mut().fFontSize = font_size;
94 self
95 }
96
97 pub fn set_height(&mut self, height: scalar) -> &mut Self {
98 self.native_mut().fHeight = height;
99 self
100 }
101
102 pub fn height(&self) -> scalar {
103 self.native().fHeight
104 }
105
106 pub fn set_leading(&mut self, leading: scalar) -> &mut Self {
107 self.native_mut().fLeading = leading;
108 self
109 }
110
111 pub fn leading(&self) -> scalar {
112 self.native().fLeading
113 }
114
115 pub fn strut_enabled(&self) -> bool {
116 self.native().fEnabled
117 }
118
119 pub fn set_strut_enabled(&mut self, enabled: bool) -> &mut Self {
120 self.native_mut().fEnabled = enabled;
121 self
122 }
123
124 pub fn force_strut_height(&self) -> bool {
125 self.native().fForceHeight
126 }
127
128 pub fn set_force_strut_height(&mut self, force_height: bool) -> &mut Self {
129 self.native_mut().fForceHeight = force_height;
130 self
131 }
132
133 pub fn height_override(&self) -> bool {
134 self.native().fHeightOverride
135 }
136
137 pub fn set_height_override(&mut self, height_override: bool) -> &mut Self {
138 self.native_mut().fHeightOverride = height_override;
139 self
140 }
141
142 pub fn half_leading(&self) -> bool {
143 self.native().fHalfLeading
144 }
145
146 pub fn set_half_leading(&mut self, half_leading: bool) -> &mut Self {
147 self.native_mut().fHalfLeading = half_leading;
148 self
149 }
150}
151
152pub type ParagraphStyle = RefHandle<sb::skia_textlayout_ParagraphStyle>;
154unsafe_send_sync!(ParagraphStyle);
155
156impl NativeDrop for sb::skia_textlayout_ParagraphStyle {
157 fn drop(&mut self) {
158 unsafe { sb::C_ParagraphStyle_delete(self) }
159 }
160}
161
162impl Clone for ParagraphStyle {
163 fn clone(&self) -> Self {
164 Self::from_ptr(unsafe { sb::C_ParagraphStyle_newCopy(self.native()) }).unwrap()
165 }
166}
167
168impl NativePartialEq for sb::skia_textlayout_ParagraphStyle {
169 fn eq(&self, rhs: &Self) -> bool {
170 unsafe { sb::C_ParagraphStyle_Equals(self, rhs) }
171 }
172}
173
174impl Default for ParagraphStyle {
175 fn default() -> Self {
176 Self::new()
177 }
178}
179
180impl fmt::Debug for ParagraphStyle {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 f.debug_struct("ParagraphStyle")
183 .field("strut_style", &self.strut_style())
184 .field("text_style", &self.text_style())
185 .field("text_direction", &self.text_direction())
186 .field("text_align", &self.text_align())
187 .field("max_lines", &self.max_lines())
188 .field("ellipsis", &self.ellipsis())
189 .field("height", &self.height())
190 .field("text_height_behavior", &self.text_height_behavior())
191 .field("unlimited_lines", &self.unlimited_lines())
192 .field("ellipsized", &self.ellipsized())
193 .field("effective_align", &self.effective_align())
194 .field("hinting_is_on", &self.hinting_is_on())
195 .field("replace_tab_characters", &self.replace_tab_characters())
196 .field("fake_missing_font_styles", &self.fake_missing_font_styles())
197 .field(
198 "letter_spacing_by_css_spec",
199 &self.letter_spacing_by_css_spec(),
200 )
201 .field("render_soft_hyphens", &self.render_soft_hyphens())
202 .finish()
203 }
204}
205
206impl ParagraphStyle {
207 pub fn new() -> Self {
208 Self::from_ptr(unsafe { sb::C_ParagraphStyle_new() }).unwrap()
209 }
210
211 pub fn strut_style(&self) -> &StrutStyle {
212 StrutStyle::from_native_ref(&self.native().fStrutStyle)
213 }
214
215 pub fn set_strut_style(&mut self, strut_style: StrutStyle) -> &mut Self {
216 self.native_mut().fStrutStyle.replace_with(strut_style);
217 self
218 }
219
220 pub fn text_style(&self) -> &TextStyle {
221 TextStyle::from_native_ref(&self.native().fDefaultTextStyle)
222 }
223
224 pub fn set_text_style(&mut self, text_style: &TextStyle) -> &mut Self {
225 self.native_mut()
227 .fDefaultTextStyle
228 .replace_with(text_style.clone());
229 self
230 }
231
232 pub fn text_direction(&self) -> TextDirection {
233 self.native().fTextDirection
234 }
235
236 pub fn set_text_direction(&mut self, direction: TextDirection) -> &mut Self {
237 self.native_mut().fTextDirection = direction;
238 self
239 }
240
241 pub fn text_align(&self) -> TextAlign {
242 self.native().fTextAlign
243 }
244
245 pub fn set_text_align(&mut self, align: TextAlign) -> &mut Self {
246 self.native_mut().fTextAlign = align;
247 self
248 }
249
250 pub fn max_lines(&self) -> Option<usize> {
251 match self.native().fLinesLimit {
252 std::usize::MAX => None,
253 lines => Some(lines),
254 }
255 }
256
257 pub fn set_max_lines(&mut self, lines: impl Into<Option<usize>>) -> &mut Self {
258 self.native_mut().fLinesLimit = lines.into().unwrap_or(usize::MAX);
259 self
260 }
261
262 pub fn ellipsis(&self) -> &str {
265 self.native().fEllipsis.as_str()
266 }
267
268 pub fn set_ellipsis(&mut self, ellipsis: impl AsRef<str>) -> &mut Self {
269 self.native_mut().fEllipsis.set_str(ellipsis);
270 self
271 }
272
273 pub fn height(&self) -> scalar {
274 self.native().fHeight
275 }
276
277 pub fn set_height(&mut self, height: scalar) -> &mut Self {
278 self.native_mut().fHeight = height;
279 self
280 }
281
282 pub fn text_height_behavior(&self) -> TextHeightBehavior {
283 self.native().fTextHeightBehavior
284 }
285
286 pub fn set_text_height_behavior(&mut self, v: TextHeightBehavior) -> &mut Self {
287 self.native_mut().fTextHeightBehavior = v;
288 self
289 }
290
291 pub fn unlimited_lines(&self) -> bool {
292 self.max_lines().is_none()
293 }
294
295 pub fn ellipsized(&self) -> bool {
296 unsafe { sb::C_ParagraphStyle_ellipsized(self.native()) }
297 }
298
299 pub fn effective_align(&self) -> TextAlign {
300 unsafe { self.native().effective_align() }
301 }
302
303 pub fn hinting_is_on(&self) -> bool {
304 self.native().fHintingIsOn
305 }
306
307 pub fn turn_hinting_off(&mut self) -> &mut Self {
308 self.native_mut().fHintingIsOn = false;
309 self
310 }
311
312 pub fn fake_missing_font_styles(&self) -> bool {
313 self.native().fFakeMissingFontStyles
314 }
315
316 pub fn set_fake_missing_font_styles(&mut self, value: bool) -> &mut Self {
317 self.native_mut().fFakeMissingFontStyles = value;
318 self
319 }
320
321 pub fn replace_tab_characters(&self) -> bool {
322 self.native().fReplaceTabCharacters
323 }
324
325 pub fn set_replace_tab_characters(&mut self, value: bool) -> &mut Self {
326 self.native_mut().fReplaceTabCharacters = value;
327 self
328 }
329
330 pub fn apply_rounding_hack(&self) -> bool {
331 self.native().fApplyRoundingHack
332 }
333
334 pub fn set_apply_rounding_hack(&mut self, value: bool) -> &mut Self {
335 self.native_mut().fApplyRoundingHack = value;
336 self
337 }
338
339 pub fn letter_spacing_by_css_spec(&self) -> bool {
340 self.native().fLetterSpacingByCSSSpec
341 }
342
343 pub fn set_letter_spacing_by_css_spec(&mut self, value: bool) -> &mut Self {
344 self.native_mut().fLetterSpacingByCSSSpec = value;
345 self
346 }
347
348 pub fn render_soft_hyphens(&self) -> bool {
349 self.native().fRenderSoftHyphens
350 }
351
352 pub fn set_render_soft_hyphens(&mut self, value: bool) -> &mut Self {
353 self.native_mut().fRenderSoftHyphens = value;
354 self
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use super::ParagraphStyle;
361
362 #[test]
364 fn paragraph_style_supports_equality() {
365 let a = ParagraphStyle::default();
366 let b = ParagraphStyle::default();
367 assert_eq!(a, b)
368 }
369}