Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

notehead/stem interaction in SVG renderings #520

Closed
craigsapp opened this issue Mar 13, 2017 · 19 comments
Closed

notehead/stem interaction in SVG renderings #520

craigsapp opened this issue Mar 13, 2017 · 19 comments

Comments

@craigsapp
Copy link
Contributor

Stems (similar to ledger lines) should be written to the SVG before noteheads, otherwise the stems occlude the notehead:

screen shot 2017-03-13 at 10 53 37 am

<g class="note highlight" id="note-L13F1" fill="red" stroke="red">
   <use xlink:href="#E0A4" x="6421" y="1535" height="720px" width="720px" />
   <rect x="6421" y="1557" height="608" width="20" />
</g>

If the order were changed:

screen shot 2017-03-13 at 10 56 31 am

<g class="note highlight" id="note-L13F1" fill="red" stroke="red">
   <rect x="6421" y="1557" height="608" width="20" />
   <use xlink:href="#E0A4" x="6421" y="1535" height="720px" width="720px" />
</g>

It might also be nice to label sub-components of the note element with class tags for more semantic addressing with CSS:

<g class="note highlight" id="note-L13F1" fill="red" stroke="red">
   <rect class="stem" x="6421" y="1557" height="608" width="20" />
   <use class="head" xlink:href="#E0A4" x="6421" y="1535" height="720px" width="720px" />
</g>

CSS currently:

<style>

svg .note.highlight use {
        fill: violet;
}

svg .note.highlight rect {
        fill: red;
}

</style>

would become:

<style>
svg .note.highlight .head {
        fill: violet;
}

svg .note.highlight .stem {
        fill: red;
}

</style>
@craigsapp
Copy link
Contributor Author

Further thoughts for possible class tags on accidentals sub-elements in <g class="note"> eleents:

accidentals could be labeled with "acc", and then as well with which type of accidental:

Natural:

<use class="acc n" ...

Sharp:

<use class="acc s" ...

Flat

<use class="acc f" ...

@lpugin
Copy link
Contributor

lpugin commented Mar 13, 2017

You should use GetElementAttr for this. Otherwise we will end up with all the MEI in the SVG.

@craigsapp
Copy link
Contributor Author

You should use GetElementAttr for this. Otherwise we will end up with all the MEI in the SVG.

What is wrong with that :-)

Labeling with "s", "f", "n" for accidentals is probably overkill, but labeling "acc" might be useful.

One idea is to have a verovio option to label sub-elements in SVG which approximately map to attributes of the MEI elements:

var options {
     font:  "Leipzig",
     pageHeight: 100,
     labelSubgroups: 1
}

or

var options {
     font:  "Leipzig",
     pageHeight: 100,
     labelSvgNoteSubelements: 1
}

When that is turned on, the class tags for things like stems, noteheads, ledger-lines, accidentals, editorial accidentals, would be added as well to the SVG image. Mostly these would be useful for controlling how to highlight notes in the SVG image, so for things other than notes this feature is less interesting/important.

Somewhat related, I have been noticing that stems are siblings of notes when inside a beam group:

<g class="beam" id="beam-L3F1-L4F1">
        <path d="M1111 1873 L1111 1252" stroke="#000000" stroke-width="20" />
        <path d="M1672 1783 L1672 1195" stroke="#000000" stroke-width="20" />
        <polygon points="1101,1232 1682,1175 1682,1265 1101,1322 " />
        <g class="note highlight" id="note-L3F1">
                <use xlink:href="#E0A4" x="895" y="1895" height="720px" width="720px" />
        </g>
        <g class="note highlight" id="note-L4F1">
                <use xlink:href="#E0A4" x="1456" y="1805" height="720px" width="720px" />
        </g>
</g>

It would probably be better to make the stems children of notes so that highlighting of a note can allow the stem of the note to be highlighted as well:

<g class="beam" id="beam-L3F1-L4F1">
        <g class="note highlight" id="note-L3F1">
                <path d="M1111 1873 L1111 1252" stroke="#000000" stroke-width="20" />
                <use xlink:href="#E0A4" x="895" y="1895" height="720px" width="720px" />
        </g>
        <g class="note highlight" id="note-L4F1">
                <path d="M1672 1783 L1672 1195" stroke="#000000" stroke-width="20" />
                <use xlink:href="#E0A4" x="1456" y="1805" height="720px" width="720px" />
        </g>
        <polygon points="1101,1232 1682,1175 1682,1265 1101,1322 " />
</g>

And then have the beam overstrike the stems by moving it to the bottom of the beam group.

@lpugin
Copy link
Contributor

lpugin commented Mar 13, 2017

I am working on a branch where each note component (note-head, stem, flag) has its own class. We can see if we want to preserve them in the SVG even thought they are not MEI classes. To be discussed

@rettinghaus
Copy link
Contributor

@craigsapp This naming convention absolutly makes sense, as single parts of a note can be controlled via @stem.* and @head.* attributes. Alternatively we could use the attribute classes att.stems and att.noteheads. This somewhat better fits the attribute-ish approach in MEI, but would be less intuitive I guess.

<g class="note highlight" id="note-L13F1" fill="red" stroke="red">
   <rect class="stem" x="6421" y="1557" height="608" width="20" />
   <use class="head" xlink:href="#E0A4" x="6421" y="1535" height="720px" width="720px" />
</g>

For accidentals I think @lpugin is right: use GetElementAttr.

@lpugin
Copy link
Contributor

lpugin commented Mar 13, 2017

I am thinking of something like:

<g class="note highlight" id="note-L13F1" fill="red" stroke="red">
  <g class="stem">
     <rect x="6421" y="1557" height="608" width="20" />
  </g>
  <g class="head"> 
    <use  xlink:href="#E0A4" x="6421" y="1535" height="720px" width="720px" />
  </g>
</g>

@craigsapp
Copy link
Contributor Author

craigsapp commented Mar 13, 2017

I checked the SVG for accidentals, and I see they have their own <g class="accid"> grouping, so of course accidentals do not need to be otherwise be labeled.

<g class="note highlight" id="note-L3F1">
        <path d="M1015 2345 L1339 2345" stroke="#000000" stroke-width="20" />
        <use xlink:href="#E0A2" x="1027" y="2345" height="720px" width="720px" />
        <g class="accid" id="accid-L3F1">
                <use xlink:href="#E262" x="825" y="2345" height="720px" width="720px" />
        </g>
</g>

(Even when it is encoded as note@accid instead of note/accid).

Example:

screen shot 2017-03-13 at 1 06 37 pm

HTML implementation:

<html>
<head>
<title>type/class mapping test</title>
</head>

<body>
<style>

svg g.note.highlight  {
	fill: violet;
}

svg g.note.highlight g.accid {
	fill: red;
}

</style>


<svg width="2100px" height="2970px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" overflow="visible">
	<defs>
		<symbol id="E050" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M441 -245c-23 -4 -48 -6 -76 -6c-59 0 -102 7 -130 20c-88 42 -150 93 -187 154c-26 44 -43 103 -48 176c-4 60 11 123 44 189c29 57 65 106 110 148s96 85 153 127c-3 16 -8 46 -13 92c-4 43 -5 73 -5 89c0 117 16 172 69 257c34 54 64 82 89 82c21 0 43 -30 69 -92 s39 -115 41 -159c2 -120 -19 -173 -67 -256c-13 -20 -63 -90 -98 -118c-13 -9 -25 -19 -37 -29l31 -181c8 1 18 2 28 2c58 0 102 -12 133 -35c59 -43 92 -104 98 -184c11 -135 -80 -229 -180 -270c8 -57 17 -110 25 -162c5 -31 6 -58 6 -80c0 -30 -5 -53 -14 -70 c-35 -64 -88 -99 -158 -103c-42 -3 -83 6 -124 26c-50 24 -77 59 -80 105c-2 34 5 63 20 87c18 28 45 42 79 44c51 4 99 -40 103 -87c4 -56 -30 -94 -105 -115c17 -24 51 -36 102 -36c62 0 116 43 140 85c9 16 13 41 13 74c0 20 -1 42 -5 67c-8 53 -18 106 -26 159zM461 939 c-95 0 -135 -175 -135 -286c0 -24 2 -48 5 -71c50 39 92 82 127 128c43 57 63 106 60 148c-4 54 -23 82 -57 81zM406 119l54 -326c80 27 116 88 109 184c-7 99 -62 146 -163 142zM382 117c-74 -2 -132 -50 -128 -127c2 -46 43 -99 75 -115c-3 -2 -7 -5 -10 -10 c-70 33 -116 88 -123 172c-5 73 42 135 88 170c23 17 49 29 78 36l-29 170c-21 -13 -52 -37 -92 -73c-50 -44 -86 -84 -109 -119c-49 -75 -71 -140 -67 -195c5 -68 35 -127 93 -176s125 -73 203 -73c25 0 50 3 75 9c-19 111 -36 221 -54 331z" />
		</symbol>
		<symbol id="E0A2" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M198 133c102 0 207 -45 207 -133c0 -92 -98 -133 -207 -133c-101 0 -198 46 -198 133c0 88 93 133 198 133zM293 -21c0 14 -3 29 -8 44c-7 20 -18 38 -33 54c-20 21 -43 31 -68 31l-20 -2c-15 -5 -27 -14 -36 -28c-4 -9 -6 -17 -8 -24s-3 -16 -3 -27c0 -15 3 -34 9 -57 s18 -41 34 -55c15 -15 36 -23 62 -23c4 0 10 1 18 2c19 5 32 15 40 30s13 34 13 55z" />
		</symbol>
		<symbol id="E262" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M136 186v169h17v-164l44 14v-91l-44 -14v-165l44 12v-91l-44 -13v-155h-17v150l-76 -22v-155h-17v149l-43 -13v90l43 14v167l-43 -14v92l43 13v169h17v-163zM60 73v-167l76 22v168z" />
		</symbol>
	</defs>
	<style type="text/css">g.page-margin{font-family:Times;} g.tempo{font-weight:bold;} g.dir, g.dynam {font-style:italic;}</style>
	<svg id="definition-scale" viewBox="0 0 21000 29700">
		<g class="page-margin" transform="translate(500, 500)">
			<g class="system" id="system-0000000195809882">
				<g class="section boundaryStart" id="section-0000001229694174" />
				<g class="measure" id="measure-L2">
					<g class="staff" id="staff-L2F1N1">
						<path d="M0 1445 L2822 1445" stroke="#000000" stroke-width="20" />
						<path d="M0 1625 L2822 1625" stroke="#000000" stroke-width="20" />
						<path d="M0 1805 L2822 1805" stroke="#000000" stroke-width="20" />
						<path d="M0 1985 L2822 1985" stroke="#000000" stroke-width="20" />
						<path d="M0 2165 L2822 2165" stroke="#000000" stroke-width="20" />
						<g class="clef" id="clef-0000000163139938">
							<use xlink:href="#E050" x="90" y="1985" height="720px" width="720px" />
						</g>
						<g class="layer" id="layer-L2F1N1">
							<g class="note highlight" id="note-L3F1">
								<path d="M1015 2345 L1339 2345" stroke="#000000" stroke-width="20" />
								<use xlink:href="#E0A2" x="1027" y="2345" height="720px" width="720px" />
								<g class="accid" id="accid-0000001947981330">
									<use xlink:href="#E262" x="825" y="2345" height="720px" width="720px" />
								</g>
							</g>
						</g>
					</g>
					<g class="barLineAttr" id="bline-0000000096464651">
						<path d="M2657 1445 L2657 2165" stroke="#000000" stroke-width="30" />
						<path d="M2777 1445 L2777 2165" stroke="#000000" stroke-width="90" />
					</g>
				</g>
				<g class="boundaryEnd section-0000001229694174" id="bdend0000000134935522" />
			</g>
		</g>
	</svg>
</svg>


</body>
</html>

@rettinghaus
Copy link
Contributor

I wouldn't wrap sub-elements in an extra <g> container. For CSS it's sufficient to have <g class="note" xml:id="some-proper-id"> and then "sub-classes" directly on path/rect/use etc.

@craigsapp
Copy link
Contributor Author

That is good:

<g class="note highlight" id="note-L13F1" fill="red" stroke="red">
  <g class="stem">
     <rect x="6421" y="1557" height="608" width="20" />
  </g>
  <g class="head"> 
    <use  xlink:href="#E0A4" x="6421" y="1535" height="720px" width="720px" />
  </g>
</g>

Although a bit verbose :-) But it will make thing more consistent, since compound graphical elements should be wrapped into a g element to label them (such as the 5 lines of a staff).

@pe-ro
Copy link

pe-ro commented Mar 13, 2017

Interesting to see you guys going in this direction since this is where MEI is also headed. 😀

@craigsapp
Copy link
Contributor Author

I was going to point that out sooner or later :-)

music-encoding/music-encoding#420

Mapping mei::@type to svg::@class has been in the works for verovio since last June :-)

#194

@pe-ro
Copy link

pe-ro commented Mar 13, 2017

I meant the SVG markup --

<g class="note highlight" id="note-L13F1" fill="red" stroke="red">
  <g class="stem">
     <rect x="6421" y="1557" height="608" width="20" />
  </g>
  <g class="head"> 
    <use  xlink:href="#E0A4" x="6421" y="1535" height="720px" width="720px" />
  </g>
</g>

mirroring the proposed MEI --

<note>
  <stem/>
  <noteHead/>
</note>

@pe-ro
Copy link

pe-ro commented Mar 13, 2017

My argument was that this markup, as opposed to --

<note stem.whatever="yeahyeah" head.whatever="sayWhat"/>

would be more useful for graphical applications mainly because it allows one to label, type, etc. at a more detailed level.

@craigsapp
Copy link
Contributor Author

A ha, the musicXMLification of MEI :-) . I.e., doing more things as element rather than attributes.

@pe-ro
Copy link

pe-ro commented Mar 13, 2017

Improvement of MEI, yes. musicXMLification, no. 😀

@notator
Copy link

notator commented Mar 14, 2017

Actually, its the SVGification of MEI. 😀
@lpugin said:

I am working on a branch where each note component (note-head, stem, flag) has its own class. We can see if we want to preserve them in the SVG even thought they are not MEI classes. To be discussed

That's very interesting: If there was a standard container structure, and standard names for the classes, then the SVG could be thought of (and used) as an interchange format containing a default implementation.

@lpugin
Copy link
Contributor

lpugin commented Apr 11, 2017

image

<chord dur="8">
    <note oct="4" pname="c">
        <accid accid="n" />
    </note>
    <note oct="3" pname="b"/>
    <note oct="3" pname="g"/>
    <note oct="3" pname="e">
        <accid accid="f"/>
    </note>
</chord>

Is now (in develop-layer branch)

<g class="chord">
	<path />
	<path />
	<g class="stem">
		<path />
		<g class="flag">
			<use xlink:href="#E241" />
		</g>
	</g>
	<g class="note">
		<use xlink:href="#E0A4" />
		<g class="accid">
			<use xlink:href="#E261" />
		</g>
	</g>
	<g class="note">
		<use xlink:href="#E0A4" />
	</g>
	<g class="note">
		<use xlink:href="#E0A4" />
	</g>
	<g class="note">
		<use xlink:href="#E0A4" />
		<g class="accid">
			<use xlink:href="#E260" />
		</g>
	</g>
</g>

@lpugin lpugin closed this as completed Apr 11, 2017
@craigsapp craigsapp reopened this Oct 19, 2017
@craigsapp
Copy link
Contributor Author

Why was this closed?

Stems should be written to the SVG before noteheads. Perhaps also wrap notehead use element in a g element.

Example demonstrating stem placed above notehead, which does not look as nice as the other way around:

screen shot 2017-10-19 at 9 09 17 am

If the notehead were to be placed after the stem:

screen shot 2017-10-19 at 9 11 54 am

Stylesheet for example:

<style>
@namespace xlink 'http://www.w3.org/1999/xlink';

g.note.highlight > use {
        fill: chocolate;
}

g.note.highlight g.accid {
        fill: limegreen;
}

g.note.highlight g.stem {
        fill: orange;
}

g.note.highlight g.artic {
        fill: red;
}

g.note.highlight use[xlink|href="#E4A2"] {
        fill: hotpink;
}

</style>

Test MEI data:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="2100.00px" height="2970.00px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" overflow="visible">
	<desc>Engraved by Verovio 2.0.0-dev-ae70647-dirty</desc>
	<defs>
		<symbol id="E050" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M441 -245c-23 -4 -48 -6 -76 -6c-59 0 -102 7 -130 20c-88 42 -150 93 -187 154c-26 44 -43 103 -48 176c-4 60 11 123 44 189c29 57 65 106 110 148s96 85 153 127c-3 16 -8 46 -13 92c-4 43 -5 73 -5 89c0 117 16 172 69 257c34 54 64 82 89 82c21 0 43 -30 69 -92 s39 -115 41 -159c2 -120 -19 -173 -67 -256c-13 -20 -63 -90 -98 -118c-13 -9 -25 -19 -37 -29l31 -181c8 1 18 2 28 2c58 0 102 -12 133 -35c59 -43 92 -104 98 -184c11 -135 -80 -229 -180 -270c8 -57 17 -110 25 -162c5 -31 6 -58 6 -80c0 -30 -5 -53 -14 -70 c-35 -64 -88 -99 -158 -103c-42 -3 -83 6 -124 26c-50 24 -77 59 -80 105c-2 34 5 63 20 87c18 28 45 42 79 44c51 4 99 -40 103 -87c4 -56 -30 -94 -105 -115c17 -24 51 -36 102 -36c62 0 116 43 140 85c9 16 13 41 13 74c0 20 -1 42 -5 67c-8 53 -18 106 -26 159zM461 939 c-95 0 -135 -175 -135 -286c0 -24 2 -48 5 -71c50 39 92 82 127 128c43 57 63 106 60 148c-4 54 -23 82 -57 81zM406 119l54 -326c80 27 116 88 109 184c-7 99 -62 146 -163 142zM382 117c-74 -2 -132 -50 -128 -127c2 -46 43 -99 75 -115c-3 -2 -7 -5 -10 -10 c-70 33 -116 88 -123 172c-5 73 42 135 88 170c23 17 49 29 78 36l-29 170c-21 -13 -52 -37 -92 -73c-50 -44 -86 -84 -109 -119c-49 -75 -71 -140 -67 -195c5 -68 35 -127 93 -176s125 -73 203 -73c25 0 50 3 75 9c-19 111 -36 221 -54 331z" />
		</symbol>
		<symbol id="E0A4" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M0 -39c0 68 73 172 200 172c66 0 114 -37 114 -95c0 -84 -106 -171 -218 -171c-64 0 -96 30 -96 94z" />
		</symbol>
		<symbol id="E262" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M136 186v169h17v-164l44 14v-91l-44 -14v-165l44 12v-91l-44 -13v-155h-17v150l-76 -22v-155h-17v149l-43 -13v90l43 14v167l-43 -14v92l43 13v169h17v-163zM60 73v-167l76 22v168z" />
		</symbol>
		<symbol id="E4A2" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M0 45c0 13.333 4.33301 24.667 13 34s19.333 14.333 32 15c14 0 25.667 -4 35 -12s14.333 -19 15 -33c0 -13.333 -4.33301 -24.667 -13 -34s-19.333 -14.333 -32 -15c-14 0 -25.667 4 -35 12s-14.333 19 -15 33z" />
		</symbol>
		<symbol id="E4A0" viewBox="0 0 1000 1000" overflow="inherit">
			<path transform="scale(1,-1)" d="M0 236l347 -119l-347 -117v33l252 84l-252 86v33z" />
		</symbol>
	</defs>
	<style type="text/css">g.page-margin{font-family:Times;} g.tempo{font-weight:bold;} g.dir, g.dynam{font-style:italic;} g.label{font-weight:normal;}</style>
	<svg class="definition-scale" viewBox="0 0 21000 29700">
		<g class="page-margin" transform="translate(500, 500)">
			<g class="system" id="system-0000000147693057">
				<g class="section boundaryStart" id="section-0000000211317838" />
				<g class="measure" id="measure-L2">
					<g class="staff" id="staff-L2F1N1">
						<path d="M0 1400 L1829 1400" stroke="#000000" stroke-width="20" />
						<path d="M0 1580 L1829 1580" stroke="#000000" stroke-width="20" />
						<path d="M0 1760 L1829 1760" stroke="#000000" stroke-width="20" />
						<path d="M0 1940 L1829 1940" stroke="#000000" stroke-width="20" />
						<path d="M0 2120 L1829 2120" stroke="#000000" stroke-width="20" />
						<g class="clef">
							<use xlink:href="#E050" x="90" y="1940" height="720px" width="720px" />
						</g>
						<g class="layer" id="layer-L2F1N1">
							<g class="note highlight" id="note-L3F1">
								<use xlink:href="#E0A4" x="1094" y="1400" height="720px" width="720px" />
								<g class="stem" id="stem-0000000078965084">
									<rect x="1094" y="1422" height="608" width="20" />
								</g>
								<g class="accid" id="accid-0000001530885643">
									<use xlink:href="#E262" x="825" y="1400" height="720px" width="720px" />
								</g>
								<g class="artic" id="artic-L3F1">
									<g class="articPart" id="artic-part-0000000021272942">
										<use xlink:href="#E4A2" x="1183" y="1265" height="514px" width="514px" />
									</g>
									<g class="articPart" id="artic-part-0000001052050792">
										<use xlink:href="#E4A0" x="1119" y="1172" height="514px" width="514px" />
									</g>
								</g>
							</g>
						</g>
					</g>
					<g class="barLineAttr" id="bline-0000001518569483">
						<path d="M1664 1400 L1664 2120" stroke="#000000" stroke-width="30" />
						<path d="M1784 1400 L1784 2120" stroke="#000000" stroke-width="90" />
					</g>
				</g>
				<g class="boundaryEnd section-0000000211317838" id="bdend-0000001273392098" />
			</g>
		</g>
	</svg>
</svg>

@lpugin
Copy link
Contributor

lpugin commented Nov 3, 2017

The best for this will be to use SVG 2 (https://www.w3.org/TR/SVG2/render.html#RenderingOrder)

I am closing it for now and we can re-open it when we move to SVG 2

@lpugin lpugin closed this as completed Nov 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants