2009-04-29 15 views
11

Es una posibilidad remota, pero ¿alguien sabe de un algoritmo para estimar y categorizar el ancho del texto (para una fuente de ancho variable) en función de su contenido?Algoritmo para estimar el ancho del texto en función del contenido

Por ejemplo, me gustaría saber que iiiiiiii no es tan amplia como abcdefgh , que a su vez no es tan amplia como WWWWWWWW, a pesar de que las tres cadenas son ocho caracteres de longitud.

Esto es en realidad un intento de construir algunas inteligencias en un método de truncamiento de cadena, que en este momento está truncando correctamente una cadena visualmente ancha, pero también trunca innecesariamente una cadena visualmente estrecha, porque ambas cadenas contienen el mismo número de caracteres . Probablemente sea suficiente para que el algoritmo clasifique la cadena de entrada como estrecho, normal o ancho y luego trunque según corresponda.

Esta pregunta no es realmente específica del idioma, pero si hay un algoritmo, entonces lo implementaré en Java. Esto es para una aplicación web. Soy consciente de que hay respuestas en SO que tratan este problema usando JavaScript para obtener el ancho de un elemento que contiene div, pero me pregunté si es posible una solución del lado del servidor.

Respuesta

15

La mayoría de los marcos de GUI proporcionan una forma de calcular las métricas de texto para fuentes en dispositivos de salida dados.

Usando java.awt.FontMetrics, por ejemplo, creo que usted puede hacer esto:

import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 

public int measureText(Graphics g, String text) { 
    g.setFont(new Font("TimesRoman", Font.PLAIN, 12)); 
    FontMetrics metrics = g.getFontMetrics(); 

    return metrics.stringWidth(text); 
} 

No se ha probado, pero se entiende la idea.


Bajo .Net puede utilizar el método Graphics.MeasureString. En C#:

private void MeasureStringMin(PaintEventArgs e) 
{ 

    // Set up string. 
    string measureString = "Measure String"; 
    Font stringFont = new Font("Arial", 16); 

    // Measure string. 
    SizeF stringSize = new SizeF(); 
    stringSize = e.Graphics.MeasureString(measureString, stringFont); 

    // Draw rectangle representing size of string. 
    e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height); 

    // Draw string to screen. 
    e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0)); 
} 
+2

Maaaybe, pero en este caso tiene la cuestión de qué contexto gráfico que elija en su servidor ... –

+0

He aceptado esta respuesta ya que en realidad trató de abordar mi pregunta fue formulada, a pesar de que la pregunta era algo ridícula y, evidentemente, ¡no era algo que pudieras intentar de verdad! –

+0

Graphics2D g = new BufferedImage (100, 100, BufferedImage.TYPE_INT_ARGB) .createGraphics(); – jlarson

1

Creo que debe elegir una de estas soluciones:

  • solución exacta: Suma el ancho para cada carácter de la cadena (la mayoría de las API le dará esta información)
  • Estimación rápida: tome el ancho máximo o mínimo y multiplíquelo con los números de los caracteres.

Por supuesto, es posible hacer algunas estimaciones mixtas, pero creo que esto es demasiado esfuerzo en la dirección incorrecta.

1

Esto es en realidad un intento de construir algunos inteligencia en un método de cadena truncamiento [...]

¿Es realmente vale la pena el esfuerzo? Tuvimos este problema exacto. Y esto fue en todos los idiomas. La solución fue dejarlo tal como está. La complejidad de mantener esta inteligencia aumenta rápidamente (y probablemente exponencialmente) con cada idioma que agregue soporte. De ahí nuestra decisión.

[...] un algoritmo para estimar y categorizar el ancho del texto (para una fuente de ancho variable) en función de su contenido?

La mayoría de las bibliotecas de fuentes le proporcionarán esta información. Pero esto es algo de bajo nivel. La idea básica es pasar una cuerda y recuperar el ancho en puntos.

+0

No, realmente no vale la pena el esfuerzo por el problema que tengo que resolver, ¡pero ha despertado mi curiosidad intelectual! –

+0

Hm. FWIW, he actualizado mi respuesta con mi experiencia personal. – dirkgently

1

Para una buena * solución del lado del cliente, puede probar un enfoque híbrido de CSS y Javascript como lo sugiere RichieHindle's answer to my question.

Dado que no sabe en qué fuente verá la página el usuario (siempre pueden anular su selección, Ctrl + la página, etc.), el lugar "correcto" para hacerlo está en el navegador. .. aunque los navegadores no lo hacen fácil!

* cuando digo "agradable", quiero decir "probablemente sea bueno pero no lo he intentado todavía".

+0

Creo que el lenguaje aquí es Java ... –

2

Para una aplicación web, no se puede (realmente) obtener una estimación correcta. Las diferentes fuentes tienen anchuras diferentes, de modo que esto no solo depende del cliente (navegador) y sus ajustes de zoom y DPI, sino también de las fuentes presentes en esa máquina (y sistema operativo) o sus sustituciones.

Si necesita una medición exacta, cree un gráfico (mapa de bits, SVG o incluso algún PDF o lo que sea) que se distribuirá y representará en el servidor y no en el cliente.

2

No hay una solución confiable del lado del servidor para calcular el ancho del texto. (fuera de crear una imagen del texto y probablemente SVG)

Si prueba una herramienta como browser-shots y la ejecuta contra páginas relativamente básicas, verá inmediatamente por qué. Es difícil predecir qué tan ancho resultará incluso los ejemplos más triviales, y mucho menos si un usuario decide hacer zoom en el navegador, etc.

No se especifica con precisión si desea truncar la cadena (podría ser útil dando soluciones potenciales), pero uno común es porque quiere cortar el texto en algún punto y proporcionar una elipse.

This can be done reliably on many browser platforms by using a css property, and NO javascript:

http://www.jide.fr/emulate-text-overflowellipsis-in-firefox-with-css

2

que realmente no tienen manera de saber qué navegador, la configuración de fuente, tamaño de pantalla, etc el cliente está utilizando. (OK, a veces las cabeceras de petición proporcionan una indicación, pero realmente no es nada consistente o confiable.)

Por lo tanto, lo haría:

  • pantalla un texto de muestra en Internet Explorer con la configuración predeterminada en un tamaño de pantalla/ventana de 1024x768 (este es generalmente el tamaño más común)
  • tome una media de caracteres/línea con esta configuración y utilícela para su estimación.

Generalmente he encontrado esto "lo suficientemente bueno", por ejemplo, para estimar el número de líneas que un texto ocupará en un navegador, para estimar cuántos anuncios mostrar junto al texto.

Si realmente fue realmente crucial para usted, entonces puedo imaginarme un esquema complicado mediante el cual inicialmente envía un mensaje de texto al cliente, que luego toma una medida y lo envía de vuelta a su servidor, y luego usa esta información para futuras páginas para ese cliente. Sin embargo, no puedo imaginar que valga la pena el esfuerzo.

+0

En lugar de tener Javascript en el lado del cliente informar el ancho del texto, no sería más fácil abrir un cuadro de mensaje pidiéndole al usuario que magnifique el texto 8x en Paint, imprimirlo y enviarlo por correo a una dirección determinada? :-P –

+1

Si lo hace, le sugiero que serialice el contexto gráfico en el momento de la impresión y luego lo envíe al servidor, ahorrando así en el tráfico vital del correo electrónico. No quiero sobrecargar al hermano mayor del Reino Unido. base de datos con correos electrónicos innecesarios! –

+0

¡Definitivamente! :) –

5

Esto funcionó para mí:

AffineTransform af = new AffineTransform();  
FontRenderContext fr = new FontRenderContext(af,true,true);  
Font f = new Font("Arial", 0, 10); // use exact font 
double width= f.getStringBounds("my string", fr).getWidth();  
+0

¡Estaba buscando en Google durante 2 días para algo como esto, gracias! – Natalia

Cuestiones relacionadas