2009-04-29 4 views
11

Это длинный снимок, но знает ли кто-нибудь об алгоритме оценки и категоризации ширины текста (для шрифта ширины переменной) на основе его содержимого?Алгоритм оценки ширины текста на основе содержимого

Например, я хотел бы знать, что iiiiiiii не так широко, как ABCDEFGH, который, в свою очередь, не так широко, как WWWWWWWW, хотя все три строки являются восемь символов в длину.

Это на самом деле попытка построить несколько умнов в методе усечения строк, который на данный момент правильно обрезает визуально широкую строку, но также излишне усекает узкую визуально узкую строку, поскольку обе строки содержат одинаковое количество символов , Вероятно, достаточно, чтобы алгоритм классифицировал входную строку как узкий, нормальный или широкий, а затем усекался при необходимости.

Этот вопрос не является специфичным для языка, но если есть алгоритм, я реализую его на Java. Это для веб-приложения. Я знаю, что есть ответы на SO, которые справляются с этой проблемой с помощью JavaScript, чтобы получить ширину содержащего элемент div, но я задавался вопросом, возможно ли решение на стороне сервера.

ответ

15

Большинство графических интерфейсов обеспечивают некоторый способ вычисления текстовых показателей для шрифтов на данных устройствах вывода.

Использование java.awt.FontMetrics, например, я считаю, что вы можете сделать это:

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); 
} 

Не тестировался, но вы получите идею.


Под .Net вы можете использовать метод Graphics.MeasureString. В 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, но в этом случае у вас есть вопрос о том, что графический контекст вы выбираете на сервере ... –

+0

Я принял этот ответ, потому что на самом деле пытались решить мой вопрос, как задал вопрос, хотя вопрос был довольно смешным и явно не то, что вы пытаетесь сделать по-настоящему! –

+0

Graphics2D g = новый BufferedImage (100, 100, BufferedImage.TYPE_INT_ARGB) .createGraphics(); – jlarson

1

Я думаю, вы должны выбрать один из следующих решений:

  • Точного решения: Сложите ширину для каждого символа в строке (большинство API, даст вам эту информацию)
  • Быстрая оценка: возьмите максимальную или минимальную ширину и умножьте ее на количество символов.

Конечно, возможны смешанные оценки, но я думаю, что это слишком много усилий в неправильном направлении.

1

Это фактически попытка построить несколько СМАРТС в метод строку усечения [...]

Является ли это действительно стоит усилий? У нас была эта точная проблема. И это было на разных языках. Исправить было оставить его как есть. Сложность сохранения этого интеллекта быстро возрастает (и, вероятно, экспоненциально) с каждым языком, на который вы добавляете поддержку. Отсюда наше решение.

[...] алгоритм для оценки и категоризации ширины текста (для шрифта ширины переменной) на основе его содержимого?

Большинство библиотек-библиотек предоставят вам эту информацию. Но это довольно низкоуровневый материал. Основная идея состоит в том, чтобы передать строку и вернуть ширину в точках.

+0

Нет, это не стоит усилий для проблемы, которую я должен решить, но это вызвало мое интеллектуальное любопытство! –

+0

Hm. FWIW, я обновил свой ответ своим личным опытом. – dirkgently

1

Для приятного * клиентского решения вы можете попробовать гибридный подход CSS-and-Javascript, предложенный RichieHindle's answer to my question.

Учитывая, что вы не знаете, какой шрифт пользователь увидит на странице (они всегда могут переопределить ваш выбор, Ctrl- + страницу и т. Д.), «Правильное» место для этого в браузере. .. хотя браузеры не упрощают!

* Когда я говорю «хорошо», я имею в виду «возможно, хорошо, но я еще не пробовал».

+0

Я верю, что язык здесь Java ... –

2

Для веб-приложения вы не можете (действительно) получить правильную оценку. Различные шрифты имеют разную ширину, так что это зависит не только от клиента (браузера), его настроек масштабирования и DPI, но также от шрифтов, присутствующих на этом компьютере (и операционной системе) или их замен.

Если вам нужно точное измерение, создайте графический (растровый, SVG или даже какой-либо PDF или любой другой), который будет размещаться и отображаться на сервере, а не на клиенте.

2

Нет надежного решения на стороне сервера для расчета ширины текста. (за пределами создания изображения текста и, вероятно, SVG)

Если вы попробуете инструмент как browser-shots и запустите его относительно относительно простых страниц, вы сразу увидите, почему. Трудно предсказать, насколько широкие даже самые мирские примеры получатся, а тем более, если пользователь решит увеличить масштаб браузера и т. Д.

Не указано, что вы, возможно, захотите усечь строку (это может быть полезно в предоставлении потенциальных решений), но общий - потому, что вы хотите в какой-то момент отрезать текст и предоставить эллипс.

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

Вы действительно не имеют никакого способа знать, какой браузер, настройки шрифта, размера экрана и т.д. клиент использует. (OK, иногда заголовки запроса обеспечивает индикацию, но на самом деле ничего не соответствуют или надежно.)

Итак, я бы:

  • дисплея некоторого образец текст в Internet Explorer с параметрами по умолчанию на экране/размере окна 1024x768 (обычно это самый распространенный размер)
  • возьмите средний символ/строку с этой конфигурацией и используйте это для своей оценки.

Я обычно нашел это «достаточно хорошим», например, для оценки количества строк, которые некоторые тексты будут обрабатывать в браузере, чтобы оценить, сколько рекламных объявлений будет показано рядом с текстом.

Если бы это было действительно очень важно для вас, то я могу представить сложную схему, по которой вы сначала отправляете клиенту Javascript, который затем берет измерение и отправляет его обратно на ваш сервер, и затем вы используете эту информацию для будущие страницы для этого клиента. Я не могу себе представить, что это обычно стоит усилий.

+0

Вместо того, чтобы на Javascript на стороне клиента отсылать назад ширину текста, не было бы проще всплывать окно с просьбой увеличить текст 8x в Paint, распечатать его и отправить его по указанному адресу? :-P –

+1

Если вы это сделаете, я бы на самом деле предложил сериализовать графический контекст во время печати, а затем отправить его на сервер, тем самым сохранив жизненно важный почтовый трафик - не хотите перегружать старшего брата Великобритании базы данных с ненужными электронными письмами! –

+0

Определенно! :) –

5

Это работает для меня:

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

Я искал в Интернете 2 дня для чего-то подобного, спасибо! – Natalia

Смежные вопросы