Ответ 1
Альтернативное предложение: вы можете использовать элемент управления RichTextBox, который поддерживает "оправдывать".
Я хочу использовать Glyphs
в WP7 для создания строки текста, которая будет оправдана, т.е. касается левой и правой границы окружающего прямоугольника.
var glyphs = new Glyphs();
glyphs.FontUri = new Uri("/MyAssembly;component/MyPath/MyFont.ttf", UriKind.Relative);
glyphs.FontRenderingEmSize = 20;
glyphs.Fill = new SolidColorBrush(Colors.Red);
// measue width of space
glyphs.UnicodeString = " ";
glyphs.Measure(availableSize);
double spaceWidth = glyphs.DesiredSize.Width;
glyphs.InvalidateMeasure();
// setup justified text
string text = "Lorem Ipsum is dummy text of the printing and typesetting industry.";
int spaceCount = 10; // number of spaces in above text
glyphs.UnicodeString = text;
glyphs.Measure(availableSize); // now DesiredSize.Width = width of left aligned text
// I suspect my error to be in this formula:
double spaceAdvance = ((availableSize.Width - glyphs.DesiredSize.Width)
/ spaceCount + spaceWidth) / glyphs.FontRenderingEmSize * 100;
string spaceAdvanceString = String.Format(",{0};", spaceAdvance);
var indices = new StringBuilder();
foreach (char c in text)
{
if (c == ' ') indices.Append(spaceAdvanceString);
else indices.Append(';');
}
glyphs.Indices = indices.ToString();
Правая сторона глифов не совсем касается прикосновения к availableSize.Width
-Border, но имеет несколько пикселей, и это выглядит при использовании нескольких строк текста, уложенных вверх.
Что не так с моими расчетами?
Альтернативное предложение: вы можете использовать элемент управления RichTextBox, который поддерживает "оправдывать".
Это может быть связано с проблемами с точностью с плавающей запятой.
Вообще говоря, каждая арифметическая операция с плавающей запятой вводит ошибку, по меньшей мере равную точности машины (т.е. наименьшее число, которое при добавлении к 1.0 приводит к результату с плавающей запятой, отличному от 1.0). Эта ошибка известна как ошибка округления. Ошибки округления являются кумулятивными и иногда зависят от порядка операций.
Вместо
double spaceAdvance = ((availableSize.Width - glyphs.DesiredSize.Width)
/ spaceCount + spaceWidth) / glyphs.FontRenderingEmSize * 100;
попробуйте переместить умножение на фронт, т.е.
double spaceAdvance = 100.0 * ((availableSize.Width - glyphs.DesiredSize.Width)
/ spaceCount + spaceWidth) / glyphs.FontRenderingEmSize;
В качестве альтернативы вы также можете попробовать
double spaceAdvance = (100.0 * (availableSize.Width - glyphs.DesiredSize.Width)
/ spaceCount + 100.0 * spaceWidth) / glyphs.FontRenderingEmSize;
Как насчет округление макета?
var glyphs = new Glyphs();
glyphs.FontUri = new Uri("/MyAssembly;component/MyPath/MyFont.ttf", UriKind.Relative);
glyphs.FontRenderingEmSize = 20;
glyphs.Fill = new SolidColorBrush(Colors.Red);
glyphs.UseLayoutRounding = false;
Кроме того, вы можете поэкспериментировать с ActualWidth вместо DesiredSize.width
double spaceAdvance = ((availableSize.Width - glyphs.ActualWidth) /
spaceCount + spaceWidth) / glyphs.FontRenderingEmSize * 100.0;