Quantcast
Channel: HTML Renderer
Viewing all articles
Browse latest Browse all 693

New Post: fonts that aren't installed on system

$
0
0
OK so I looked into this some more and have a solution to propose.

The key is in CssUtils.GetCachedFont(), which is the only place in the code where Font's are created.

This is the relevant code:
        if (font == null)
        {
            font = new Font(family, size, style);
            _fontsCache[family][size][style] = font;
        }
That particular Font() constructor which takes the family name will only look into the INSTALLED fonts on the system. If the family name is not found, MS Sans Serif is substituted. That's straight from MS Docs. The problem is the application may have fonts loaded into memory via PrivateFontCollection, and they may not be installed in the system. My application does this, and there are many reasons why you would want to do this. If you Google "C# embed font" you will find tons of info on it.

Alternatively if you use the Font() constructor which takes the FontFamily instance, then the font does not have to be installed on the system, and for example can be loaded into a PrivateFontCollection() instance instead. The other way to look at this is if the FontFamily is already in memory, the the Font() constructor has no need to go look at the system fonts, it is already in memory.

So what I suggest is we do the following:
  • expose a new library-level public singleton PrivateFonts for setting an optional global PrivateFontCollection instance via property of the same name.
  • modify GetCachedFont() so that when it needs to create an uncached font, it first checks the singleton to see if the requested font family has already been loaded into memory. If it is, then the Font(FontFamily, string, string) ctor is used to directly create the font from the in-memory font family. If the FontFamily is not found, then the other constructor is used to load the font from the system installed fonts.
As you can see, a nice side-effect of this solution is it avoids the good'ol "Windows Font Fight" between applications. One major shortfall of Windows is it has ONE place to store ALL fonts shared among ALL applications. Two applications that installed different versions of the same font will fight, and the last in wins, and the first one ends up using the wrong font. With this solution, the application would always embed the specific fonts it uses as Embedded Resources, load them into it's own PrivateFontCollection, and it can then set this reference into a library singleton for HtmlRenderer. The application would then be guaranteed to always get the correct fonts, regardless of what fonts are or are not installed on the system.

So this solution would add one new source file for the singleton, and minor modification to CssUtils.GetCachedFont().

What do you think? I can't think of any reason why this wouldn't work.

Later,
Ryan

Viewing all articles
Browse latest Browse all 693

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>