[wxPython-users] LCD vs CRT Monitors Issues (!)

Robin Dunn robin at alldunn.com
Fri Nov 2 14:51:45 PDT 2007


Nitro wrote:
> Am 02.11.2007, 13:12 Uhr, schrieb Andrea Gavana <andrea.gavana at gmail.com>:
> 
>> Hi Robin and All,
>>
>> On 11/2/07, Robin Dunn wrote:
>>> Andrea Gavana wrote:
>>>
>>> > Curiously, just replacing this line:
>>> >
>>> > fnt = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
>>> >
>>> > with this line:
>>> >
>>> > fnt = wx.SystemSettings_GetFont(wx.SYS_ANSI_VAR_FONT)
>>> >
>>> > Fixed the issue. I have no idea why, but it works.
>>>
>>> Probably because the font used in that case on your system is either a
>>> bitmap font (instead of a vector format like TTF) or doesn't specify any
>>> hinting that the system will use for anti-aliased drawing.
>>>
>>> I expect that the only way to truly solve this for any font is to make
>>> sure that the text only gets drawn once.  If it needs to be drawn again
>>> for some reason, such as it is part of the update region in a paint
>>> event, then you either need to redraw everything 'behind' it too, or
>>> don't use dc.SetBackgroundMode(wx.TRANSPARENT).  To better see what is
>>> happening you should get a tool that lets you zoom in on the display and
>>> see the individual pixels magnified.  If you look at some text then if
>>> it's using anti-aliasing (or 'font smoothing' or 'ClearType') you'll see
>>> some pixels along the curves and corners that are not fully black, or
>>> that may even have some color.  If the same text gets redrawn at the
>>> same place then those aliased pixels will be blended with the ones that
>>> are already there and they will become a little bit darker, and a little
>>> more dark the next time it is drawn.
>>
>> I found that the issue is *not* related to multiple drawing of the
>> text, but actually on a strange behavior of wx.Mask/wx.MemoryDC. Let
>> me explain.
>>
>> To speed up the drawing, the first time I paint the menubar (and after
>> every resize event), I paint the menu label (with its accelerator) to
>> a bitmap using a wx.MemoryDC() and I save a reference to this bitmap
>> in the menu class. All the next paint event (generated by
>> EVT_ENTER_WINDOW, EVT_LEAVE_WINDOW and others) use this bitmap instead
>> of redrawing the text because it's much faster (redrawing the text
>> requires more calculations, background drawing, line drawing etc...).
>>
>> Ok, the problem is, I paint the menu background using the following code:
>>
>> bmp = wx.EmptyBitmap(rect.width, rect.height)
>> memDc = wx.MemoryDC()
>> memDc.SelectObject(bmp)
>>
>> # Fill the bitmap with the maksing colour
>> memDc.SetPen(wx.Pen(wx.Colour(0, 128, 128)))
>> memDc.SetBrush(wx.Brush(wx.Colour(0, 128, 128)))
>> memDc.DrawRectangle(0, 0, rect.width, rect.height)
>>
>> And then I do all the voodoo to correctly paint the menu label. In the
>> end, what I do to store the bitmap is:
>>
>> bmp.SetMask(wx.Mask(bmp, wx.Colour(0, 128, 128)))
>> item.SetTextBitmap(bmp)
>>
>> The problem is with wx.Mask: it doesn't mask correctly the
>> wx.Colour(0, 128, 128), or whatever other colour you choose for the
>> wx.Pen, wx.Brush and wx.Mask. I attach a simple example which
>> demonstrates the problem: you will notice that the text saved to a
>> bitmap (and then painted on the DC) is blurred. Obviously you will see
>> this strange behavior on LCD screens or on CRT screens with ClearType
>> on.
>>
>> Does anyone know what I can do to obtain the bitmap with the correct
>> mask? Any other solution?
> 
> I guess what's happening is that the anti-aliased text is blended with 
> your mask colour, thereby slightly altering it. 

Correct.  Zoom in on the text that the sample draws and you'll probably 
see that the same pixels in the top test are also getting shades of grey 
(because the black text is being blended with the white background.)  So 
if you can imagine using white as your mask color in that case and 
drawing it on a blue background you can see that you would have the same 
problem.

> Then the mask won't work 
> anymore because it masks exactly one colour. You can think of masks as 
> 1-bit alpha channels. Anti-aliasing has varying levels of alpha and thus 
> the 1-bit won't cut it anymore.
> One way to solve this is to use some kind of 8-bit alpha channel. The 
> background colour of the bitmap would be completely transparent. Then 
> the text drawing would fill the bitmap in such a way that the alpha 
> channel is taken account of. Meaning 50% anti-aliased pixels get an 
> alpha value of 128 while fullly drawn pixels use an alpha of 255.
> Now I am not sure if wx can do all this kind of alpha handling. I guess 
> especially the "draw font into bitmap preserving alpha information" part 
> might be impossible. Then you could probably just fill the bitmap with 
> the background colour initially instead.

Just doing DrawText when you need to draw it would probably be more 
efficient than trying to play games with alpha and bitmaps.  The 
platform has already optimized the heck out of text drawing and aliasing 
so you may as well use it.


-- 
Robin Dunn
Software Craftsman
http://wxPython.org  Java give you jitters?  Relax with wxPython!





More information about the wxpython-users mailing list