SVG Export: Text and Fonts vs. Paths and Lines
This is something that @lasconic has requested and I want to start a discussion about it prior to doing any work. There are several issues that result in several possible implementations. The first open question is:
What are you trying to accomplish by using fonts and text instead of paths and lines?
I see these possible benefits:
- Reduced SVG file size
- Centralized styling for your SVG scores, which can go beyond fonts. In terms of fonts, it can allow you to change the font for your SVG score "on-the-fly" with a single change that cascades through all of the SVG text elements, which is a substantial portion of the MuseScore graphics.
That's what I see. Feel free to add other potential or desired benefits to the list. Then review these four different implementation possibilities:
1) The font-family and font-size attributes appear in each and every text element in the SVG doc. This is a lot of extra, repeated text, which defeats one possible purpose of this new functionality: a smaller SVG file. The file is self-contained, no external references.
2) A preset, hardcoded stylesheet is embedded in the SVG file. This stylesheet handles the font-family and font-size attributes in a single location within the standalone SVG file that still has no external references. There are various levels of detail at which you can style the SVG sheet music from a stylesheet vs. inside each element. I do as much as possible in the stylesheet, which for text attributes includes 22 classes in 13 style rules, and I set font-family, font-size, font-weight, font-style, text-anchor, and fill attributes. Note vs. Tempo vs. Tuplet, for example, all three of those require different text styles. I captured the original values from standalone SVG exports, so they are essentially the MuseScore defaults. I may not have fully covered every type of MuseScore graphical element, but it's a solid starting point.
3) An external CSS file that has a preset file name. This is the option I use, and it is the most compact. The content of this file is essentially the same as the embedded style sheet, it's simply managed in a single external file that can be used by multiple SVG files. Each SVG file must include a reference to this external file.
4) My current code does even more than this in terms of CSS styling. All the lines and shapes have preset values in MuseScore. Consolidating those values by class reduces the file size, increases its readability/editability, and allows you to manipulate an entire album of scores from a central CSS file. In total now I have >40 classes styled by ~30 rules using additional attributes mostly relating to stroke vs. fill. It's a very good starting point, but probably not complete. Ideally, MuseScore could export a CSS file based on a score's own style settings. That's a whole separate project, unfortunately.
Your thoughts?
FYI - I just tried to upload a copy of my CSS file for sheet music, but apparently the .css extension is blocked. If it's something you really want to see I'll zip it or something.
Comments
To note some specific issues with class-based CSS styling: Barlines and GlissandoSegments
The wavy line glissando graphic is a text character in the MuseScore font. The straight line glissando is a line, not text. The GLISSANDO_SEGMENT element type applies to both the line and the "gliss." alphanumeric text that appears alongside that line. It is thus impossible, without further sub-classing, to distinguish between the graphical text of the wavy line and the alphanumeric text of the "gliss." label. They each use a different font.
My current implementation simply doesn't support the wavy line, and styles the alphanumeric text. I don't think that's an acceptable solution for MuseScore in general. It's not a big deal to do the further sub-classing, or you can leave it out of the CSS, but I want you to understand some of the specific challenges that can arise with isolated element types/classes.
Regarding Barlines, they have sub-types in MuseScore already, and I use the sub-types as sub-classes, but I don't style them all in CSS. I style the "normal" single bar line's stroke properties, but that's it. The sub-classing is used to separate normal from non-normal in a binary fashion, and then style only the normal in CSS.
I have encountered and handled a solid quantity of MuseScore element types via CSS styling. For the ones I have not addressed yet, there will be additional issues like these two. Not horrible, but not ideal. A complete CSS solution that covers everything and remains sane and maintainable is a wonderful idea, but it's not a reality today for MuseScore. Some attributes will simply be left embedded in some SVG elements because they are impossible to encapsulate that way. Part of the effort, if you want to maximize the use of CSS stylesheets, is to slog through all the element types and figure out the details for each one. That's regardless of whether you hardcode or auto-generate that CSS.
In reply to To note some specific issues by sideways
The problem with GLISSANDO_SEGMENT, you will probably have the same with arpeggio.
Please use https://gist.github.com for passing on ASCII content of files which not supported in the upload.
In reply to Please use by Thomas
Here we go:
https://gist.github.com/sidewayss/ad6cea3893d4f2e953dd7bd09e8e39a7
That's my MuseScore CSS file for SVG. It makes some hardcoded decisions about alphanumeric fonts that are probably not acceptable for MuseScore in general. Those will need to be made dynamic or not handled in CSS.
Also note that I am working on animating SVG, and that adds a whole other set of requirements and limitations on top of what MuseScore needs today. It doesn't affect this CSS file much, but it does affect it.
"What are you trying to accomplish by using fonts and text instead of paths and lines?"
Besides all the advanced features your building in here's another point for your initial question:
Text can be selected, copied and searched if it's true text.
This would be also possible when someone wanted to create a PDF (e.g. in Libreoffice) with SVG examples. A problem of course might be the font rendering in browser and the embedding of the fonts into a PDF if the fonts are not present on the user side.
In reply to "What are you trying to by musikai
Most of the MuseScore text uses a Unicode extended character set in the Emmentaler font. For purposes of SVG it is best to render those characters as XML entities. For example, a round note head is:
{syntaxhighlighter SPEC}{/syntaxhighlighter}
That's not a common, alphanumeric search. I'm simply refining the point you're making. Yes, some MuseScore text is alphanumeric, but the sheet music itself is a bunch of XML entities, mostly a single character per SVG text element.
Regarding the disadvantage if you don't make the font files available to the user: That's true, but it's easy to distribute the fonts, and I'm more focused on what benefits we're trying to achieve here, so that we can decide on an implementation strategy. This will be a new option to users. The existing 100% self-contained SVG export functionality remains. This is additional functionality and you need to be prepared to follow some rules if you want to take advantage of it. For me and my project I've gone whole hog for CSS styling. For me, the advantages far outweigh the effort required to make the font files available.
You are causing me to remember another advantage that the CSS styling provides: The potential for user-control of these settings, such as font and color. A 3rd party can style your score to their preferences as they view it in a browser. That's another separate project or set of projects to code, but CSS styling opens the door. I have some prototypes in that regard, as it is a topic of interest for me. It's not hard to set up in HTML. There the question becomes: How far do you go? How many style parameters to you open up to user control?
Sorry for the late answer...
First, let me comment about the reasons of using fonts vs paths. While I agree that the file size could be smaller, and that alone is a good reason to use fonts, I disagree on the second point, "changing the font for your SVG score 'on-the-fly'". MuseScore and a MuseScore user takes great care of the layout of their score. MuseScore uses the font metrics to layout the score, to attach the notehead to the stems etc... A MuseScore user will make sure that texts are not colliding and MuseScore 3 will try to avoid the collision by itself. In most cases, changing the musical font or the font of the texts used in the music will completely destroy the readability of the score. It's somehow a similar issue than the note alignment discussed previously.
Then, I see several use cases for "SVG export" or "Screen capture to SVG" in MuseScore:
(Do I miss anything?)
I don't really know the current status of SVG support for all the software listed but that's definitely one of the factor to choose what/how we will export. Here is a list of options we need to choose from or implement as settings.
1. Export of the whole score in one SVG or export one file per page
2. Export Paths or Fonts
3. If we export text with fonts, do we export the fonts? If yes, which format (WOFF?) In the css attached earlier, the fonts are premade, if we go this direction we will need to export them directly from MuseScore and include them in base64 in css or as external resources.
4. Export without CSS, with Internal CSS or with External CSS
5. If we export CSS wether external or internal, what do we put in the file, only the fonts or also the width, color of lines and shapes (barline, staffline, ledger lines, slur, crescendo etc...)
We need to answer these questions before considering adding anything in MuseScore.
I tried this branch https://github.com/sidewayss/MuseScore/tree/SMAWS22c which seems to be the most recent one. Even with the attached css, a lot of resources are missing (images and fonts in particular). Are you still working on this? What's the status of your implementation? How can I help?