Skip to content

[BUG] pango::shape_full does not work when passing paragraph_text #1680

@LeoSchae

Description

@LeoSchae

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions