Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Silverlight: Glyphs Width

Scenario

I want to use Glyphs on WP7 to create a line of text that is justified, i.e. touches the left and right border of the surrounding rectangle.

My solution

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

Problem and Question

The right side of the glyphs is not exactly touching the availableSize.Width-Border but is some pixels off, and that looks weired when there are several lines of text stacked up.

What is wrong with my calculation?

like image 560
Tilo Avatar asked Mar 10 '11 19:03

Tilo


2 Answers

This could be down to problems with floating point accuracy.

Generally speaking, every floating-point arithmetic operation introduces an error at least equal to the machine accuracy (i.e. the smallest number that, when added to 1.0, produces a floating-point result that is different from 1.0) into the result. This error is known as roundoff error. Roundoff errors are cumulative and sometimes dependent on the order of operations.

Instead of

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

try moving the multiplication to the front, i.e.

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

Alternatively, you could also try

double spaceAdvance = (100.0 * (availableSize.Width - glyphs.DesiredSize.Width)          / spaceCount + 100.0 * spaceWidth) / glyphs.FontRenderingEmSize; 
like image 131
Chris Bednarski Avatar answered Oct 22 '22 07:10

Chris Bednarski


Alternative proposal: You can use the RichTextBox control which supports "justify".

like image 23
Jasper Avatar answered Oct 22 '22 07:10

Jasper