Loading Font Resource and Setting Baseline - wpf

Is there a way to load a font as a resource and set its baseline?
The following works:
<FontFamily x:Key="DefaultFontFamily">/Swift.UiResources;component/Resources/Fonts/#Meta Offc</FontFamily>
But adding the baseline like so:
<FontFamily x:Key="DefaultFontFamily" Baseline="0.9">/Swift.UiResources;component/Resources/Fonts/#Meta Offc</FontFamily>
Results in the following error:
TypeConverter syntax error encountered while processing intialization string '/Swift.UiResources;component/Resources/Fonts/#Meta Offc'. Element attributes are not allowed on objects created via TypeConverter.
I should point out that the problem I'm trying to solve is that the font handed down from marketing, when centered vertically, is render higher than the previous font.

You could create a composite font, and have all Unicode ranges map to your embedded font. You'll need to create a new file with a .CompositeFont extension, and give it a Build Action of "Resource". Its contents should be:
<!-- File: "Resources/Fonts/Custom Font.CompositeFont" in Swift.UiResources -->
<FontFamily xmlns="http://schemas.microsoft.com/winfx/2006/xaml/composite-font"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
Baseline="0.9">
<FontFamily.FamilyNames>
<s:String x:Key="en-US">Custom Font</s:String>
</FontFamily.FamilyNames>
<FontFamily.FamilyMaps>
<FontFamilyMap Scale="1.0"
Target="/Swift.UiResources;component/Resources/Fonts/#Meta Offc"
Unicode="0000-007F" />
</FontFamily.FamilyMaps>
</FontFamily>
Then, when referencing your font in Xaml, use this format:
/Swift.UiResources;component/Resources/Fonts/#Custom Font
The font name following the # should match the value you set in FontFamily.FamilyNames above.
If you want to map more than the standard ASCII range, you can add more comma-separated character ranges to the Unicode property.
In the past, I have noticed that when you create a composite font that uses a resource URI in one or more of its mappings, it doesn't display properly in the Visual Studio designer, though it works properly at runtime. They may have fixed this since I reported it.

Related

How can I use SVG image format use as WPF image source

I want to use a SVG image format as an button image because I want these images is shown with high quality so I have decided to use SVG format.
I have searched about it and There are some people that say SVG format can be used as WPF image source.
But when I use SVG image Like this:
<Image Source="Images/hard.svg"/>
I have error.
Absolutely Microsoft website says I can use SVG file as Image source.
https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.media.imaging.svgimagesource?view=winrt-19041
How can I use SVG image format as my WPF image souse?
You have to convert svg to xaml using this library https://github.com/BerndK/SvgToXaml
Sample output:
<DrawingImage x:Key="ic_close">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
<GeometryDrawing Brush="Red"
Geometry="F0 M24,24z M0,0z M5.21723,16.4509C4.64003,17.0905 4.68203,17.8189 5.21723,18.3421 5.75123,18.8653 6.65362,18.8329 7.15522,18.3421 7.52928,17.977 10.3498,15.0233 11.7599,13.5448 13.1706,15.0243 15.9893,17.977 16.3633,18.3402 16.8649,18.8298 17.7673,18.8634 18.3013,18.3402 18.8365,17.8206 18.8785,17.091 18.3013,16.4514L13.8049,11.7618 18.3013,7.07225C18.8785,6.43265 18.8365,5.70425 18.3013,5.18105 17.7673,4.65785 16.8649,4.69025 16.3633,5.18105 15.9892,5.54616 13.1687,8.49985 11.7585,9.97833 10.3479,8.4988 7.52916,5.54607 7.15523,5.18287 6.65363,4.69327 5.75123,4.65967 5.21723,5.18287 4.68203,5.70247 4.64003,6.43207 5.21723,7.07167L9.71363,11.7613 5.21723,16.4509z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
Sample usage:
<Image Width="14"
Height="14"
Source="{StaticResource ic_close}" />
If you look at the namespace of that page you linked, you will see:
Windows.UI.Xaml.Media.Imaging
Meaning this is uwp rather than wpf.
You could use SharpVectors
https://github.com/ElinamLLC/SharpVectors
Or you could manually extract the path or paths from in that svg and use those in wpf. Since this is a manual conversion that might not be attractive if there are a number of svg you wish to use or appropriate if they are somehow dynamic.
Another option to consider is xaml islands.
You could host a uwp image control in a xaml island
https://blogs.windows.com/windowsdeveloper/2018/11/02/xaml-islands-a-deep-dive-part-1/#:~:text=XAML%20Islands%20is%20a%20technology,Windows%20Forms%20and%20WPF%20technologies.
Note that this introduces a dependency on win 10 creators edition or later.
WPF renders vector based but cannot render SVG files directly. You would have to use a vector based image processing application to convert the SVG to XAML.
Generally, the XAML obtained from the exported SVG usually consists of Path or Geometry elements, which you wrap into a Viewbox for scaling.
Adobe Illustrator (not free, trial available) yields the best results. You use it to convert the SVG image to .ai file and then Blend or a plug-in to export the .ai file as XAML.
AB4D (not free, trial available) is another application which also outputs very good results and allows to export directly to XAML.
InkScape is free and works too, but the results are not very good and most of the time require manual post-processing. Complex graphics never look good out of the box.
There are more tools like SvgToXaml, but I don't remember the quality.

Font not rendering properly on WPF desktop application

I have a custom font in my project. But WPF is not rendering it properly.
<TextBlock Text="This is a test sentence"
Foreground="Black" FontSize="50"
FontFamily="Assets/Fonts/#Custom Font"/>
Now I have two font files named:
Custom Font Medium Italic.ttf
Custom Font Bold Extended Italic.ttf
When I open these two files, the font name shown is only Custom Font. In the above textblock, if I use full file name,i.e., Custom Font Medium Italic.ttf, it doesn't work. So how to use these fonts in the textblock differently.
You need to reference the name of the font and not the name of the font file. I think that you also need to add a '#' character as well... try something like this:
<FontFamily x:Key="testfont">Assets/Fonts#Custom Font Bold Italic</FontFamily>
From the FontFamily Class page on MSDN:
XAML Values
fontFamilyFolderReference
A string specifying a folder containing the font, along with a font family name. The folder and font family name are delimited by a # character. The folder reference may be absolute, or relative. For example, "Custom Fonts#My Custom Font".
you can put the font files into different folders. e.g.
/Resources/Font/Medium/Custom Font Medium Italic.ttf
/Resources/Font/Bold_Extended/Custom Font Bold Extended Italic.ttf
then they can be referenced separately.

wpf / Visual Studio default styles

If I open a new project, and put a label or button on the main window, I get the Segoe UI font at size 12px.
Where is this coming from? Can I choose what I would like the default font / size to be? I had a good look around but can't find anything.
Thanks
The available fonts are set according to System.Windows.Media.Fonts.SystemFontFamilies.
If multiple versions of the same font family reside in the same directory, the Windows Presentation Foundation (WPF) font enumeration returns the most recent version of the font. If the version information does not provide resolution, the font with latest timestamp is returned. If the timestamp information is equivalent, the font file that is first in alphabetical order is returned.
There is also Fonts.SystemTypefaces.
Presumably it is possible to change the selected family or create your own. In fact it is, this post (WPF - Add Custom Font) gives more information on this.
I hope this helps.

How can we extract actual font family from a CompositeFontFamily applied to a run in WPF RichTextBox

A composite font family is a collection of FontFamilies. On applying the composite font to a run, appropriate font from its font-collection is applied depending on text.
How can we get which actual font is being used in a run on which a composite font has been applied?
EDIT2: Suppose I have a run
<Run Text="Some text with different unicode characters not available in applied FontFamily" FontFamily="Global User Interface"/>
Now if I check run.FontFamily it returns "Global User Interface", but actual font applied is one from the FontFamily collection of this composite font. So I want to find out which font it is?
EDIT1: One way I can think of is - to find it the way WPF applies a font. For each language, the composite font specifies a set of fonts corresponding to specified range of characters. So we can find each of the character in a run of text, then lookup the font corresponding to this character in the fontfamilymap for current language.
Is this the right way? Are there any cases where it may fail?
Is it the only way? Is there any API\straightforward way instead?
Thanks

How do I convert an Illustrator file to a path for WPF

Our graphics person uses Adobe Illustrator and we'd like to use her images inside our WPF application as paths. Is there a way to do this?
You can go from AI to SVG to XAML.
From Adobe Illustrator: File -> Save As -> *.SVG.
SVG "Profile 1.1" seems to be sufficient.
Note that to preserve path/group names in XAML you should enable "Preserve Illustrator Editing Capabilities" (or at least as it's called in CS4).
SharpVectors can convert SVG data to XAML data. This will produce a fragment of XAML with root <DrawingGroup>.
Do what you need to do to copy-paste and otherwise use the XAML, such as placing it into an Image like below. Named objects or groups in the AI file should still have their names in the XAML i.e. via x:Name="...".
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ... the output from step #2 ...>...</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
Coordinate systems can be a pain if you want to be animating things. There are some other posts such as this which may have insights.
Get her to export the illustrations as some other format (recent versions of Illustrator support SVG) that you can use or convert to something that will work.
The detour suggested by #ConcernedOfTunbridgeWells is starting to make sense now. Other solutions are not being maintained and do not work anymore.
Hence, you can use this option as workaround:
Save files as svg.
Convert them to XAML using Inkscape.
This solution even has the advantage of text will stay text and is not converted to a path.
How to convert many files?
Inkscape also supports a batch mode to convert many files at once. I took a great script (by Johannes Deml) for batch conversions on Windows that takes vectors files and converts them to various other formats using Inkscapes batch mode. I adapted it to convert to XAML, too.
You can find the script that includes XAML on Github. Some instructions on how to use the script are provided by the original author.

Resources