verovio icon indicating copy to clipboard operation
verovio copied to clipboard

Support for vertical and horizontal offsets on fingering and potentially other elements

Open infojunkie opened this issue 2 years ago • 6 comments

Describe the problem Fingering indication does not respond to relative positioning @ho / @vo.

To Reproduce Steps to reproduce the behavior:

  1. Load the data attached into Verovio MEI Viewer
  2. Observe that the fingering above the first E note is not moved from its default position, even though the corresponding fing element includes @ho and @vo attributes.

Expected behavior The fingering indication would be moved according to these attributes, as per the specification.

Input data Attached.

Verovio information

  • Version of Verovio: 3.16.0-dev-51fe2cf
  • Binding: JavaScript

infojunkie avatar Jun 22 '23 04:06 infojunkie

Offset attributes are currently not supported.

rettinghaus avatar Jun 22 '23 09:06 rettinghaus

Yes, @rettinghaus is right. This is a general feature request. I've been thinking about it for a while. (See this discussion. It seems that the common understanding for offsets if for them to be applied after the layout algorithm has been performed. This can potentially yield collision, since that might precisely be the desired goal.

I am working on a project where offsets will be useful, so I will add them in the couple of months. I am renaming the issue accordingly.

lpugin avatar Jun 22 '23 12:06 lpugin

Fingering indication does not respond to relative positioning @ho / @vo.

@ho can often better be described with @tstamp (and for elements with an endpoint @tstamp2, rather than using @startid/@endid. Once @ho is implemented there can be semantic problems when dealing with dynamic score layout if you are not careful.

@vo is more generally useful to have, although there are many verovio options that can be used to accomplish the same thing.

Both would be necessary to refine notation so that musicians reading from a verovio typeset score from complaining. (But this would typically be to optimize a static layout of the music.)

Here is an example:

Screenshot 2023-06-25 at 6 13 58 PM
Click to view MEI data for above example.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="5.0.0-dev">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt />
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2023-06-25T18:14:00" version="3.16.0-dev-bac8070">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
  <workList>
   <work>
    <title xml:id="title-L1" analog="humdrum:Xfi" type="translated">extract -s 0,1,2</title>
   </work>
  </workList>
  <extMeta>
   <frames xmlns="http://www.humdrum.org/ns/humxml">
    <metaFrame n="0" token="!!!Xfilter: extract -s 0,1,2" xml:id="L1">
     <frameInfo>
      <startTime float="0" />
      <frameType>reference</frameType>
      <referenceKey>Xfilter</referenceKey>
      <referenceValue>extract -s 0,1,2</referenceValue>
     </frameInfo>
    </metaFrame>
   </frames>
  </extMeta>
 </meiHead>
 <music>
  <body>
   <mdiv xml:id="m18yh31h">
    <score xml:id="s1av1t0v">
     <scoreDef xml:id="s1vq96fo">
      <staffGrp xml:id="sr8yrcd">
       <staffDef xml:id="staffdef-L2F2" n="1" lines="5">
        <clef xml:id="c19yl24l" shape="G" line="2" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L2F1">
      <measure xml:id="measure-L1">
       <staff xml:id="staff-L2F2" n="1">
        <layer xml:id="layer-L1F2N1" n="1">
         <note xml:id="note-L3F2" dur="4" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L4F2" dur="4" oct="4" pname="d" accid.ges="n" />
         <note xml:id="note-L5F2" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L9F2" dur="4" oct="4" pname="f" accid.ges="n" />
        </layer>
       </staff>
       <fing xml:id="fing-L3F3" place="above" staff="1" startid="#note-L3F2">
        <rend xml:id="r8x1a20" fontsize="small">1</rend>
       </fing>
       <fing xml:id="fing-L4F3" place="above" staff="1" startid="#note-L4F2">
        <rend xml:id="re2g4n9" fontsize="small">2</rend>
       </fing>
       <fing xml:id="fing-L5F3" place="above" staff="1" startid="#note-L5F2">
        <rend xml:id="r1qo2vif" fontsize="small">3</rend>
       </fing>
       <fing xml:id="fing-L7F3" place="above" staff="1" tstamp="3.500000">
        <rend xml:id="rb6h569" color="red" fontsize="small">1</rend>
       </fing>
       <fing xml:id="fing-L9F3" place="above" staff="1" startid="#note-L9F2">
        <rend xml:id="r823jwa" fontsize="small">2</rend>
       </fing>
      </measure>
      <measure xml:id="measure-L10">
       <staff xml:id="staff-L10F2N1" n="1">
        <layer xml:id="layer-L10F2N1" n="1">
         <note xml:id="note-L11F2" dur="4" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L12F2" dur="4" oct="4" pname="d" accid.ges="n" />
         <note xml:id="note-L13F2" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L17F2" dur="4" oct="4" pname="f" accid.ges="n" />
        </layer>
       </staff>
       <fing xml:id="fing-L11F3" place="above" staff="1" startid="#note-L11F2">
        <rend xml:id="rqqwuf" fontsize="small">1</rend>
       </fing>
       <fing xml:id="fing-L12F3" place="above" staff="1" startid="#note-L12F2">
        <rend xml:id="r9bu7g4" fontsize="small">2</rend>
       </fing>
       <fing xml:id="fing-L13F3" place="above" staff="1" startid="#note-L13F2">
        <rend xml:id="r7xhi1e" fontsize="small">3</rend>
       </fing>
       <fing xml:id="fing-L15F3" place="above" staff="1" tstamp="3.750000">
        <rend xml:id="r1u8w261" color="red" fontsize="small">1</rend>
       </fing>
       <fing xml:id="fing-L17F3" place="above" staff="1" startid="#note-L17F2">
        <rend xml:id="r1h3lnky" fontsize="small">2</rend>
       </fing>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>

The placement of the red fingering could be improved. The first measure uses @tstamp="3.5" while the second one uses @tstamp="3.75". Preferably the 3.5 timestamp should look like the 3.75 example (or even more preferably, 3.5 should generate a horizontal position exactly in the middle between the two adjacent fingerings.

You can post an example of what you want. Probably you are thinking of something different: you want to attach the fingerings to a specific @startid and offset from the verovio automatic placement:

Screenshot 2023-06-25 at 6 45 18 PM

In which case @ho and @vo would be required.

craigsapp avatar Jun 26 '23 01:06 craigsapp

Thanks for the detailed response. Yes, I am trying to emulate (and improve upon) a Finale rendering that looks like this:

finale.

I'd like to avoid mixing timing information with layouting information if at all possible. I guess I could also target the relevant svg elements and explicitly move them after rendering, but too many of these hacks will get messy.

infojunkie avatar Jun 26 '23 02:06 infojunkie

In your particular case @ho and @vo are the best to use, and not @tstamp (for @ho). When the layout changes, you do not want the spacing between the notes and fingerings to change for various horizontal layout spacings. For @tstamp the spacing will change.

craigsapp avatar Jun 26 '23 02:06 craigsapp

@craigsapp there is also @to (see https://music-encoding.org/guidelines/dev/attribute-classes/att.visualOffset.to.html), which I think would be quite interesting to support for dynamic rendering. However, the common understanding for that one might be more to be a pre-layout calculation offset, though, and a clarification on this might be necessary.

lpugin avatar Jun 26 '23 06:06 lpugin