Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify caching behavior #84

Closed
chinedufn opened this issue Feb 13, 2020 · 2 comments
Closed

Clarify caching behavior #84

chinedufn opened this issue Feb 13, 2020 · 2 comments

Comments

@chinedufn
Copy link
Contributor

chinedufn commented Feb 13, 2020

Alright so I might be looking in the wrong places - but here's what I'm observing.

The Problem

The process_queued method documentation includes the following:

Processes all queued sections, calling texture update logic when necessary

However - I ran process_queued on a text section containing the text Hello World and saw some of the same glyphs repeated.

Screenshot Example

image

Note the repeated o and l

The Question

Is it expected behavior for the texture updater to cache the same glyph multiple times? I might have expected a character to be cached once and then re-used.

If I'm understanding correctly the texture is being used to cache the entire section as documented in the process_queued method.

Is there a downside to caching the section's glyph rectangles in memory while only caching each character on the texture only once?

The advantage being that a smaller texture could fit more glyphs.

Thanks and cheers!!


Source Code

Some source code illustrating how I generated the image above.

// This derefs to my GlyphBrush
let mut text_font_res = TextFontResource::new_with_test_font();

text_font_res.resize_texture(512, 512);

let mut font_cache = image::DynamicImage::new_luma8(512, 512);

let text = OwnedSectionText {
    text: "Hello World".to_string(),
    scale: Scale::uniform(30.),
    color: [1., 1., 1., 1.],
    font_id: FontId(0),
};

let section = OwnedVariedSection {
    screen_position: (0., 0.),
    layout: Layout::default_single_line().h_align(HorizontalAlign::Left),
    text: vec![text],
    ..OwnedVariedSection::default()
};

text_font_res.queue(&section);

let brush_action = text_font_res
    .process_queued(
        |rect, pixels| {
            let glyph_width = rect.width();
            let glyph_height = rect.height();
            let pixel_count = glyph_width * glyph_height;

            let mut glyph = DynamicImage::new_luma8(glyph_width, glyph_height);

            for (idx, pixel) in pixels.iter().enumerate() {
                let idx = idx as u32;

                let x = idx % glyph_width;
                let y = idx / glyph_width;
                glyph.put_pixel(x, y, image::Rgba([*pixel, 0, 0, 0]));
            }

            image::imageops::overlay(
                &mut font_cache,
                &glyph,
                rect.min.x as u32,
                rect.min.y as u32,
            );
        },
        |glyph_vertex| {
            TextFontResource::glyph_vertex_to_ui_quad(glyph_vertex, 512, 512, UILayer::Zero)
        },
    )
    .unwrap();

font_cache.save("/tmp/font-cache.png");
@alexheretic
Copy link
Owner

alexheretic commented Feb 13, 2020

The gpu cache/draw cache will indeed return multiple versions of the same glyph at different subpixel positions. You can adjust this by setting the position tolerance.

Right now this is required for high quality text as glyph positioning is always exactly as drawn. So if you have high position tolerance it means you only draw a single glyph (at a given scale) but it will potentially be drawn in the wrong subpixel position.

@chinedufn
Copy link
Contributor Author

Ah thanks! Added that to the docs here chinedufn@68ff932 in #83

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants