Custom Dictionaries
02 October 09 09:33 PM | text | 6 Comments   

Most current editors provide built in spell checking which validates user input. Spell checkers can be found in anything from word processors, to email clients, and even web browsers. Depending on the scenario, these spell checking utilities vary in complexity. Simple spell checkers compare the input against a default dictionary and then highlight mismatches. More complex spell checkers allow dynamic modification of the dictionary.

 

WPF includes a spell checker, but currently it only uses the OS provided dictionary for input validation. It lacks the functionality to allow the default dictionaries to be augmented with custom dictionaries provided by an application. This has been a major issue for apps which target specific industries with specialized lingo. Those apps are plagued by misspelling notifications.

 

A chat client is a classic example of an application that displays specialized words. In such an application, web slang such as lol, brb, or ttyl is frequently used. While these acronyms are not official words in English, in the context of a chat client these are not misspelled words.

 

This problem has been fixed in WPF 4.0. The ability to augment spelling support, via an application provided custom dictionary, has been added to the framework.

 

 

 

Custom Dictionaries API

The property CustomDictionaries has been added to the SpellCheck class.

·        CustomDictionaries - This is a read-only dependency property which is an IList of URIs. Each URI points to a custom dictionary to be used for spell checking.  If spell checking is disabled, SpellCheck.IsEnabled == false, no spell checking will occur, even if a custom dictionary is provided.

 

Custom Dictionary Format

Custom dictionaries are simple text files with single words on each line. Each line represents a legitimate word which should not be marked as misspelled.

 

The first line of this file can specify a language that the custom dictionary should correspond to (e.g. “#LID 1033” means that this custom dictionary applies to US English). If no language is set, the custom dictionary will apply to all default dictionaries.

·        #LID 1033 – English

·        #LID 3082 - Spanish

·        #LID 1031 - German

·        #LID 1036 - French

 

Comments are not supported inside the custom dictionary file.

 

 

<Window x:Class="CustomSpellerDictionaries.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:sys1="clr-namespace:System;assembly=system"

        Title="Custom Dictionaries Example">

    <Grid>

        <TextBox Text="Finallly, my name, Chipalo, is not marked as misspelled."

                 TextOptions.TextFormattingMode="Display">

            <SpellCheck.IsEnabled>true</SpellCheck.IsEnabled>

            <SpellCheck.CustomDictionaries>

                <sys1:Uri>D:\TEMP\dictionary.lex</sys1:Uri>

            </SpellCheck.CustomDictionaries>

        </TextBox>

    </Grid>

</Window>

 

Contents of D:\TEMP\dictionary.lex

Chipalo

 

CustomDictionaries

TextBlock created with the above XAML. Notice that spell checking is enabled but “Chipalo” is not marked as misspelled.

 

 

 

Custom Dictionaries Suggested Usage

 

Custom dictionaries should be used when an application wants a set of words, which are not found in the default dictionary for a language, to not be marked as misspelled. Specifying a langue for a custom dictionary will limit the use of the dictionary to only the denoted language. A custom dictionary which is not marked as language specific will be used for spell checking in all languages which spell checking is supported.

 

Spelling support in WPF is limited to four languages: English, Spanish, French, and German. Custom dictionaries are designed to augment the default dictionaries for these languages and not to extend spelling support to other languages. Creating a custom dictionary which contains common Russian words, marking the dictionary as a Russian dictionary, and adding it to the SpellCheck object of a TextBox or RichTextbox will not add Russian spelling support. If the first line of a custom dictionary denotes that the dictionary is used for a language which is not supported, that dictionary will be ignored. 

 - Chipalo

Filed under: ,
Bindable Run
01 September 09 11:01 PM | text | 2 Comments   

Since the initial release of WPF, Run.Text has been a normal CLR property. This has meant that Run.Text lacks all the benefits of the WPF dependency property system, most notably the ability to be bound. In some cases, one could substitute Runs for TextBlocks, which can be bound to; however this can quickly create text flow problems (see example below). The omission of a bindable Run has given birth to many homebrew solutions (eg. here and here). Feeble workarounds and custom solutions are no longer necessary. In WPF 4.0 we have done the work to back Run.Text with a dependency property.

 

 

Bindable Run API

The property Run.Text has been converted to a dependency property. Now Run.Text enjoys all of the benefits of full dependency properties (binding, styling, templating, etc…).

 

 

<Window x:Class="TextBlogDWriteDemo.Window1"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="Window1">

    <Window.Resources>

        <TextBox x:Key="DataStore1" Text="how text does not

                                          flow correctly"/>

        <TextBox x:Key="DataStore2" Text="This is an example

  of how text flows correctly when only

  using bound Runs"/>

    </Window.Resources>

        <FlowDocument>

            <Paragraph>

                <Run Text="This is an example of"/>

                <TextBlock Text="{Binding Source=

                   {StaticResource DataStore1},

                   Path=Text}"/>

                <Run Text="when using a combination of Runs

                           and TextBlock"/>

            </Paragraph>

            <Paragraph>

                <Run Text="{Binding Source={StaticResource

                           DataStore2}, Path=Text}"/>

            </Paragraph>

        </FlowDocument>

</Window>

BindableRun

This is a screenshot of the text produced by the above XAML. Notice the spacing issues which are fixed by binding to a Run as opposed to a TextBlock.

 

 

 

Bindable Run Usage

 

One way data binding is fully supported. A Run can be bound to a data source and the content of the Run will reflect the value of what it is bound to. The bound Run will receive and display any changes that occur in the data source.

 

Two way data binding is partially supported. If a bound Run is updated via calls to the WPF property system, the data source which the Run is bound to will reflect the changes to the Run. On the other hand, if a bound Run is updated via a RichTextBox or the text object model, the Run will lose its binding.

 

- Chipalo

Filed under:
Caret Brush
01 September 09 12:55 AM | text | 0 Comments   

WPF provides extensive customizability to app authors, allowing them to change the default look and feel of most controls. One exception to this has been the color of the caret in WPF TextBoxes and RichTextBoxes.  Since this functionality was not originally provided, the community has been forced to create complex workarounds. In WPF 4.0, control over the caret color has been exposed in an intuitive and simple to use manner.

 

 

Caret Brush API

The property CaretBrush is now available for use on TextBox, RichTextBox, and PasswordBox.

·         CaretBrush - The brush assigned to this property will be used to draw the caret.

 

<TextBox CaretBrush="Yellow" FontSize="12pt"/>

YellowKorean

 

 - Chipalo

Filed under: ,
Selection Brush
28 August 09 06:29 PM | text | 2 Comments   

The default visual appearance of most objects in WPF can be easily tweaked, if not swapped out for a completely different visual tree.  This provides developers far greater power over the visual look of an application than ever before. Facilitating the creation of highly customized apps has become a major adoption point for WPF. Despite WPF’s extensibility, the color of selection in text boxes and document viewers was originally baked into the framework. With the release of WPF 4.0, developers can now control the text selection color in their applications.

 

Selection Brush API

The properties SelectionBrush and SelectionOpacity are now available for use on TextBox, RichTextBox, FlowDocumentPageViewer, FlowDocumentScrollViewer, FlowDocumentReader and PasswordBox.

·         SelectionBrush - The brush assigned to this property will be used to draw the selection overlay for text.

·         SelectionOpacity -  The opacity for the selection overlay. Note that if this value is set to 1 and the brush being used does not have some transparency specified in the alpha channel, selected text will be obscured by the selection overlay. In general, you don’t worry about setting the SelectionOpacity. It defaults to a value of .6.

 

<TextBox SelectionBrush="Red" FontSize="12pt"/>

SimpleSelectionBrush

TextBox created with the above XAML. Notice that the red selection gets rendered as a pink due to the default value of SelectionOpacity. 

 

<TextBox SelectionBrush="Red" SelectionOpacity="1"  FontSize="12pt"/>

SelectionBrushFail

SelectionBrush FAIL. The text is obscured by the selection overlay because the SelectionBrush is not transparent and the SelectionOpacity has been set to 1.

 

Selection Brush Usage

We have added this feature to complement your creativity. SelectionBrush can be used whether you want to completely customize your application or just add a little flair to text selection. When using this feature, remember that SelectionOpacity effects the color of the selection drawn to the screen. If the rendered color of your selection is not the exact color of the SelectionBrush, it is probably due to the interaction of SelectionOpacity and SelectionBrush. If the selection is obscuring you text, remember to tweak SelectionOpacity or give SelectionBrush some transparency.

 

Below is a slightly more interesting application of SelectionBrush using a GradientBrush.

 

<TextBox FontSize="12pt">

    <TextBox.SelectionBrush>

        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">

            <GradientStop Color="Transparent" Offset="-.2" />

            <GradientStop Color="Blue" Offset="0.25" />

            <GradientStop Color="Blue" Offset="0.75" />

            <GradientStop Color="Transparent" Offset="1.2" />

        </LinearGradientBrush>

    </TextBox.SelectionBrush>

</TextBox>

GradientSelectionBrush

 

- Chipalo

Filed under: ,
Layout Rounding
27 August 09 08:41 AM | text | 6 Comments   

WPF’s layout engine frequently gives elements sub-pixel positions. Antialiasing algorithms cause these sub-pixel positioned elements to be rendered over multiple physical pixels after filtering. This can result in blurry lines and other non desirable rendering artifacts. Layout rounding has been introduced in WPF 4.0 to allow developers to force the WPF layout system to position elements on pixel boundaries, eliminating many of the negative side effects of sub-pixel positioning.

 

Two common situations where negative side effects display themselves are grid and image rendering.  Many times grids are created using “star sizing,” resulting in all rows having proportional sizes (The same technique can be used for columns. For simplicity's sake, I will just refer to rows in this post). If the space being divided into rows is not a multiple of the smallest row, each row will have a fractional size. When this occurs, the content of each row will be antialiased at row boundaries. An example of this is below. The effect of the antialiasing creates the banding effect.

 

<Grid Height="100" Width="200">

    <Grid.RowDefinitions>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

    <Rectangle Grid.Row="0" Fill="DarkBlue"/>

    <Rectangle Grid.Row="1" Fill="DarkBlue"/>

    <Rectangle Grid.Row="2" Fill="DarkBlue"/>

</Grid>

XAML for a grid that uses “star sizing” to measure row height. Each row will have a height of 33.33… since the total space for all rows is 100, and this space must be divided equally between three rows.

 

grid banding 

The grid rendered from the above XAML and zoomed to 200%. Since the only contents of each row are a dark blue Rectangles, one could reasonably expect a solid dark blue window. Without layout rounding, seams will be rendered at the row boundaries. These are artifacts from antialiasing.

 

 

Image clarity can also be improved by layout rounding. Bitmap images contain color information for individual pixels.

 

smiley2

A bitmap image of a smiley face. Each red square represents one image pixel.


 

If an image is not placed on whole pixel boundaries, the color of one physical pixel has contributions from multiple image pixels. This results in a blurry rendered image.

 

smiley rendered

The bitmap image from above is placed at (1.5, 1.5). This results in the color of each physical pixel (black) depending on the color of 4 image pixels (red).

 

 

Below are a couple examples of the effect that sub-pixel image positioning can have on the clarity of an image.

 

 

squares

The left image is the original. The right image is rendered on sup-pixel boundaries

 

lady

The left image is the original. The right image is rendered on sup-pixel boundaries

 

Layout Rounding API

The attached property UseLayoutRounding has been introduced to allow layout rounding functionality to be toggled on or off.

This property can either be True or False. The value of this property is inherited by an element’s children.

·         True – This element will use layout rounding

·         False (default) – This element will not use layout rounding

Code snipit of this property in action

 

<Grid UseLayoutRounding="True" Height="100" Width="200">

    <Grid.RowDefinitions>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

    <Rectangle Grid.Row="0" Fill="DarkBlue"/>

    <Rectangle Grid.Row="1" Fill="DarkBlue"/>

    <Rectangle Grid.Row="2" Fill="DarkBlue"/>

</Grid>

 

no grid banding

The grid rendered from the above XAML and zoomed to 200%. Notice that setting UseLayoutRounding=”True” resolved the banding issue in the image above.

 

 

UseLayoutRounding Usage

Layout rounding should be used in UI scenarios where the exact location of objects can be sacrificed for overall appearance of the application. Since rounding of layout parameters occurs when using this feature, precise element placement is lost.  A few of the effects layout rounding can have on exact layout are…

·         width and or height of elements may grow or shrink by at most1 pixel

·          placement of an object can move by at most 1 pixel

·          centered elements can be vertically or horizontally off center by at most1 pixel

If your app has an unexpectedly blurry image or icon, fuzzy lines or borders that should be crisp, or grid banding try using layout rounding.

-Chipalo

Filed under: ,
WPF 4.0 Text Stack Improvements
24 August 09 07:23 PM | text | 25 Comments   

Please note that the screenshots in this post are not displaying correctly. To view them in their full fidelity, right click on them and save them as a .PNGs.  Then use your image viewing program of choice.

 

 

Text Formatting API

The attached property TextOptions.TextFormattingMode has been introduced to switch the text metrics used by WPF while formatting text. There are two settings for this property, and the value of this property is inherited by an element’s children.

·         Ideal – Ideal text metrics are the metrics which have been used to format text since the introduction of WPF. These metrics result in glyphs’ shapes maintaining high fidelity with their outlines from the font file. The glyphs’ final placement is not taken into account when creating glyph bitmaps or positioning the glyphs relative to each other.

·         Display – In this new formatting mode, WPF uses GDI compatible text metrics. This ensures that every glyph has a width of multiple whole pixels and is positioned on whole pixels. The use of GDI compatible text metrics also means that glyph sizes and line breaking is similar to GDI based frameworks. That said, glyph sizes are not the only input into the line breaking algorithm used by WPF. Even though we use the same metrics as GDI, our line breaking will not be exactly the same.

 

Here is a small code snipit of this property in action…

 

<StackPanel>

    <TextBlock>

        Hello World ...  Ideal text formatting

    </TextBlock>

    <TextBlock TextOptions.TextFormattingMode="Display">

        Hello World ... Display text formatting

    </TextBlock>

</StackPanel>

 

Screenshot of the code snipit above. It is a comparison of ideal vs. display mode text

 

 

The above screenshot makes it hard to really get a sense for how much text quilty has been improved. Below is an excerp from the Magna carta rendered with ideal mode (top) and display mode (bottom). Notice that the display mode text looks much better. In specific, the stems of letters are more crisp, the text appears to be darker, and there is no color fringing around glyphs.

 

 

 

 

TextFormattingMode Usage

Both text formatting modes have their advantages and drawbacks. Ideal mode text offers optimally shaped and spaced text. This translates to less reading fatigue for end users; however at small text sizes, these benefits are negated by blurry rendering. On the other hand, display mode text provides the clarity of pixel snapped text at the expense of glyph shape and placement.

Many times, the difference between ideal and display mode rendering can be very small; however there are some scenarios that lend themselves to specific formatting methods. These scenarios are called out below. If none of these scenarios are pertainent to your app, try out both formatting modes to see which provides the best results.

 

Ideal Mode

·         Large Text – As the size of text increases, the clarity issues with ideal mode text dissapate. After about 15pt, ideal mode text is just as clear, and better spaced, than display mode text.

·         Transformed Text – Ideal mode text is designed to be drawn anywhere as opposed to display mode text which only looks good if it is rendered on pixel boundaries. Applying transforms to display mode text can easily skew pixel alignment that the WPF text stack has applied to the text. This causes the display mode text to become blurry. If a transform is applied to text, we recommend that ideal mode be used.

·         Zoomed Text – Zooming text is a special case of transforming text. This is the worst of all 2D transforms for display mode text. For display mode text, the text metrics no longer scale linearly with a linear size scale. While in ideal mode the bounding box of text rendered at a 2.0 X and Y scale (using a WPF RenderTransform) is exactly twice the size of the same text rendered at a 1.0 scale. This is no longer true for display mode text. In order to maintain correct hit testing and rendering for display mode text in a RenderTransform, we must scale up the text bitmap from the original 1.0 scale. This results in blurriness and artifacts at any significant scale change. If an app requires that text be zoomed, we suggest that this be implemented by increasing the text size.

·         Design Scenarios – When the shape of glyphs are very impartant, ideal mode should be used. This is most common in designer scenarios.

 

Display Mode

·         Small Text – Depending on many factors (eg. monitor type, screen resolution, text antialiasing algorithm, etc…), small WPF text can appear more blurry than text rendered using a GDI based technology. In these scenarios, switching to display mode should solve these problems.

 

 

Text Rendering API

The attached property TextOptions.TextRenderingMode has been introduced to control the antialiasing algorithm used by WPF when rendering text. There are four values for this property, and it is respected by all children of an element

·         Auto – This mode will use ClearType unless system settings have been set to specifically disable ClearType on the machine.

·         Aliased – No antialiasing will be used to draw text.

·         Grayscale – Grayscale antialiasing will be used to draw text.

·         ClearType – ClearType antialising will be used to draw text.

 

 

Here is a small code snipit of this property in action…

 

<StackPanel TextOptions.TextFormattingMode="Display">

    <TextBlock>

        Hello World ... ClearType

    </TextBlock>

    <TextBlock TextOptions.TextRenderingMode="Grayscale">

        Hello World ... Grayscale

    </TextBlock>

    <TextBlock TextOptions.TextRenderingMode="Aliased">

        Hello World ... Aliased

    </TextBlock>

</StackPanel>

 

Comparison of ClearType vs Grayscale vs Aliased text. All text in this screenshot is using display mode.

 

 

TextRenderingMode Usage

In general, Default is the best setting for TextRenderingMode. In a world where LCD monitors are becoming ubiquitous, ClearType often produces the crispest text. In scenarios not conducive to ClearType (eg. CRT monitors, users who have abnormally high color sensitivity, etc…), users sometimes disable this technology via system settings. When TextRenderingMode is not set or specifically set to Default, WPF will use ClearType unless the framework determines that the user has disabled it.

 

 

 

East Asian Text

The new WPF 4.0 text stack also contains improvements to East Asian text rendering. In specific, our text stack can now take advantage of embedded bitmaps. Some East Asian fonts contain bitmaps for certain characters at small sizes. Using these bitmaps can produce clearer text than letting the text stack create bitmaps from the font’s geometric data. Embedded bitmaps will not be necessary once displays have high enough resolutions to clearly render the intricacies of small East Asian text.  Until that point, these embedded bitmaps provide a decent alternative. Below is an example of the improvements provided by embedded bitmaps.

 

String of East Asian text produced via font file data and rendered with ClearType

 

Same string of East Asian text (above) rendered via embedded bitmaps

 

 

Using this feature only requires that an app use a font which contains embedded bitmaps. Here is a list of the East Asian fonts that have this support.

Language

Font

Traditional Chinese

MingLiu

Simplified Chinese

SimSun

Japanese

MS Gothic

Korean

Gulium

Korean

Batang

 

-Chipalo

Back to WPF Text Blog
22 August 09 01:29 AM | text | 0 Comments   

Since DirectWrite will now be using a different blog, the name of this blog will return to WPF Text Blog.

- Chipalo

DirectWrite blog posts moving to the DirectX blog
17 July 09 02:26 AM | text | 0 Comments   

In order to consolidate information from various blogs about the DirectX family of APIs, we have created a central DirectX blog site -http://blogs.msdn.com/DirectX/

 

All future posts on DirectWrite will be posted on the DirectX blog along with information on other DirectX APIs.   If you are using a RSS reader to monitor DirectWrite postings, please update the URL within your RSS reader.   We will continue to post links to DirectWrite related posts on this blog.

 

-Sriram 

 

Filed under:
New WPF 4.0 Features
24 June 09 06:35 PM | text | 12 Comments   

WPF 4.0 Beta1 was released last month. While many exciting features were included in Beat1, there was no work targeting text, flow, or layout. This will all be reversed with WPF Beat2. Below is a brief overview for each of the features included in Beta2 which target text, flow, or layout. I will make subsequent posts giving more detail about each feature, including API details. For now, I just want to let everyone know that great features are coming!

 

 

Text clarity improvements

In previous versions of WPF, all text is formatted without specifically accounting for pixel boundaries. This approach provides uniform scalability and ensures that glyph outlines adhere to font specifications. Unfortunately, small text appears blurry when it is rendered across pixel boundaries, and this has affected our customers.  In the past, we have only been able to say “we are working on a fix.”  Now I can tell you that this is solved in WPF4.0!

 

As of Beta2, WPF provides developers with the ability to control how text is both formatted and rendered. Text can now be formatted to either strictly adhere to font specifications or fall on pixel boundaries. This new option allows text to be rendered more clearly at the slight expense of glyph shape and position.

 

The option to set the rendering mode for text (eg, aliased, grayscale, ClearType) is also conveniently exposed. In most situations ClearType is an obvious win; however ClearType can degrade the user experience on CRTs and for people whose eyes are color sensitive. In the past, WPF forced all apps to use ClearType. Now, developers can choose between two additional rendering modes.

 

 

A Bindable Run

The inability to bind Run.Text has forced many people to create home brew solutions. In WPF4.0, Run.Text has been converted to a Dependency Property.  Run.Text now enjoys most of the benefits that come with this change, such as the ability to be bound, styled, and templated.

 

One-way binding is fully supported. Unfortunately, we did not have time to implement full support for two-way binding. This scenario is supported if a run is only modified through the property system, but not when the run is modified via a RichTextBox or the text object model.

 

 

LayoutRounding 

WPF’s layout engine frequently causes subpixel rendering along element boundaries. This can lead to both rendering artifacts and blurry rendering, as antialiasing causes subpixel rendered elements to be displayed over multiple actual pixels. A classic example of this problem is small icons which get blurred because the icon images are placed on subpixel boundaries. Enabling LayoutRounding forces the WPF layout engine to place elements on whole pixel boundaries, thus removing most of the rendering artifacts caused by this problem.

 

 

Caret and Selection Brush

The default visual appearance of most objects in WPF can be easily tweaked or completely changed.  This provides developers far greater power over the visual look of an application than ever before. Facilitating the creation of highly customized apps has become a major adoption point for WPF. Despite WPF’s extensibility, the color of text selection and carets in text boxes and document viewers remains baked into the framework. WPF now exposes properties to control the brushes used to paint text selection and carets.

 

 

-Chipalo

Introducing the DirectWrite Font System
15 April 09 09:00 PM | text | 3 Comments   

Hi, my name is Niklas Borson and I’m a developer on the DirectWrite team at Microsoft. DirectWrite has multiple layers of functionality, including text layout, script processing, glyph rendering, and the font system. In this post, I’d like to talk about some of the thinking behind the design of the font API in DirectWrite, and how it differs from GDI.

Logical vs. Physical Fonts

It will be helpful in the discussion that follows to distinguish between logical and physical fonts. Of course you might argue that fonts were really only “physical” back in the days of metal type. However, what I mean by a physical font in the context of computer typography is the actual data that defines the appearance of text in a particular font. A physical font can be represented as an OpenType file on your hard disk or as a virtual file embedded in a document.

A logical font, on the other hand, is something closer to a typical user’s conception of a font. Users rarely deal directly with font files. If you’re using a word processor, you select the name of a font family from a list. If you want to make the text bold you click a button or check a box. Doing so might mean the text is rendered using timesbd.ttf instead of times.ttf, but you neither know nor care about that. Thus, a logical font is not really the font itself, but a set of abstract properties that describe the font you want.

The reason for making this distinction is that different application scenarios naturally fit at one level or another. If you just want to draw some simple text on the screen, it makes sense to work at the logical font level – for example, just specify “Times New Roman” and let the text formatting engine handle the details. Among those details are what to do if times.ttf can’t render some of the characters you specify. Since you’re working at the logical font level, the text formatting engine has the flexibility to fall back to a different physical font.

On the other hand, some applications need to work with fonts at a lower level. For example, if an application implements its own text formatting engine, it ultimately needs a physical font so it can map Unicode characters to glyphs (character shapes), position the glyphs, and render them.

The level of abstraction affects a developer’s expectations of an API. At a high level, it can be helpful if an API just “does the right thing,” even if that means making certain decisions for you like falling back to a different font. However, developers using low-level APIs tend to value control and predictability more than convenience. For example, glyph indices are font-specific – they don’t have a standard meaning like Unicode characters – so if you’re rendering glyph indices you really want to know exactly what physical font will be used.

Fonts in GDI

In GDI, one typically creates a font by filling in a LOGFONT structure and then calling CreateFontIndirect, which returns a font handle (HFONT). As you would expect from the name, a LOGFONT structure is a logical font – i.e., merely a set of properties that describe the font you want. What might surprise you is that an HFONT is also a logical font. For example, you can fill in a LOGFONT with a face name of “Fred” and successfully create an HFONT from it, whether or not a font named “Fred” actually exists. If you draw some text using that HFONT, GDI will look for a matching physical font to draw the text with. If it doesn’t find a “Fred” it will use some other font. This font mapping process is entirely internal to GDI and there’s no way for an application to determine the physical font it used.

As described above, there are a lot of application scenarios where working at the logical font level makes sense, and HFONT works well for this. For applications that need to work with fonts at a lower level, GDI does have some functions that can really be thought of as physical font APIs. Examples are GetFontData, GetGlyphIndices, and even ExtTextOut when used with the ETO_GLYPH_INDEX flag. Yet these “physical” font functions still use an HFONT to specify the font. This means font mapping still occurs under the hood, though since no text is specified there is no font fallback and the same HFONT always maps to the same physical font internally. While this model works, the lack of a true physical font object in GDI can make it harder for application developers that use these low-level functions to be sure of what is going on.

Fonts in DirectWrite

DirectWrite has multiple layers of functionality, in which the lowest layers are intended to provide a solid foundation on which higher-level services can be built. The lowest layer of the font API is the IDWriteFontFace interface, which represents a physical font. This interface exposes low-level methods for getting glyph metrics, glyph indices, and so on. It is also used with other low-level APIs for complex script analysis and glyph rendering. Because a physical font encapsulates font data, you create an IDWriteFontFace object by specifying the source of the data: an IDWriteFontFile object.

We thought about introducing another interface to represent a logical font. However, after a lot of thought and discussion, we eventually concluded that a so-called “logical font” isn’t really a font at all, but merely a set of properties used to select a font. Also, since these logical font properties are inputs to the text formatting process, the appropriate place to specify them is in the text formatting API. Thus, DirectWrite’s nearest equivalent to GDI’s LOGFONT structure is the IDWriteTextFormat interface, which has properties for font family name, font weight, font style, font stretch, and font size. You can also set each of these properties individually on ranges of text after creating an IDWriteTextLayout object.

In between those two layers is the font collection API. A font collection is simply a set of fonts, which can be either the system font collection (i.e., the set of installed fonts) or a custom font collection (i.e., a set of fonts enumerated by an application-defined callback). Font collections are organized hierarchically. The collection itself contains a list of font families each of which contains a list of fonts. An application can use the font collection API to implement a font selection UI such as a font dialog box.

The reason I say the font collection API is “in between” the logical and physical layers is that it can serve as a bridge between the two. Suppose you were implementing your own text formatting engine. As inputs you would take logical properties like family name, weight, etc., from which you would somehow need to obtain a physical font. The font collection API provides lookup methods that enable you to find the physical font that best matches to a given set of properties. By way of analogy, you could think of a font collection as a database, a physical font as a record in the database, and a logical font as a query.

Both the physical font API and the font collection API have extensibility mechanisms. You create a physical font object from an IDWriteFontFile interface, but this interface doesn’t have to be a conventional Win32 file. It can be a virtual file implemented in terms of callbacks you define. Similarly, you can also create a custom font collection by implementing a callback interface that enumerates font files. This allows you to format and render text using application-defined fonts without having to install them first. Because the custom font collection is completely separate from the system font collection, this approach also avoids any naming conflicts that might otherwise arise between your custom fonts and fonts already installed on the system.

Weight/Width/Slope Font Model

One final difference I should mention between DirectWrite and GDI concerns the way fonts are grouped into font families. DirectWrite uses the Weight/Width/Slope font model, which means you can have any number of fonts in the same font family as long as each can be uniquely differentiated by weight, stretch (aka. width), and/or style (aka. slope). This is the same model used by WPF, as described in an earlier blog post about the WPF font selection model.

To give a specific example, if you enumerate font families using GDI’s EnumFontFamiliesEx function, you’ll find that the following are all enumerated as separate family names by GDI:

  • Franklin Gothic Book
  • Franklin Gothic Demi
  • Franklin Gothic Demi Cond
  • Franklin Gothic Heavy
  • Franklin Gothic Medium
  • Franklin Gothic Medium Cond

In DirectWrite, “Franklin Gothic Book” is a separate family, but all of the other fonts are grouped into a single font family called “Franklin Gothic.” In GDI, you’d specify the demi-bold condensed font using the name “Franklin Gothic Demi Cond”. If you did the same thing with DirectWrite, you’d find that the family name wasn’t recognized and DirectWrite would fall back to another font entirely like Arial. Instead, you would specify “Franklin Gothic” as the family name, DWRITE_FONT_WEIGHT_DEMI_BOLD as the weight, DWRITE_FONT_STRETCH_CONDENSED as the stretch, and DWRITE_FONT_STYLE_NORMAL as the style.

If your application only uses DirectWrite then none of the above is likely to cause you any problems. After all, DirectWrite is internally consistent and won’t enumerate family names that it doesn’t recognize! However, you may need to take special care if you use DirectWrite in combination with another API. More on that below.

Interoperability with GDI

The DirectWrite font system has two levels of interoperability with GDI. First, at the logical font level, we provide round-trip conversions to and from GDI’s LOGFONT. Second, at the physical font level, there is a one-way conversion from an HFONT (selected into an HDC) to an IDWriteFontFace. All of these are exposed through the IDWriteGdiInterop interface.

The LOGFONT conversions exist to compensate for the fact that DirectWrite uses a different font model than GDI. As described in the previous section, you sometimes use a different name to specify a font in DirectWrite than you’d use to specify the same font in GDI. If you use both DirectWrite and GDI in the same application, you may need to convert the family name and other logical font properties back and forth between the two systems. The ConvertFontToLOGFONT and CreateFontFromLOGFONT methods enable you to do this. There is also a ConvertFontFaceToLOGFONT method, which takes a font face object as input but is otherwise functionally equivalent to the ConvertFontToLOGFONT method.

For example, suppose your application uses DirectWrite internally but also uses the Win32 common font dialog box. In this case, you would call CreateFontFromLOGFONT to convert the LOGFONT returned by the dialog box to an IDWriteFont object. From this you could get the logical font properties compatible with DirectWrite’s font system. A subtler example would be an application that uses DirectWrite internally but uses a file format that stores GDI-style font names. In this case, you might use CreateFontFromLOGFONT when reading from the file and ConvertFontToLOGFONT when writing to the file.

Warning: All of the LOGFONT conversions described above operate at the logical font level, which means they don’t offer the kind of strong guarantees you would expect from a physical font API. They are useful for the kind of high-level scenarios described in the previous paragraph but should not be used if you require a specific physical font. For example, you might be tempted to render a DWRITE_GLYPH_RUN using GDI by converting the fontFace member to a LOGFONT, creating an HFONT and selecting it into an HDC, and then using ExtTextOut with ETO_GLYPH_INDEX. Don’t do this! It is not guaranteed that GDI will select the same physical font as the fontFace member you started with, in which cases (since glyph indices are font-specific) you’ll get garbage output.

We do provide one conversion that works at the physical font level, but it works on only one direction: from an HDC to an IDWriteFontFace. It is intended for a very specific scenario. Suppose your application already has a complicated text formatting engine which uses GDI (and perhaps Uniscribe) and renders glyphs using ExtTextOut with ETO_GLYPH_INDEX. You don’t want to rewrite your whole text engine, but you’d like to use DirectWrite (or maybe Direct2D) for just the final step of rendering the glyphs. To do so, you would remove the ExtTextOut call, and instead call CreateFontFaceFromHdc to get an IDWriteFontFace object, which you could then use to render the glyph indices. Unlike the LOGFONT conversions described above, this method is guaranteed to yield the same physical font that would have been used by GDI to render the glyphs.

If you’ve made it this far, thank you for your attention! The DirectWrite font system does differ from the familiar GDI way of doing things, and I hope the above will help people understand how it differs and why. We all look forward to hearing what you think!

DirectWrite Questions and Answers
13 April 09 10:57 PM | text | 4 Comments   

Hi, my name is Mikhail Leonov, and I’m a Senior Software Development Engineer on the DirectWrite team at Microsoft. I would like to address common user feedback on DirectWrite in a relatively informal ‘simple question – simple answer’ format. Feedback themes were gathered mostly from the user comments on various DirectWrite related blogs. Please feel free to post additional questions in the comments section right after this blog post. Throughout this post, I will assume the reader is familiar with DirectWrite basics. This link provides a good starting point: http://channel9.msdn.com/pdc2008/PC18/.

DirectWrite from the programmer’s point of view
I want to experiment with DirectWrite in my application. How do I start using it?

DirectWrite can be used from native C++ code by including DWrite.h header file and linking to the DWrite.lib library. At the runtime, the application will automatically load DWrite.dll.

To start with, the application needs to call DWriteCreateFactory. The factory pointer returned by DWriteCreateFactory implements IDWriteFactory interface, which can be used to perform actions such as creating DirectWrite font and layout objects.

For more information, please refer to the introductory DirectWrite materials linked in the beginning of this post.

DirectWrite on pre-Windows 7 operating systems
My application needs to work on Vista and XP. Is using DirectWrite an option for me?

DirectWrite technology will ship first with Windows 7. After Windows 7 ships, DirectWrite will be made available for Windows Vista as well. There are no plans today to make DirectWrite available on Windows XP.

Microsoft platforms and applications using DirectWrite
Does Microsoft use DirectWrite in its own products? I installed Windows 7, and I don’t see natural ClearType anywhere on the screen.

DirectWrite is used by the Windows 7 ClearType Text Tuner control panel applet and by the XPS Viewer application. It is worth noting that DirectWrite is a new technology, and it takes time for customers to evaluate their existing text functionality and determine how to take advantage of DirectWrite.

Supported font formats
Does DirectWrite only support TrueType fonts? How about Type 1 fonts or bitmap fonts?

DirectWrite supports font files conformant to the OpenType specification version 1.5, which can be accessed here: http://www.microsoft.com/typography/otspec/default.htm. This support includes OpenType fonts with both TrueType and CFF outlines, and TrueType fonts with embedded bitmaps. Simply speaking, if your font has a TTF, OTF or TTC extension, DirectWrite should support it well.

DirectWrite does not support bitmap or vector .FON font files, and DirectWrite does not support Adobe Type 1 .PFM/.PFB font files.

Installed fonts, local fonts, embedded fonts, per user fonts
My application uses a custom font for certain user interface elements. Do I have to install it on the system in order for DirectWrite to be able to use it?

No, one doesn’t have to install a font in order for DirectWrite to be able to use it. DirectWrite provides full support for font files that are local to an application.

The application that uses DirectWrite needs to register its own IDWriteFontFileLoader interface implementation that manages the association between the font file location and contents. To support local font file enumeration functionality, the application needs to register its own IDWriteFontCollectionLoader interface.

Rendering technologies to use DirectWrite with
Can I use DirectWrite in my GDI+ application? How about using DirectWrite with Direct3D or GDI?

DirectWrite font stack is designed to be independent from any rendering technology, so clients have flexibility to use any existing rendering mechanism in their IDWriteTextRenderer implementation. In addition, DirectWrite is designed to work well with Direct2D rendering components, and Direct2D provides convenient wrappers such as ID2D1RenderTarget::DrawText() for drawing text on D2D surfaces.

DirectWrite itself provides GDI interoperability helpers via IDWriteGdiInterop interface. One can create a DirectWrite font face object that corresponds to a font selected in a GDI HDC and easily replace ExtTextOut(…, ETO_GLYPH_INDEX, …) calls with DirectWrite based glyph run drawing calls without requiring significant changes to the rest of the application code. One can also create a LOGFONT description for a DirectWrite font face object to re-use existing GDI based controls from a DirectWrite based text processing component. On top of that, one can create GDI surfaces that satisfy DirectWrite rendering requirements through IDWriteGdiInterop::CreateBitmapRenderTarget() method, and draw DirectWrite glyph runs on that surface using IDWriteBitmapRenderTarget::DrawGlyphRun() method.

Interoperability with GDI+ can be achieved via GetHdc() and FromHdc() methods provided by the GDI+ Graphics object. The client has a choice of starting with a Graphics object and only switching to HDC methods for DirectWrite interoperability calls, or starting with an HDC obtained from IDWriteBitmapRenderTarget::GetMemoryDC() and switching to Graphics object derived from it. Which of these two approached is the best depends on the application needs.

Applications that render using Direct3D usually need to obtain text in either bitmap or outline form. To get the former, the client can ask DirectWrite to produce alpha textures containing text using IDWriteGlyphRunAnalysis interface. To get the latter, the client can use IDirectWriteFontFace::GetGlyphRunOutline() method to produce a geometry containing text.

Rendering quality
How do I specify text rendering options in DirectWrite? I want to use the new natural ClearType for text paragraphs, while having text in my menus and buttons look like the rest of the operating system.

In your case, two different measuring modes should be used—DWRITE_MEASURING_MODE_NATURAL for text paragraphs, and DWRITE_MEASURING_MODE_GDI_CLASSIC for menu and button text. The measuring mode then gets passed to drawing calls such as ID2D1RenderTarget::DrawText() and DrawGlyphRun() as an input parameter. For clients who create IDWriteTextLayout themselves, DWRITE_MEASURING_MODE_NATURAL corresponds to calling IDWriteFactory::CreateTextLayout(), and DWRITE_MEASURING_MODE_GDI_CLASSIC corresponds to calling IDWriteFactory::CreateGdiCompatibleTextLayout() with useGdiNatural set to FALSE.

DirectWrite beta documentation
16 January 09 01:42 AM | text | 0 Comments   

There is now DirectWrite content in MSDN as part of the Win7 beta documentation.    The content includes overview docs, API reference and sample code.  If you have downloaded the Windows 7 beta, try out the DirectWrite APIs and send us your feedback either on this blog, or via the MSDN feedback dialog box, the “Send comments about this topic to Microsoft” link, as well as the Community Content section at the bottom of each topic.

-Sriram

DirectWrite
11 December 08 04:33 PM | text | 4 Comments   

Hello – my name is Sriram Subramanian and I am a Senior Program Manager on Windows 7 for text.  As you can see from the updated title – this blog will start discussing the new DirectWrite text APIs in Windows 7 in addition to the WPF text and layout functionality.   While I was at it, I thought it would be a good idea to update the theme also.

DirectWrite is being introduced in Windows 7 and  is one of the new additions to the DirectX family of APIs.   It provides the ease of use and the layered programming model for application developers to improve the text experience for their Windows applications.   This is largely driven by the fact that modern Windows applications have sophisticated requirements for text in their UI and documents. These include better readability, support for a large variety of languages and scripts, and superior rendering performance. In addition, most existing applications require a way to carry forward existing investments in the Win32® code base.    DirectWrite addresses these requirements.  Check out the DirectWrite whitepaper that was distributed at the PDC.

-Sriram

Filed under:
WPF Text Clarity Doc
18 August 08 07:25 PM | text | 7 Comments   

I have posted a doc about: problems inherent to rendering small text, how WPF tackles these problems, and workarounds that can be employed to mitigate some rendering problems until these issues are resolved. You can find it on WindowsClient.net here, check it out.

New Blog Admin
18 July 08 09:25 PM | text | 3 Comments   
Hi, my name is Chipalo, and I am a program manager on WPF. Unfortunately, Chris is no longer with Microsoft. I wanted to introduce myself because I have taken over his responsibilities and will be maintaining this blog in the future.
More Posts Next page »
Page view tracker