Silverlight: ширина символов - PullRequest
       2

Silverlight: ширина символов

29 голосов
/ 10 марта 2011

Сценарий

Я хочу использовать 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, но находится на расстоянии нескольких пикселей, и это выглядит усталым, когда есть несколько строк текстасложены.

Что не так с моими вычислениями?

Ответы [ 3 ]

2 голосов
/ 16 июня 2011

Это может быть связано с проблемами с точностью с плавающей запятой.

Вообще говоря, каждая арифметическая операция с плавающей запятой вносит в результат ошибку, по крайней мере, равную точности станка (то есть наименьшему числу, которое при добавлении к 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;
1 голос
/ 26 апреля 2012

Альтернативное предложение: вы можете использовать элемент управления RichTextBox, который поддерживает «justify».

1 голос
/ 21 июня 2011

А как насчет округления макета ?

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...