arcdps_imgui\fonts/
glyph_ranges.rs

1use crate::sys;
2
3#[derive(Clone, Eq, PartialEq, Debug)]
4enum FontGlyphRangeData {
5    ChineseSimplifiedCommon,
6    ChineseFull,
7    Cyrillic,
8    Default,
9    Japanese,
10    Korean,
11    Thai,
12    Vietnamese,
13    Custom(*const sys::ImWchar),
14}
15
16/// A set of 16-bit Unicode codepoints
17#[derive(Clone, Eq, PartialEq, Debug)]
18pub struct FontGlyphRanges(FontGlyphRangeData);
19impl FontGlyphRanges {
20    /// The default set of glyph ranges used by imgui.
21    pub fn default() -> FontGlyphRanges {
22        FontGlyphRanges(FontGlyphRangeData::Default)
23    }
24    /// A set of glyph ranges appropriate for use with simplified common Chinese text.
25    pub fn chinese_simplified_common() -> FontGlyphRanges {
26        FontGlyphRanges(FontGlyphRangeData::ChineseSimplifiedCommon)
27    }
28    /// A set of glyph ranges appropriate for use with Chinese text.
29    pub fn chinese_full() -> FontGlyphRanges {
30        FontGlyphRanges(FontGlyphRangeData::ChineseFull)
31    }
32    /// A set of glyph ranges appropriate for use with Cyrillic text.
33    pub fn cyrillic() -> FontGlyphRanges {
34        FontGlyphRanges(FontGlyphRangeData::Cyrillic)
35    }
36    /// A set of glyph ranges appropriate for use with Japanese text.
37    pub fn japanese() -> FontGlyphRanges {
38        FontGlyphRanges(FontGlyphRangeData::Japanese)
39    }
40    /// A set of glyph ranges appropriate for use with Korean text.
41    pub fn korean() -> FontGlyphRanges {
42        FontGlyphRanges(FontGlyphRangeData::Korean)
43    }
44    /// A set of glyph ranges appropriate for use with Thai text.
45    pub fn thai() -> FontGlyphRanges {
46        FontGlyphRanges(FontGlyphRangeData::Thai)
47    }
48    /// A set of glyph ranges appropriate for use with Vietnamese text.
49    pub fn vietnamese() -> FontGlyphRanges {
50        FontGlyphRanges(FontGlyphRangeData::Vietnamese)
51    }
52
53    /// Creates a glyph range from a static slice. The expected format is a series of pairs of
54    /// non-zero shorts, each representing an inclusive range of codepoints, followed by a single
55    /// zero terminating the range. The ranges must not overlap.
56    ///
57    /// As the slice is expected to last as long as a font is used, and is written into global
58    /// state, it must be `'static`.
59    ///
60    /// Panics
61    /// ======
62    ///
63    /// This function will panic if the given slice is not a valid font range.
64    pub fn from_slice(slice: &'static [u16]) -> FontGlyphRanges {
65        assert_eq!(
66            slice.len() % 2,
67            1,
68            "The length of a glyph range must be odd."
69        );
70        assert_eq!(
71            slice.last(),
72            Some(&0),
73            "A glyph range must be zero-terminated."
74        );
75
76        for (i, &glyph) in slice.iter().enumerate().take(slice.len() - 1) {
77            assert_ne!(
78                glyph, 0,
79                "A glyph in a range cannot be zero. \
80                 (Glyph is zero at index {})",
81                i
82            )
83        }
84
85        let mut ranges = Vec::new();
86        for i in 0..slice.len() / 2 {
87            let (start, end) = (slice[i * 2], slice[i * 2 + 1]);
88            assert!(
89                start <= end,
90                "The start of a range cannot be larger than its end. \
91                 (At index {}, {} > {})",
92                i * 2,
93                start,
94                end
95            );
96            ranges.push((start, end));
97        }
98        ranges.sort_unstable_by_key(|x| x.0);
99        for i in 0..ranges.len() - 1 {
100            let (range_a, range_b) = (ranges[i], ranges[i + 1]);
101            if range_a.1 >= range_b.0 {
102                panic!(
103                    "The glyph ranges {:?} and {:?} overlap between {:?}.",
104                    range_a,
105                    range_b,
106                    (range_a.1, range_b.0)
107                );
108            }
109        }
110
111        unsafe { FontGlyphRanges::from_slice_unchecked(slice) }
112    }
113
114    /// Creates a glyph range from a static slice without checking its validity.
115    ///
116    /// See [`FontGlyphRanges::from_slice`] for more information.
117    ///
118    /// # Safety
119    ///
120    /// It is up to the caller to guarantee the slice contents are valid.
121    pub unsafe fn from_slice_unchecked(slice: &'static [u16]) -> FontGlyphRanges {
122        FontGlyphRanges::from_ptr(slice.as_ptr())
123    }
124
125    /// Creates a glyph range from a pointer, without checking its validity or enforcing its
126    /// lifetime. The memory the pointer points to must be valid for as long as the font is
127    /// in use.
128    ///
129    /// # Safety
130    ///
131    /// It is up to the caller to guarantee the pointer is not null, remains valid forever, and
132    /// points to valid data.
133    pub unsafe fn from_ptr(ptr: *const u16) -> FontGlyphRanges {
134        FontGlyphRanges(FontGlyphRangeData::Custom(ptr))
135    }
136
137    pub(crate) unsafe fn to_ptr(&self, atlas: *mut sys::ImFontAtlas) -> *const sys::ImWchar {
138        match self.0 {
139            FontGlyphRangeData::ChineseFull => sys::ImFontAtlas_GetGlyphRangesChineseFull(atlas),
140            FontGlyphRangeData::ChineseSimplifiedCommon => {
141                sys::ImFontAtlas_GetGlyphRangesChineseSimplifiedCommon(atlas)
142            }
143            FontGlyphRangeData::Cyrillic => sys::ImFontAtlas_GetGlyphRangesCyrillic(atlas),
144            FontGlyphRangeData::Default => sys::ImFontAtlas_GetGlyphRangesDefault(atlas),
145            FontGlyphRangeData::Japanese => sys::ImFontAtlas_GetGlyphRangesJapanese(atlas),
146            FontGlyphRangeData::Korean => sys::ImFontAtlas_GetGlyphRangesKorean(atlas),
147            FontGlyphRangeData::Thai => sys::ImFontAtlas_GetGlyphRangesThai(atlas),
148            FontGlyphRangeData::Vietnamese => sys::ImFontAtlas_GetGlyphRangesVietnamese(atlas),
149            FontGlyphRangeData::Custom(ptr) => ptr,
150        }
151    }
152}