SVG scaling on import and export

• Mar 4, 2016 - 17:54

@lasconic raised this issue in this thread on github: https://github.com/musescore/MuseScore/pull/2338#issuecomment-173463216 (see earlier in the thread for further details)

One real symptom: Imported SVG looks smaller that it should.
Many ways to reproduce: drag/drop, copy/paste, inside frames, in the score, etc.

The issue stems from the additional scaling that MuseScore does to adapt the core 72dpi to something that looks bigger on hi-res screens. I am not fully familiar with that code, but it seems to be wrapped up in MuseScore::physicalDotsPerInch(), Ms::DPI, and the user preferences for magnification, the key element being physicalDotsPerInch().

SVG Export currently does no scaling relative to MuseScore::physicalDotsPerInch(). So, when you view the exported SVG in your browser or other app, it will likely look smaller than it looks inside MuseScore. This is because it is likely that your screen's physicalDotsPerInch() is greater than 72.

SVG Import also does no scaling relative to physicalDotsPerInch(). This is the one fix that I believe should be implemented. I do not believe that SVG Export should do any additional scaling. But others may disagree. It is certainly possible to scale exported SVG to be the same default size as the size displayed inside MuseScore, as scaled by physicalDotsPerInch(). Remember that SVG is scalable, and this would only affect the default size for an exported image.

The change must be made inside image.cpp in Image::layout(). That code now scales an incoming SVG by dividing it by a literal value of 10. This needs to change to factor in the real _spatium value (which might not be 5.0), and also the physicalDotsPerInch().

I have not made any changes yet, as I'd like some verification as to the approach/ideas. Here is the key line of code in image.cpp:
https://github.com/musescore/MuseScore/blob/a6ec8aa17069595db360a21c8de…

Of course there might be other places that need to change, but they will reveal themselves in the process of debugging this one change, and this looks like the best place to start.


Comments

It is also worth considering how imported PNG images are sized. That is, to ask a pretty basic question: at what resolution should one export a PNG file from MuseScore so that when imported again, it shows the same size as it started? The answer seems to differ between 2.0.2 and the current master - presumably because of the DPI changes. And second question: isn't the DPI value stored within the PNG file, which should theoretically make it possible to get the same size on import regardless of what resolution it was exported at?

In reply to by Marc Sabatella

And second question: isn't the DPI value stored within the PNG file, which should theoretically make it possible to get the same size on import regardless of what resolution it was exported at?

Yes, same with SVG. This is why I recommend only scaling on the Import side of the equation.

On the flip side, if you're building a document outside of MuseScore and you want to import SVG (or PNG) images of a score into that document, they have to be scaled inside that container document if you want to achieve your original display size in MuseScore. That makes it not a win-win decision. For example: imagine exporting to SVG, scaled by physicalDotsPerInch(), then importing that same image and scaling by physicalDotsPerInch() all over again. The result will not be the original size. If you want the process of export-then-re-import of the same image to be the same size, you can only scale on one side, import or export, not both.

The only way to achieve both functions, would be to create an option in the Export: "maintain size" vs. "no scaling" or hopefully some better names than that. "maintain scaling" would scale relative to physicalDotsPerInch(), so you would not be required to do additional scaling when you import/pastes the image into MS Word, Inkscape, Libre Office, or whatever external app. No scaling would be for re-importing into MuseScore and/or whatever other purpose someone might have for a non-scaled image. Without that additional option, scaling on import-only is sanest solution, IMO. Exporting and re-importing must maintain the original size, and any truly external image will need to be scaled relative to everything else in MuseScore when you import it. Scaling on export is the "additional" option relative to base functionality.

In reply to by Marc Sabatella

I may have found a solution! sideways mentioned it earlier when kindly helping me understand SVGs, but there was so much discussion (and the SVG format is very counterintuitive) that I overlooked it.

Apparently I can change the width and height of the SVG file while retaining the viewBox. If I increase the width and height, this has the effect of zooming in, thus making the SVG appear larger.

I tested an example on my blog, and on macOS nothing happens—because the desktop browsers correctly obey the width and height overrides defined in the HTML.

On iOS, the SVG music examples do in fact display larger—since iOS browsers currently ignore any width and height overrides defined in the HTML and instead only display the dimensions embedded in the SVG files themselves.

If this is indeed a proper way to scale SVGs internally, then all I need to do is post-process SVGs output from MuseScore by grabbing their width and height and multiplying them by whatever scaling factor I need. For various reasons, that would be even better than defining these dimensions in the HTML. I can easily run them through a simple script. In fact, I could even do it with a single command, since MuseScore has command line support that also trims SVGs (which the GUI doesn't do). I could write a simple shell script that calls musescore and then post-processes the SVG(s) to multiply width and height by my desired scaling factor. Thus, I could just run one command and the SVG files at my desired resolution would be the result. Then I can just upload them to my site and use them on any screen without having to calculate their width and specify the dimensions in the HTML, since they'd already be specified in the SVG files.

I do still think setting MuseScore to obey the "PNG/SVG DPI" setting for export would be even better since no post-processing would be needed, but I could live pretty happily with this solution.

sideways, Jojo and Marc, thanks for kindly providing this input. If anyone knows of any downsides to this method, please do let me know.

In reply to by key-notes

FYI, simply changing these values is what you're scaling factor "upgrade" to MuseScore would do via C++ code. I assumed that's what you were going to do anyway. It's what you said you wanted to do...

If you want to see the entire contents of the svg, no cropping or scrolling, the viewBox must encompass all the elements' coordinates, and then the width/height change the displayed width/height. That's how it works on a very basic level, using the default preserveAspectRatio, and with your viewBox encompassing the entire "image". MuseScore currently sets them both the same, and it's been that way since before I ever saw the code.

If doing the multiplication and applying the results elsewhere is easier for you then it's easier for everyone else. I don't know much about the MuseScore command line, and I can't say I understand the specifics of how you're going to do it, but if it works, great.

In reply to by sideways

In my test file I changed this:

{syntaxhighlighter xml}

{/syntaxhighlighter}

... to this:

{syntaxhighlighter xml}

{/syntaxhighlighter}

I don't yet understand the remaining coordinates (the paths later in the file).

Basically, I set a larger width and height but maintained the viewBox. Earlier, you wrote:

"Keep all that in mind when designing your changes, as you will be messing with width/height, not viewBox. That's how you scale without cropping."

This is what I'm now changing. I assume this is what you meant? I just hope I'm doing it correctly and that my edited SVGs will display correctly in all browsers.

In reply to by sideways

Oh, I think I'm starting to get it! Here's an example SVG:

{syntaxhighlighter xml}

{/syntaxhighlighter}

If I understand your explanation, all those numbers are within the viewBox. Width and height can then be changed to anything, and the whole image will still display as long as the viewBox stays the same.

So all I wanted to do was multiply width and height by some scaling factor. Evidently my misunderstanding was the assumption that *all* the numbers in the SVG file needed to change, but apparently this isn't the case—only width and height need to be changed and the whole image will scale. I had assumed that adding the scaling factor to the C++ code would multiply all the numbers in the SVG file, not just width and height.

If I'm now understanding everything correctly, this means the solution is really simple. I can just use MuseScore as-is and then run a simple script to multiply width and height by a given scaling factor, then upload the images to my website and they should display perfectly on any device and browser.

A very sincere thank-you for kindly persisting and enlightening me on the SVG format. I do still suspect that (re-)implementing scaling SVGs on export may be worth incorporating into the code for other users, so maybe others can chime in, but assuming I'm now on the right track I can be happy with this solution.

In reply to by key-notes

Changing all the numbers except the width/height/viewBox in the svg element, the document element, is what happens when you make staff spacing changes.

...and am I nuts for not remembering this deleted feature? I don't think it had anything to do with SVG, but I could be wrong. My only encounter with scaling in the code was via staff spacing (the spatium).

I just completed some fixes to the SVG Export functionality, and I want to revive this discussion, if possible.

So far no one has disagreed with the above proposal to scale SVG on import relative to physicalDotsPerInch, so I might take that as tacit agreement with the proposal.

In reply to by sideways

Hello,

I'm afraid this change has cost me a couple days of lost work. I'm at least happy that after much confusion and bug reporting, Marc Sabatella noticed the discussion and pointed me to this forum, suggesting that I contact you.

In principle, yes, SVGs are (or should be!) scalable, but to my surprise, in practice it's not always nearly this easy. For some reason, mobile browsers on iOS ignore any width and height attributes specified in the HTML when using SVGs in img tags. This means that the exact desired display dimensions need to be defined in the SVG file itself.

Unfortunately, even that has proven frustratingly difficult, since each program outputs different XML, sometimes mandating manual changes. One change in post processing can then necessitate subsequent editing steps, none of which ought to be necessary. For hundreds of SVGs, this can add up to far too much effort.

The only solution is to be able to export SVGs at a desired PPI/DPI resolution. I note that this was evidently the original intent and behavior of MuseScore. (Removing export PPI without also changing the "PNG/SVG Resolution" label in the settings panel has caused much confusion and time lost. I suppose this is part of the price of open source software, but I hope that this can be fixed.)

May I kindly ask you to revert the changes? For my (common) application, it turns out it's necessary to output SVGs at the exact desired dimensions. While I understand your use case and desire to import MuseScore-exported SVGs at the same PPI, I'm guessing that a far more common use case is exporting SVGs for use elsewhere rather than for re-importing them into MuseScore. Either way, I'm sure the PPI import issue can be reasonably solved by specifying the default value of 72.

Many thanks in advance.

In reply to by Jojo-Schmitz

Won't removing width and height from the SVG make it expand to 100% of the viewport? This is exactly what shouldn't happen with music notation in particular. It would make all music examples display at completely different resolutions. They need to be consistent (so, say, all treble clefs display at the same size), and the only way to accomplish that (and ensure they display consistently on all browsers and devices) is to define the dimensions directly in the SVG files by specifying a PPI on export. I really hope this can be corrected soon.

In reply to by key-notes

They would scale to fit and no longer ignore the width and height specified in the html img tag, I think?. Currently width and height are the same values as in viewport
IE11 on Windows 7 does allow and honours width and height to be different in the img tag from what is inside the SVG, as does Chrome

In reply to by Marc Sabatella

Believe me, this was just as confusing to me too. I chose SVG precisely because it should be resolution-independent, but SVGs are not properly scalable because of how mobile browsers work, at least on iOS. I've racked my brain over this and concluded that the best solution is to be able to define the exact pixel dimensions directly in the SVG files. That's why this feature is important.

In reply to by key-notes

Again, though, if in the end you have concluded you want an exact pixel dimension, why SVG? And if there is a bug in iOS mobile browsers, should it really be MuseScore's job to create sub-optimal SVG files just to work around someone else's bug? I'm still trying to understand, but so far, I'm just not getting this request.

In reply to by Marc Sabatella

I think there's some confusion at play here. SVGs look best on screens of any resolution since they're vectors. On my Retina MacBook Pro they even look sharper than double density PNGs (@2x) at the exact same pixel dimensions, perhaps because bitmap images are anti-aliased and fine lines therefore are thicker and slightly blurred. Many screens nowadays have different pixel densities, and @2x bitmap images won't look the sharpest there since they will be scaled by the OS to some factor other than 2x, thus losing clarity. We don't know the resolution of future devices. All these are strong reasons to use SVGs.

"Pixels" in this context refers to a unit length of screen real estate—not to the exact number of pixels of an image's width or height. This is why bitmap formats like PNG are no longer optimal. On high-density displays a "pixel" no longer refers to one pixel of the physical display but rather a "virtual" concept that may be 2 or 3 physical pixels wide, depending on the pixel density of the actual screen.

The SVG definition allows for "paper" size, PPI and various units of length including physical units such as mm. Outputting a desired user-specified PPI does not make suboptimal SVG files. On the contrary, this is part of the very SVG specification. It would be incorrect to assume that all SVGs should somehow have one and only one pixel density.

The short answer to your question of why use SVGs is that they look best on any screen and are future-proof. There's also some confusion as to what "pixel" means in this context. I hope I've been able to clarify it somewhat. (Believe me, it was at least as confusing to me too.) All music notation on a website needs to appear at the same size. This can only be measured in pixel density for vector images.

In sum, MuseScore's default SVG pixel density makes the notation too small. I uploaded some examples to a forum of professional vector illustrators and they replied that the SVG images were far too small and improperly defined since they had to zoom in many times to see them. This was simply the output of MuseScore. For my application I just need to scale the SVGs by a predetermined amount. Again, choosing a desired PPI for SVGs was apparently part of the intent of MuseScore and this was evidently changed (without also updating the settings dialog or documentation). I'm just asking that this change be reverted or this detail implemented. It would really make working with SVGs much easier.

If I'm misunderstanding anything or anyone has any suggestions, I'd certainly be grateful for any input.

In reply to by Marc Sabatella

SVGs exported by MuseScore already have exact pixel dimensions. Here's an example:

https://assets.key-notes.com/1_ledger_line.svg

Here's the SVG code from MuseScore:

{syntaxhighlighter css}

{/syntaxhighlighter}

The dimensions are 58x28 px. (SVG units default to pixels but can also be points, inches, feet, yards, mm, cm and m.) This is what I'm trying to scale.

Another possibility (besides setting PPI/DPI) would be a scaling factor that multiplies all coordinates by a certain number. I wonder if there's an SVG editor that can scale an image by a given factor in a batch process. That would also work if MuseScore has a reason for 72 PPI to be hard-coded.

In reply to by Jojo-Schmitz

Good point. I forgot that I had "cleaned" (minified) the SVG before uploading to save bandwidth. This process is nondestructive so the results are identical.

Here's the original code:

{syntaxhighlighter css}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

1_ledger_line
Generated by MuseScore 2.1.0

{/syntaxhighlighter}

(This is also the code for the full page, prior to cropping to the image boundaries.)

In reply to by key-notes

This is the code for the same SVG, this time trimmed, and output from the command line:

{syntaxhighlighter css}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

1_ledger_line
Generated by MuseScore 2.1.0

{/syntaxhighlighter}

You can see that the SVG definition requires exact dimensions. The dimensions default to pixels.

Maybe the best option would be a multiplier? In MuseScore, DPI would seem to be the right variable, but clearly we wouldn't want to mess up other internal things by changing it.

In reply to by Jojo-Schmitz

I tried removing the width and height from the SVG file, but as suspected this just makes the images fill the entire width of their container.

iOS still ignores the width and height overrides in the HTML for some reason.

I've attached a screenshot to demonstrate. Basically, all music notation needs to display at a consistent size, and web developers need to be able to control that size. The only simple and consistent way to accomplish this is to define PPI in the SVG files themselves. I hope this example makes the problem clear.

Attachment Size
IMG_0003.jpg 262.67 KB

In reply to by key-notes

P.S. Note how tiny the F clef is at the very bottom of my example. This is MuseScore's default SVG output. I corrected the examples above it by hand so that they're readable on a website, but this would be extremely tedious for hundreds of images. This is why it's necessary to be able to define output PPI for SVG files.

In reply to by key-notes

removing height and width from SVG and not specifying it in the html of course fills all the available space.
iOS ignoring heihgt and width im img tags is a bug there, and needs to get fixed there.
On the 2 browsers I checked (IE11 and Chrome on Windows 7) this works as it should and the height and width of the img tag overwrites the ones from the SVG.
As all SVGs from MuseScopre are apparently created at 72 DPI, they should all be of a consistent size (in absence of overwrites in the img tag), shouldn't they?

In reply to by Jojo-Schmitz

Yes, it does seem that iOS's ignoring width and height in img tags is a bug in iOS—but MuseScore's ignoring its own "PNG/SVG resolution" in DPI setting is also a bug in MuseScore as we've discussed. (If only PNG resolution is user-definable, then the incorrect dialog setting is a bug; if the dialog setting is correct and MuseScore ignores it for SVGs, then this is a bug in SVG export.)

SVGs output by MuseScore are of a consistent size; however, this size is too small for display on the web. Also (believe it or not), SVGs are not all that easily scalable, at least not if you need to multiply the dimensions by a specific factor.

Given the apparent iOS bug *and* MuseScore's own "PNG/SVG resolution" setting, the only easy and reasonable solution would be for MuseScore to obey its own user-definable DPI setting and output SVGs at any DPI the user desired. Why impose a rigid DPI setting on all users?

In reply to by key-notes

Well, a poorly-labelled dialog isn't exactly a bug, at least not of the same sort as what you seem to be describing for iOS, but sure, the dialog could be improved.

Anyhow, to me, the point of SVG is to be scalable, so I would naively expect there to *never* be *anything* tying an SVG file to any particular size. I gather somehow this is not the case and for whatever reason, some sort of "suggested size" (?) is encoded within the file. I'm not an expert on SVG, so I'll defer to others. Just still struggling to understand why anyone would choose a scalable format if one didn't intend to actually scale it.

In reply to by Marc Sabatella

The incorrectly labeled dialog box is a bug when it costs me hours of time. I guess this is the price of open source software.

As for SVG, again, I'm with you here. I also naively assumed that a vector format wouldn't (and shouldn't) contain any size information other than relative coordinates, but to my dismay that turns out to be completely wrong and has caused problems trying to get SVGs to display consistently in any browser on any device.

There's not a "suggested size" encoded within the SVG format—there's an exact size (believe it or not). This was as surprising to me as it must be to you.

Again, I *do* want scalable graphics for my application. This is why I want to use SVGs. Vector images for music notation look best on any device past, present or future. SVGs look better than PNGs, even "Retina" (@2x) PNGs.

Imagine reading a book about music. The book contains hundreds of music notation examples. Imagine all those music examples being at a different size ("font" size): Some notes and musical symbols are microscopic while others take up an entire page. This is effectively the problem I'm dealing with. All the notation needs to appear at a consistent size, and that size needs to be controllable.

The only solution is to encode the SVGs with the proper DPI. All I'm asking is to be able to change the default 72 DPI to something else. Judging from both the settings dialog box and this discussion that the DPI settings were changed last year, I gather that the original intent of MuseScore's developers was for users to be able to change this setting. This isn't too much to ask.

I don't follow the logic for removing the ability to set export DPI. Apparently the logic is that just in case someone wanted to *import* an already exported SVG back *into* MuseScore, it wouldn't be at exactly the same size as the rest of the notation. (In that case I'm sure one could "eyeball" it and resize the SVG manually.) I don't know how others are using MuseScore, but my guess is that at least 99% of use cases involve creating SVGs in MuseScore for use elsewhere, rather than exporting SVGs only to import them back into MuseScore. Why make a rigid decision for the <1% when it might negatively impact the majority of use cases? Why assume *all* users require one and only one DPI setting?

All I'm asking is to revert the changes so that we can change the default 72 DPI to something else. This isn't too much to ask. Can someone, anyone, kindly help me rather than continuing to argue about a small detail not worth arguing about? This should really be quite a simple change.

In reply to by Jojo-Schmitz

Also, again, for whatever reason (bugs, I assume), not all browsers obey the html img tag's width and height attributes for SVGs. Instead they only render what's encoded directly in the SVG file itself.

This is why we need to be able to have control over the size info in the SVG file. The way to do that is through DPI. The default value of 72 is a variable. We just need to be able to change that number.

In reply to by Jojo-Schmitz

I just double checked the latest Safari, Firefox and Chrome on the latest iOS on the latest iPad Pro. All of them ignore the width and height attributes in an img tag for SVG; they only display the dimensions encoded in the SVG file itself.

So it's far from just one browser. I don't have access to other OS's and browsers, but properly encoding the SVG files with the desired display dimensions, rather than trying to manipulate them after-the-fact using HTML or CSS, will make them look correct on the widest range of devices.

Moreover, it would be much easier to work with SVGs on websites if you didn't need to calculate width and height and manually input them into the HTML. How do you know what width and height correspond to your desired PPI? I had to export bitmaps at the desired display size, then take the width and height from those files and add them to the HTML for every SVG. It's a time-consuming process, even if I partially automate it via script.

The far superior method is to define SVGs at the desired size. (All SVGs are defined at some size anyway.) Then a simple img tag without any width or height attributes suffices to display them perfectly at the correct size on any screen.

In reply to by key-notes

... iPad Pro. ... I don't have access to other OS's and browsers,...That doesn't make sense, where are you generating your SVGs then? Won't ben on the iPad, as that doesn't run MuseScore, so there you have another OS...
Chrome on Windows 7 does not ignore them.

In reply to by key-notes

As I recall, Apple forces all third party browsers to use Apple's rendering engine, so they are basically all Safari under the hood. Still, I suspect the real problem is that you might not be setting the size correctly. My (very limited) understanding is that it is not intended to be sufficient to set the height and width in the img itself, it needs to be done at the level of the element containing the SVG. So most likely you could solve your problem immediately by generating more correct HTML.

Still, I have to say that at a fundamental level I continue to be confused as to why you are using SVG at all if you just intend to generate it at a specific size. If you intend to scale, the size shouldn't matter (once you work out the correct HTML to make this happen). If you don't intent to scale - that is, if you are generating an image at the exact desired dimensions - PNG works great.

All that said, sure, if there is a way for some future version of MuseScore to allow user-definable size / resolution of SVG, great. But I'm still interested in solving your immediate problem today, and I'm very much convinced it can be done without waiting for a future version of MuseScore (or rolling back to an older one) but instead just making different choices in how you are doing things to better take advantage of the unique properties of PNG and SVG. This to me is not "continuing to argue about a small detail not worth arguing about" - it's actually solving your problem, right here, right now.

In reply to by Jojo-Schmitz

There are 23 matches for "resolution" in svggenerator.cpp. Line 156 contains this:

class SvgPaintEnginePrivate : public QPaintEnginePrivate
{
public:
SvgPaintEnginePrivate()
{
size = QSize();
viewBox = QRectF();
outputDevice = 0;
resolution = Ms::DPI;

Line 526 refers to 72 DPI:

// Set stroke-width attribute, unless it's zero or 1 (default is 1)
if (spen.widthF() > 0 && spen.widthF() != 1) {
// Formatting for vertical alignment of elements
qts.setRealNumberPrecision(2); // with DPI=72 only 2 decimals necessary
qts.setRealNumberNotation(QTextStream::FixedNotation);
qts << SVG_STROKE_WIDTH << spen.widthF() << SVG_QUOTE;
qts.setRealNumberNotation(QTextStream::SmartNotation);
}

Line 644 (commented out) also refers to 72 DPI:

// if (d->font.pixelSize() == -1)
// d->attributes.font_size = QString::number(d->font.pointSizeF() * d->resolution / 72);

Hope we can track down this setting somewhere.

Maybe someone has access to an earlier OS X binary that might have allowed for setting this variable?

In reply to by key-notes

libmscore/mscore.h
I'm pretty sure changing it screws up a lot of things

Also master and 2.1 seem to behave differently, in master it seems to use 360 DPI and not 72 like in 2.x, so uses DPI rather than PPI?
And indeed, see 97d8957

"change raw literal 72 to Ms::DPI", only that DPI is 360 and not 72

Also:
if (ext == "svg") mag = 1; // SVG is not scaled, it's scalable.

In reply to by Jojo-Schmitz

Looks like this may be it:

double mag = 1; //converterDpi / DPI;

(Formerly line 2525 of mscore/file.cpp)

This is what user sidewayss removed on 1/9/2016. He or she posted the reasoning at the beginning of this thread. Unfortunately I wasn't around with my application then to have this discussion. Hopefully sidewayss will chime in.

I don't follow all the other related changes, but this "double mag = 1; //converterDpi / DPI;" looks to be exactly the factor I mentioned for scaling an SVG on output.

I strongly believe this should be restored. I don't see the justification for imposing one rigid resolution on all users for all applications. I also assumed that SVGs are by definition scalable, but the reality is that they can be very tricky, inconsistent and buggy to work with. The only real solution is to encode them with the desired size rather than try to scale them after-the-fact.

In reply to by key-notes

This looks to be it:

User sidewayss changed this in mscore/file.cpp:

{syntaxhighlighter c++}
printer.setSize(QSize(w * mag, h * mag));
printer.setViewBox(QRectF(0.0, 0.0, w * mag, h * mag));
{/syntaxhighlighter}

... to this (line 2535):

{syntaxhighlighter c++}
printer.setSize(QSize(w, h));
printer.setViewBox(QRectF(0, 0, w, h));
{/syntaxhighlighter}

This means that the scaling factor (variable "mag") was removed. This is what needs to be reverted.

Note that the scaling factor does not appear to be identical to DPI, with its default value of 72. (It's called DPI in the MuseScore settings dialog for exporting SVGs—this is why I've been referring to it as DPI. Practically speaking, they're the same, but these may have very different effects internally.)

In reply to by key-notes

This is the saveSVG function (starting on line 2516 of file.cpp as of 1/6/2016) before the ability to scale it on export was removed:

{syntaxhighlighter c++}
bool MuseScore::saveSvg(Score* score, const QString& saveName)
{
SvgGenerator printer;

QString title(score->title());
printer.setTitle(title);
printer.setDescription(QString("Generated by MuseScore %1").arg(VERSION));
printer.setFileName(saveName);
const PageFormat* pf = cs->pageFormat();
double mag = 1; //converterDpi / DPI;

QRectF r;
if (trimMargin >= 0 && score->npages() == 1) {
QMarginsF margins(trimMargin, trimMargin, trimMargin, trimMargin);
r = score->pages().first()->tbbox() + margins;
}
else
r = QRectF(0, 0, pf->width() * DPI * score->pages().size(), pf->height() * DPI);
qreal w = r.width();
qreal h = r.height();

printer.setSize(QSize(w * mag, h * mag));
printer.setViewBox(QRectF(0.0, 0.0, w * mag, h * mag));

score->setPrinting(true);
MScore::pdfPrinting = true;

QPainter p(&printer);
p.setRenderHint(QPainter::Antialiasing, true);
p.setRenderHint(QPainter::TextAntialiasing, true);
//p.scale(mag, mag); // mag == 1 now, 1:1 scaling, the default
if (trimMargin >= 0 && score->npages() == 1)
p.translate(-r.topLeft());

foreach (Page* page, score->pages()) {
// 1st pass: StaffLines
foreach (System* s, *(page->systems())) {
for (int i = 0, n = s->staves()->size(); i < n; i++) {
if (score->staff(i)->invisible())
continue; // ignore invisible staves

// The goal here is to draw SVG staff lines more efficiently.
// MuseScore draws staff lines by measure, but for SVG they can
// generally be drawn once for each system. This makes a big
// difference for scores that scroll horizontally on a single
// page. But there is an exception to this rule:
//
// ~ One (or more) invisible measure(s) in a system/staff ~
// In this case the SVG staff lines for the system/staff
// are drawn by measure.
//
bool byMeasure = false;
for (MeasureBase* mb = s->firstMeasure(); mb != 0; mb = s->nextMeasure(mb)) {
if (!static_cast(mb)->visible(i)) {
byMeasure = true;
continue;
}
}
if (byMeasure) { // Draw visible staff lines by measure
for (MeasureBase* mb = s->firstMeasure(); mb != 0; mb = s->nextMeasure(mb)) {
Measure* m = static_cast(mb);
if (m->visible(i)) {
StaffLines* sl = m->staffLines(i);
printer.setElement(sl);
paintElement(p, sl);
}
}
}
else { // Draw staff lines once per system
StaffLines* firstSL = s->firstMeasure()->staffLines(i)->clone();
const StaffLines* lastSL = s->lastMeasure()->staffLines(i);
firstSL->bbox().setRight(lastSL->bbox().right()
+ lastSL->pagePos().x()
- firstSL->pagePos().x());
printer.setElement(firstSL);
paintElement(p, firstSL);
}
}
}
// 2nd pass: the rest of the elements
QList pel = page->elements();
qStableSort(pel.begin(), pel.end(), elementLessThan);

Element::Type eType;
foreach (const Element* e, pel) {
// Always exclude invisible elements
if (!e->visible())
continue;

eType = e->type();
switch (eType) { // In future sub-type code, this switch() grows, and eType gets used
case Element::Type::STAFF_LINES : // Handled in the 1st pass above
continue; // Exclude from 2nd pass
break;
default:
break;
} // switch(eType)

// Set the Element pointer inside SvgGenerator/SvgPaintEngine
printer.setElement(e);

// Paint it
paintElement(p, e);
}
p.translate(QPointF(pf->width() * DPI, 0.0));
}

// Clean up and return
score->setPrinting(false);
MScore::pdfPrinting = false;
p.end(); // Writes MuseScore SVG file to disk, finally
return true;
}
{/syntaxhighlighter}

https://github.com/musescore/MuseScore/blob/0c01f644383875734657dae9031…

I believe this version needs to be restored. If any bugs were fixed or other substantive changed made, we should be careful to keep them. Only scaling on export should be restored.

In reply to by Jojo-Schmitz

Jojo, please forgive my directness, but I honestly don't know if you're being sarcastic or if there is just miscommunication here. mag is a variable that obviously can be changed. Obviously if you multiply n by 1 you get n. Perhaps this variable was intended for a use that wasn't implemented and was then deleted, but my whole point is that the SVG export needs a scaling factor. Apparently this variable, mag, was intended to be that scaling factor.

I appreciate your time and hope we can communicate more clearly and eventually solve this issue for MuseScore users.

In reply to by key-notes

Yes, once upon a time that variable was meant to do some scaling. I have no idea why it got removed, I can see though why it got removed in the above code, it was just a NOP there.

Not sure how stating facts can be construed as being sarcastic? I was just taking you by your own words, and the code you cited won't do anything to get scaling to work.

As mentioned there are some differences in code between master 2.1 and 2.0.2 (2.0.3 was the one that actually had the scaling removed, it seems)

Compare https://github.com/musescore/MuseScore/blob/2.1/mscore/file.cpp#L2552-L… and https://github.com/musescore/MuseScore/blob/master/mscore/file.cpp#L259… and https://github.com/musescore/MuseScore/blob/2.0.2/mscore/file.cpp#L2521…

Edit: I've now tried with a 2.0.2 portable app and can confirm that there the DPI settings were honoured. Also height and width were set in mm, not px there.

So there you have a possible workaround: use a 2.0.2 portable app to create your SVGs

In reply to by Jojo-Schmitz

Sorry, I've been offline since last Thursday.
The mag variable was removed because it was unnecessary. See the version 2.0.4 code for fixes to scaling, it's a line or two of code in svggenerator.cpp
You might try the opposite of the original suggetsion: remove the viewBox attribute and keep the width/height attributes intact.

I'll read up on this thread a bit more to see if I can add any other suggestions, but I wanted to reply before my laptop battery dies and my internet cafe connection dies...

In reply to by sideways

I have to go offline for most of the rest of the day, so here are some final thoughts until later:
1) I can't tell from what I've read if you want non-px units like in or mm. SVG defaults to px, but you can use mm or in if you really want. I've tried to get px as a unit in MuseScore, in addition to in and mm, but that has not worked out yet. You can simply put "mm" or "in" in the viewBox, width and height attribute values. I've never used it and don't really trust it, but it's supposed to work.
2) continuing that thought: Pixels are the native units of SVG and HTML. Using other units in an export feature can cause various types of problems.
3) I posted this thread originally to have a discussion before I made some decisions. Some assumptions have to be made, so I made them in the most generic way I could, seeking input from all interested parties prior to making the changes. This is how it turned out.
4) The scaling bug in 2.0.3 came up months ago and was fixed in a very simple way in 3.0 and I'm certain that @lasconic added it to 2.0.4 too. I'm not in a position at this time to be searching in github and posting links, but it should be easy to find. Look for PRs under my userid sidewayss in github and you'll see the code mods.
Good luck until I'm back online for real tonight or tomorrow!

In reply to by Jojo-Schmitz

And what is the release date for 2.1? If you're really in trouble you can download that source and compile it, or integrate the couple of lines of code involved into whatever branch you're working on. Here is the scaling code PR:
https://github.com/musescore/MuseScore/pull/2564/files

Here is the original issue for the PR:
https://musescore.org/en/node/107081

You might want to look at these two later fixes I made too:
- tiny tab formatting fix: https://github.com/musescore/MuseScore/pull/2663/files
- more important, rounding error fix: https://github.com/musescore/MuseScore/pull/2758/files

Yes, I'm back online.

2.1 and 3.0 have the scaling/rotating/etc. fix. All types of transformations should be functioning correctly because it's using the full 2D matrix, no need for 3D in MuseScore yet...

So what is the issue here, is it a scaling issue via the spatium/staff spacing variable? That is fixed in the newer code. Is it now just the iOS "bug" we're dealing with? I'd definitely try the eliminate the viewBox / keep the width+height option. That should force the browser to always paint the SVG at that exact size, never scaling it up or down. It works in Firefox and Chrome that way for sure, I can't speak for iOS Safari.

In reply to by Marc Sabatella

Congratulations on the release! I see now that it says 2.1 on the download button on the home page.

You can get around 72dpi by scaling the score via staff spacing. That's a scaling issue that is resolved in 2.1. Setting the staff spacing to a larger number effectively scales the entire score upwards in size. You cannot do it via the image copy/export feature for just any portion of the score, it is only available as full-score scaling. You can always undo it after exporting if you have other uses for the score.

That's a simple, use-as-intended solution, so if it's the only real issue, then it's a non-issue.

I would like to reiterate my suggestion about object vs. img tags. That can help change browser behavior and work around potential or perceived bugs in many cases. The img tag is not as precise as the object tag in wrapping SVG and definitely behaves differently, in my experience. The only downside is that you can't set a tooltip via the title attribute as you can for img. But if that's not a serious problem, make the switch for all your SVG content and you will have fewer issues in general. That's my experience in both Firefox and Chrome. I'll get to iOS mobile some time later this year...

In reply to by sideways

I'd like to clear up some possible confusion about SVG, relating to some specific points raised by Marc. One of the purposes of this is to give you an idea of the multitude of implementation options for SVG inside HTML and the accompanying multitude of different settings, side-effects, and "bugs" that can arise:

1) Explicitly setting the height and/or width attributes of the object or img that "contains" the SVG file for purposes of HTML display:
This is an interesting point. It depends on a few different aspects of your deployment scenario. Do you want the SVG "image" to scroll vertically and/or horizontally, or do you want to always have it fit in the space provided? If you're interested in details about that, look into the preserveAspectRatio attribute, and then learn about how the viewBox and width/height attributes interact for the svg document element (the svg tag itself).
This current discussion clearly wants no scrolling at all, so setting the width and/or height attributes of the containing object or img is a good idea, even if you're using HTML flex layout, although that opens up a whole bunch of possibilities. Usually you only need to set one, height or width, because the default is to preserve the inherent aspect ratio. Remember to include space for borders, padding, etc. in that width/height value, which can be in HTML or CSS for object and img.
Also note: there are two other ways to get SVG into the browser:
a) simply open the .svg file in the browser, no HTML whatsoever
b) inline SVG, where the contents of the .svg file appear as text within the HTML itself
Those are both very valid options. I am currently using object tags for simple icons/buttons and inline SVG for more complex displays, for example. I often view SVG files directly in the browser when I'm working on them.

2) It's SVG, what do you mean I need to specify a display size?
First, SVG draws on a canvas using x and y coordinates. You can chose to display any portion of that canvas at any resolution. It's all in the coordination between the viewBox and width/height attributes. So you might want to crop the bottom right corner off of an image, or you might want to center the image with padding. All possible via viewBox vs. width/height + preserveAspectRatio and however you decide to implement your SVG within the browser. A web search will turn up plenty of documentation and articles on these subjects.

So just because you want to display something so that it "looks good" on your iPhone, doesn't mean that's the default way anyone else wants to see anything else anywhere else. The W3C is into open-ended configurability, so that's what SVG is. SVG sounds easy, but depending on your project, it's got a lot of options you might need to learn about and experiment with. C'est la vie.

In reply to by sideways

I really appreciate everyone's helpful suggestions! I'll try the different options and hopefully find one that's easiest to implement.

In general, it seems the best option (easiest and compatible with most devices) is to define the desired display dimensions directly in the SVG file itself. While by definition SVGs are scalable, defining one size and trying to display another gets very messy very quickly. It seems that SVGs are very easy and straightforward to implement as long as everything is neatly defined in the files themselves, but that any transformations can make them very inconsistent and difficult to work with.

Also, it seems the 72 DPI is different from the scaling factor. It looks like what I need is a scaling factor that changes the dimensions but that 72 DPI should be retained in the SVG files themselves (or another SVG standard such as 90, 150 or 300 like in Adobe Illustrator). What makes this confusing is that MuseScore has a setting for SVG (and PNG) export called DPI. Apparently this "DPI" is really the scaling factor. (Experts, please correct me if I've misunderstood anything.)

The easiest option for me (barring a scaling factor being incorporated into the code) may be to scale each score using staff spacing, as suggested by sideways. Hopefully I can do this in a batch process, as I have hundreds of music examples to edit.

In reply to by key-notes

I should mention that scaling using staff spacing will work for small (1- to 3-measure) examples, but it will break the desired system breaks for longer examples unless I scale the paper size by the same amount. This can become pretty tedious, when a scaling factor on export would work for any score. I therefore think adding a scaling factor to the code would be the best solution, and since it just multiplies each coordinate by a user-defined constant (and had already been implemented!) it should be fairly easy to implement.

In reply to by key-notes

You can add a scaling factor to your code, but it's not necessarily something anyone else will want, so it may not make it into the MuseScore master. I can't tell if you're coding something just for yourself or whether you're trying to make a change to MuseScore for everyone.

Yes, staff spacing part of the page layout, and it's best if you set it early in the process. It will zoom everything both horizontally and vertically, so it will bump up against page height and width and your margins.

What you say about 72dpi is better said this way: MuseScore operates in a default scale, 72dpi. That's the scale defined by the Emmentaler and the other fonts. That scale must be translated into pixels at some point to be converted to SVG. The simplest (and best) way is simply to treat it as 72ppi, and do no conversions from dots/points to pixels. Staff spacing changes alter this dpi/ppi relationship and effectively changes the font size. Every individual element in the SVG file is scaled.

You want to approach this from the opposite direction, changing the svg element's viewBox and width/height while maintaining the staff spacing. Since you want to increase size you will probably want to reduce the width/height numbers in the svg element, keeping the viewBox the same. Or maybe it's the opposite, I get these things backwards sometimes.

Your other option, the one that works for me using object tags, is the one mentioned by others earlier in this thread: get rid of width/height attributes for the svg element, viewBox only, then explicitly set the width and/or height of the object tag itself. Works perfectly for me on Chrome and Firefox. Sounds almost simpler to do in a batch text editor than via mods to MuseScore C++, but I am not using iOS (yet) and I am not familiar with your skill set.

In reply to by sideways

To add to my below reply, most importantly, the correct dimensions really do need to be part of the SVG file itself. Any post-processing is extremely tedious. How do we even know what dimensions to scale an individual file to? I also output PNG at a specific PPI, then read the PNG resolution to use for the SVG. That's terribly tedious—and also doesn't even work consistently on all browsers and devices.

Instead, users should simply be able to export SVG from MuseScore and just upload the images to their websites. If the dimensions are properly contained in the SVG file, nothing more is needed and it will save a great deal of time and frustration.

As a summary, there are two problems currently with SVG export as I see it:

1. The files are way too small—small enough that professional illustrators have complained that they're poorly defined. My examples open at > 2500% zoom in vector graphics programs. This means that outputting 72 DPI = 72 PPI is far from an optimal choice.

2. There's no scaling factor.

We can kill two birds with one stone by creating a scaling factor and setting it to something higher than 72 PPI by default. Perhaps most users won't need to change it, but it will be there for those of us who do.

In reply to by Jojo-Schmitz

ad 1: they are 5 times lager in master than in 2.x, take a look at the nightly builds

That's because of the 5x multiplier that Werner added late last year. I have yet to adapt the SVG to that factor or even really study what Werner did, sorry. I've been busy trying to get all my SVG to work inside a full-blown HTML interface...

In reply to by key-notes

I think at this point it would be worth your starting a new thread and explaining your actual use case in more detail. I think part of the miscommunication here comes from the fact that we don't understand at even the most basic level what you are actually trying to do - build a web site? create an app? desgin a new notation program? What are you starting with, what are you trying to end up this?

Again, this seems like something worth starting a new thread about, then we can better understand why you seem unwilling to just use PNG (the obvious natural chocie if you don't need your browser to scale the image) or just use the correct HTML to get the browser to scale it if you *do* want the browser to do this. It keeps sounding like you are saying there is some sort of problem with using PNG even though you aren't scaling the result after generating it, and also saying there is some sort of problem getting browsers to scale the SVG file, but so far we don't understand how *either*of those statements could possibly be true, much less how *both* could be true at once for your use case.

In reply to by Marc Sabatella

I'm just trying to display music notation on a website at the sharpest possible resolution on any end user screen.

SVG is sharper than PNG—even when set to the same resolution. Also, some users zoom in on their devices; only SVGs zoom cleanly while PNGs become pixelated. Therefore, I might set a webpage to display at a static size, but the end user is free to zoom. SVGs are also future-proof. These are some reasons why I greatly prefer SVG. In short, SVG is superior to PNG. (Please see my previous reply for an explanation of your assumptions regarding browser scaling, as there's still evidently a misunderstanding here.)

In reply to by key-notes

SVG is not sharper than PNG at the native PNG resolution. PNG can shade things in ways that are hard to do in SVG. Browsers do all kinds of fudging when rendering SVG, dealing with fractional pixel sizes and opacity variations for different colors. The PNG is what the PNG is at its native resolution, and that can be plenty better than any attempt to do the same in an SVG.

Of course, how much that applies to sheet music is debatable, as the range of colors and shadows is limited.

edit: The place where it applies to sheet music is curves of any kind. Note heads are a great example for zooming in on that rendering scenario.

In reply to by sideways

(At this point I might just give up and revert to PNG.)

I'm developing and testing on Apple's "Retina" screens, so on these at least SVGs (of music notation) do look sharper than PNGs even at the same resolution. I assume it's because PNGs are anti-aliased, and HiDPI screens probably don't need anti-aliasing.

Then again, I'm not looking on low-res screens—but if I were to use PNG, I definitely would use one and only one PNG per image rather than try to serve different images to different devices based on CSS media queries (which my CMS doesn't even support anyway). Also, a PNG optimized for @2x resolution might not scale down well to @1x, and there SVG would likely look better than a scaled-down PNG.

In reply to by sideways

To clarify one other point about the code comparisons you all were making:

The mag variable was there to handle staff spacing. But the actual scaling was happening in svggenerator.cpp. So I removed duplication and consolidated code when I removed that variable.

Just an fyi to anyone digging around in there...

In reply to by sideways

A comment on the idea of using staff spacing as a workaround for lack of ability to set export resolution explicitly

In addition to the drawback of also requiring you to change page size by the same amount, it also affects print, meaning you can't use the same source file for both print and web or other electronic media. So, not really the best option. *If* it truly is the case that SVG files are not in fact scalable by some of the programs that people need to be able to use, then I do believe we need to provide such an option on export.

However, I still am very unconvinced there *is* a problem. As far as I know, if you generate correct HTML, then all modern browsers - including Safari on iOS - can scale an SVG. So if you intend to scale the SVG, you can get that result, right now, no need for any changes to MuseScore. Just generate the HTML differently than you currently are. And if you are *not* planning on having the browser scale the image, there is no reason to use SVG - just use PNG.

In reply to by Marc Sabatella

100% agreed. My original post on the subject addresses the issue in a lame way as "undo" or "don't save the file that way".

But also 100% agreed that the farther this discussion progresses, the more it seems that this is an issue for one user, with one CMS that he doesn't really like but has to use.

I am starting to like the idea of offering an "auto-scale" option on the export preferences, to only export the viewBox, not width/height. The main thing is that it seems there aren't many MuseScore users actively exporting SVG (yet), so it's hard to tell what's useful to how many people. I do think that for simple "clip art" type exports, the "auto-size" option will be desirable. That's how sites like thenounproject.com prepare their stuff, and they distribute a lot of SVG "clip art".

In reply to by sideways

Yes, I'm using a CMS that I don't really like but have to use. Still, embedding the desired size directly in the SVG files is by far preferable even if I weren't using that CMS. The reason is that if width and height are not defined, for music notation it's rather difficult to figure out what size they should be if more than one music notation example is to display on a webpage. My workaround is to export PNG and use the PNG's dimensions for the SVG when embedding, but that's pretty tedious.

If width and height are not exported, SVGs will default to full width. At least at the current 72 DPI, all SVGs display with a consistent font size (even if I find it too small).

In general, I'm strongly in favor of options. Some users may greatly prefer an auto-scale option, while others like me may need a certain scaling factor or PPI or whatever we may call it. I just don't see the justification for imposing one and only one size for all users for all possible applications, especially given that SVGs are (sadly) not nearly as "scalable" in practice as they are in theory.

In reply to by sideways

Make the change in your fork/branch. Get it to work for you first anyway, if it's what you really need, which seems like it might just be.

Yea, getting things to look right in different platforms and even different hardware can be stupidly difficult. Then consider the reason the feature was removed as part of the PR to integrate it into MuseScore.

In reply to by Marc Sabatella

Thanks, Marc. Some clarification:

1. Yes, having to maintain different .mscz files for web and print would be tedious.

2. WYSIWYG HTML editors like those used most commonly in CMS's unfortunately corrupt "correct" HTML all too often. (I hate WYSIWYG editors for this reason, but that's all I'm able to use for my application.)

3. Again, "pixels" are not pixels. I'm using "pixels" for on-screen measurement, but this completely depends on the pixel density of the end user's display. This pixel density is increasing as screens get sharper. Therefore there is a strong reason to use SVG and discontinue bitmap formats. To (hopefully) be clear, an SVG defined at 200x100 may be very different from a PNG at 200x100—it may be equivalent to a PNG at 400x200, 600x300... or 200x100 or something else. "Virtual" pixels used for sizing in browsers on modern screens don't correspond 1:1 to the conventional pixels you're thinking of in bitmaps. This is why there is a very clear reason to prefer SVG over PNG.

I believe the scaling factor should be a MuseScore feature for all users.

It's worth noting that Sibelius (7.1.3—I didn't bother upgrading and happily turned to LilyPond and MuseScore instead) also outputs SVGs at 72 DPI, but their dimensions are roughly 8x bigger. This means that they're not microscopic and are readable at 1x zoom. MuseScore can retain 72 DPI, but the dimensions still should really be scaled by default to something that doesn't require several levels of zoom to be readable. (Pro illustrators complained that the SVGs output by MuseScore have improper dimensions since they're extremely tiny. This needs to be fixed whether or not a user-definable scaling factor is added.)

However, other than this MuseScore outputs clean SVG with proper paths (vectors) for all symbols. Sibelius's SVG output (at least the older version 7.1.3) is unusable without significant post-processing since it relies on all fonts, including the music notation font (!), being installed on all machines. This makes them effectively useless for deployment. MuseScore would be perfect if only it fixed the size issue. Again, I assume this should be quite straightforward to change, and I do think this would benefit other users too.

In reply to by key-notes

You have tunnel vision on this subject. You need to keep in mind all the other ways that all the other people are using SVG in MuseScore.
You are also not necessarily implementing your HTML wrapping of SVG correctly, at least I cannot be certain of that.

My experience on two different browsers with a combined user base that's at least triple that of iOS Safari is different from yours. For me, the standard SVG export resolution is fine, very similar to the size I see in MuseScore.

You need to increase your understanding of both subjects prior to making that PR to MuseScore. Otherwise the feature will not serve anyone but you.

Please don't take this as a personal insult or offense. I'm simply trying to do what's best for MuseScore. I took a lot of time and asked for a lot of feedback when I made the SVG changes I made, which were deep and structural, but clearly affected the UI and the user experience. Please make sure you understand the implications of your feature before you try to introduce it into the mainstream.

Where are you going to put this scale factor in the UI? In the File menu Export... dialog? That's a native dialog, and only allows certain types of changes. Are you going to add a new dialog? Where? Will all users always have to deal with this dialog even if they don't want to scale anything?

I'm asking you to separate your short term needs from the long term point of view required when adding features to a program. Thanks.

...edit-> And what you say about fonts and SVG is incorrect. I have my own version of MuseScore with and SVG export that relies on fonts, which are defined via @font-face in CSS. You don't have to install fonts on the client machine, you simply have to make them available on the server where you're hosting the SVG.

You really need to understand a lot more about SVG implementation or you will make all kinds of bad implementation decisions.

In reply to by sideways

pngResolution from Preferences/Export used to work for SVG in 2.0.2 and before, and could get made to work again. But maybe we need a different setting there, as 72 DPI for SVG seems a decent default (and matches what other SVG produducers seem to use), but for PNG 300 DPI seems more reasonable.

In reply to by Jojo-Schmitz

"pngResolution from Preferences/Export used to work for SVG in 2.0.2 and before, and could get made to work again. But maybe we need a different setting there, as 72 DPI for SVG seems a decent default (and matches what other SVG produducers seem to use), but for PNG 300 DPI seems more reasonable."

It's important to note that while in the settings this is called "DPI," it's actually different from the DPI of the SVG file. SVGs contain both a DPI setting that apparently conforms to standards, including 72, 150 and 300. I've learned that some professional vector illustration programs retain one setting, like MuseScore.

The scaling factor is a transformation from DPI to PPI. I believe this would be beneficial, and I assume I can't be the only user who could benefit from this, but sideways obviously has much more experience than I do both with MuseScore and with SVGs. Thanks in advance for enlightening me on this subject. (I'm genuinely not trying to argue here, just interested in understanding, finding a solution and, if it's relevant, making a tiny contribution to a wonderful program.)

In reply to by key-notes

Again, to be precise (and I too am guilty of imprecision in an earlier post here - I was trying to avoid this long-winded definition):

DPI is Dots Per Inch. It is a unit for display monitors, not for fonts or any software thing.
PPI is Points per Inch. Points are the units of fonts and PPI is a unit for printers. Do a web search for long-winded historical explanations.
Pixels are the software units that are generally equivalent to hardware Dots. The per inch part is all about displaying on a screen or printing on a page. Inches are physical, hard units. Pixels are variable in size and overall density on the screen.

For purposes of this discussion, and any discussion about SVG, it's best to leave Inches and Millimeters out of it. In other words, the specific number 72dpi is a red herring here. Qt takes the font, somehow turns it into vectors and matrices, and svggenerator.cpp spits out the SVG text. Let's talk about scaling the default font size and avoid using DPI or PPI and the number 72. It will only distract from the pertinent facts.

In reply to by sideways

Good idea. This discussion gets all the more confusing now that HiDPI displays (such as Apple's "Retina" displays, 4K phones, etc.) are common. (Such displays are the very reason I thought now is the time to switch to vector graphics.) In these cases the OS uses a multiplier based on the density of the display compared to older resolutions, so 1 "pixel" is really 2, 3 or more actual pixels wide or tall, depending on the screen density. I don't know what vocabulary to use anymore.

In reply to by sideways

I appreciate it and certainly won't pretend I'm an expert. As for where to put it, note that there's already a setting "PNG/SVG resolution" in the Export tab of the settings. Apparently this is a "vestigial" feature, but unfortunately it wasn't updated and cost me hours of frustration and lost work. I assume it was added for a reason, so all I'm suggesting is that this value be read on SVG export, not just PNG.

I'll certainly look into different HTML when embedding SVGs. I did try different combinations as you suggested, but nothing has worked so far. I haven't exhausted the possibilities, however.

Regardless, I do think an important argument in favor of a scaling factor is that SVGs behave just like bitmaps if they have defined width and height attributes embedded directly in the files. It's possible to scale a PNG or JPG using HTML, but barring such overrides the browser simply displays them at 1:1 size based on the actual image dimensions (if it's not wider than its container). SVGs do the same. It's by far easiest to work with them, and most reliable, when they contain the desired dimensions.

Surely I may be misunderstanding something, so I appreciate your thoughts. Still, I don't understand the argument that outputting one and only one size (resolution) for all SVGs is somehow best practice. (Note that we've moved on from 72 DPI and are now talking about a transformation from DPI to PPI during export.)

I appreciate all your suggestions and hope to find an easy solution soon.

In reply to by key-notes

I agree that there should be additional SVG export options. @lasconic and I have discussed integrating my "use the fonts, not paths" option, but it requires sub-classing of SvgGenerator or maybe it's the other class in there (it's been a few months since I poked around in there).

If there used to be a Preferences option, then that's minimally invasive, so long as it defaults to 100% or 1:1 or whatever it might be called.

Otherwise let's put some context around this, think about the specific different ways people will want to display their exported SVGs. You might find that many people want a viewBox but no width or height, as that auto-scales to the max by default. It works that way because the W3C decided that was the best default, so it's probably a useful option. That's one simple example of an approach that might serve MuseScore in general

edit: Note: I exported viewBox and identical width/height attribute values because that was what MuseScore and Qt were already doing. It was a no change situation.

Also note that there is a predefined value for svg element width/height: "auto". It's very useful, but needs to be used carefully depending on the display wrapping.

Keep all that in mind when designing your changes, as you will be messing with width/height, not viewBox. That's how you scale without cropping.

In reply to by sideways

"You really need to understand a lot more about SVG implementation or you will make all kinds of bad implementation decisions."

I certainly won't argue that I need to understand a lot more about SVGs. I naively assumed (like Marc) that they're totally size-independent. I was surprised to discover that they contain actual dimensions at all. I also had no idea how difficult they can be to work with.

There's something I don't understand, however. The issue is that for whatever reason (bugs?), some browsers (all iOS browsers) don't obey width and height overrides for SVGs. It seems to me that the solution must be to embed the desired size directly in the SVG files themselves. That would really make things much easier, also since width and height would no longer need to be specified in the HTML at all. Is there something wrong with my assumption here?

Currently I'm using this simple embed code:

{syntaxhighlighter SPEC}

{/syntaxhighlighter}

I tried object tags instead but didn't have success (they also don't display at all in my CMS, unlike img tags). I also found tips on implementing SVGs on websites and at least one professional suggests img tags as the current best practice. If possible, my preference would simply be this:

{syntaxhighlighter SPEC}

{/syntaxhighlighter}

My strong preference is also not to have to do any post-processing on the SVG files, as this becomes very tedious. That plus the simple embed code would truly be simple. Hopefully that's not wishful thinking!

Thanks again to all of you for your kind help. I'm certainly not an expert in SVGs and just thought that the time may be right to replace all bitmap images on my site with vectors. There's quite a learning curve.

In reply to by key-notes

1) take my advice and switch to object. img is not as controllable.

2) try using style="width:Npx; height:Npx;" it might make a difference. And here you must specify units. I actually use "rem" units, root em space, and I do it in an external CSS file. That gives me control over how the HTML and SVG scale together. This suggestion is a trial-and-error last resort kind of thing, but it might make a difference.

3) learn about how viewBox and width/height interact in the svg tag element. experiment with different values by manually editing a single example. i do this a lot and I still get confused about what's up and down in that realm, so it really helps to see it in action.

that's a good start. i was not an expert in SVG, and probably still am not, but i have been implementing it inside HTML in great detail since the beginning of this year, and it has taken a lot of trial and error to get things right, unfortunately. SVG is W3C spec, and caniuse.com says all the browsers support v1.1, but in reality there is a lot about it that is still "bleeding edge" technology in the browsers. The more SVG gets adopted the better this will get, but it's not in a perfectly clean, well documented or necessarily well implemented place right now. It's close, but depending on what you're trying to do you can bump into all kinds of restrictions that require pure trial and error debugging.

In reply to by sideways

I appreciate these suggestions and will try them out.

My very strong preference, again, is not to have to do any post-processing at all. Even specifying the dimensions in the HTML is a pain, since I have to calculate them for each SVG. Yes, I did write a little script that searches my image folder for an eponymous @2x PNG (a fallback if necessary), reads the width and height and appends that to the SVG HTML, but that requires exporting PNG for each SVG and running a script, and this for every edit to every SVG. I also have to edit all pages that particular SVG is used on in my CMS, every time. It's just too tedious.

All of this would be obviated if the desired width and height were contained in the SVG files. It would really make things much easier.

In reply to by key-notes

The correct width/height are in the SVG file, if you define "correct" as scaled 1:1 from the original MuseScore/Qt base.

If you can find a way to do this normally, via removing the width/height attributes and specifying width/height in the object tag, you can do that in the Qt editor's search files feature, or in many batch search/replace programs.

That really should work, and would indicate to me that an export option to use viewBox only might be the more desirable way to go - also very easy to implement in svggenerator.cpp.

In reply to by sideways

By "correct" I mean "desired," so not 1:1 but 1:n with n being the scaling factor. I'd much prefer not to have to specify width and height at all—just like bitmaps are displayed at their actual dimensions barring any overrides. The overrides are really very tedious to work with and require many additional steps, from exporting PNGs to running scripts to editing each page in a CMS.

I'll play around with viewBox, etc., though I still do think that exporting at any desired scaling factor would be the best solution for everyone. Honestly, I still don't see any downside. Most users could just leave the default setting of 1:1 alone, and those of us who want a different size could change it as needed. Besides, it's already provided for in the MuseScore settings—and had even already been implemented—so no additional dialog box is needed. I see zero potential downside and considerable potential upside.

In reply to by key-notes

Just trying to make sure you know what you're doing before you commit to it. And that you're thinking inside the larger box of all MuseScore users.

I'm saying that as an "and/or" with your change, specifying only the viewBox might be extremely useful and simple to implement.

I'm also saying that you should fully understand your SVG + HTML deployment before you decide what you need the SVG export to do for you.

In reply to by sideways

I did try removing width and height from the SVG and only using viewBox. This would indeed be simple to implement, but it had exactly the opposite of the desired effect:

If img tags are used, iOS browsers still ignore width and height attributes in the HTML. The SVG now stretches all the way across the container, making music notation completely inconsistent in size and outright huge.

If object tags are used, the images don't display at all—they're completely invisible. Perhaps this is my CMS—I don't know—but this is the case on macOS and iOS. (I also can't change my CMS for technical reasons.)

The best solution is still to make the actual SVG file as big or small as I need. At this point I don't see real counterarguments to (re-)implementing a scaling factor in MuseScore export, though as always I'm listening.

In reply to by key-notes

and you changed the src attribute to a data attribute on the object tag?
just checking...

did you try setting the style width/height instead of the object's width/height?

in the style you must specify units

you should definitely be able to display an svg via the object tag in iOS Safari. I'd debug that until it works and maybe search for a stackoverflow posting on the subject to get your HTML/CSS right.

In reply to by sideways

Oh, you're right, I forgot to change src to data. :-)

I made the change and it *does*, amazingly (to me), work... sort of. The problems are with my CMS:

(1) For some reason it automatically adds width="300" height="150" to object tags:
{syntaxhighlighter html}

{/syntaxhighlighter}

(I forgot I was already specifying width and height using CSS rather than HTML attributes.)

(2) For each image it seems I have to do two "passes" to edit the HTML part of the WYSIWYG editor, since the editor deletes some of my HTML on the first pass.

(3) The WYSIWYG editor doesn't show objects, so I can't see any music examples in the editor.

(Please no comments on the CMS—I'm generally "anti-CMS" and prefer a purely programmatic solution I write, but for business reasons this was necessary, and there is zero chance of switching to anything else.)

It looks like my only option is to define a scaling factor in the exported SVGs. ;-)

In reply to by sideways

think about it this way: If you add a feature to MuseScore based on a bogus SVG deployment with bogus requirements, then you are encouraging all other MuseScore users to opt for that same bogus deployment. It propagates when you make it a general use feature.

I have zero doubt that iOS Safari supports SVG display via the object tag.

See here for some code that does it:
https://stackoverflow.com/questions/38107006/make-an-html-svg-object-al…

As one example from less than a year ago.

In reply to by sideways

I disagree. Surely MuseScore users may need to output their SVGs at whatever dimensions they need for their application. Why rigidly impose one and only one resolution on all users?

You even mentioned Sibelius's exporting of SVG files at > 6x MuseScore's. Perhaps you find that too big, but clearly Sibelius's authors didn't arrive at the same output resolution; presumably they thought a different PPI would be more suitable in general.

Why not give MuseScore users control? After all, this had already been built into MuseScore, the setting is already there (and was never removed), it's easy to re-implement, and causes no harm whatsoever. Why are you so intent on imposing "one size fits all" when clearly one size doesn't fit all?

In reply to by sideways

Though for people who copy/past SVG from MuseScore into MS Word, for example, this might be useful. But even there you can size the image to suit your needs, and that is, as Marc keeps saying, the exact reason for using SVG.

In reply to by sideways

Even if users are pasting notation examples into MS Word for use in, say, an article or book, they'll surely want all examples to display at the same font size. This is impossible if each image needs to be scaled and "eyeballed." If they can just output a desired scaling factor, the problem would automatically be solved, just like for my application of displaying music notation on web pages.

In reply to by key-notes

Again, please start a new thread to discussion your application specifically. It is too hard to follow this by now deeply nested discussion about an application we don't know the first thing about. So no surprise if we keep talking across each other - we literally have no idea what it is you are trying to do and why the normal conventions of using PNG for fixed sized images but SVG for images you intend to scale later is for whatever not working for you. A separate thread focused on your particular use case is the best place to discuss this.

In reply to by sideways

"Because the correct deployment puts that control in the HTML/CSS."

If this were the case, why have professional vector graphics illustrators complained that the SVGs output by MuseScore are improperly defined in that they're far too small?

In reply to by sideways

As I posted in another part of this strangely ordered sub-thread, one of the biggest problems is that there don't seem to be many users using SVG export. I get very little feedback when I ask for it, and there seems to be generally very little chatter on the subject.

I'd love to see some specific, successful deployments by people, or attempts that failed. I've seen very little, and responded to every single commentary that has come my way.

In reply to by key-notes

With all respect, what is the downside to (re-)implementing a scaling factor for SVG export? It was already implemented, the code is already there, it's easy to implement (just a multiplier), and the setting is even already there. If users need it, they can change the default; if not, they can just ignore it. I see zero downside and considerable upside.

In reply to by key-notes

Go ahead. But someone removed the feature for a reason. Factor that into your PR. What's so hard about that?
You haven't even implemented it yet. We don't need to discuss this any further. You made a whole lot of general claims that I felt I had to refute. I yielded on your PR several posts ago. I have no authority anyway. That all happens during the PR process. I posted that part too.

In reply to by sideways

I'll be happy to try to implement it, though this is my first look at MuseScore's code so I'll probably be very likely to break something.

Since this is a very small detail and a very simple change, hopefully we can just implement such small changes in the future and save much back-and-forth. After all, there's already a transformation (in this case from 72 to 72, or 1:1), and my very small request is for this to be user-definable as is already provided for in the settings anyway. Surely it would have been much easier to fork the code and make a couple of minor edits rather than have a big debate about a tiny detail.

My understanding of why this was removed is that somebody wanted to import SVGs back into MuseScore and wanted them to display at a consistent size. My counterargument is that probably > 99% of users export graphics to use elsewhere, and exceedingly few need to re-import them. I don't see the justification for imposing a rigid change on everyone just for a tiny minority of use cases.

My case may also be a minority, but (1) that may change as more users adopt SVG, and (2) reverting to the previous behavior does not negatively impact other users since they can just ignore this setting and use the default if they desire.

In reply to by key-notes

So first, start another thread, as Marc suggested. If you want it to be a general feature in MuseScore you would start it as a feature request or something like that. There are some docs on that somewhere... Pick the right forum and start a thread. Link to that thread here. Those who want to can join you there. If you need help implementing this, I'll tag along.

But leave out the PR and general use part of it for now and get it done for your short term needs, which appears to be your personal priority anyway. You clearly want this, so make it happen. Then the general use integration can take place later. You've got to make it work for you before you create the PR anyway.

I am not familiar with this feature before it was removed or after. Sounds like something for PNGs that you want to adapt to SVG output. Dig into the code, start a new thread, and see what comes of it. The changes you'll want to make to the SVG Export are all in svggenerator.cpp, as far as I can tell from what you've said, which is simply to modify the svg element width/height attribute values.

In reply to by key-notes

Sorry for the extra post after suggesting an end to this thread, but something about your last post kept scratching at me:

Are you suggesting that I would "just implement" this change for you? It seems that you are. First of all, my work here is 100% volunteer. Second, I have no idea how simple this change is. The change to the svggenerator code sounds simple, but I have no familiarity with this previous feature. Sounds like it's PNG feature that you want to adapt for SVG. I really don't know. I was not aware of it as an SVG feature in the past. I don't think it's a matter of copying/pasting some old code. I really have no idea. And third, finally, I'm not available to do the work for you, if that's what you were suggesting by "hopefully we can just implement...".

As for the implication that it would have been just as easy to implement this thing as have this discussion, you're comparing apples to oranges. I'm certainly not going to write any code, especially for public use, before thoroughly discussing it and thinking it through. I hope I'm not in the minority in that category.

It's up to you to make this change and request the PR and the whole deal, unless you can find or hire someone else to do it. That's what open source is. I was trying to help you resolve this without changes to the code, but that's not working for you, so you're on to the next level.

In reply to by sideways

Of course I don't expect open source volunteers to implement my desired changes at whim. In this case, my understanding is that this had already been implemented and then removed for a reason that doesn't strike me as really justified. Also, I'm reasonably, but by no means absolutely, sure that this is just a minor change that should be relatively easy to implement. I just thought we can all save much time in the future if someone just forked the code and played around. If the change is good, it can be submitted for peer review. Of course, I'm coming late to the party and need to be familiarized with the development process. (I'm also now downloading the code and am very likely to break things trying to get this to work.)

In reply to by sideways

"And what you say about fonts and SVG is incorrect. I have my own version of MuseScore with and SVG export that relies on fonts, which are defined via @font-face in CSS. You don't have to install fonts on the client machine, you simply have to make them available on the server where you're hosting the SVG."

I was referring only to the music symbols font. Yes, I've noticed that other typefaces are defined using @font-face. In these cases I personally prefer to convert all fonts to paths, as for my purposes SVGs should be similar to bitmaps in that regard and not embed any font information or assume the user—or server—can access the required font files.

In reply to by sideways

I just output a simple 1-measure test file with treble clef, time signature and 1 note, using the Bravura font, and got this:

{syntaxhighlighter xml}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

test
Generated by MuseScore 2.1.0

{/syntaxhighlighter}

Happily there's no @font-face; MuseScore converts the music symbols to paths (unlike Sibelius).

I did notice that if text is added (such as lyrics), then MuseScore outputs @font-face for the text.

In reply to by key-notes

Yes, exactly. So either inline or in an external CSS file define the font face and font-family attribute and off you go! You can use relative paths to the files, or if you're serving this via a web server, you can use absolute paths (relative to /htdocs).

Also, look at the font size here: 128!!! that's 128px!

That's why Sibelius looks so big in SVG. The default font size for MuseScore, via Qt SVG export, is 20px. It's a factor of 6.4 greater, to be precise.

In reply to by sideways

As a final commentary on your deployment/implementation/whatever:

Given your approach, and depending on how well your CMS can help you with this, you might find that inline SVG is the best way to deploy. It will guarantee you a better level of cross-browser support because there is no object or img wrapping the SVG, it's right there inside the HTML. You're trying to bypass any intermediate settings anyway.

If your CMS makes blending all this text together into the final HTML, that might be your best solution.

In reply to by sideways

And as a final request, could you please explain your project, as Marc requested earlier. It's good for the folks at MuseScore to know about unusual deployments and uses, etc. And it's just good practice here in the forums. Give us a description of what you are trying to accomplish, your users, et cetera, the high-concept view of the project. Maybe a bit about the music involved.

Thanks.

Do you still have an unanswered question? Please log in first to post your question.