#algorithm #graphics #text #2d #surface
#алгоритм #графика #текст #2d #Поверхность
Вопрос:
Я ищу стабильный алгоритм для рисования возможно длинного текста по горизонтали и вертикали с центром на 2D поверхности. Это не зависит от языка, поэтому, если вы можете предоставить примеры на любом языке, это было бы очень полезно.
Следующая информация, которую я имею о тексте, который я хочу нарисовать, и поверхности:
Текстовая информация:
- размер текста в пикселях (высота строки), конечно, намного меньше высоты поверхности
- начертание (может быть любым)
- простой набор символов от ASCII32 до ASCII126
- текст может быть относительно длинным, слова разделяются пробелами
- текст должен «автоматически» разбиваться на пробелы, как только он больше не будет вписываться в ширину поверхности
- текст на английском языке.
Информация о поверхности:
- ширина и высота
- координаты x и y в глобальной системе координат (при условии, что начало координат находится в левом верхнем углу экрана)
Я реализовал свой собственный подход, но он был очень нестабильным: текст растекался по поверхности, выравнивание было неправильным, иногда вообще не центрировался. Также поискал в Google несколько хороших подходов, хотя не смог найти что-то полезное. Я надеюсь, что сообщество stackoverflow сможет мне помочь. Большое вам спасибо.
Комментарии:
1. Можете ли вы опубликовать свой подход? Было бы полезно посмотреть, что отбросить.
Ответ №1:
Подход прост по концепции, немного сложен в исполнении. Это включает в себя всего несколько шагов:
Split the text into lines that will fit horizontally
Compute the vertical position of the first line
for each line
Compute its width and the X position
Display it at the Y position
Add the line height to the current Y position
Сложная часть — это первый шаг. Остальное просто.
Если у вас шрифт фиксированной ширины, то разбить текст на строки не так уж сложно. Вы просто вычисляете, сколько символов поместится в заданной ширине, индексируете строку в эту позицию, а затем возвращаетесь к предыдущему разрыву слова. Переместите подстроку из начала предыдущей строки (или начало строки для первой строки) в эту позицию, и это ваша строка. Повторяйте, пока не дойдете до конца строки.
Со шрифтом переменной ширины все немного сложнее, потому что вы не можете просто индексировать строку по n * character_width
символам. Вместо этого вам нужно угадывать, проверять, уточнять предположение и т. Д. У каждой графической подсистемы, с которой я работал, был какой-то MeasureString
метод, который сообщал мне, сколько пикселей потребуется для отображения строки с учетом определенного шрифта. Учитывая это, то, что я делал в прошлом, это:
Divide the surface width by the font's average character width
Index that far into the string, and find the next (or previous) word break.
Measure the string
If the result is wider than the width, go back one word and measure again.
If the result is narrower than the width, go forward one word and measure again.
Repeat the measure/adjust until you find the string that will fit.
Как только вы нашли подходящую подстроку, переместите начальный индекс вперед к началу следующей строки и делайте это снова, пока не дойдете до конца строки.
Вертикальное центрирование группы линий:
starting_position.Y = (Surface_height - (num_lines * line_height)) / 2
Горизонтальное центрирование линии выполняется легко:
starting_position.X = (Surface_width - Measured_string_width) / 2
Вы должны вычислить starting_position.X
для каждой строки. Координата Y увеличивается на line_height
для каждой последующей строки.
Ответ №2:
Итак, вам нужно следовать нескольким правилам
- центрируйте каждую строку текста
- если длина строки> ширина страницы, начните новую строку
- центрировать весь текст по вертикали
Таким образом, вы маркируете свой ввод пробелами. Вам понадобится набор строк и currentIndex. В то время как строки [currentIndex] токен.длина <Ширина страницы, вы можете добавить маркер в строки [currentIndex]. Как только условие не выполняется, вы увеличиваете currentIndex и продолжаете.
После завершения ввода вы центрируете каждую строку по горизонтали. Вы должны вычислить ширину каждой строки в пикселях. Затем вы выполняете x = Ширина страницы / 2 — Ширина строки / 2.
Затем выполните те же вычисления для высоты вашего текстового блока, но с учетом всех строк (возможно, используйте ограничивающий прямоугольник вокруг текста). Затем вы можете получить значение y с помощью той же формулы y = Высота страницы / 2 — Высота текста / 2
Ответ №3:
Это индивидуальный подход. Это будет работать, если длина текста составляет 30 символов или меньше, а первое слово перед пробелом не длиннее 15 символов. Однако эти характеристики можно очень легко изменить. Текст будет сохранен в массиве с 2 размерами, и он будет сохранен в 2 строках, если одна строка недостаточно велика. После сохранения текста с центром в 2-мерном массиве его просто нарисовать. Я надеюсь, что это будет полезно.
char[][] t = new char[2][15];
public void putTextInMatrix(String text) {
int len = text.length();
int start;
if(len<=15) {
start = (15-len)/2;
for (int i=0, j=0; i<15; i )
if(i<start || i>=len start)
t[0][i] = ' ';
else {
t[0][i] = text.charAt(j);
j ;
}
}
else {
int last = len;
for (int i=0; i<15; i ) {
if (text.charAt(i) == ' ')
last = i;
}
start = (15-last)/2;
for (int i=0, j=0; i<15; i )
if(i<start || i>=last start)
t[0][i] = ' ';
else {
t[0][i] = text.charAt(j);
j ;
}
start = (15-(len-last))/2;
for (int i=0, j=last 1; i<15; i )
if(i<start || j>=len)
t[1][i] = ' ';
else {
t[1][i] = text.charAt(j);
j ;
}
}
}