David
David

Reputation: 4873

Converting System.Windows.Forms.Font to System.Windows.Media.FontFamily not working for irregular styles

So, I know there are multiple thread on how to do the conversion between the aforementioned systems. And I know they're not 1-to-1. However, I'm hoping there's a way to be able to get things to work.

The fonts specifically in question are just examples, as I'm sure others have the same issue, Segoe UI just happens to be my default font. What's not working though, is when I select Segoe UI Semibold Italic or some other in-between font.

Here's my conversion code:

// Font family
FontFamilyConverter ffc = new FontFamilyConverter();
TextContent.FontFamily = (System.Windows.Media.FontFamily)
    ffc.ConvertFromString(fontDialog.Font.Name);
// Font size
TextContent.FontSize = fontDialog.Font.Size;

// Bold?
TextContent.FontWeight = (fontDialog.Font.Bold ? FontWeights.Bold : FontWeights.Normal);

// Italic?
TextContent.FontStyle = (fontDialog.Font.Italic ? FontStyles.Italic : FontStyles.Normal);

// Underline and strikethrough?
TextContent.TextDecorations = new TextDecorationCollection();
if (fontDialog.Font.Strikeout) {
    TextContent.TextDecorations.Add(TextDecorations.Strikethrough);
}
if (fontDialog.Font.Underline) {
    TextContent.TextDecorations.Add(TextDecorations.Underline);
}

// Color
TextContent.Foreground = new SolidColorBrush(
    System.Windows.Media.Color.FromArgb(fontDialog.Color.A,
                                        fontDialog.Color.R,
                                        fontDialog.Color.G,
                                        fontDialog.Color.B)
                                        );

From using the debugger, I know that the Italic property is being properly set, but the font isn't coming through as Semibold Italic it's just coming through as Semibold. If (when in the debugger) I change the FontFamily to "Segoe UI Semibold Italic" then it works.

Is there something I'm missing to be able to get all the styles to come across correctly?

Thanks.

Note: I know size isn't working correctly. Just haven't fixed it yet

Upvotes: 1

Views: 3407

Answers (1)

David
David

Reputation: 4873

Here is what I ended up with:

After the dialog returns OK:

FontFamilyConverter ffc = new FontFamilyConverter();
TextContent.FontFamily = (System.Windows.Media.FontFamily) ffc.ConvertFromString(getFontName(fontDialog.Font));

A helper method:

private List<string> limitFontList(List<string> fontList, string word) {
    // Create a new list
    var newFontList = new List<string>();

    // Go through each element in the list
    foreach (var fontFamily in fontList) {
        // If the elment contains the word
        if (fontFamily.ToLower().Contains(word.ToLower())) {
            // Add it to the new list
            newFontList.Add(fontFamily);
        }
    }

    // Return the new list if anything was put in it, otherwise the original list.
    return newFontList.Count > 0 ? newFontList :  fontList;
}

getFontName:

private string getFontName(Font font) {
    // Holds the font we want to return. This will be the original name if
    // a better one cannot be found
    string fontWanted = font.FontFamily.Name;

    // Create a new Media.FontFamily
    var family = new System.Windows.Media.FontFamily(fontWanted);

    /// Get the base font name
    string baseFont = ""; // Holds the name
    /* FamilyNames.Values will holds the base name, but it's in a collection
    ** and the easiest way to get it is to use a foreach. To the best of my
    ** knowledge, there is only ever one value in Values.
    ** E.g. If the font set is Segoe UI SemiBold Italc, gets Segoe UI.
    */
    foreach(var baseF in family.FamilyNames.Values){
        baseFont = baseF;
    }

    // If the baseFont is what we were passed in, then just return
    if(baseFont == fontWanted) {
        return fontWanted;
    }

    // Get the typeface by extracting the basefont from the name.
    // Trim removes any preceeeding spaces.
    string fontTypeface = fontWanted.Substring(baseFont.Length).Trim();


    // Will hold all of the font names to be checked.
    var fontNames = new List<string>();


    // Go through all of the available typefaces, and add them to the list
    foreach (var typeface in family.FamilyTypefaces) {
        foreach(var fn in typeface.AdjustedFaceNames) {
            fontNames.Add(baseFont + " " + fn.Value);
        }
    }

    // Limit the list to elements which contain the specified typeface
    fontNames = limitFontList(fontNames, fontTypeface);


    // If the font is bold, and the original name doesn't have bold in it (semibold?)
    if(!baseFont.ToLower().Contains("bold") && font.Bold) {
        fontNames = limitFontList(fontNames, "bold");
    }
    // In a similar manner for italics
    if (!baseFont.ToLower().Contains("italic") && font.Italic) {
        fontNames = limitFontList(fontNames, "italic");
    }

    // If we have only one result left
    if(fontNames.Count == 1) {
        return fontNames[0];
    }

    // Otherwise, we can't accurately determine what the long name is,
    // So hope whatever the short name is will work.
    return fontWanted;
}

Upvotes: 1

Related Questions