Skip to content

Width calculated by get_string_width is slightly too small for multi_cell #1393

@andreaswimmer

Description

@andreaswimmer

Error details
get_string_width returns a (slightly) too small a value, leading to multi_cell splitting the string.

In the snippet below, I calculate the width of a string with get_string_width and then create a multi_cell with exactly that width (127.512)
However multi_cell deems that too small and inserts a line break. It is not due to c_margin, which I set to 0/include in the calculation.

This bug is very finicky and hard to hit. Small changes in the text, increasing the value by a tiny amount (length += 1e-12), changing the font or the page unit all make it disappear.

From what I can tell, this is a classic floating point error: MultiLineBreak calculates the width as 127.51200000000001 - which is above the limit of 127.512 - and inserts a line break.

Is this fixable?
My current workaround is to round up the values of get_string_width, is there a better way you'd recommend?

Minimal code
You will need the font Inter, which you can get for free at https://rsms.me/inter/download/
I tried to reproduce the issue with a default font, but couldn't.

from fpdf import FPDF
from fpdf.enums import MethodReturnValue

doc = FPDF(unit="pt")
doc.add_font("Inter", fname="./Inter.ttc")
doc.set_font("Inter")
doc.add_page()
# the bug occurs even if not setting c_margin to 0, since it is included in the length below
doc.c_margin = 0
text = "2025-03-11 17:42 UTC"
length = doc.get_string_width(text) + doc.c_margin * 2
# length = 127.512
print(f"length = {length}")
lines = doc.multi_cell(
    text=text,
    dry_run=True,
    output=MethodReturnValue.LINES,
    w=length,
)

# this fails
assert len(lines) == 1, lines

Environment

  • Operating System: Windows 11
  • Python version: 3.9.21
  • fpdf2 version used: 2.8.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions