Skip to content

fix: set_font() early-return skips current_font restore when font state diverges#1872

Merged
andersonhc merged 2 commits into
py-pdf:masterfrom
gaoflow:fix/set-font-early-return-current-font
Jun 26, 2026
Merged

fix: set_font() early-return skips current_font restore when font state diverges#1872
andersonhc merged 2 commits into
py-pdf:masterfrom
gaoflow:fix/set-font-early-return-current-font

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 24, 2026

Copy link
Copy Markdown

Problem

set_font() has an early-return guard that fires when font_family, font_style, and font_size_pt all match the requested values. However it does not check whether current_font is consistent with those high-level attributes.

When a fallback font is rendered (see line ~4167 in fpdf.py), the code updates self.current_font to the fallback font object while leaving self.font_family pointing to the primary font. After rendering, calling set_font('primary') finds font_family == 'primary' (match), font_style == '' (match), and font_size_pt (match), so it returns early without restoring current_font back to the primary font object.

This is the root cause of #1488: subsequent PDF rendering uses the stale fallback current_font.

Fix

Add self.current_font.fontkey == fontkey to the early-return condition. When current_font has diverged from font_family (inconsistent state), the guard no longer fires and set_font() proceeds through its full logic to select the correct font.

As a minor cleanup, fontkey = family + style is now computed once before the early-return check (instead of again immediately after).

Test

Added test_set_font_restores_current_font_after_state_divergence in test/fonts/test_set_font.py that:

  1. Creates the divergent state by setting font_family = 'helvetica' while current_font = times_font
  2. Calls set_font('Helvetica') and asserts current_font.fontkey == 'helvetica'

The test fails on the old code and passes with this fix.

This pull request was prepared with the assistance of AI, under my direction and review.

…verges

When a fallback font is used during rendering, the internal `current_font`
can diverge from `font_family`: `font_family` stays as the primary font
name while `current_font` is updated to the fallback font object (fpdf.py
line ~4167). After rendering, `set_font('primary')` hits the early-return
guard that checks `font_family == family`, finds a match, and returns
without restoring `current_font` to the primary font object.

Add `current_font.fontkey == fontkey` to the early-return condition so
that a diverged state (font_family matches but current_font does not)
is always corrected by proceeding through the full `set_font()` logic.

Moves `fontkey = family + style` above the early-return check to avoid
computing it twice.

Fixes py-pdf#1488

@andersonhc andersonhc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @gaoflow

Can you please add an entry in CHANGELOG.md?

I'm good to merge after it.

@gaoflow

gaoflow commented Jun 25, 2026

Copy link
Copy Markdown
Author

Added the changelog entry in e92eb1399.

Local verification:

  • python -m pytest test/fonts/test_set_font.py::test_set_font_restores_current_font_after_state_divergence -q
  • git diff --check

@andersonhc

Copy link
Copy Markdown
Collaborator

@allcontributors please add @gaoflow for code

@allcontributors

Copy link
Copy Markdown

@andersonhc

I've put up a pull request to add @gaoflow! 🎉

@andersonhc andersonhc merged commit fe53997 into py-pdf:master Jun 26, 2026
23 checks passed
@andersonhc

Copy link
Copy Markdown
Collaborator

Merged. Thank you @gaoflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants