diff --git a/imgui/src/fonts/atlas.rs b/imgui/src/fonts/atlas.rs index 7f49fd5..537e4d1 100644 --- a/imgui/src/fonts/atlas.rs +++ b/imgui/src/fonts/atlas.rs @@ -357,7 +357,8 @@ impl FontConfig { raw.GlyphMaxAdvanceX = self.glyph_max_advance_x; raw.FontBuilderFlags = self.font_builder_flags; raw.RasterizerMultiply = self.rasterizer_multiply; - raw.EllipsisChar = self.ellipsis_char.map(|x| x as u16).unwrap_or(0xffff); + // char is used as "unset" for EllipsisChar + raw.EllipsisChar = self.ellipsis_char.map(|c| c as u32).unwrap_or(!0); if let Some(name) = self.name.as_ref() { let bytes = name.as_bytes(); let mut len = bytes.len().min(raw.Name.len() - 1); diff --git a/imgui/src/fonts/font.rs b/imgui/src/fonts/font.rs index e401b5b..fcb3317 100644 --- a/imgui/src/fonts/font.rs +++ b/imgui/src/fonts/font.rs @@ -24,7 +24,7 @@ pub struct Font { pub ascent: f32, pub descent: f32, pub metrics_total_surface: c_int, - pub used_4k_pages_map: [u8; 2], + pub used_4k_pages_map: [u8; 34], } unsafe impl RawCast for Font {} diff --git a/imgui/src/fonts/glyph_ranges.rs b/imgui/src/fonts/glyph_ranges.rs index dcadeb0..b22ae50 100644 --- a/imgui/src/fonts/glyph_ranges.rs +++ b/imgui/src/fonts/glyph_ranges.rs @@ -13,7 +13,7 @@ enum FontGlyphRangeData { Custom(*const sys::ImWchar), } -/// A set of 16-bit Unicode codepoints +/// A set of Unicode codepoints #[derive(Clone, Eq, PartialEq, Debug)] pub struct FontGlyphRanges(FontGlyphRangeData); impl FontGlyphRanges { @@ -51,7 +51,7 @@ impl FontGlyphRanges { } /// 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 + /// non-zero codepoints, each representing an inclusive range, 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 @@ -61,7 +61,12 @@ impl FontGlyphRanges { /// ====== /// /// This function will panic if the given slice is not a valid font range. - pub fn from_slice(slice: &'static [u16]) -> FontGlyphRanges { + // TODO(thom): This takes `u32` for now, since I believe it's fine for it to + // contain surrogates? (It seems plausible that font data can describe what + // to show for unpaired surrogates) Would be nice to be sure, if so, this + // should accept `char` (we'd still have to check that the range doesn't + // fully contain the surrogate range though) + pub fn from_slice(slice: &'static [u32]) -> FontGlyphRanges { assert_eq!( slice.len() % 2, 1, @@ -79,7 +84,14 @@ impl FontGlyphRanges { "A glyph in a range cannot be zero. \ (Glyph is zero at index {})", i - ) + ); + assert!( + glyph <= core::char::MAX as u32, + "A glyph in a range cannot exceed the maximum codepoint. \ + (Glyph is {:#x} at index {})", + glyph, + i, + ); } let mut ranges = Vec::new(); @@ -118,7 +130,7 @@ impl FontGlyphRanges { /// # Safety /// /// It is up to the caller to guarantee the slice contents are valid. - pub unsafe fn from_slice_unchecked(slice: &'static [u16]) -> FontGlyphRanges { + pub unsafe fn from_slice_unchecked(slice: &'static [u32]) -> FontGlyphRanges { FontGlyphRanges::from_ptr(slice.as_ptr()) } @@ -130,7 +142,7 @@ impl FontGlyphRanges { /// /// 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 { + pub unsafe fn from_ptr(ptr: *const u32) -> FontGlyphRanges { FontGlyphRanges(FontGlyphRangeData::Custom(ptr)) } diff --git a/imgui/src/io.rs b/imgui/src/io.rs index 440984d..8bc6238 100644 --- a/imgui/src/io.rs +++ b/imgui/src/io.rs @@ -334,9 +334,25 @@ impl Io { } /// Peek character input buffer, return a copy of entire buffer pub fn peek_input_characters(&self) -> String { - let c16_slice = self.input_queue_characters.as_slice(); - String::from_utf16(c16_slice).unwrap() + self.input_queue_characters().collect() } + + /// Returns a view of the data in the input queue (without copying it). + /// + /// The returned iterator is a simple mapping over a slice more or less what + /// you need for random access to the data (Rust has no + /// `RandomAccessIterator`, or we'd use that). + pub fn input_queue_characters( + &self, + ) -> impl Iterator + DoubleEndedIterator + ExactSizeIterator + Clone + '_ { + self.input_queue_characters + .as_slice() + .iter() + // TODO: are the values in the buffer guaranteed to be valid unicode + // scalar values? if so we can just expose this as a `&[char]`... + .map(|c| core::char::from_u32(*c).unwrap_or(core::char::REPLACEMENT_CHARACTER)) + } + pub fn update_delta_time(&mut self, delta: Duration) { let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0; if delta_s > 0.0 {