SVG export leaves space between stems and heads

• Apr 19, 2016 - 14:55
Reported version
S4 - Minor

In certain cases, SVG export puts heads slightly away from the end of stem so they look disconnected.


This is connected to the Staff space setting in the Page Layout dialog, which is the spatium value used internally for scaling the score. 5.0 points/pixels or 1.764mm = 100% scaling, any other value causes proportional scaling of the score, larger or smaller. The example score has a Staff space value of 2.164mm, which is scaling by 123%.

If you set the Staff space value to 1.764mm the problem goes away, although the resulting export is also smaller, which is not what you want.

I'll work on a fix and post a PR when I have one.

If you urgently need a workaround, change the Staff space value to 1.764, then scale the SVG itself, wherever you're using it. That's the great thing about SVG!

Pull request here:

One line of code changed. I had misunderstood the way scaling works in the SVG and the Qt transform matrices, which are different btw. Now it's correct. You'll see that the resulting SVG export is now properly scaled at 123% in your example file. The spaces between note heads and stems was not the whole problem. But it's all solved in this PR.

In case it helps, I've attached a "non-fail" version of your file's export. It was exported with the code in the PR.

Attachment Size
graphic export.svg 23.58 KB

it failed the travis build for reasons I do not comprehend. I am waiting for a new version of the PR to complete the initial checks, then I'll repost the PR. Sorry - the code change is so simple I could not imagine that there could be a failure.

The Travis CI build failed again, in mtest, which I did not change. The branch appears to be properly rebased, only one commit ahead of master. What is the problem? Someone else can make the same change and try creating a PR - the change is less than 20 characters, and I have compiled and run it successfully.

Here is the new, failed PR:

A note about this fix (in case anyone cares...):

Scaling via the Staff Space or spatium value is scaling of the entire document. To accomplish that, this fix creates a transform in SVG for each individual element in the SVG file. That's a lot of identical transforms, repeated throughout the file.
In SVG, the correct way to scale the whole document is through the viewBox, width, and height attributes. That way there is one change, a modified pair of values, versus potentially thousands of changes, one per score element.

The issue here is that MuseScore and Qt scale the elements individually. If the code wants to make a better SVG file, scaling via the viewBox attribute, it would have to:
a) temporarily revert the spatium to 5.0 points (1.764mm)\
b) export the SVG with scaled viewBox values
c) then restore the spatium to the user-specified value
or something along those lines. Sounds clumsy and potentially screen-flicker-causing to me.

The current code is not seriously inefficient, nor is it wrong in any way. I am simply immersed in this stuff right now, and for my larger scores, efficiencies like this are important to me, because they add up across thousands of elements. So I want to clarify this detail for others as best I can.

I recommend:

1) If you're planning to export an entire score to SVG, set your Staff space value in the Page Layout dialog to 1.764mm or 5.0 points/pixels. Then export to SVG, and scale the score in a container app (like Inkscape, Libre Office or MS Word), or by directly editing the viewBox attribute values in a text editor.

2) If you're collecting snippets of a score to import into another document, and you want those snippets to be generally larger or smaller in their default size, then scale the score with the Staff space value in Page Layout. It will save you the hassle of resizing your snippets in the final document, and you have one setting that controls the scaling of all your snippets.

1. I suppose your fix solves this finding:

2. I can understand your idea to accomplish the scaling with the viewbox only, without transform of individual elements. But the way of changing the whole score to default, and then scaling this, wouldn't that result in a different layout? With different numbers of bars per line?
You would also have to change the page dimensions for preserving this, wouldn't you?

1) Yes it should fix that. It should definitely be re-tested against this issue.

2) I suppose it depends on your page size. Why are you scaling the score in the first place? Understanding that is key to understanding your desired results. You might be right that for some scores, depending on the specific Staff Space value, additional steps are required to properly complete what I was describing. But it also might be that you are scaling the score unnecessarily, and that zooming via the View menu might be what you really need, for example. If you provide details, we can walk through it here and make sure your needs are properly met. Why are you scaling? Why are you exporting to SVG? How do you present the SVG in your final "document"?

It's important to remember that in SVG pages don't exist, they're just horizontal offsets on one big canvas.

But what are you exporting to SVG and why? What is your intention for the "pages" in SVG?

If you are specifically planning to export a full score to SVG, you might make sure your staff spacing is the default, no scaling. Yes it makes the staff lines closer together vertically, but it scales x and y axes the same - proportional scaling. And make your page size anything you want, or specifically make it all one huge page, because that's what SVG is.

I'm just trying to understand what you're trying to do, so I can provide a specific response.

I'm also trying to impress upon you that SVG is a different paradigm, of sorts, than the printed page, and you should approach it differently; give some serious thought to what you want out of a full-score SVG document.

Ok, i can see that the exported svg can be useful for different uses.
But i wanted to make sure that you can export your score with the exact same layout that you see on the screen to svg file. So you can use these with the exact same wysiwyg layout in page layout programs.
Also the possibility to export to individual svgs per page would be useful for creating books.

Maybe i just don't understand the way you want to go with temporarily setting the staffsize to default.?
So someone has an orchestral score of very small staff spacing and presses export to svg. If the exporter would make musescore change the staffspacing to default then the whole layout will be changed, perhaps the instrumentrs no longer fit on one page. Fewer bars will fit into one line. Custom page breaks will appear senseless. The number of pages would increase etc. Or wouldn't musescore change the layout according to how the music fits onto the pages?

Recommendation #1 is a way to avoid scaling each element in the file. If you can't do it because of other constraints, then the pending PR will export the file properly. It's only that the file could be more efficient and smaller if you can follow recommendation #1.

Separate files for each page is something that came up late last year, and I believe @lasconic agreed that it was a good idea, so as to make SVG Export the same as PNG Export. I had left it as something for someone else to do... It's not a feature I would use in the foreseeable future.

Would it be possible to group the pages or add some kind of info into the svg so that one could split the svg afterwards easier?

Just asking. Perhaps there is an easy way to do that during export. For musescore 2.0.2 i wrote a svg splitter that compares all coordinates of the elements and that was the non elegant way. But the coordinates were easy to find because they all were in the same form of "transformmatrix".

sorry for the edits, but it's all coming back to me now: the file is in page order, easily separated, as mentioned below. But the problem is that the location of the elements on later pages is offset very far to the right. So you can separate easily, but it's difficult to remove the offset value, because it's embedded in the path and polyline numbers.

The order of elements in the SVG file is back-to-front, bottom-to-top, by element type, but it's also by page (my original post of this comment was wrong). So the file is already that way. Just look for barlines, they're usually the first thing drawn on each page. There might be a slursegment if there's a bracket on the staves.

I don't think the code change to export pages as separate files is difficult, it's just a priority thing.

Gosh darn it! I misspoke: it's Staff Lines, not bar lines at the top. And you might try wrapping the entire page in a group element with transform=translate(-xoffset * pageNumber, 0)

Thanks for the ideas.
As long as i can find out what is on what page the rest is easy.

Using the viewbox i don't have to move the elements i just move the viewbox. Thats what i did in my 2.0.2 svg splitter, optional deleting the stuff outside of the viewbox.

Only for this deletion option to remove the unused stuff it was necessary to scan the elements.
For importing svg images into inkscape or libreoffice it's just nice to work with smaller files that don't contain stuff outside the viewbox.

For showing the svg page-wise on eg. a website one can use the whole multipage svg and just alter the viewbox to only show a chosen page.

Yes, viewBox is a good way to do it. I wasn't sure of your skill level in working inside the SVG.

If you're showing the score in a web page you might consider reformatting it so that it's all one page. That's what I do, scores that scroll horizontally or vertically on a single page in a browser. Horizontal scrolling is the best for full scores. One page, one system, like continuous view in MuseScore. Pages are a legacy concept in SVG, HTML, and the browser in general. Embrace the future!

See #119721 for full response. It was broken by my last PR which fixed problems with tablature. It's a simple fix that requires putting ".0" after a number twice. See #119721 for further details and info on the pending PR.