How to align text vertically without making it shake

Hi, I’m trying to create a simple text alignment program using ofTrueTypeFont.

I found out ofTrueTypeFont draws string based on its bottom left corner as a default.

So I tried to change it’s vertical alignment base(Top/Middle/Bottom) with a key press.

Here’s the test code below.

I used Sansation font for the testing. Sansation.ttf.zip (14.2 KB)

in ofApp.h

ofTrueTypeFont font;
string text;

enum ALIGN_MODE {
    
    ALIGN_TO_BOTTOM,
    ALIGN_TO_MIDDLE,
    ALIGN_TO_TOP
};
ALIGN_MODE alignMode;

in ofApp.cpp

//--------------------------------------------------------------
void ofApp::setup(){
 
    font.load("Sansation.ttf", 50);
    alignMode = ALIGN_TO_BOTTOM;
}

//--------------------------------------------------------------
void ofApp::update(){

    //set text with a randomly changing value
    text = "Value : " + ofToString(ofRandom(100));
}

//--------------------------------------------------------------
void ofApp::draw(){

    ofTranslate(100, 100);
    ofSetColor(ofColor::red);
 
    float stringHeight = font.stringHeight(text);
    
    switch (alignMode) {
            
        case ALIGN_TO_BOTTOM:
            font.drawString(text, 0, 0); //doesn't shake
            break;
        case ALIGN_TO_MIDDLE:
            font.drawString(text, 0, stringHeight/2); //shakes
            break;
        case ALIGN_TO_TOP:
            font.drawString(text, 0, stringHeight); //shakes badly
            break;
        default:
            break;
    }
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

    switch (key) {
        case '1':
            alignMode = ALIGN_TO_BOTTOM;
            break;
        case '2':
            alignMode = ALIGN_TO_MIDDLE;
            break;
        case '3':
            alignMode = ALIGN_TO_TOP;
            break;
        default:
            break;
    }
}

If you run the program, it will look like the screenshot below.

And If you change the alignment by pressing key ‘2’ or ‘3’, you will see the text shaking up and down badly.

I think it is due to ofTrueTypeFont::stringHeight() returning different values depending on the string.

Would it be possible to align the text vertically without making it shake up and down depending on the string?

Thank you very much in advance!

you can use font.getLineHeight()which will give you the total line height including the separation with a possible previous line. or you can use getAscenderHeightwhich will give you the maximum height of any character from the baseline

1 Like

Thanks @arturo

I decide to select a reference letter “I” to get the stringHeight instead of getting the actual text’s height.

float stringHeight = font.stringHeight(“I”);

And it no longer shakes and still aligns nicely.

If you are going to do that, then the x is usually the reference for the height for glyphs without ascender or descender.

2 Likes

You mean the small ‘x’ right? Thank you so much @arturo :slight_smile:

yes

1 Like

I think for alignment purpose, the letter ‘x’ as the reference isn’t correct.

This is when I aligned to top using ‘x’ as the reference.
font.drawString(text, 0, font.stringHeight("x"));

And this is when I aligned to top using ‘I’ (capital i) as the reference.
font.drawString(text, 0, font.stringHeight("I"));

i see, what i meant is that the x is the standard height for letters without ascender or descender:

https://www.fonts.com/content/learning/fontology/level-1/type-anatomy/x-height

so you can use half that to align to the middle

then with getAscenderHeight you know the maximum height of any glyph so that’s better to align to the top for any possible character

1 Like