Created
September 25, 2025 12:10
-
-
Save davepagurek/29d3f7a9f93fe9d722792bb9a6da0393 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const verticalAlign = (font, fontSize) => { | |
| const { | |
| font: { | |
| // the height of the tallest character above the baseline | |
| ascender, | |
| // the most negative height below the baseline that any character dips | |
| // down to (think of characters like j) | |
| descender, | |
| unitsPerEm, | |
| tables: { | |
| os2: { sCapHeight }, | |
| }, | |
| }, | |
| } = font | |
| let averageCharacterDescent | |
| let averageCharacterAscent | |
| if (sCapHeight) { | |
| // Some fonts might contain `sCapHeight`, which is a hand-picked estimate | |
| // of the average capital letter's height above the baseline (estimate | |
| // because this is not an exact average or anything, the font designer | |
| // picked it.) | |
| // | |
| // We'll approximate that most letters do not go below the baseline at all. | |
| averageCharacterAscent = sCapHeight | |
| averageCharacterDescent = 0 | |
| } else { | |
| // If the font designer didn't provide us with an average, we can try to | |
| // approximate it differently by just using the ascender. Probably the | |
| // average character isn't quite as tall as the ascender, which is the max, | |
| // but it's good enough to handle the edge case where we aren't given a | |
| // better estimage from the font. | |
| // | |
| // Since we know the ascender will be an overestimate, we'll pretend that | |
| // the average character also dips as far down as the lowest character, | |
| // which is an overestimate in the opposite direction. Hopefully those | |
| // cancel each other out. | |
| averageCharacterAscent = ascender | |
| averageCharacterDescent = descender | |
| } | |
| const averageCharacterHeight = | |
| averageCharacterAscent + averageCharacterDescent | |
| // When vertically centering text at a y value, p5 makes the y value be | |
| // halfway through the ascender. | |
| const defaultOffset = ascender / 2 | |
| // When we have a different estimate of average height, we want to be halfway | |
| // through that instead | |
| const targetOffset = averageCharacterHeight / 2 | |
| const offsetDifference = targetOffset - defaultOffset | |
| // Convert internal font metric units to size on screen | |
| const scale = fontSize / unitsPerEm | |
| return scale * offsetDifference | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment