Skip to content

SysFont on Windows clobbers base fonts with alternate styled versions #3092

Open
@rmccampbell

Description

@rmccampbell

Environment:

Platform:               Windows-11-10.0.22631-SP0
System:                 Windows
System Version:         10.0.22631
Processor:              Intel64 Family 6 Model 154 Stepping 3, GenuineIntel     SSE2: Yes       AVX2: Yes    NEON: No
Architecture:           Bits: 64bit     Linkage: WindowsPE

Python:                 CPython 3.12.5 (tags/v3.12.5:ff3bc82, Aug  6 2024, 20:45:27) [MSC v.1940 64 bit (AMD64)]
pygame version:         2.5.1
SDL versions:           Linked: 2.30.6  Compiled: 2.30.6
SDL Mixer versions:     Linked: 2.8.0   Compiled: 2.8.0
SDL Font versions:      Linked: 2.22.0  Compiled: 2.22.0
SDL Image versions:     Linked: 2.8.2   Compiled: 2.8.2
Freetype versions:      Linked: 2.11.1  Compiled: 2.11.1

Display Driver:         windows
Mixer Driver:           wasapi

Current behavior:

Fonts which have multiple variants (see mods) are normalized on Windows by stripping certain keywords, and if multiple variants have the same name after normalization, only the last version will be kept. This may clobber the base version of fonts. For example, on my computer requesting the font "Arial" results in the actual font "Arial Narrow". Interestingly, this does not strip the word "Regular", so you end up with some odd cases such as "lucidasans" mapping to Lucida Sans Unicode or "lucidafax" to Lucida Fax Demibold while "lucidasansregular" and "lucidafaxregular" map to the plain fonts.

Expected behavior:

  1. The regular fonts should be preserved. I.e. "Arial" should be "Arial"
  2. Alternate font style variants should be selectable individually. So "Arial Narrow" should give the narrow font.

To preserve some backwards compatibility, I think the best solution is to register fonts with multiple aliases: the full name which only strips bold/italic, and the stripped name which does the complete normalization. If there are collisions between a full name and a stripped name then the full name font should always be preferred. There also should probably be some special casing for "Regular".

Test code

import pygame as pg
pg.init()
s = pg.display.set_mode((640, 480))
s.fill((255, 255, 255))

f = pg.font.SysFont('Arial', 48)
img = f.render('Hello, World!', True, (0, 0, 0))
s.blit(img, (50, 50))

f2 = pg.font.Font('C:/Windows/Fonts/arial.ttf', 48)
img2 = f2.render('Hello, World!', True, (0, 0, 0))
s.blit(img2, (50, 150))

pg.display.flip()
input()

Screenshot of test code
(these should match)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugNot working as intendedsysfontpygame.sysfont

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions