[wxPython-users] LCD vs CRT Monitors Issues (!)
Andrea Gavana
andrea.gavana at gmail.com
Fri Nov 2 05:12:05 PDT 2007
Hi Robin and All,
On 11/2/07, Robin Dunn wrote:
> Andrea Gavana wrote:
>
> > Curiously, just replacing this line:
> >
> > fnt =3D wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
> >
> > with this line:
> >
> > fnt =3D 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 =3D wx.EmptyBitmap(rect.width, rect.height)
memDc =3D 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?
Thank you for your suggestions.
Andrea.
"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
-------------- next part --------------
import wx
class MaskProblem(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.SetBackgroundColour(wx.WHITE)
self.CreateBitmap()
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)
self.Bind(wx.EVT_SIZE, self.OnSize)
def GetText(self):
return "&Edit", 1
def CreateBitmap(self):
rect =3D wx.Rect(0, 0, 100, 100)
bmp =3D wx.EmptyBitmap(rect.width, rect.height)
memDc =3D wx.MemoryDC()
memDc.SelectObject(bmp)
self.DrawText(memDc, rect, kind=3D1)
memDc.SelectObject(wx.NullBitmap)
# Set masking colour to the bitmap
bmp.SetMask(wx.Mask(bmp, wx.Colour(0, 128, 128)))
self.bitmap =3D bmp
def DrawText(self, dc, rect, kind=3D0):
labelOnly, location =3D self.GetText()
fnt =3D wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
fnt.SetPointSize(20) =
if kind:
# Fill the bitmap with the maksing colour
dc.SetPen(wx.Pen(wx.Colour(0, 128, 128)))
dc.SetBrush(wx.Brush(wx.Colour(0, 128, 128)))
dc.DrawRectangle(0, 0, rect.width, rect.height)
dc.SetFont(fnt)
=
# underline the first '&'
before =3D labelOnly[0:location]
underlineLetter =3D labelOnly[location] =
after =3D labelOnly[location+1:]
ww, hh =3D dc.GetTextExtent(labelOnly)
textOffset =3D (rect.width - ww) / 2
=
# before
dc.DrawText(before, textOffset, 0)
# underlineLetter
if "__WXGTK__" not in wx.Platform:
w1, h =3D dc.GetTextExtent(before)
fnt.SetUnderlined(True)
dc.SetFont(fnt)
dc.DrawText(underlineLetter, textOffset + w1, 0)
else:
w1, h =3D dc.GetTextExtent(before)
dc.DrawText(underlineLetter, textOffset + w1, 0)
# Draw the underline ourselves since using the Underline in GTK=
, =
# causes the line to be too close to the letter
=
uderlineLetterW, uderlineLetterH =3D dc.GetTextExtent(underline=
Letter)
dc.DrawLine(rect.x + w1 + textOffset, rect.y + uderlineLetterH =
- 2,
rect.x + w1 + textOffset + uderlineLetterW, rect.y =
+ uderlineLetterH - 2)
# after
w2, h =3D dc.GetTextExtent(underlineLetter)
fnt.SetUnderlined(False)
dc.SetFont(fnt)
dc.DrawText(after, w1 + w2 + textOffset, 0)
=
def OnPaint(self, event):
dc =3D wx.BufferedPaintDC(self)
=
dc.SetBrush(wx.WHITE_BRUSH)
dc.Clear()
fullRect =3D self.GetClientRect()
dc.DrawRectangleRect(fullRect)
dc.DrawBitmap(self.bitmap, 0, 40, True)
rect =3D wx.Rect(0, 0, 100, 100)
self.DrawText(dc, rect)
fnt =3D wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
dc.SetFont(fnt)
dc.DrawText(" =3D=3D> Masked Bitmap", 200, 50)
dc.DrawText(" =3D=3D> Correct Text", 200, 10) =
=
def OnErase(self, event):
pass
def OnSize(self, event):
self.Refresh()
event.Skip()
if __name__ =3D=3D "__main__":
=
app =3D wx.PySimpleApp()
frame =3D wx.Frame(None, -1, "MemDC Troubles", size=3D(500, 400))
panel =3D MaskProblem(frame)
frame.CenterOnScreen()
frame.Show()
app.MainLoop()
=
=
=20
More information about the wxpython-users
mailing list