skia_safe/utils/
custom_typeface.rs

1use crate::{
2    prelude::*, typeface::FactoryId, Data, Drawable, FontArguments, FontMetrics, FontStyle,
3    GlyphId, Path, Rect, Typeface,
4};
5use skia_bindings::{self as sb, SkCustomTypefaceBuilder};
6use std::fmt;
7
8pub type CustomTypefaceBuilder = Handle<SkCustomTypefaceBuilder>;
9unsafe_send_sync!(CustomTypefaceBuilder);
10
11impl NativeDrop for SkCustomTypefaceBuilder {
12    fn drop(&mut self) {
13        unsafe { sb::C_SkCustomTypefaceBuilder_destruct(self) }
14    }
15}
16
17impl fmt::Debug for CustomTypefaceBuilder {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        f.debug_struct("CustomTypefaceBuilder").finish()
20    }
21}
22
23impl CustomTypefaceBuilder {
24    pub fn new() -> Self {
25        Self::from_native_c(unsafe { SkCustomTypefaceBuilder::new() })
26    }
27
28    pub fn set_glyph<'a>(
29        &mut self,
30        glyph_id: GlyphId,
31        advance: f32,
32        typeface_glyph: impl Into<TypefaceGlyph<'a>>,
33    ) -> &mut Self {
34        unsafe {
35            use TypefaceGlyph::*;
36            match typeface_glyph.into() {
37                Path(path) => self.native_mut().setGlyph(glyph_id, advance, path.native()),
38                DrawableAndBounds(drawable, bounds) => sb::C_SkCustomTypefaceBuilder_setGlyph(
39                    self.native_mut(),
40                    glyph_id,
41                    advance,
42                    drawable.into_ptr(),
43                    bounds.native(),
44                ),
45            }
46        }
47        self
48    }
49
50    pub fn set_metrics(
51        &mut self,
52        font_metrics: &FontMetrics,
53        scale: impl Into<Option<f32>>,
54    ) -> &mut Self {
55        unsafe {
56            self.native_mut()
57                .setMetrics(font_metrics.native(), scale.into().unwrap_or(1.0))
58        }
59        self
60    }
61
62    pub fn set_font_style(&mut self, font_style: FontStyle) -> &mut Self {
63        unsafe { self.native_mut().setFontStyle(font_style.into_native()) }
64        self
65    }
66
67    pub fn detach(&mut self) -> Option<Typeface> {
68        Typeface::from_ptr(unsafe { sb::C_SkCustomTypefaceBuilder_detach(self.native_mut()) })
69    }
70
71    pub const FACTORY_ID: FactoryId = FactoryId::from_chars('u', 's', 'e', 'r');
72
73    // TODO: MakeFromStream
74    // TODO: This is a stand-in for `from_stream`.
75
76    pub fn from_data(data: impl Into<Data>, font_arguments: &FontArguments) -> Option<Typeface> {
77        Typeface::from_ptr(unsafe {
78            sb::C_SkCustomTypefaceBuilder_FromData(data.into().into_ptr(), font_arguments.native())
79        })
80    }
81}
82
83#[derive(Debug)]
84pub enum TypefaceGlyph<'a> {
85    Path(&'a Path),
86    DrawableAndBounds(Drawable, Rect),
87}
88
89impl<'a> From<&'a Path> for TypefaceGlyph<'a> {
90    fn from(path: &'a Path) -> Self {
91        Self::Path(path)
92    }
93}
94
95impl From<(Drawable, Rect)> for TypefaceGlyph<'_> {
96    fn from((drawable, bounds): (Drawable, Rect)) -> Self {
97        Self::DrawableAndBounds(drawable, bounds)
98    }
99}
100
101#[test]
102fn build_custom_typeface() {
103    let mut builder = CustomTypefaceBuilder::new();
104    let path = Path::new();
105    builder.set_glyph(10u16, 0.0, &path);
106    builder.set_glyph(11u16, 0.0, &path);
107    let typeface = builder.detach().unwrap();
108    assert_eq!(typeface.native().ref_counted_base()._ref_cnt(), 1);
109}