Autor Thema: einzeilige \score in \markup-Zeile vertikal ausrichten  (Gelesen 3780 mal)

Arnold

  • Member
einzeilige \score in \markup-Zeile vertikal ausrichten
« am: Donnerstag, 31. Januar 2013, 09:05 »
Hallo,

ich möchte mehere kurze \score (je ein Staff, meist ein Takt lang) in einer Text-Markup-Zeile vertikal auf die gleiche Höhe bringen, gemessen an den Staff-Notenlinien. Ohne weitere Eingriffe ist die Oberkante der Score-Ausdehnung mit der Grundlinie der Schrift ausgerichtet, und jede Musikbeispiel benötigt einen eigenen \raise-Wert.
Ich benutzte dies um zu dokumentieren, welche Noten ich bem Abschreiben als falsch erachtet habe und wie korrigiert habe.

Jetzt habe ich als Methode entdeckt, den "Vertical_align_engraver" zu entfernen - und dann ist die eine Notenzeile auf Y = 0 festgenagelt und ich benötige nur noch einen konstanten Höhenversatzwert. Bei mehreren Notenzeilen (z. Bsp. Pianostaff) wird das wohl nicht mehr klappen, aber meine Hauptanwendung sind eben nur einzeilige Notenkurzbeispiele.
Ein weiterer Nachteil: Es hagelt Warnungen der Art »Programmierfehler: didn't find a vertical alignment in this system; Fortsetzung, die Daumen drücken«.
\version "2.16.0" % 2.17.5
\markuplist {
  \column {
    \justified-lines {
      Takt 36, Viola:
      \raise #0.56 \score {
        { \override Staff.TimeSignature #'stencil = ##f
          \clef alto \key c \major \time 4/4
          c'8( e' g' d'')_"*" g'( f' g' e')
        }
        \layout {
          indent = 0 \mm
          \context { \Score
            \remove "Vertical_align_engraver"
            % dies legt zwar die Mitte der Notenzeile wie gewünscht auf Y = 0,
            % aber es hagelt die Meldung (bei 2.17.5 immerhin seltener):
            % »Programmierfehler: didn't find a vertical alignment in this system«
            % »Fortsetzung, die Daumen drücken«
          }
        }
      }
      #(ly:wide-char->utf-8 #x2192)
      \raise #0.56 \score {
        { \override Staff.TimeSignature #'stencil = ##f
          \clef alto \key c \major \time 4/4
          c'8( e' g' c')_"*" g'( f' g' e')
        }
        \layout {
          indent = 0 \mm
          \context { \Score
            \remove "Vertical_align_engraver"
          }
        }
      }
    }
  }
}

Hat jemand eine bessere Lösung parat?

Arnold

eluze

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #1 am: Donnerstag, 31. Januar 2013, 10:49 »
hallo Arnold

ich kannte den Vertical_align_engraver (noch) nicht er scheint mir aber sehr nützlich! (und die ständigen fehlermeldungen sind wirklich nervig - ich werde vermutlich noch einen bug report verfassen)

auch ich hasse es, wenn man ständig an der ausrichtung herumkorrigieren muss und benutze deshalb \vcenter für die texte.

dein beispiel könnte demnach so aussehen:

myLayout = \layout {
  indent = 0 \mm
  \context {
    \Score \remove "Vertical_align_engraver"
  }
  \context {
    \Staff \override TimeSignature #'stencil = ##f
  }
}
\markuplist {
  \column {
    \justified-lines {
      \vcenter \line { Takt 36, Viola: }
      \score {
        {
          \clef alto \key c \major \time 4/4
          c'8( e' g' d'')_"*" g'( f' g' e')
        }
        \layout {\myLayout }
      }
      \vcenter #(ly:wide-char->utf-8 #x2192)
      \score {
        {
          \clef alto \key c \major \time 4/4
          c'8( e' g' c,,)_"*" g'( f' g' e')
        }
        \layout {\myLayout }
      }
    }
  }
}

gruss
Eluze

harm6

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #2 am: Donnerstag, 31. Januar 2013, 12:14 »
Hallo Arnold,

ein andere Hack wäre es, die Y-Ausdehnung des Notenschlüssels so zu verändern, daß er die unterschiedliche Y-Ausdehnung der Staffs "auffängt". Dann kann man einen fixen Wert für \raise benutzen.

\version "2.16.1"

myLayout = \layout {
  indent = 0 \mm
  \context {
    %\Score \remove "Vertical_align_engraver"
  }
  \context {
    \Staff \override TimeSignature #'stencil = ##f
    \override Clef #'Y-extent = #'(-5 . 5)
  }
}

lnI =
\markup \justified-lines {
      \line { Takt 36, Viola: }
      \raise #5.7
      \score {
        {
          \clef alto \key c \major \time 4/4
          c'8( e' g' d'')_"*" g'( f' g' e')
        }
        \layout {\myLayout }
      }
      #(ly:wide-char->utf-8 #x2192)
      \raise #5.7
      \score {
        {
          \clef alto \key c \major \time 4/4
          c'8( e' g' c,,)_"*" g'( f' g' e')
        }
        \layout {\myLayout }
      }
    }


\markuplist {
  \column {
    \lnI
    \lnI
    \lnI
  }
}

Gruß,
  Harm

EDIT: Versions-Angabe im Code korrigiert.
« Letzte Änderung: Freitag, 1. Februar 2013, 00:40 von harm6 »

Arnold

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #3 am: Donnerstag, 31. Januar 2013, 12:43 »
Hallo Harm,

so etwas ähnliches habe ich auch schon überlegt.
Da ich aber nicht die Ausdehnung nach oben unnötig mit einem unbedrucktem Bereich vergrößern möchte, habe ich sogar überlegt, in einer speziellen Markuproutine zwei \score-Berechnungen laufen zu lassen, einmal mit und einmal ohne die Überhöhung, und aus der Differenz dann die Verschiebung berechnen, welche auf den \score-stencil ohne Überhöhung anzuwenden ist, bevor er zurückgegeben wird.

Arnold

eluze

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #4 am: Donnerstag, 31. Januar 2013, 18:16 »
@Harm
stimmt dein beispiel - ich kriege nur vertikal verschobene systeme!? (version 2.17.11, aber die sollte es nicht ausmachen)

@Arnold
primär geht es doch nur um die ausrichtung der elemente (texte und scores) untereinander - was man nachher mit ihnen macht ist belanglos solange sie untereinader stimmig sind.

Eluze

harm6

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #5 am: Freitag, 1. Februar 2013, 00:51 »
Zitat von: Eluze
@Harm
stimmt dein beispiel - ich kriege nur vertikal verschobene systeme!? (version 2.17.11, aber die sollte es nicht ausmachen)

Mein Beispiel funktioniert schon, aber nur mit 2.16.1. Meine Versionsangabe (2.12.3) war da natürlich wenig hilfreich. Habe ich jetzt korrigiert.
Mit 2.17.10 klappt der Y-extent-override für Clef tatsächlich nicht.
Ich hab' mal auf der internationalen Liste eine Frage dazu gestellt. Mal sehen was dabei raus kommt.
Allerdings geht es nach wie vor für StaffSymbol,TimeSignature und MultimeasureRest. (Soweit habe ich es zumindest getestet.)

Gruß,
  Harm



Arnold

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #6 am: Freitag, 1. Februar 2013, 09:56 »
Ja, Eluze, es geht um die vertikale Ausrichtung untereinander.

Ganz allgemein habe ich mir folgende Theorie überlegt:
Gäbe es »Ankerpunkte«, die man im \score-markup setzen könnte, und anschließend aus dem stencil (nach interpret-markup) dessen Koordinaten herauslesen könnte, wäre das Problem schon gelöst, wenn auch noch nicht die markup-funktion implementiert.
Offen ist, ob es nur einen Ankerpunkt geben darf, oder mehrere (benannte).
Im \score müßte man natürlich angeben können »anchorpoint #'RightHandStaff at Startpoint of this Staff« (für die benannten Ankerpunkte - dann könnte man sogar die Koordianten für linke und rechte Hand eines Pianostaff abfragen und die Verschiebung auf deren Mittelwert beziehen).
Das ganze könnte auch im normalen \score hilfreich sein bei after-line-breaking-Bearbeitungen (z. Bsp. Objekte nochmal verschieben).
Die einfachste Art eines Ankerpunktes wäre ein unstichtbarer Text (z. Bsp. als Instrumentenbezeichnung in meinem Fall), zusammen mit der Möglichkeit, dessen Position aus einem Stencil zu extrahieren.

Arnold

eluze

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #7 am: Samstag, 2. Februar 2013, 00:49 »
tut mir leid aber ich verstehe dein anliegen nicht recht - jetzt hast du ja verschiedene ansätze die score fragmente auszurichten und brauchst sie doch nur noch in ein \markup (mit \column, \line oder was auch immer) einzusetzen.

kannst du ein beispiel geben?

Eluze

Arnold

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #8 am: Montag, 4. Februar 2013, 08:54 »
Nun, immerhin habe ich seit Samstag abend eine Version, die ohne \remove "Vertical_align_engraver" auskommt. Zum Beweis habe ich Liedtext hinzugefügt.
Warum ich dennoch nicht zufrieden bin (mit der »Werteübergabe mittels eines globalen Parameters«), steht im Code. Es wäre einfach zu schön, wenn ich diesen Wert aus dem zurückgegebenen Stencil extrahieren könnte.
#(define-public caught-staff-offset 0.0)

#(define (staff-offset-catching grob)
  (let* ((my-system (ly:grob-system grob))
         (orig (ly:grob-original grob))
         (siblings (if (ly:grob? orig)
                    (ly:spanner-broken-into orig)
                    '()))
         (Y-distance (ly:grob-relative-coordinate grob my-system Y)))
   (if (or (null? siblings) (eq? grob (car siblings))) ; first system only
    (set! caught-staff-offset (- Y-distance)))))

#(define-markup-command (raiseByCaughtStaffdistance layout props additional-delta score)
  (number? markup?)
  ;;; Interpret the \score markup, where the relevant Staff uses
  ;;; `\override Staff.StaffSymbol #'after-line-breaking = #staff-offset-catching´
  ;;; to store it's Y position releativ to the upper limit of the score markup.
  ;;; Then shift the resulting stencil up by the value stored in `caught-staff-offset´
  ;;; and return it.
  ;;; NOTICE:
  ;;;   a) a malfunction of staff-offset-catching will induce an old offset to be used.
  ;;;   b) This is a critical code for parallel processing in multiple threads!
  ;;;      Execute only one instance of this code at the same time!
  ;;;      This becomes improtant if one day lilypond will use multiple threads to interpret
  ;;;      the markups.
  (let ((markup-stencil (interpret-markup layout props score)))
   ;;; (for-each display (list "\n distance to raise = " caught-staff-offset " "))
   (ly:stencil-translate-axis markup-stencil (+ additional-delta caught-staff-offset) Y)))


\markuplist {
  \column {
    \justified-lines {
      Takt 36, Viola:
      \raiseByCaughtStaffdistance #0.56 \score {
        <<
        { \override Staff.TimeSignature #'stencil = ##f
          \override Staff.StaffSymbol #'after-line-breaking = #staff-offset-catching
          \clef alto \key c \major \time 4/4
          c'8\( e' g' d''\)_"*" g'\( f' g' e'\)
        }
        \addlyrics { c' e' g' d'' g' f' g' e' }
        >>
        \layout { indent = 0 \mm }
      }
      #(ly:wide-char->utf-8 #x2192)
      \raiseByCaughtStaffdistance #0.56 \score {
        <<
        { \override Staff.TimeSignature #'stencil = ##f
          \override Staff.StaffSymbol #'after-line-breaking = #staff-offset-catching
          \clef alto \key c \major \time 4/4
          c'8\( e' g' c'\)_"*" g'\( f' g' e'\)
        }
        \addlyrics { c' e' g' c' g' f' g' e' }
        >>
        \layout { indent = 0 \mm }
      }
      #(ly:wide-char->utf-8 #x2190)
      \raiseByCaughtStaffdistance #0.56 \score {
        { \override Staff.TimeSignature #'stencil = ##f
          \override Staff.StaffSymbol #'after-line-breaking = #staff-offset-catching
          \clef alto \key c \major \time 4/4
          c'1 \break d'1 \break e'1 \bar "|."
        }
        \layout { indent = 0 \mm ragged-right = ##t }
      }
    }
  }
}
Arnold

eluze

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #9 am: Montag, 4. Februar 2013, 12:53 »
beeindruckend!

woher kommt eigentlich der wert 0.56?

Eluze





Arnold

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #10 am: Montag, 4. Februar 2013, 14:31 »
Hallo Eluze,

die 0,56 ist der Versazt-Wert, den die Mitte der Pfleil-Zeichnes U+2192 bzw. U+2190 des benutzten Standardfonts über der Gundlinie der Schrift liegt.
In meinem ersten Beispiel hatte ich noch die \raise-Anweisung (mit diesem Zahlenwert) eingebunden. Nachdem ich jetzt sowiese eine »\raise mit 'on the fly' Wert« Funktion habe, konnte ich den Offset gleich mit dazu angeben und draufaddieren. So spare ich mir, sieben Zeichen (einschließlich des Leerzeichens) bei der Eingabe, als wenn ich \raise nochmal separat angeben würde.
Hätte die Schriftart gar nicht diese Pfeile, und hätte ich deshalb einen eigenen Pfeil-Markup zusammengestellt, würde der wahrscheinlich ein bischen höher bei 1,0 liegen.
Als veränderbaren Wert habe ich diesen Offset belassen, denn ich traue der Zukunft nicht - andere Schriftarten, skalieren von Text oder Notensnippet, all das könnte einen anderen Wert nötig machen.

Arnold.


eluze

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #11 am: Samstag, 16. Februar 2013, 15:12 »
hallo Arnold

wäre das was fürs LSR!?

gruss
Eluze

Arnold

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #12 am: Montag, 18. Februar 2013, 08:25 »
Bevor ich's ins LSR stellem würde ich gerne noch der Frage nachgehen, ob man die Koordinate statt »hintenrum« über eine globale Variable durch den »Stencil getunnelt« übergeben kann.

Arnold

Arnold

  • Member
Re: einzeilige \score in \markup-Zeile vertikal ausrichten
« Antwort #13 am: Dienstag, 12. März 2013, 16:42 »
Hallo,

wenn ich es richtig interpretiere, dann hat sich mit Version 2.17.14 da etwas Entscheidendes http://git.savannah.gnu.org/gitweb/?p=lilypond.git;a=commit;h=692b4e4ed7c1aae4d4d53ad59c26c22f2dd2d90f verändert!

Damit lässt sich wahrscheinlich auch ein Incipit als instrumentName = \markup { \with-dimensions ... \score { ... } } definieren - die textliche Instrumentenbezeichnung steht letztlich im (inneren) score-Block.

Arnold