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