简体   繁体   中英

.NET PrivateFontCollection - load fonts of different styles

I'm trying to port an application from traditional ASP.NET to Azure and I'm running into a font issue. There's a component that renders images with text drawn on it in a particular non-standard font (Lets call the font "Water").

Water exists as several different TTF files which each represent a different style. I have 12 different TTF files in total, covering styles such as "Water Black Italic", "Water Light", "Water Regular", "Water Ultralight" etc.

On ASP.NET, it was a simple case of installing the fonts in the Windows dir and then from the code calling:

Font _fontMedium = new Font("Water Medium", iFontMedium, FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);

However, on Azure, you can't install your own fonts. Therefore, in order to be able to draw these fonts on an image, I need to upload the font files as content with the application, and use the PrivateFontCollection class to load them individually.

My current code is this:

        PrivateFontCollection fontcollection = new PrivateFontCollection();
        string fontpath = string.Concat(System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "assets\\");
        fontcollection.AddFontFile(string.Concat(fontpath,"water-bold-webfont.ttf"));
        fontcollection.AddFontFile(string.Concat(fontpath, "water-ultralight-webfont.ttf"));
        fontcollection.AddFontFile(string.Concat(fontpath, "water-medium-webfont.ttf"));
        FontFamily[] privatefontfamilies = fontcollection.Families;


        Font _fontMedium = new Font("Water Medium", iFontMedium, FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
        Font _fontSmall = new Font("Water UltraLight", iFontSmall, System.Drawing.GraphicsUnit.Pixel);
        Font _fontMini = new Font("Water Bold", iFontMini, System.Drawing.GraphicsUnit.Pixel);

The problem I have is that after breaking after the font files have been added, there is only one Family in the fontcollection.Families collection: "Water".

Similarly, after the font objects have been declared, the Family defaults to a Microsoft Sans-Serif. If I instead use:

Font _fontMedium = new Font("Water", iFontMedium, FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);

The font loads with the "Water" family, but doesn't seem to give me the ability to select the style properly. My only options for the font style are those defined in the FontStyle enum, which don't cover all the font styles that I'm trying to load.

In short, given a particular font and all of its available styles loaded in separate TTF files, how would you load them into a PrivateFontCollection and use them individually?

referring to your code above, you could try...

Font _fontMedium = 
    new Font(privatefontfamilies[0] , iFontMedium, FontStyle.Regular, 
             System.Drawing.GraphicsUnit.Pixel);

instead of parametizing the font with the fontname string.

Microsoft says (Source: MSDN ):

The first argument passed to the Font constructor is the font family name (not a FontFamily object as is the case for other variations of the Font constructor)

I struggled out that this is definitly wrong (and does not work)! Using the name of the fontfamily the font you want to create is replaced by a similar one (like you've written above). Using the fontfamily-object as parameter works fine (for me).

I have an answer to this. I struggled for a while trying to get PrivateFontCollection to work, and GDI wouldn't have any of it.

I started to dig into native Win32 functions like AddFontResource to see if they could do anything. I eventually figured out that all you need to do is to package the TTF font files as content with the package, add registry entries to "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" for each font to register it, and then you can create a new Font just fine with the name that you gave to the registry key.

In short:

AddFont("Water (TrueType)", string.Concat(fontpath, "Water-Black.ttf"));

Font myfont = new Font("Water Black",16f);

private void AddFont(string fontname, string path) {
    Registry.SetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", fontname, path, RegistryValueKind.String);
}

This seems to work great on dev, I'll go test on staging and report back.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM