Antialiasing with staff lines

• May 10, 2009 - 10:24
S5 - Suggestion
won't fix

MuseScore 0.9.4 WinXP
The staff lines on screen at 100% magnification appear to have different widths - simply because the line separation is calculated as a fraction and the line drawing algorithm has to use anti-aliasing - so some lines have one pixel width and some have two pixel width, at different levels of grey.

On Sibelius for example, the 100% magnification level is chosen to give integer staff line spacing, which avoids the antialiasing difficulty. Sibelius also paints the lines at lower magnifications as a shade of grey, rather than black.

The Sibelius data, on my system:

Magnification	grey level	line width (pixels)	line repeat (pixels)
25%			192			1			2
50%			160			1			4
62.5%			128			1			5
75%			96			1			6
100%			64			1			8
200%			0			2			16

(in other words, it tries to paint a 2 pixel width line in black at 200%, and the shade of grey is determined by the line drawing algorithm at lower magnifications.)

I've had a brief look at the code, and it seems to be to do with the variable _spatium? But I'm not familiar with the term 'spatium' and haven't figured out the exact mechanism how this is used.
At one point we have
PDPI = wi.logicalDpiX();
and it might be safer to use the Y direction if staff line spacing is to be the determining factor.

I mention this issue because MuseScore is looking *really* promising (thankyou) :) - and the refinements will help it stand with the established commercial programs.



Status (old) active won't fix

Implementation of the line drawing routines is deeply buried in the Qt libraries. MuseScore has only the choice of anti-aliasing or not. Experimenting with this i found out that switching anti-aliasing off gives unusable results. There is also no special case for 100% magnification as MuseScore (and Qt) uses floating point for all layout calculations and you (almost) never get any plain integer pixel values for drawing whatever magnification you choose. In the end the antialiasing algorithm has to choose.

Thanks for looking at it, Werner.

> There is also no special case for 100% magnification

I don't have MuseScore available here, but doesn't it start up at 100%, and you can then select different magnification levels from a drop down box? So aren't those magnifications 'special cases'?

My point was that for these predefined special case magnification levels, the line spacing could be organised to be on integer pixels; then Qt's line drawing algorithm would automatically do the right thing. This is what happens with Sibelius. Of course, if the user then chooses by hand a different magnification, for example 93.65%, then the lines *will* have awkward anti-aliasing - exactly the same as on Sibelius.

Have I explained that better? It's simply that MuseScore does not look as good as Sibelius on screen - so I felt there was a case for copying what they do.

Many thanks again for all your work


I noticed in Finale/Sibelius, StaffLine/ Stem have same width and in exact pixel width.
As mentioned above, at 100% it's 1 pixel, less than 100% it's 1 pixel and grey in scale, in (100%, 200%) it's 1 pixel, in [200%, 300%) it's 2 pixels. and so on.
I tried in Qt example/painting/painterpaths, indeed when set antialias, all line widthes are out of control.
Can we draw StaffLine/ Stem in special mode and switch off antialias for them? so we can set line width in pixel, not in float?

To werner:
What is "Experimenting with this i found out that switching anti-aliasing off gives unusable results." ?

It means that staff lines disappeared for some mag values. I expected them to be at least one pixel width (zero pixel width is explicitly defined in X11 drawing as a one pixel line).
Please keep in mind that MuseScore is really WYSIWYG in that the same drawing routines are used for printing and for screen (only the scaling is different). The staff line width is defined in the standard style as 0.08 in spatium units (which is the distance between two staff lines). The actual pixel values also depend on the screen resolution.

I tried to set pen.setCosmetic(true); then whatever value the magnification will be, staffline has at least width of 1.
I also turn off antialias before draw staffline, and backup after drawn, now it looks better.

QPainter::RenderHints oldHint = p.renderHints();
p.setRenderHint(QPainter::Antialiasing, false);

QPen pen(p.pen());
if (pen.widthF() * p.worldMatrix().m11() < 1.0)

// draw staffline


Switch render hint mode maybe slow down whole program, at least when the score is not that big, it runs well.

screen is a low resolution device, usually 96/120 dpi, a double value of line thick often refer to different integer value. about antialias, I think we usually do that with irregular shape, like a charactor in font, or notehead (not an ellipse), but we do not do that on straight line.
so one way to improve this to draw same integer value thick line for each staffline, stem, single barline, leger, etc,. use pen.setWidth();
As to printer, it has higher resolution, > 600 dpi, so it can use a double value of line thick.