Visual Studio 11 CSS3 Parser
Was spelunking in the folders of my Visual Studio 11 installation a couple of weeks ago and found Microsoft.CSS.Core.dll (located in C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\Web\CSS3).
I was intrigued and needed to look deeper and what I found was a CSS parser that you can use from your application e.g. I needed a CSS unpacker (that turns a minimized CSS file into a readable format). With the built in formatter I was able to do this:
static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("cssunpack [input] [output]"); Environment.Exit(-1); } var parser = new CssParser(); var css = parser.Parse(File.ReadAllText(args[0]), insertComments: false); var formatter = new CssFormatter(); File.WriteAllText(args[1], formatter.Format(css)); }
So if we do some small tweaks to the CssFormatterOptions we can build a minimizer as well:
static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("csspack [input] [output]"); Environment.Exit(-1); } var parser = new CssParser(); var css = parser.Parse(File.ReadAllText(args[0]), insertComments: false); var formatter = new CssFormatter { Options = new CssFormattingOptions { IndentType = IndentType.Spaces, IndentSize = 0, SpacesPerTab = 0, InitialIndentString = string.Empty, QuoteType = QuoteType.Double, BlockBracePosition = BracePosition.Compact, SortProperties = false, CompactBlocks = false, CompactBlockThreshold = 0, RemoveEscapes = true, ConvertColorsToHex = true, CompressColors = true, ElementSelectorCasing = Casing.Lowercase, PropertyNameCasing = Casing.Lowercase, RemoveLastSemicolon = true, IndentRuleHierarchy = false, ForStyleBlock = true } }; File.WriteAllText(args[1], formatter.Format(css).Replace(Environment.NewLine, "")); }
There is a lot of more features so take a look for yourself.
I don’t know about the license but it’s probably ok to use on your local dev machine if you have VS11 installed.
WPF 4.0 Text stack improvements
So in the latest beta of .NET 4.0 we got some nice improvements to the WPF text stack, this is short intro what those improvements was, and how I create a small Visual Studio 2010 extensions to make use of these improvements to save my eyesight.
Text formatting
The attached property TextOptions.TextFormattingMode has been added to make it possible to switch text formatting metrics. You now have two matrices to choose from:
- Ideal This is the default format used by WPF, It always tries to maintain high glyphs shape fidelity, ignoring final glyphs relative placement to each other.
- Display This is the GDI compatibility text metrics, this formatter ensures that every glyph has a width of multiple whole pixels and is positioned on whole pixels.
Text rendering
The attached property TextOptions.TextRenderingMode has been added to control the antialiasing algorithm used by WPF for text rendering, these are the four options available:
- Auto This is the same as ClearType (if ClearType is enabled)
- Aliased No antialiasing is used
- Grayscale Antialiasing using grey pixels in the proper position such that is appears less jagged.
- ClearType Microsofts Subpixel antialiasing, each pixel is made up of sub-pixels consisting of 3 components (generally RGB).
You have the option to set theses properties either direct in the XAML or in your code.
Bellow is short XAML example using the TextFormattingMode.Display together with the TextRenderingMode.Aliased, TextRenderingMode.Grayscale andTextRenderingMode.ClearType.
<Window x:Class="TextRenderingAPI.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="91" Width="294"> <Grid> <StackPanel TextOptions.TextFormattingMode="Display"> <TextBlock> [ABCDEFGHIJKLMNOPQRSTUVWZ] - ClearType </TextBlock> <TextBlock TextOptions.TextRenderingMode="Grayscale"> [ABCDEFGHIJKLMNOPQRSTUVWZ] - Grayscale </TextBlock> <TextBlock TextOptions.TextRenderingMode="Aliased"> [ABCDEFGHIJKLMNOPQRSTUVWZ] - Aliased </TextBlock> </StackPanel> </Grid> </Window>
The rendered result using my programming font as FontFamily is:The rendered result using my programming font as FontFamily is:
Visual Studio 2010
does not expose any of the TextFormattingMode or TextRenderingMode settings from the Options dialog. So the programming font I like looks like the ClearType example in the image above, staring at that blur all day long is starting to give me a headache.
But all hope is not lost, because VS 2010 comes with many new extensibility points we as developers can hook into and with not that much research I found IWpfTextView. The msdn documentation describes the interface in this way:
Represents a view of text in an ITextBuffer. It is the base class for a platform-specific interface that has methods to allow the formatted text to be rendered.
So we will hook into the rendering of the TextView and set our preferred values for TextFormattingMode and TextRenderingMode.
To create a new VS2010 Integration Package (VSIX) you will need to have the VS2010 SDK installad, then follow these steps to setup the project:
- Create a new project of type Visual Studio Integration Package.
- Build your project.
- Add your dll file as an MEF Component to the source.extension.vsixmanifest
We have now prepared the VSIX to export a MEF Component, we can now create the MEF extension.
The extension we want to export is IWpfTextViewCreationListener. This extention gets every new IWpfTextView created in VS, but we also have to create an event handler for that TextView so that every LayoutChange event can be updated with our own TextFormattingMode and TextRenderingMode. If we don’t update on every LayoutChange event the editor will return to ClearType. We also have to listen on the Closed event, so all event handlers can be closed and the IWpfTextView can be collected by the GC.
This is the code I use to get aliased text rendering, with GDI text formatting:
[Export(typeof(IWpfTextViewCreationListener))] [TextViewRole(PredefinedTextViewRoles.Document)] [ContentType("text")] public class WpfTextViewCreationListener : IWpfTextViewCreationListener { public void TextViewCreated(IWpfTextView textView) { new WpfTextViewEventHandler(textView); } private class WpfTextViewEventHandler { private IWpfTextView _textView; public WpfTextViewEventHandler(IWpfTextView textView) { _textView = textView; _textView.LayoutChanged += LayoutChanged; _textView.Closed += Closed; } private void LayoutChanged(object s, TextViewLayoutChangedEventArgs e) { TextOptions.SetTextFormattingMode(_textView.VisualElement, TextFormattingMode.Display); TextOptions.SetTextRenderingMode(_textView.VisualElement, TextRenderingMode.Aliased); } private void Closed(object sender, EventArgs e) { _textView.LayoutChanged -= LayoutChanged; _textView.Closed -= Closed; } } }
This is my before and after shot from Visual Studio:
Before:
After:
If you are a font fanatic like me I recommend trying some different settings to see what looks best with your favorite font. For the final build of Visual Studio 2010 I hope that that these settings will be available in the options dialog .
