Skip to content

Use FcPatternGetCharSet to fast skip fonts in findSystemFontFileForUChar

HorizontalTextLayouter checks fallback font for every character that newFontNeeded is true. It finally calls GlobalParams::findSystemFontFileForUChar to list available fonts and find the first font satisfying the uChar. However, this is slow as supportedFontForEmbedding() needs to load and parse all fonts file until it finds the appropriate one. To make things worse, poppler has to do this for every single character that default font could not render.

I added std::chrono::system_clock inside drawMultiLineText. On my laptop this following sentences (341 chars) requires 1.1s to render, with default font set as Noto Sans (tested with Okular "inline note" mode):

噫吁嚱,危乎高哉,蜀道之难,难于上青天!蚕丛及鱼凫,开国何茫然。尔来四万八千岁,不与秦塞通人烟。西当太白有鸟道,可以横绝峨眉巅。地崩山摧壮士死,然后天梯石栈相钩连。上有六龙回日之高标,下有冲波逆折之回川。黄鹤之飞尚不得过,猿猱欲度愁攀援。青泥何盘盘,百步九折萦岩峦。扪参历井仰胁息,以手抚膺坐长叹。问君西游何时还,畏途巉岩不可攀。但见悲鸟号古木,雄飞雌从绕林间。又闻子规啼夜月,愁空山。蜀道之难难于上青天,使人听此凋朱颜。连峯去天不盈尺,枯松倒挂倚绝壁。飞湍瀑流争喧豗,砯厓转石万壑雷。其险也如此,嗟尔远道之人胡为乎来哉。剑阁峥嵘而崔嵬,一夫当关,万夫莫开。所守或匪亲,化为狼与豺。朝避猛虎,夕避长蛇。磨牙吮血,杀人如麻。锦城虽云乐,不如早还家。蜀道之难难于上青天,侧身西望长咨嗟。

This is slow as findSystemFontFileForUChar needs to load and parse 24 fonts for every character every time, thus it needs about 3ms to render a single character. Setting default font to something like Source Han Sans workarounds this bug, but:

  • Distro/Software default font settings might set to a Latin font even when users work with their own languages.
  • The Latin part of these fonts may be worse, and then users might not prefer to set them as default.

To avoid loading and parsing lots of fonts manually, this patch utilizes fontconfig API: it uses FcCharSetHasChar() to make sure current font could handle current uChar, and then call supportedFontForEmbedding() to check if it supports unicode bmp cmaps.

This is faster (though still have a lot of room for improvement) -- it takes 0.47s, a 2.3x performance improvement. And also this helps add caching for supportedFontForEmbedding later as it only needs to check fonts that could really render characters that we want.

Merge request reports