Silverlight:字形宽度

时间:2011-03-10 19:08:01

标签: c# .net silverlight windows-phone-7

方案

我想在WP7上使用Glyphs来创建一条对齐的文本行,即触及周围矩形的左右边框。

我的解决方案

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 个答案:

答案 0 :(得分:2)

这可能归结为浮点精度问题。

一般来说,每个浮点算术运算都会引入一个至少等于机器精度的误差(即,当加到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 :(得分:1)

layout rounding怎么办?

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。宽度

double spaceAdvance = ((availableSize.Width - glyphs.ActualWidth) / 
             spaceCount + spaceWidth) / glyphs.FontRenderingEmSize * 100.0;

答案 2 :(得分:1)

替代提案:您可以使用支持“justify”的RichTextBox控件。