awesome-inc / FontAwesome.Sharp

A library for using Font Awesome in WPF & Windows Forms applications
Apache License 2.0
376 stars 87 forks source link

Add Geometry generation #85

Closed josephdrake-stahls closed 1 year ago

josephdrake-stahls commented 2 years ago

I came across a situation in where I was looking to replace the vector used in an expandable TreeViewItem (WPF).

Unless there are dependency issues, this is a fairly easily implemented feature with System.Windows.Media.FormattedText. I wrote a MarkupExtension for the interim

using FontAwesome.Sharp;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
using System.Windows.Media;

namespace FaSample
{
    [MarkupExtensionReturnType(typeof(Geometry))]
    public class FaGeometryExtension : MarkupExtension
    {
        public FaGeometryExtension(IconChar icon)
        {
            Icon = icon;
        }

        [ConstructorArgument("icon")]
        public IconChar Icon { get; init; }

        public IconFont? IconFont { get; init; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            var dpi = GetDpi();
            var ft = new FormattedText(Icon.ToChar(), CultureInfo.GetCultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, TypefaceFor(Icon, IconFont ?? default), 1, IconHelper.DefaultBrush, dpi);
            ft.SetFontSize((IconHelper.DefaultSize / (float)dpi) * 96);
            return ft.BuildGeometry(new System.Windows.Point(0,0));
        }

        private static Func<IconChar, IconFont, Typeface>? _typefaceFor;
        private static Func<IconChar, IconFont, Typeface> TypefaceFor => _typefaceFor ??= typeof(IconHelper).GetMethod("TypefaceFor", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, new[] { typeof(IconChar), typeof(IconFont) })!.CreateDelegate<Func<IconChar, IconFont, Typeface>>();

        private static Func<int>? _getDpi;
        private static Func<int> GetDpi => _getDpi ??= typeof(IconHelper).GetMethod("GetDpi", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, Array.Empty<Type>())!.CreateDelegate<Func<int>>();
    }
}

WPF usage

<Path Stretch="Fill" Data="{local:FaGeometry SearchPlus, IconFont=Regular}" Fill="Black" />
mkoertgen commented 2 years ago

Hi @josephdrake-stahls ,

This one slipped my attention. Sorry for that. What a great enhancement to build path geometries! I would assume that many folks will find this helpful. Let's have a look how and when to integrate it into the library.

Best regards

mkoertgen commented 1 year ago

Done in 6