Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate the exact size of a font glyph

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.

Update

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.

like image 790
pstenstrm Avatar asked Jun 20 '14 10:06

pstenstrm


People also ask

How do you calculate font size?

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.

How do you find the font that has the glyph you need?

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.

How do you measure font size in pixels?

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.

What is UPM size?

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.


1 Answers

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

like image 156
kyledavide Avatar answered Sep 19 '22 14:09

kyledavide