By default, the Image element will scale uniformly to fill the available space within a layout. Uniform scaling is typically the right choice for an image, but for some scenarios a different technique is desirable.

Let’s use a sample photo I took to illustrate the different values:

Screenshot of Avalon markup, illustrating the differences in values for the Image.Stretch property

  • Uniform: Scale the image uniformly (i.e. maintain the original aspect ratio) such that the entire image is always visible. Once again, this is the default behavior.
  • None: Do not scale the image at all, always display at it’s original size. If the available space is larger than the image, you’ll see unoccupied white space in your layout; if it’s smaller, the image will be clipped.
  • Fill: Scale the image non-uniformly (i.e. disregard the original aspect ratio) such that the entire image is always visible. The image will always occupy all the available space, and none of it’s content is clipped (although the image will be distorted since the original aspect ratio is not maintained).
  • UniformToFill: Scale the image uniformly until the entire available space is consumed. This is a mix of the other values, the aspect ratio is maintained, and the available space is always filled, but part of the image is clipped.

Here’s another screenshot of the same XAML at a different window size:

Screenshot of Avalon markup, illustrating the differences in values for the Image.Stretch property

UniformToFill can be especially useful when creating a nice layout, I’ll illustrate this in the next post. For now, here’s the markup I used for the screenshots:

<Grid xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" Background="Gray">
  <Grid.Resources>
    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="VerticalAlignment" Value="Bottom" />
      <Setter Property="HorizontalAlignment" Value="Center" />
      <Setter Property="Margin" Value="12.5" />
      <Setter Property="FontFamily" Value="Consolas, Lucida Console" />
      <Setter Property="FontSize" Value="20" />
    </Style>

    <Style TargetType="{x:Type Border}">
      <Setter Property="Margin" Value="5" />
      <Setter Property="BorderThickness" Value="10, 10, 10, 40" />
      <Setter Property="BorderBrush" Value="White" />
    </Style>
  </Grid.Resources>

  <Grid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

  <Border Grid.Row="0" Grid.Column="0">
    <Image Source="http://fortes.com/2005/06/21/imagescaling/sunset.jpg"
           Stretch="Uniform"
           HorizontalAlignment="Center" VerticalAlignment="Center" />
  </Border>
  <TextBlock Grid.Row="0" Grid.Column="0">Uniform</TextBlock>

  <Border Grid.Row="0" Grid.Column="1">
    <Image Source="http://fortes.com/2005/06/21/imagescaling/sunset.jpg"
           Stretch="None"
           HorizontalAlignment="Center" VerticalAlignment="Center" />
  </Border>
  <TextBlock Grid.Row="0" Grid.Column="1">None</TextBlock>

  <Border Grid.Row="1" Grid.Column="0">
    <Image Source="http://fortes.com/2005/06/21/imagescaling/sunset.jpg"
           Stretch="Fill"
           HorizontalAlignment="Center" VerticalAlignment="Center" />
  </Border>
  <TextBlock Grid.Row="1" Grid.Column="0">Fill</TextBlock>

  <Border Grid.Row="1" Grid.Column="1">
    <Image Source="http://fortes.com/2005/06/21/imagescaling/sunset.jpg"
           Stretch="UniformToFill"
           HorizontalAlignment="Center" VerticalAlignment="Center" />
  </Border>
  <TextBlock Grid.Row="1" Grid.Column="1">UniformToFill</TextBlock>
</Grid>

Drawing of a rose in Avalon

Yesterday, I mentioned that you can use rounded corners on Border to do some silly things. The (admittedly poor) rendition of a rose above was created using only nested Border elements, along with a two-row Grid with a Viewbox wrapped around the entire thing. Clearly, this is not the way to make a drawing in Avalon (you should use Shapes), but I thought I’d share any way.

<Viewbox xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" Margin="10">
  <!-- Background -->
  <Border Background="VerticalGradient LightBlue White" Grid.RowSpan="2" Padding="10">
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Background="RadialGradient #ff6 transparent">
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>

      <!-- Stem -->
      <Border BorderBrush="VerticalGradient #630 #191" BorderThickness="0,0,10,0" CornerRadius="50,300,50,50" Margin="30,50,80,10" Grid.RowSpan="2"/>

      <!-- Petals -->
      <Border Grid.Row="1" BorderBrush="HorizontalGradient #060 #353" BorderThickness="10,30" CornerRadius="10,50,10,50" Margin="20,20,80,0" />
      <Border Grid.Row="1" BorderBrush="VerticalGradient #262 #292" BorderThickness="10,30" CornerRadius="50,10,50,10" Margin="80,20,20,0"/>
      <Border Grid.Row="1" BorderBrush="HorizontalGradient #040 #492" BorderThickness="30, 10, 30, 10" CornerRadius="80, 10, 80, 10" Margin="80, 0, 40,0" />
      <Border Grid.Row="1" BorderBrush="VerticalGradient #040 #492" BorderThickness="30, 30, 30, 30" CornerRadius="10, 80, 10, 80" Margin="40, 0, 80, 0" />

      <!-- Rose -->
      <Border BorderBrush="RadialGradient #900 #a22" Background="HorizontalGradient #d22 #c00" BorderThickness="0, 0, 10, 10" CornerRadius="150, 250, 350, 300" HorizontalAlignment="Center" Margin="0,0,50,20">
        <Border BorderBrush="RadialGradient #900 #a22" Background="HorizontalGradient #d22 #c00" BorderThickness="15, 0, 0, 15" CornerRadius="300, 200, 200, 50" Opacity="1">
          <Border BorderBrush="RadialGradient #a00 #c33" Background="RadialGradient #a00 #d22" BorderThickness="0,20,20,0" CornerRadius="100, 40, 60, 200">
            <Border BorderBrush="RadialGradient #c33 #a00" Background="RadialGradient #a00 #c33" BorderThickness="0,0,10,20" CornerRadius="10,60,60,60">
              <Border BorderBrush="HorizontalGradient #f00 #a00" Background="#a00" BorderThickness="20, 10, 0, 0" CornerRadius="40, 20, 20, 20">
                <Border BorderBrush="VerticalGradient #f66 #a00" Background="#a00" BorderThickness="0,0,10,10" CornerRadius="20,20,10,30">
                  <Border BorderBrush="HorizontalGradient #a33 #d22" Background="#d03" BorderThickness="10,10,0,0" CornerRadius="30,30,20,20">
                    <Border BorderBrush="RadialGradient #a00 #d33" BorderThickness="10" CornerRadius="30, 20, 30, 20"/>
                  </Border>
                </Border>
              </Border>
            </Border>
          </Border>
        </Border>
      </Border>
    </Grid>
  </Border>
</Viewbox>

Border provides built-in functionality for drawing rounded corners through its CornerRadius property. Let’s go through some quick examples that introduce the functionality; we’ll use what we’ve learned here in later posts in order to create something more sophisticated.

First, here is a basic border without rounded corners :

A screenshot of Avalon, showing a border element with square corners

<Border HorizontalAlignment="Center" BorderBrush="Black" BorderThickness="5" Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
</Border>

By setting the CornerRadius property on Border, we can quickly setup rounded corners:

A screenshot of Avalon, showing a border element with rounded corners

<Border HorizontalAlignment="Center" BorderBrush="Green" BorderThickness="5" CornerRadius="50"  Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
</Border>

Notice how the rounded borders end up overlapping with the text in the previous example, this is because we haven’t set any padding for the contents. Border doesn’t try to automatically compensate for this overlap, so we’ll set the Padding property ourselves. I’ll also use a couple of simple gradients for the BorderBrush and Background in order to give a simple, button-like look to our border:

A screenshot of Avalon, showing a border element with rounded corners on only two edges

<Border HorizontalAlignment="Center" BorderBrush="VerticalGradient #eee #aaa" Background="VerticalGradient #bbb #eee" BorderThickness="5" CornerRadius="20" Padding="20"  Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
</Border>

Border suppors non-uniform values for CornerRadius and BorderThickness, I’ve used this to create a simple tab-like look for the border:

A screenshot of Avalon, showing a border element with heterogeneous rounded corners

<Border HorizontalAlignment="Center" BorderBrush="VerticalGradient #eee #aaa" Background="#eee" BorderThickness="5, 10, 5, 0" CornerRadius="20, 20, 0, 0" Padding="20, 10" Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
</Border>

As you can see, it’s easy to use Border to quickly create a traditional UI-look — this is useful for when you want to style Avalon’s built-in controls, or create your own custom control. Obviously, you’ll want to tweak the layouts in order to provide hover/activation/etc states as well.

Gray buttons are pretty boring, especially given how easy it is to be silly / creative with your borders; here two more quick examples:

A screenshot of Avalon, showing a border element with heterogeneous rounded corners

A screenshot of Avalon, showing a border element with rounded corners

Here’s the full markup for all these borders in a single XAML file:

<StackPanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
  <Border HorizontalAlignment="Center" BorderBrush="Black" BorderThickness="5" Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
  </Border>

  <Border HorizontalAlignment="Center" BorderBrush="Green" BorderThickness="5" CornerRadius="50"  Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
  </Border>

  <Border HorizontalAlignment="Center" BorderBrush="VerticalGradient #eee #aaa" Background="VerticalGradient #bbb #eee" BorderThickness="5" CornerRadius="20" Padding="20"  Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
  </Border>

  <Border HorizontalAlignment="Center" BorderBrush="VerticalGradient #eee #aaa" Background="#eee" BorderThickness="5, 10, 5, 0" CornerRadius="20, 20, 0, 0" Padding="20, 10" Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
  </Border>

  <Border HorizontalAlignment="Center" BorderBrush="#008" Background="VerticalGradient #ffe #eea" BorderThickness="10" CornerRadius="200, 20, 200, 20" Padding="50"  Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
  </Border>

  <Border HorizontalAlignment="Center" BorderBrush="HorizontalGradient #060 #3c3" Background="VerticalGradient #f93 #fc9" BorderThickness="50,5" CornerRadius="200, 20, 200, 20" Padding="50, 30"  Margin="10">
    <TextBlock FontSize="25" FontFamily="Pericles">Lorem Ipsum</TextBlock>
  </Border>
</StackPanel>
Aside I’ve used Pericles in these examples, another Ascender font we’re hoping to include in the Avalon SDK.

I’m short on time, so here’s a quick screenshot and markup sample that illustrates the use of the Typography.NumeralStyle property (I’ve left it as an exercise to the reader to spot the difference between the two):

Using numerals in Avalon

<TextFlow xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" FontFamily="Pescadero" FontSize="30" TextAlignment="Right">
    <Paragraph><Inline Typography.NumeralStyle="Lining">1234567890</Inline>: Abcdefghij</Paragraph>
    <Paragraph><Inline Typography.NumeralStyle=" OldStyle">1234567890</Inline>: Abcdefghij</Paragraph>
</TextFlow>
Aside I’ve used Pescadero, an upcoming font by Ascender. We’re working with Ascender and hope to be able to include Pescadero, along with a few other OpenType fonts, in order to include these fonts in SDK under a license will allow developers to redistribute them with their Avalon based apps, something they can’t legally do with the other fonts supplied by Microsoft, or with most fonts acquired from third parties without a special license.

Bickham Script Pro is a very sophisticated OpenType font, with very nice contextual alternates and ligatures. What sets Bickham apart is the alternate forms it provides — here are the ten (10!) different versions of the lowercase letter “h” available in the font:

Ten forms of the lowercase letter h, shown in Bickham Script Pro

In Avalon, you can choose between the alternates through the Typography.StylisticAlternates property. Most of the alternate forms shown above look best at the beginning of a word, but some (like #9) are meant for the end of the word.

Here’s the full markup for the screenshot shown above:

<Grid xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" HorizontalAlignment="Center">
  <Grid.Resources>
    <Style TargetType="{x:Type Border}">
      <Setter Property="Margin" Value="5" />
      <Setter Property="Padding" Value="20,0" />
      <Setter Property="BorderThickness" Value="1" />
      <Setter Property="BorderBrush" Value="#ccc" />
    </Style>
    <Style x:Key="AlternateDisplay" TargetType="{x:Type TextBlock}">
      <Setter Property="FontFamily" Value="Bickham Script Pro" />
      <Setter Property="FontSize" Value="60" />
    </Style>
    <Style x:Key="AlternateLabel" TargetType="{x:Type TextBlock}">
      <Setter Property="FontFamily" Value="Calibri, Verdana" />
      <Setter Property="FontSize" Value="20" />
      <Setter Property="Margin" Value="10" />
      <Setter Property="HorizontalAlignment" Value="Center" />
      <Setter Property="VerticalAlignment" Value="Bottom" />
    </Style>
  </Grid.Resources>

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <Border>
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="0">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="1">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="1">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="2">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="2">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="3">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="3">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="4">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="4">h</Inline></TextBlock>
  </Border>
  <Border Grid.Row="1">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="5">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="1" Grid.Row="1">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="6">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="2" Grid.Row="1">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="7">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="3" Grid.Row="1">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="8">h</Inline></TextBlock>
  </Border>
  <Border Grid.Column="4" Grid.Row="1">
    <TextBlock Style="{StaticResource AlternateDisplay}"><Inline Typography.StylisticAlternates="9">h</Inline></TextBlock>
  </Border>

  <!-- Labels -->
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Column="0">0</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Column="1">1</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Column="2">2</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Column="3">3</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Column="4">4</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Row="1" Grid.Column="0">5</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Row="1" Grid.Column="1">6</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Row="1" Grid.Column="2">7</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Row="1" Grid.Column="3">8</TextBlock>
  <TextBlock Style="{StaticResource AlternateLabel}" Grid.Row="1" Grid.Column="4">9</TextBlock>
</Grid>

A new Avalon / Indigo CTP was released today. One of the new features in this release is support for CFF fonts (something brought up in a previous entry’s comments).

This means Avalon applications can use the OpenType features set with many more fonts. To demonstrate, here’s a screenshot of the excellent Bickham Script Pro drawn with a gradient fill using Avalon:

The words 'Bickham Script Pro' written in the Bickham Script Pro font

Here’s a snippet of the markup used for the screenshot (I’ll explain how it works in the next post):

<TextBlock FontSize="60" FontFamily="Bickham Script Pro" Foreground="VerticalGradient #f00 #00f">
  <Inline Typography.StylisticAlternates="1">B</Inline>ickham Script Pro
</TextBlock>

Those who have upgraded to WordPress 1.5.1 have noticed that the upgrade broke a few plugins, such as Post Levels.

This was due to some changes in the WordPress architecture that allow plugin developers to replace some of the core functions in WordPress. However, this means that those functions will not be available when your plugin gets loaded. The functions are now defined in wp-includes/pluggable-functions.php, as of 1.5.1 the following functions are pluggable:

  • get_currentuserinfo
  • get_userdata
  • get_userdatabylogin
  • wp_mail
  • wp_login
  • auth_redirect
  • wp_redirect
  • wp_setcookie
  • wp_clearcookie
  • wp_notify_postauthor
  • wp_notify_moderator

Plugins that depend on any of the above functions need to make sure all uses of the function occur after all plugins have loaded. This is only an issue for code that is executed when the plugin is initialized (as opposed to code that is hooked into an action or filter). Initialization code should be refactored to run after WordPress has initliazed, as in the sample below:

// Run setup after the pluggable functions have loaded
add_action('init', 'myplugin_setup')

function myplugin_setup()
{
  // Code lives here
}

Alternatively, you can hook into plugins_loaded, which is also executed after the pluggable functions have loaded.

Version 0.2 of the Post Levels plugin has been released. This release makes the plugin compatible with WordPress 1.5.1. There are no new features in this release.

Download

Post Levels Plugin v0.2.1

Update 5/22: Sigh, as mentioned in the comments, single-post view is broken. This is due to an issue in WordPress that I unfortunately cannot change within a plugin. I’ve filed a bug; in the meanwhile, I recommend staying on 1.5 until this (and other) issues (hopefully) get fixed in 1.5.1.1

In my last post, I briefly mentioned the difference between a layout-affecting transform and a render-only transform. Here’s a screenshot and markup for a quick sample which illustrates the difference between the two:

A diagram illustrating the different between layout and render transforms in Avalon

The screenshot shows a two by three Grid, with a Button and a Rectangle within each cell. The first row is used as a control, the Buttons in the second row have a layout-affecting transform, and those in the third have a render-only transform. Here’s the markup:

<Grid xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
  <Grid.RowDefinitions>
    <RowDefinition Height="150" />
    <RowDefinition Height="150" />
    <RowDefinition Height="150" />
  </Grid.RowDefinitions>

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="150" />
    <ColumnDefinition Width="150" />
  </Grid.ColumnDefinitions>

  <Rectangle Margin="5" Fill="VerticalGradient #99f #66c" />
  <Rectangle Margin="5" Fill="VerticalGradient #f9f #c6c" Grid.Column="1"/>
  <Rectangle Margin="5" Fill="VerticalGradient #9f9 #6c6" Grid.Row="1"/>
  <Rectangle Margin="5" Fill="VerticalGradient #f99 #c66" Grid.Row="1" Grid.Column="1"/>
  <Rectangle Margin="5" Fill="VerticalGradient #ff9 #cc6" Grid.Row="2" />
  <Rectangle Margin="5" Fill="VerticalGradient #9ff #6cc" Grid.Row="2" Grid.Column="1"/>

  <Button Margin="10">
    None
  </Button>
  <Button Grid.Column="1" Margin="10">
    None
  </Button>

  <TransformDecorator Transform="rotate 45" Grid.Row="1" Margin="10">
    <Button>Layout</Button>
  </TransformDecorator>
  <TransformDecorator Transform="scale 1.5" Grid.Column="1" Grid.Row="1" Margin="10">
    <Button>Layout</Button>
  </TransformDecorator>

  <Button RenderTransform="rotate 45" Grid.Row="2" Margin="10">
    Render
  </Button>
  <Button RenderTransform="scale 1.5" Grid.Row="2" Grid.Column="1" Margin="10">
    Render
  </Button>
</Grid>

As you can see, the cells with render-only transforms end up drawing outside of their cells. Unlike layout-affecting transforms, the render-only transforms do not factor into layout; the content’s layout is performed as usual, with a transformation applied to the final result.

During my last few posts, I’ve made heavy use of Viewbox in order to scale content; today I’ll introduce the TransformDecorator, which provides a slightly different approach to scaling.

The contents of a Viewbox do not re-layout due to changes in window size; they’re essentially frozen to a particuar layout, then scaled as a whole by the Viewbox. In contrast, the contents of a TransformDecorator will re-layout given changes in window size, just like other layouts such as Border. TransformDecorator is special because it can manipulate how its content lays out through scaling and rotation.

Let’s start with some text and an Ellipse within a TextFlow, which I’ve placed inside a Border contained within a TransformDecorator. Here’s the markup:

<TransformDecorator xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
                    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
                    VerticalAlignment="Center" HorizontalAlignment="Center"
                    Transform="scale 1.0">
  <Border Background="RadialGradient #eef #aaf">
    <TextFlow FontFamily="Segoe Print, Comic Sans MS" FontSize="15" Margin="10">
      <Paragraph>
        Duis effet finis suspicit quast. Quisque vitae sem. In magna felis,
        fermentum ut, interdum nec, venenatis et, leo.
      </Paragraph>
      <Paragraph TextAlignment="Center">
        <Ellipse Fill="HorizontalGradient #0fff #c00" Width="300" Height="150" />
      </Paragraph>
    </TextFlow>
  </Border>
</TransformDecorator>

A screenshot of Avalon showing filler text with a red ellipse

TransformDecorator has a Transform property; currently, it’s set to scale 1, which scales the content by a factor of 1 (boring). If we change the value to scale .6, we see the following:

A screenshot of Avalon showing filler text with a red ellipse, zoomed to a smaller size through a layout transform

Notice that all the content has been scaled and the text has reflowed to fit the window’s width. Let’s make our content bigger by changing the value to scale 1.5:

A screenshot of Avalon showing filler text with a red ellipse, zoomed to a larger size through a layout transform

If you resize the window, you’ll notice that, unlike Viewbox, the content inside the TransformDecorator isn’t frozen and reflows when resizing. This makes TransformDecorator a good choice if you want to scale your content and still resize.

This type of transform is related to RenderTransform, but differs because the RenderTransform is applied after layout occurs. I’ll cover this in more detail in a future post.

Aside I’ve used Segoe Print, another new Microsoft font in the same family as Segoe Script