JackTrapper / DelphiBugs

Bug tracker for Delphi
7 stars 2 forks source link

TStatusBar does not erase background before painting text #1

Open JackTrapper opened 5 years ago

JackTrapper commented 5 years ago

Tested

Background

If you .Invalidate a TStatusBar, the paint cycles does not erase the background. This leaves the pixels of the existing text. When anti-aliased text is again re-drawn, it leaves to darkening of the anti-aliased edges:

image

image

image

Raymond Chen explained this bug in his 2006 blog post Pitfalls of transparent rendering of anti-aliased fonts: (archive)

Windows provides a variety of technologies for rendering monochrome text on color displays, taking advantage of display characteristics to provide smoother results. These include grayscale anti-aliasing as well as the more advanced ClearType technique. Both of these methods read from the background pixels to decide what pixels to draw in the foreground. This means that rendering text requires extra attention.

If you draw text with an opaque background, there is no problem because you are explicitly drawing the background pixels as part of the text-drawing call, so the results are consistent regardless of what the previous background pixels were. But if you draw text with a transparent background, then you must make sure the background pixels that you draw against are the ones you really want.

The most common way people mess this up is by drawing text multiple times. I've seen programs which draw text darker and darker the longer you use it.

The solution is to draw text over the correct background. If you don't know what background is on the screen right now, then you need to erase it in order to set it to a known state. Otherwise, you will be blending text against an unknown quantity, which leads to inconsistent (and ugly) results.