Search code examples
pythonpymupdf

PyMuPDF get optimal font size given a rectangle


I am making an algorithm that performs certain edits to a PDF using the fitz module of PyMuPDF, more precisely inside widgets. The font size 0 has a weird behaviour, not fitting in the widget, so I thought of calculating the distance myself. But searching how to do so only led me to innate/library functions in other programming languages. Is there a way in PyMuPDF to get the optimal/maximal font size given a rectangle, the text and the font?


Solution

  • As @Seon wrote, there is rc = page.insert_textbox(), which does nothing if the text does not fit. This is indicated by a negative float rc - the rectangle height deficite.

    If positive however, the text has been written and it is too late for optimizing the font size.

    You can of course create a Font object for your font and check text length beforehand using tl = font.text_length(text, fontsize=fs). Dividing tl / rect.width gives you an approximate number of lines in the rectangle, which you can compare with the rectangle height: rect.height / (fs * factor) in turn is a good estimate for the number of available lines in the rect.

    The fontsize fs alone does not take the actual line height into account: the "natural" line height of a font is computed using its ascender and decender values lh = (font.ascender - font.descender) * fs. So the above computation should better be rect.height / lh for the number of fitting lines.

    .insert_textbox() has a lineheight parameter: a factor overriding the default (font.ascender - font.descender).

    Decent visual appearances can usually be achieved by setting lineheight=1.2.

    To get a good fit for your text to fit in a rectangle in one line, choose fs = rect.width / font.text_length(text, fontsize=1) for the fontsize.

    All this however is no guarantee for how a specific PDF viewer will react WRT text form fields. They have their own idea about necessary text borders, so you will need some experimenting.