-
-
Notifications
You must be signed in to change notification settings - Fork 131
Description
Bug description
The wrapper pango::shape_full
around pango::ffi::pango_shape_full
seems to incorrectly pass the text and paragraph_text. The function pango::shape_with_flags
seems to have the same problem.
When use_safe
is set to true in the below code example, the image will not contain any text and the log contains:
(process:215897): Pango-CRITICAL **: 17:28:02.640: pango_shape_internal: assertion 'paragraph_text + paragraph_length >= item_text + item_length' failed
Calling pango::ffi::pango_shape_full directly (i.e. setting use_safe
to false) and passing the texts and lengths as pointers fixes the problem.
Code Example (using pango, cairo and pangocairo):
fn test() {
let s = cairo::ImageSurface::create(Format::ARgb32, 100, 100).unwrap();
let c = cairo::Context::new(&s).unwrap();
let pc = create_context(&c);
let mut fd = pango::FontDescription::new();
fd.set_size(13 * pango::SCALE);
pc.set_font_description(Some(&fd));
let text = "Hallo!";
let glyphs = pango::itemize(&pc, text, 0, text.len() as i32, &AttrList::new(), None);
let glyphs = glyphs.into_iter().map(|i| {
let mut glyphs = pango::GlyphString::new();
let item_text = &text[i.offset() as usize..(i.offset() + i.length()) as usize];
let use_safe = true;
if use_safe {
// This branch does not produce the correct image
pango::shape_full(item_text, Some(text), &i.analysis(), &mut glyphs);
} else {
// This works as expected
unsafe {
pango::ffi::pango_shape_full(
std::mem::transmute(item_text.as_ptr()),
item_text.len() as i32,
std::mem::transmute(text.as_ptr()),
text.len() as i32,
i.analysis().as_ptr(),
glyphs.as_ptr()
);
}
}
(i, glyphs)
});
for (i, mut glyphs) in glyphs {
let font = i.analysis().font();
c.move_to(10.0, 75.0);
pangocairo::functions::show_glyph_string(&c, &font, &mut glyphs);
}
// save to png
let mut file = File::create("test.png").unwrap();
s.write_to_png(&mut file).unwrap();
}
Remarks
The wrapper passes item_text.to_glib_none().0
as the pointer. Running
let item_text = "test";
let p0: usize = std::mem::transmute(item_text.as_ptr());
let c: *const c_char = item_text.to_glib_none().0;
let p1: usize = std::mem::transmute(c);
assert_eq!(p0, p1);
panics with message:
assertion `left == right` failed
left: 93825029359978
right: 93825038488816
It seems to me, that item_text.to_glib_none().0 does not point to the original memory location of the text.