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



Created a gist (https://gist.github.com/1162771) containing a patch
and a small pygame program I used to test it (it runs through all
bold/italic combination of all the system fonts, navigation by
clicking the left and right arrows on the keyboard). The originally
provided sysfont_hang.py script now successfully completes.

In the patch I've removed the while loop, since it has no effect
(other than to potentially cause infinite loops). In the case that
neither the request style nor the default style (no bold and no
italic) is available, it defaults to an arbitrary style that does
exist. It then sets gotbold and gotitalic as appropriate (these are
flags that determine whether fake bolding or italicizing should be
done).

On Mon, Aug 22, 2011 at 8:41 AM, René Dudfield <renesd@xxxxxxxxx> wrote:
> 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?
>> >
>
>