Алгоритм оценки ширины текста на основе содержимого

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

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

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

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

Ответ 1

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

Используя 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. В С#:

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

Это можно сделать надежно на многих платформах браузера с помощью свойства css и НЕТ javascript:

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

Ответ 5

У вас действительно нет способа узнать, какой браузер, настройки шрифта, размер экрана и т.д. клиент использует. (ОК, иногда заголовки запросов содержат указание, но на самом деле ничего не последовательное или надежное.)

Итак, я бы:

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

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

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

Ответ 6

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

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

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

Ответ 7

На самом деле это попытка построить некоторые умные методы в методе усечения строк [...]

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

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

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

Ответ 8

Для хорошего * клиентского решения вы можете попробовать гибридный подход CSS-и-Javas, предложенный RichieHindle, ответ на мой вопрос.

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

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