Packaging TeX Live For MSYS2

Use Custom Application fonts with Pango/GTK

Custom Application Fonts GTK and Pango

 

I was recently working with Pango, to make it use with a Python binding called ManimPango, and found that Pango still does not make it easy to use custom (aka. application) fonts, and it still does not allow turning OpenType features on or off.  So I decided to give Pango some love 💗.

Whatever I say for Pango will apply for GTK also because GTK uses Pango internally for rendering fonts. So, if you are creating a GTK app say something like Inkscape, it also works for you 😊.

By application fonts, I mean when an application wants to use a font file that it ships, but is not installed in the system or user font directories. For example you are rendering a SVG file with a font which isn't installed in the Users computer.

There isn't a direct way to do that in Pango, so you should use the backend API for adding the fonts to the search path, before calling Pango.

Here is a list of Backend available per Operating System

  • Windows - pangowin32(default), fontconfig(optional)

  • macOS - coretext(default), fontconfig(optional)

  • Linux - fontconfig (default)

For Windows

Win32 API

For Windows, you have to wingdi API, AddFontResourceExA API. This will work if you are going to use the native pangowin32 backend.


Before calling into Pango, do this:

  1. Find the font file you want the add. See the file formats which are recognized here.
  2. Then call AddFontResourceExA or AddFontResourceExW, according whether your application uses UNICODE or not.
  3. Make sure you pass FR_PRIVATE as fl parameter so that you can use your font with Pango.
  4. Use Pango as you otherwise would.

A sample code on how you would use that.

AddFontResourceExA("myapp/cutom.ttf", FR_PRIVATE, 0);

You can see a full example in this repository: https://gitlab.com/naveen521kk/blog-posts/-/tree/master/pango-app-fonts

Fontconfig

Here is one way to do it, using fontconfig API:
Before calling into Pango, do this:
  1. Add fonts to it using FcConfigAppFontAddFile() or FcConfigAppFontAddDir(), set current config as FcConfigGetCurrent()
  2. Use Pango as you otherwise would.

This would work when you have and environment variable called PANGOCAIRO_BACKEND to fc or fontconfig on your User's computer and Pango is compiled with fontconfig enabled. You can also set it before calling Pango but it may crash your application if Pango wasn't compiled with fontconfig and that variable is set. See documentation about this function.

A sample code would be

FcConfigAppFontAddFile(FcConfigGetCurrent(), "myapp/cutom.ttf");

For macOS

Coretext

You should use CTFontManagerRegisterFontsForURL() for registering the font. See the corresponding documentation https://developer.apple.com/documentation/coretext/1499468-ctfontmanagerregisterfontsforurl

Since the API is for objc you can use a binding like Carbon to call the function. The fontURL parameter can be created by using CFURLCreateWithBytes() and pass it the previous function.

A sample code would be


  CFURLRef cf_url = CFURLCreateWithBytes(NULL, "myapp/font.ttf", b, 0x08000100, NULL)
  CTFontManagerRegisterFontsForURL(cf_url, kCTFontManagerScopeProcess, NULL)
  

Fontconfig

This is same as Windows section.

For Linux

This is same as Windows section but here the default backend is Fontconfig and the environment variable needn't be set. There is also a article from here which may explain in detail about using Pango with fonconfig.

Python Apps

For python, it would be simple to depend on a library I created ManimPango for Manim, which can be used across platforms and has a simple API for registering font. https://manimpango.manim.community/en/latest/reference/manimpango.register_font.html

Comments