Calcular el tamaño exacto de un glifo de fuente

Necesito una forma de encontrar el tamaño exacto y la posición de un glifo en relación con su cuadro delimitador.

Estamos utilizando D3.js para crear un SVG con un encabezado, un byline más pequeño y un texto de cuerpo corto. Bastante esto:

Lorem ipsum

Lorem ipsum dolor

Lorem ipsum dolor sit amet,
Consectetur adipisicing elit,
sed do eiusmod tempor
incididunt ut labore et dolore
magna aliqua

Como en este ejemplo, necesito que el texto esté alineado a la izquierda independientemente del tamaño de la fuente.

El problema es que se alinean cada cuadro de delimitación de líneas y no los glifos. Lo que hace que los encabezados se vean con sangría. ¿Cómo puedo calcular ese espacio entre el cuadro delimitador y el glifo para poder alinear correctamente el texto?

Un colega se sentó y midió esto manualmente para la fuente en inglés, que funciona bastante bien. Probablemente podríamos hacer esto en Adobe Illustrator, pero necesitamos la información para las fonts en inglés, chino y árabe. Hacer esto a mano es más o menos imposible.

La única solución que se me ocurre es escribir cada carácter en un elemento del canvas y asignar cada píxel para ver dónde comienza y termina el glifo.

Lo que creo que sería ideal es una forma de utilizar la información de la ruta de la fuente SVG para encontrar los extremos, de esa manera obtendríamos los números exactos en lugar de estimaciones. Nuestras estimaciones tienen un gran margen de error. ¿Hay una manera de hacer eso con node.js?

Un ejemplo de cómo se ve el SVG:

     Lorem ipsum   Lorem ipsum dolor    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua     

Son los valores x e y en el text y los elementos tspan que necesitamos calcular, los valores negativos x en particular. Nota: en realidad no usamos las familias de fonts serif o sans-serif , usamos una fuente personalizada. No creo que la fuente en inglés se cree teniendo en cuenta el uso de la web. Usamos fontsquirrel.com para crear el archivo de fuente SVG.

Actualizar

Las fonts SVG parecían ser la opción más lógica, ya que tiene toda la información de ruta en el archivo legible en el nodo. Solo tendrías que interpretarlo. Pero encontramos y decidimos ir con opentype.js que funciona con las fonts otf y ttf.

Todavía me gustaría saber si es posible hacer esto con las fonts SVG.

Creo que esto puede hacer lo que quieras. Tenga en cuenta que requiere jQuery y es un poco hacky. Es posible que desee establecer la altura de línea en el objeto css.

 function glyphSize(glyph,css){ var span = $('
'); 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 } */

edición: demostración rápida aquí

Vi tu pregunta y tuve el problema yo mismo. Lo resolví muy simple en mi opinión. Acabo de crear un nuevo elemento de texto con opacidad 0.0. Lo agrego al svg, obtengo el bbox y lo elimino. La bbox contiene el ancho y alto:

 getBBox : function(svgId, text, styleClass) { // Add tmp text element to the SVG var tempSvgTextElement = d3.select("#" + svgId) .append("text") .style("opacity", 0.0) .attr("class", styleClass); var tSpanTextNode = document.createTextNode(text); var svgTSpan = tempSvgTextElement.append("tspan").attr("class", styleClass).node(); svgTSpan.appendChild(tSpanTextNode); var bbox = tempSvgTextElement.node().getBBox(); tempSvgTextElement.remove(); return bbox; }