我们可以在LINQpad中加载和显示未安装的字体吗?

时间:2014-09-02 02:15:11

标签: wpf xaml svg fonts linqpad

在LINQpad中的附加引用下加载我的PCL DLL之后,我尝试了两种不同的技术来加载和显示字体。第一个是最直接的:

var xaml = @"
<UserControl
    xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
    <TextBox
        FontFamily=""/Songhay.Portable.Resources;Component/Fonts/#FontAwesome""
        FontSize=""64""
        Text=""&#xf09b;""
        />
</UserControl>
";

var control = (UserControl)XamlReader.Parse(xaml);
control.Dump();

上面的XAML声明在WPF中工作得很好,但LINQpad显示空白方块。所以我尝试了更明确的路线:

var dll = Assembly.GetAssembly(typeof(Songhay.Portable.Resources.ResourceModule));
dll.GetManifestResourceNames().Dump();

var resourceName = dll.GetManifestResourceNames().First(i => i.EndsWith("FontAwesome.otf"));
using (var stream = dll.GetManifestResourceStream(resourceName))
{
    var localData = new PrivateFontCollection();
    var fontdata = new byte[stream.Length];
    stream.Read(fontdata, 0, (int)stream.Length);
    unsafe
    {
        fixed(byte * pFontData = fontdata)
        {
            localData.AddMemoryFont((System.IntPtr)pFontData, fontdata.Length);
        }
    }
    localData.Dump();

    var textBox = new TextBox
    {
        FontFamily = new System.Windows.Media.FontFamily(localData.Families.First().Name),
        FontSize = 64,
        Text = System.Net.WebUtility.HtmlDecode("&#xf09b;")
    };
    textBox.Dump();
}

同样的问题:空方块。 LINQpad的边缘情况太多了吗?

顺便说一下,解决这个问题会让LINQpad成为一个非常强大的设计工具---在Blend / Visual Studio仪式之外的非正式草图板。

1 个答案:

答案 0 :(得分:0)

利用SVG网络字体格式和XAML Path元素:

var path = @"..\font-awesome-4.2.0\fonts\fontawesome-webfont.svg";
//You cannot stop .NET from condensing entities so load as string:
var xml = File.ReadAllText(path).Replace("unicode=\"&#", "unicode=\"&amp;#");
var fontAwesomeSvg = XDocument.Parse(xml);

var scrollViewer = new ScrollViewer
{
    Background = new SolidColorBrush(Colors.Azure),
    Padding = new Thickness(4),
    VerticalScrollBarVisibility = ScrollBarVisibility.Visible,
    Width = 960, Height = 600
};
var wrapPanel = new WrapPanel { Orientation = Orientation.Horizontal };

scrollViewer.Content = wrapPanel;

XNamespace svg = "http://www.w3.org/2000/svg";
fontAwesomeSvg.Descendants(svg+"glyph")
    .ToList().ForEach(i =>
    {
        var d = i.ToAttributeValueOrDefault("d", string.Empty);
        var unicode = i.Attribute("unicode").Value;
        var xaml = @"
        <Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
            Margin=""4"">
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBox
                Background=""Transparent""
                BorderThickness=""0""
                HorizontalContentAlignment=""Center""
                Text=""{Binding EntityDisplayText, Mode=OneWay}""
                />
            <Border Grid.Row=""1""
                BorderThickness=""2"" BorderBrush=""DarkGray""
                MinHeight=""96"" Padding=""4""
                Width=""96"" Height=""Auto"">
                <Path
                    Data=""{Binding StreamGeometry, Mode=OneWay}""
                    Fill=""Black""
                    RenderTransformOrigin=""0.5,0.5""
                    Stretch=""Uniform"">
                    <Path.RenderTransform>
                        <ScaleTransform ScaleY=""-1"" />
                    </Path.RenderTransform>
                </Path>
            </Border>
        </Grid>
        ";
        var control = (Grid)XamlReader.Parse(xaml);
        control.DataContext = new
        {
            StreamGeometry = d,
            EntityDisplayText = unicode
        };
        wrapPanel.Children.Add(control);
    });

scrollViewer.Dump();

一个警告:SVG dglyph的{​​{1}}属性未完全映射到XAML path(请注意Path如何使用)