Tk Source Code

View Ticket
Login
Ticket UUID: c81e0ccee2b971b01f58a9adb8bfa42ae66b785e
Title: Named font late creation
Type: Bug Version: >= 8.0
Submitter: chw Created on: 2025-06-06 05:46:08
Subsystem: 44. Generic Fonts Assigned To: nobody
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2026-10-24 14:22:21
Resolution: Fixed Closed By: nemethi
    Closed on: 2026-10-24 14:22:21
Description:

Named fonts are not configured properly when the font name is used in a widget prior to the creation of the named font by the font create command as shown in the following snippet.

proc step1 {} {
    after 1000 step2
    ttk::style configure TLabel -font ANamedFont
    label .l1 -text "A normal label" -font ANamedFont
    ttk::label .l2 -text "A ttk::label"
    pack .l1 .l2
}
proc step2 {} {
    after 1000 step3
    font create ANamedFont -family Helvetica -size 30
}
proc step3 {} {
    ttk::label .l3 -text "Another ttk::label"
    pack .l3
}
step1

The expected outcome would be the first two labels having Helvetica 30 after a second, and the third label having that same font after two seconds. However, no font change happens both on Win32 and POSIX (Mac untested), i.e. the system chosen fallback font remains in use. In contrast, this snippet does what one expects:

proc step1 {} {
    after 1000 step2
    ttk::style configure TLabel -font ANamedFont
    font create ANamedFont -family Helvetica -size 30
    label .l1 -text "A normal label" -font ANamedFont
    ttk::label .l2 -text "A ttk::label"
    pack .l1 .l2
}
proc step2 {} {
    after 1000 step3
    font delete ANamedFont
    font create ANamedFont -family Courier -size 30
}
proc step3 {} {
    ttk::label .l3 -text "Another ttk::label"
    pack .l3
}
step1

So there's some confusion in the font subsystem regarding caching of named and unnamed fonts and when to perform updates. Therefore I attach a proposed fix as a patch against core-8-6-branch.

User Comments: nemethi (claiming to be Csaba Nemethi) added on 2026-10-24 14:22:21:

Christian, Harald, and Serhiy, many thanks! Merged into main, core-9-0-branch, and core-8-6-branch by commits [f89023e3ee], [3e71cad9], and [a344fe53].


serhiy.storchaka added on 2026-10-24 14:08:24:

Thank you, Marc. Which check-in did you test? The fix was merged into main in [f89023e3ee] and into core-9-0-branch in [3e71cad966] today. If your build includes it, the first script should show the labels in Helvetica 30 after a second.


marc_culler (claiming to be Marc Culler) added on 2026-10-24 13:52:31:
On macOS,

* With the first script I see two labels appear in a small Helvetica font.
Then one second later the third appears, also in the small Helvetica font.


* With the second script I see the first two labels appear in a large
Helvetica font.  Then after a second they change to Courier in the same  
size.  Then after another second a third label appears in Courier.

I think that means that the problem is the same on macOS, which is
consistent with the claim that the problem is in tkFont.c.

serhiy.storchaka added on 2026-09-26 17:54:51:

The patch looks good, but has a few conflicts with main, so I created a rebased branch named-font-late-creation with two more low-level tests, one of them for a regression from [8da7af2f8e]. The examples from the ticket (including ttk) work on Linux, and the font and ttk tests pass.

The regression: if a font name was used before font create with that name (e.g. by font actual), the unused font, which is now kept in the cache until idle time, shadowed the new named font. The patch fixes it too. If there are issues with this patch, I can create a separate fix for the regression.


oehhar added on 2025-06-06 13:39:30:

Christian,

I see your reson. But then, most tests should do so.

AFAIK, we have a test start argument, to run tests individually. I suppose, the reason why this is not done systematically is test time. Don Ported does that and finds dependencies between the tests.

Thanks for all, Harald


chw added on 2025-06-06 13:29:37:

Harald,

while I can live with the test, doing this in another interp serves a purpose: to get a ultra clean (Mr Proper) start condition for the test, since that interp loads and initializes its own little Tk world. Just a thought.


oehhar added on 2025-06-06 12:47:49:

Thanks ! Added test by commit [c81e0cce].

I simplified the test (removing the interpreter) and commented it, so even I do understand it ;-).

If you resist in writing to branches directly, you have to live with my stupid commits....

Thanks for all, Harald


chw added on 2025-06-06 12:16:21:

Without further instrumentation it might be possible to test it somehow unsharp with this approach

test font-x.x {Named font late creation} -setup {
    catch {interp delete foo}
} -body {
    interp create foo
    foo eval {
        load {} Tk
        font create F1 -family Helvetica -size 100
        label .l -font F1 -text LARGE
        pack .l
        update
        set W1 [winfo width .l]
        destroy .l
        font delete F1
        label .l -font F2 -text LARGE
        pack .l
        update
        font create F2 -family Helvetica -size 100
        update
        set W2 [winfo width .l]
        destroy .l
        font delete F2
    }
    set result [foo eval {expr {$W1 == $W2}}]
    foo eval {destroy .}
    interp delete foo
} -result 1

but this is a sketch only. Please refine.


oehhar added on 2025-06-06 11:36:54:

Yes. Could you provide a test case? I think, with a test case, this may quickly be merged.

Thanks, Harald


chw added on 2025-06-06 11:23:41:

Harald,

thanks for testing. Indeed is this problem as old as Tk 8.0 as far as can be seen in tkFont.c. In the second snippet of the ticket, the font delete is essential, since it proves that on re-creation of the same named font an update is performed. But the fix addresses the initial case, i.e. named font non-existent, font subsystem uses a fallback, and after that the named font is created in the expectation to be immediately used.


oehhar added on 2025-06-06 10:59:59:

I can confirm, that the patch is effective, and that the additional "font delete" is not required any more.

My environment: win32+MS-VC6 on MS-Win11 64 bit GER.

I can also confirm, that the bug is also present in Tk 9.0.1

Comments and tests welcome

Great job, Christian ! Harald


oehhar added on 2025-06-06 10:00:11:

Pathch now in commit [ed0d5d23], VC6 optimized. Tests pass with MS-VC6 Thanks, Harald


Attachments: