I need a way to find the exact size and position of a glyph relative to its bounding box.
We're using D3.js to create an SVG with a heading, a smaller byline and a short body text. Pretty much this:
Lorem ipsum
Lorem ipsum dolor
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor
incididunt ut labore et dolore
magna aliqua
As in this example, I need the text to be left-aligned regardless of font-size.
The problem is that it is each lines bounding box that's aligned and not the glyphs. Which makes the headings look indented. How can I calculate that space between the bounding box and the glyph so I can correctly align the text?
A colleague sat down and manually measured this for the English font, which works pretty well. We could probably do this in Adobe Illustrator, but we need the information for English, Chinese and Arabic fonts. To do this by hand is more or less impossible.
The only solution I can come up with is to type each character in a canvas element and map each pixel to see where the glyph starts and ends.
What I think would be ideal is a way to use the SVG font path information to find the extremes, that way we would get the exact numbers instead of estimates. Our estimates have a big margin of error. Is there a way to do that with node.js?
An example of what the SVG looks like:
<svg viewBox="0,0,1008,1424" height="1052px" width="744px" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg">
<g transform="translate(50,150)" class="container">
<g transform="translate(0,205)" class="textContainer">
<g fill="white" font-family="serif" font-size="" class="header">
<text>
<tspan y="147.7104222717285" style="" font-size="208"
x="-21.8359375">Lorem ipsum</tspan>
</text>
<text>
<tspan y="201.46275431823733" style="" font-size="45"
x="-4.72412109375">Lorem ipsum dolor</tspan>
</text>
</g>
<g lengthAdjust="spacingAndGlyphs" textLength="297" fill="white"
transform="translate(0,214)" font-family="sans-serif"
class="paragraph" font-size="14">
<text y="16.8" x="0">Lorem ipsum dolor sit amet,</text>
<text y="33.6" x="0">consectetur adipisicing elit,</text>
<text y="50.4" x="0">sed do eiusmod tempor</text>
<text y="67.2" x="0">incididunt ut labore et dolore</text>
<text y="84" x="0">magna aliqua</text>
</g>
</g>
</g>
</svg>
It is the x
and y
values on the text
and tspan
elements we need to calculate, the negative x
values in particular. Note: we don't actually use the serif
or sans-serif
font families, we use a custom font. I don't think the English font is created with web use in mind. We used fontsquirrel.com to create the SVG font file.
SVG fonts seemed like the most logical option, since you have all the path information in the file readable in node. You'd just have to interpret it. But we found, and decided to go with, opentype.js which works with otf and ttf fonts.
I'd still like to know if this is at all possible to do with SVG fonts.
A font is often measured in pt (points). Points dictate the height of the lettering. There are approximately 72 (72.272) points in one inch or 2.54 cm. For example, the font size 72 would be about one inch tall, and 36 would be about a half of an inch.
1. In the Character Viewer, click a Category, and scroll to find the glyph you want, then follow the procedure I outlined above. Examine each of the glyphs displayed in the Font Variation section, and pick the font that includes the glyph display you like.
1 pixel (px) is usually assumed to be 1/96th of an inch. 1 point (pt) is assumed to be 1/72nd of an inch. Therefore 16px = 12pt.
In digital type, the Em is simply an imaginary space, subdivided into a grid for design purposes. The division is usually 1000 or 2048 units, referred to as Units Per eM (UPM) size.
I think this may do what you want. Note that it requires jQuery and is a bit hacky. You may want to set line-height in the css object.
function glyphSize(glyph,css){
var span = $('<div>');
span.text(glyph);
span.css({
display:'inline-block',
position:'fixed',
top:'100%'
}).css(css);
$('body').append(span);
var out = {
width:span.width(),
height:span.height()
}
span.remove();
return out;
}
var size = glyphSize('a',{
'font-family':'fantasy, sans-serif' // css to apply to the test element
});
/* size = {
width:7,
height:20
} */
edit: quick demo here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With