[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] BUG: SysFont hangs when loading certain fonts (with cause and fix ideas)



Ah sorry, I posted it through the Google Groups mirror and I think it
may have eaten my original message. Here it is again:

SysFont hangs when loading certain fonts. For example, on my Windows 7
machine, I can produce a hang with the line

pygame.font.SysFont("vivaldi", 12)

(See the attached script, sysfont_hang.py, which should reproduce it
on any machine.)

The problem is that SysFont assumes that every system font has a
non-bold, non-italic version, and this assumption causes it to enter
an infinite loop. In the example above, the font "vivaldi" in fact
only has one version, an italic, non-bold version. This messes with
the following code from lib/sysfont.py:

-------------------

def SysFont(name, size, bold=False, italic=False, constructor=None):
    if constructor is None:
        constructor = font_constructor
    if not Sysfonts:
        initsysfonts()

    gotbold = gotitalic = False
    fontname = None
    if name:
        allnames = name
        for name in allnames.split(','):
            name = _simplename(name)
            styles = Sysfonts.get(name)
            if not styles:
                styles = Sysalias.get(name)
            if styles:
                while not fontname:
                    plainname = styles.get((False, False))
                    fontname = styles.get((bold, italic))
                    if not fontname:
                        fontname = plainname
                    elif plainname != fontname:
                        gotbold = bold
                        gotitalic = italic
            if fontname: break
    set_bold = set_italic = False
    if bold and not gotbold:
        set_bold = True
    if italic and not gotitalic:
        set_italic = True
    return constructor(fontname, size, set_bold, set_italic)

-------------------

This while loop is the part that hangs:

-------------------

            if styles:
                while not fontname:
                    plainname = styles.get((False, False))
                    fontname = styles.get((bold, italic))
                    if not fontname:
                        fontname = plainname
                    elif plainname != fontname:
                        gotbold = bold
                        gotitalic = italic

-------------------

The problem is that "styles", in the case of a font like "vivaldi" on
Windows 7, is this map:

{(0, 1): "PATH_TO_FONT"}

With a bit of examination, it can be seen that in such a case, this
while loop will never terminate.

I haven't attached a patch because I'm not sure exactly the right way
to fix this. Should it simply return list(styles.values())[0] in this
case, should it throw an exception, or should it default to pygame's
default font?

Thanks for reading,

Jeremy Sharpe

On Wed, Aug 17, 2011 at 5:18 PM, René Dudfield <renesd@xxxxxxxxx> wrote:
> On Wed, Aug 17, 2011 at 11:10 PM, Jeremy Sharpe
> <jeremy.adamson.sharpe@xxxxxxxxx> wrote:
>>
>> I see that rev 964 fixed a similar bug in this area of code, but seems to
>> have missed the case where both fontname AND plainname are None, which is
>> what results in the infinite loop.
>
> Hello,
>
> I think I may have missed an earlier email...  What should be changed to fix
> it?
>

Attachment: sysfont_hang.py
Description: Binary data