Posterous theme by Cory Watilo

Filed under: silverlight4

Silverlight 4 font woes

This may or may not be a specific RichTextBox problem so I'm going to treat it like it is not.

The situation is that I'm displaying a document with text that can specify any font that it desires.  Of course, you cannot display text in a font that isn't installed.  Silverlight 4 does not give any kind of font list by font name.

Wait! Fonts.SystemFontFaces will give you a list of all fonts installed on the local system.  It will give you a list of font FILE NAMES.  Not a list of actual font names.  There does not seem to be anyway to translate a font file name to a font name.  So that's a big fat dead end.

Supposedly, Silverlight should just fall back on the system default which is "Portable User Interface" which is a best effort on Silverlight's part to display text.  That ought to be fine for me when I'm trying to display a font that isn't installed.

However, that isn't what happens for the RichTextBox.  What does happen is that the RichTextBox decides to have a CATASTROPHIC FAILURE in it's MeasureOverride method when trying to size up the box.  What seemingly happens is that the fallback mechanism just doesn't work.  I've specified a font that doesn't exist and Silverlight blows up.  Actually, it loops the exception for a while then throws up an unhandled crash box thing.  If I try to manually handle the error and give a reasonable size back, then it's an infinite loop :)

The solution is to manually specify a fallback font when I'm setting the FontFamily through code:

new FontFamily(formatting.FontName + ", " + TextFormatting.DefaultFontName);

DefaultFontName currently spits out "Arial" which is no good for non-latin languages.  So I'll have to solve that later.  I had hoped I could simply put "Portable User Interface" to be the default but that doesn't work at all.

If anyone knows of anything better, please comment.

 

Adventures in Silverlight 4 hit-testing.

Problem:

I have misspelled words in a RichTextBox contained a DataGrid.  I want to be able to right click on it and get the suggestions.  

I use TransformToVisual on the ContextMenu with 0,0 to transform to the RichTextBox's relative points.  I then iterate over the characters in the proper Run in the RichTextBox using GetCharacterRect and testing of the point from the ContextMenu's point 0,0 is contained within the Rect of the character.

This all works at 100% Browser ZoomFactor.  

Now, I'm not sure if it's a RichTextBox problem (I've reported a major BiDi bug to Microsoft) since it's new or it has something to do with the DataGrid but as soon as you change the Browser's Zoom, the system is out of wack.

By doing TransformToVisual(null).Transform(new Point()) in different levels of zoom, I saw that the ContextMenu was right but the RichTextBox is wrong.  Also, the GetCharacterRect results were following the RichTextBox, which it should.  Turns out, the difference is in the zoom factor.

Solution:

I decided to go absolute: use TransformToVisual(null) for both the ContextMenu and the RichTextBox.  I get my desired point from the ContextMenu via TransformToVisual(null).Transform(new Point()).  Then I get the Transform for the RichTextBox with TransformToVisual(null).  This is a bad transform because it doesn't take the zoom factor into account.  I just need to change it.

 

TransformGroup transform = new TransformGroup();

transform.Children.Add(this.TransformToVisual(null) as Transform);

transform.Children.Add(new ScaleTransform()

{

ScaleX = 1D / Application.Current.Host.Content.ZoomFactor,

        ScaleY = 1D / Application.Current.Host.Content.ZoomFactor,

});

 

Now my transform is useful.  But I have to apply it to the Rects returned from TextPointer.GetCharacterRect then those Rects are correct to see if my ContextMenu's point is in them.

I did a test project to see if the RichTextBox is at fault and it doesn't appear to be.  Maybe it's the DataGrid?  Maybe I'll see another day.

Silverlight 4 WCF Server-side Exceptions are harder to deal with than they should be.

All I want is a nice stacktrace from the server to the client.  Is that so hard to ask?  Apparently, it is.

Honestly, I don't care what soap or security requires.  I don't think I've gotten an explanation as to why it was hard in Silverlight 2/3.  

Read these and let your eyes glaze over at the hacks:

http://msdn.microsoft.com/en-us/library/dd470096(VS.95).aspx

http://msmvps.com/blogs/theproblemsolver/archive/2009/01/27/returning-exception-information-to-a-silverlight-client-through-wcf.aspx

http://forums.silverlight.net/forums/p/12698/45061.aspx

http://forums.silverlight.net/forums/p/147717/328978.aspx

Fortunately, Silverlight 4 makes it "easy" by switching the client-side http stack.  Which is buried on an updated version of the first link above: http://msdn.microsoft.com/en-us/library/ee844556(VS.95).aspx

Of course, there can be some gotchas by using a http stack that isn't in the browser.  For me, I'm not sure what they are.  Seemingly, the only thing is that you cannot access cookies.  However this solves my problem.

http://msdn.microsoft.com/en-us/library/system.net.browser.webrequestcreator.clienthttp(VS.95).aspx

http://msdn.microsoft.com/en-us/library/system.net.browser.webrequestcreator.browserhttp(VS.95).aspx

Now, all I have to do is includeExceptionDetailInFaults="true" on the serverDebug element and I'm in the business of catching FaultException<ExceptionDetail> objects.

This does all feel a bit sloppy, but then again, so does the "correct" way.

ComicTool 0.4.3 and NUnrar 0.7.2

Pulling double duty here.  Needed a change to NUnrar for ComicTool.

ComicTool 0.4.3

-Lots of changes trying to make things more responsive for large files. Largest I tested was 200mb.
-Did some refactoring to make the code cleaner. Probably being anal.
-UI will freeze a bit more during page/thumbnail loads but overall loading is much faster.

Try it

 

NUnrar 0.7.2

Added fix for old-style multi-part file naming.
Added Open overloads for RarArchive and RarReader to not close the stream that is passed to it. (By default, it does close).