Friday 6 November 2009

Xps and Silverlight

I’ve recently been asked to investigate displaying an Xps file using Silverlight.

What I initially found was this sample posted by Koen Zwikstra.  It turns out that the format of the Xps file is pretty similar to the Xaml use by Silverlight.  What this sample does is replace or remove the items in the Xps file which Silverlight doesn’t understand.

The main item which needs translating is the Glyphs element, because of the way that Xps uses obfuscated fonts.  For the Glyph element to use an obfuscated font in Silverlight it must be a resource of the Silverlight application.  The problem with this is unless you have a predetermined set of Xps file to show you have no idea which fonts you need to embed as resources.

To get around this Koen converts the Glyphs to TextBlock to allow the use of the FontSource class which must use a stream which contains the unobfuscated font. 

There was a small problem with the way Koen’s example deobfuscated the font which might have been because I’m using Silverlight 3 and the example was written for Silverlight 2.  What I had to do was replace code in the ObfuscatedFontStream constructor.

   1: public ObfuscatedFontStream(Stream source, string fontFileName)



   2: {



   3:     if (source == null) {



   4:         throw new ArgumentNullException("source");



   5:     }



   6:     if (fontFileName == null) {



   7:         throw new ArgumentNullException("fontFileName");



   8:     }



   9:     this.source = source;



  10:  



  11:     string name = Path.GetFileNameWithoutExtension(fontFileName);



  12:     Guid guid;



  13:     try {



  14:         guid = new Guid(name);



  15:     }



  16:     catch (Exception e) {



  17:         throw new ArgumentException(string.Format("File name {0} does not contain a valid GUID", fontFileName), e);



  18:     }



  19:  



  20:     byte[] guidBytes = new byte[16];



  21:     for (int i = 0; i < guidBytes.Length; i++)



  22:     {



  23:         guidBytes[i] = Convert.ToByte(guid.ToString("N").Substring(i * 2, 2), 16);



  24:     }



  25:  



  26:     long position = source.Position;



  27:  



  28:     if (source.CanSeek)



  29:     {



  30:         source.Seek(0, SeekOrigin.Begin);



  31:     }



  32:  



  33:     this.header = new byte[32];



  34:     source.Read(this.header, 0, 32);



  35:     byte[] key = guid.ToByteArray();



  36:  



  37:     for (int i = 0; i < 32; i++) {



  38:         int gi = guidBytes.Length - (i % guidBytes.Length) - 1;



  39:         header[i] ^= guidBytes[gi];



  40:     }



  41:     // reset stream position



  42:     if (source.CanSeek)



  43:     {



  44:         source.Seek(position, SeekOrigin.Begin);



  45:     }



  46: }




There was still one problem with the sample and that was that it was not able to display Xps files generated from the Xps printer driver.  For some reason the normal method of getting the resouces out of the Xps file using Application.GetResourceStream doesn’t work.



I found that I could use SilverlightContribs Zip methods to open the Xps file.  What I did was change Koen’s Load method in XpsReader to use ZipFile if Application.GetResourceStream fails.





   1: private StreamResourceInfo Load(Uri uri)



   2:         {



   3:             StreamResourceInfo streamResourceInfo = Application.GetResourceStream(_xps, uri);



   4:             if (streamResourceInfo == null)



   5:             {



   6:                 // Zipfile closes the underlying stream when it is disposed, which we don't really want.



   7:                 // so we copy the original stream and let ZipFile close that.



   8:                 Stream zipStream = CopyStream(_xps.Stream);



   9:                 using (var zipFile = new ZipFile(zipStream))



  10:                 {



  11:                     if (zipFile.FindEntry(uri.ToString(), true) > 0)



  12:                     {



  13:                         ZipEntry entry = zipFile.GetEntry(uri.ToString());



  14:                         Stream stream = zipFile.GetInputStream(entry.ZipFileIndex);



  15:                         MemoryStream depressed = CopyStream(stream);



  16:                         streamResourceInfo = new StreamResourceInfo(depressed, string.Empty);



  17:                     }



  18:                 }



  19:             }



  20:             return streamResourceInfo;



  21:         }



  22:  



  23:         private MemoryStream CopyStream(Stream stream)



  24:         {



  25:             var ms = new MemoryStream();



  26:             if (stream.CanSeek)



  27:             {



  28:                 stream.Seek(0, SeekOrigin.Begin);



  29:             }



  30:             var buffer = new byte[32768];



  31:             int read;



  32:             do



  33:             {



  34:                 read = stream.Read(buffer, 0, buffer.Length);



  35:                 if (read > 0)



  36:                 {



  37:                     ms.Write(buffer, 0, read);



  38:                 }



  39:             } while (read > 0);



  40:             ms.Seek(0, SeekOrigin.Begin);



  41:             return ms;



  42:         }






I found that I had to return an uncompressed stream due to the implementation of the InflaterInputStream not working with the rest of the sample.



Technorati Tags: ,,

Saturday 24 October 2009

Resharper 5

Yesterday I installed the EAP build of Resharper 5.  Once of the cool features I’ve found is that it adds support for the Microsoft Source Server to VS2005.

If you navigate to a type that is in MS code it will go off and download the reference source.

image

Then you get taken to that type in the reference code.

image

Technorati Tags: ,

Saturday 17 October 2009

Playing with Asp.Net MVC Preview 2

Having played with xVal with MVC 1 I was interested to see the built in client side validation added to the MVC2.

After a little bit of searching and playing around I got the page set up.

 

   1: <script type="text/javascript" src="../../Scripts/jquery-1.3.2.js"></script>
   1:  
   2: <script type="text/javascript" src="../../Scripts/jquery.validate.js">
   1: </script>
   2: <script type="text/javascript" src="../../Scripts/MicrosoftMvcJQueryValidation.js">
</script>



   2:  



   3:     <h2><%
   1: = Html.Encode(ViewData["Message"]) 
%></h2>



   4:     <p>



   5:         To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.



   6:         <%
   1: = Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") 
%>



   7:         <%
   1:  
   2:             Html.ClientValidationEnabled = true; 
%>



   8:         <%
   1: using (Html.BeginForm())
   2:           {
%>



   9:           <%
   1: =Html.EditorForModel() 
%>



  10:            <input type="submit" value="Save" />



  11:         <%
   1: } 
%>



  12:     </p>






Using this simple class as the model.





   1: using System.ComponentModel.DataAnnotations;



   2:  



   3: namespace MvcApplication6.Models



   4: {



   5:     public class Address



   6:     {



   7:         [Required(ErrorMessage = "The House Number or Name field is required")]



   8:         public string HouseNumberName { get; set; }



   9:         [Required]



  10:         public string Street { get; set; }



  11:  



  12:         [Required]



  13:         public string City { get; set; }



  14:  



  15:         [Required]



  16:         public string PostCode { get; set; }



  17:     }



  18: }





Gave me this result.



Validation



I’m not sure about having the <%  Html.ClientValidationEnabled = true; %> line, it doesn’t feel right.  I’m also not sure about the usefulness of Html.EditorForModel() I need to poke around a bit more and see if there is some way of changing the captions.



Apart from that it seems pretty simple.  I would like to see if it can be hooked up to nHibernate validation.



Technorati Tags:

Friday 28 August 2009

Does Windows Live Writer work

Test message to see if Live Writer will post to blogger with out crashing.

Technorati Tags:

Wednesday 17 June 2009

Oracle client to be deprecated in .Net 4

From the ADO.NET team blog Oracle client to be deprecated in .Net 4.

I must say I can understand why. When I was doing Oracle I usually used the Oracle Data Provider for .Net (ODP.NET). It was more up to date and supported more of Oracles advance features.

Hopefully this will give Oracle a bit of a kick to get them to release new versions of ODP.NET when new versions of .Net are released, instead of 6 months after a new release has come out.

Sunday 31 May 2009

IE6 not showing background images

I just wasted an afternoon with this bug.  In my case if the div was the first on the page the background images didn't show.  If you inserted another div with the same styles the first div would be messed up, but the second would be fine.  Below is the fix.

Here is the link to the problem and solution http://www.webcredible.co.uk/user-friendly-resources/css/internet-explorer.shtml. It is number 3 on the list.

Technorati Tags: ,