[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)



Hello,

thank you very much for your explanation!

So if there is no plain one available, it should try and use the italic or bold instead I guess.

So I think that should be the fix we should apply.  Are you able to supply a patch for that?

cheers,



On Wed, Aug 17, 2011 at 11:20 PM, Jeremy Sharpe <jeremy.adamson.sharpe@xxxxxxxxx> wrote:
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?
>