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

Support for Paragraphs/Word Wrapping #2

Open
cetra3 opened this issue Jul 21, 2017 · 7 comments
Open

Support for Paragraphs/Word Wrapping #2

cetra3 opened this issue Jul 21, 2017 · 7 comments

Comments

@cetra3
Copy link

cetra3 commented Jul 21, 2017

So I'm wondering if there is a way to either support word wrapping when writing text so newlines are automatically inserted, or provide some metrics around glyph sizes so it can be handled externally.

The idea is to be able to support a paragraph of text which wraps when the width is full.

Supporting centered and right aligned text is an obvious extension of this, but is harder to do.

@fschutt
Copy link
Owner

fschutt commented Jul 21, 2017

I'll see if I can do a simple \n replacer tomorrow, it is annoying to do manual line breaks.

I was working on a scale-bar generator and noticed that centering text is really cumbersome right now. Currently you still need to import freetype-rs into your project and calculate the position manually. PDF only starts the text at the lower left corner, everything else is up to you.

Something like this (for centered text):

/// Calculates the lower left of a centered string, to position it correctly in the document
/// 
/// Parameters:
/// 
/// - text: The actual text that will be embedded in the document
/// - font_scale: The current scale of the font
/// - parent_width: the width of the element in which relation the text should be centered
/// - font_face: The font-face of the text
/// 
pub fn calc_lower_left_for_centered_text(text: &String, font_scale: i64, parent_width: f64, font_face: &freetype::Face)
-> f64
{
    let s_w = calc_text_width_pt(text, font_scale, font_face);
    ((mm_to_pt!(parent_width) / 2.0) - (s_w / 2.0)) * 0.352778
}


pub fn calc_text_width_pt(text: &String, font_scale: i64, font_face: &freetype::Face)
-> f64
{
    // vertical scale for the space character
    let vert_scale = {
        if let Ok(ch) = font_face.load_char(0x0020, ft::face::NO_SCALE) {
            font_face.glyph().metrics().vertAdvance
        } else {
            1000
        }
    };

    // calculate the width of the text in unscaled units
    let sum_width = text.chars().fold(0, |acc, ch| 
        if let Ok(ch) = font_face.load_char(ch as usize, ft::face::NO_SCALE) {
            let glyph_w = font_face.glyph().metrics().horiAdvance;
            acc + glyph_w
        } else { acc }
    );

    sum_width as f64 / (vert_scale as f64 / font_scale as f64)
}

The calc_lower_left_for_centered_text would then calculate the horizontal position of the lower left corner where the text should be drawn.

Right-aligned text is done the same way, essentially. Once you have the space of the text that will fill one line, it's simple to do alignment. Block text is more difficult, because there you have to distribute spaces sort-of evenly. I'll see what I can do.

@cetra3
Copy link
Author

cetra3 commented Jul 21, 2017

I was thinking maybe as a "wrapper" function(s), like with use_text but instead it has max width and alignment as argument params.

@cetra3
Copy link
Author

cetra3 commented Jul 21, 2017

Lemme see if I can do a PR for you

@TKGgunter
Copy link

Hello,
the example you gave above was great. However is there a way to do this with the builtin fonts.
And more to the point a calc_text width might be a useful function for users. Then users can do alignments or whatever themselves.

@fschutt
Copy link
Owner

fschutt commented Apr 12, 2018

@TKGgunter yeah, I haven't worked on this ... mostly because I don't use builtin fonts. It isn't possible to calculate the width and height from builtin fonts, because you'd need the .ttf or .otf file to do that - which, for builtin fonts, doesn't exist. I'd also really like to do layout in a seperate library, not in printpdf - this library should only contain what the PDF spec says and contain the "primitives" for building a PDF. Anything fancy, like tables, page breaks, etc. should be done in a seperate library.

@visualcode-t
Copy link

Is it still not possible to calculate the width of a built-in font?

@fschutt
Copy link
Owner

fschutt commented Nov 27, 2020

No, how would that be possible? Built-in fonts can even vary from PDF viewer to PDF viewer.

You'd need the Helvetica.ttf files to do that, but I can't include them into the library because those fonts are copyrighted.

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

4 participants