Text und Noten sollen die ganze Breite füllen

Begonnen von stefanhuglfing, Samstag, 7. Oktober 2017, 21:53

« vorheriges - nächstes »

stefanhuglfing

Ich möchte Texte vor Notenzeilen schreiben. Damit soll möglichst die ganze Seitenbreite gefüllt werden.

So ist mir rechts zu viel frei:
\version "2.19.54"

\markup
{
  \concat
   {
    "Text vor der Notenzeile"
    \score { { c'4 d' e' f' g'1 g'4 f' e' d' c'1 } }
   }
}

\layout {}


mit "ragged-right = ##f" wird zwar die Notenzeile gestreckt,
was ich mir wünsche, aber sie ragt übers Papier hinaus:

\version "2.19.54"

\paper { ragged-right = ##f }

\markup
{
  \concat
   {
    "Text vor der Notenzeile"
    \score { { c'4 d' e' f' g'1 g'4 f' e' d' c'1 } }
   }
}

\layout {}


Mit fill-line statt concat überlappen sich Text und Noten:

\version "2.19.54"

\paper { ragged-right = ##f }

\markup
{
  \fill-line
   {
    "Text vor der Notenzeile"
    \score { { c'4 d' e' f' g'1 g'4 f' e' d' c'1 } }
   }
}

\layout {}


Es sollen mehrere unterschiedlich breite Notenzeilen und Texte sein,
der Text soll  linksbündig, die Notenzeilen rechtsbündig sein
und die Notenzeilen so gestreckt oder gestaucht, dass keine großen Lücken entstehen.
Weiß jemand, wie ich das am besten hinbekomme?

Malte

Hm ... schwierige Angelegenheit. Wenn ich richtig verstehe, soll auf jeder Zeile immer genau ein Text und eine Notenzeile sein, oder? Und die Notenzeile soll sich in ihrer Breite so anpassen, daß die gesamte Zeilenbreite ausgefüllt wird? Das hieße also in etwa
    Notenbreite = Zeilenbreite gesamt − (Textbreite + konstante Breite für Lücke)

Nach längerem Suchen und Probieren habe ich folgendes Zwischenergebnis:\version "2.19.65"

#(define-markup-command
  (with-linewidth-minus-markup layout props width-markup show-markup)
  (markup? markup?)
  (let*
   ((interpret-width-markup (interpret-markup layout props width-markup))
    (extent (ly:stencil-extent interpret-width-markup X))
    (width (- (cdr extent) (car extent)))
    (old-line-width (ly:output-def-lookup layout 'line-width))
    (line-width (- old-line-width width))
    ;(new-layout (ly:output-def-clone layout)))
    (new-layout layout))
   ;(print "~a, ~a\n" old-line-width line-width)
   (ly:output-def-set-variable! new-layout 'line-width line-width)
   (interpret-markup new-layout props
     show-markup)))

\layout {
  ragged-right = ##f
  indent = 0
}

\markup \column {
  \concat {
    "Laaaaaaaaaaaaaaaaaaaaanger Text"
    "kurzer Text"
  }
  \fill-line {
    "Laaaaaaaaaaaaaaaaaaaaanger Text"
    \with-linewidth-minus-markup "Laaaaaaaaaaaaaaaaaaaaanger Text"
    \score {
      { c'4 d' e' f' g'1 g'4 f' e' d' c'1 }
    }
  }
  \fill-line {
    "kurzer Text"
    \with-linewidth-minus-markup "kurzer Text"
    \score {
      { c'4 d' e' f' g'1 g'4 f' e' d' c'1 }
    }
  }
}
Zeile 14 (die mit dem print) kann man auskommentieren, um sich die Gesamtzeilenbreite und die errechnete Notenzeilenbreite bei jedem Anwenden des Befehls ausgeben zu lassen. Ich müßte hier mit einer Kopie von layout arbeiten (Zeile 12 statt 13), aber das läßt mir aus irgendeinem Grund Ghostscript sterben. Macht man keine Kopie, dann wird bei jedem Anwenden des Befehls die Textbreite abgezogen, beim nächsten Mal aber mit dieser verkürzten Zeilenbreite weitergerechnet  :-\ (Die erste Zeile der Ausgabe mit dem \concat soll nur zeigen, daß die Lücke in der zweiten Zeile genau die Länge ist, die in der dritten Zeile abgezogen wird. Anscheinend werden die \markups von unten nach oben abgearbeitet.)

Edit: Das ganze ist natürlich nur ein erster Entwurf, besonders anwenderfreundlich wärs in der Version ja noch nicht. Da kann man aber viel abkürzen ;)

Malte

Zitat von: Malte am Sonntag,  8. Oktober 2017, 01:19
Ich müßte hier mit einer Kopie von layout arbeiten (Zeile 12 statt 13), aber das läßt mir aus irgendeinem Grund Ghostscript sterben.
Die PS-Datei hat in diesem Fall anscheinend den Emmentaler-Font nicht eingebettet, vermutlich der (oder ein) Grund ...

Manuela

Malte, eine blöde Frage. Wieso gibt deine (wieder einmal geniale) Funktion nicht gleich beide Parameter in einer Zeile aus? So müsste man nicht vorher den Text extra schreiben.

BTW, ich hätte eine ähnliche Idee gehabt, jedoch sind meine Scheme-Kenntnisse noch immer unzureichend, um die Idee auszuprogrammieren. Du hast das eh schon erledigt  ;) jetzt kann ich wieder  was lernen
Danke für eure Hilfe
viele Grüße
-- Manuela

harm6

Hallo Malte,

bei mir funktioniert (ly:output-def-clone layout) tadellos. Mit Ubuntu 16.04 64-bit und Ghostscript 9.18.
Was genau klappt bei Dir nicht? Welche gs-Version?

Gruß,
  Harm

Malte

Zitat von: Manuela am Sonntag,  8. Oktober 2017, 07:29
Malte, eine blöde Frage. Wieso gibt deine (wieder einmal geniale) Funktion nicht gleich beide Parameter in einer Zeile aus? So müsste man nicht vorher den Text extra schreiben.
Ganz einfach: Solche Optimierungen wollte ich erst anfangen, wenn die ganze Sache an sich läuft ...
Zitat
BTW, ich hätte eine ähnliche Idee gehabt, jedoch sind meine Scheme-Kenntnisse noch immer unzureichend, um die Idee auszuprogrammieren. Du hast das eh schon erledigt  ;) jetzt kann ich wieder  was lernen
Das ist für mich auch alles noch sehr neu mit output-defs etc., und wie gesagt noch nicht optimiert (wozu auch anständige Variablennamen etc. gehören) ;)

Zitat von: harm
Was genau klappt bei Dir nicht? Welche gs-Version?
Ich bin der Meinung, daß es schon vor gs daran scheitert, daß Emmentaler nicht eingebettet wird. LilyPond 2.19.65 (offizieller Release, nicht selbst kompiliert) für 64-bit-Linux, Linux Manjaro mit gs-Version 9.21. Hier mal ein diff der Eingabedateien und ein grep nach Emmentaler in den ausgegebenen PS-Dateien (ich habs mal per --ps gar nicht bis zu Ghostscript kommen lassen):
malte@HOSTNAME$ diff -u problem_no-clone.ly problem_output-def-clone.ly
--- problem_no-clone.ly 2017-10-08 10:32:20.896396079 +0200
+++ problem_output-def-clone.ly 2017-10-08 10:32:12.959466209 +0200
@@ -9,7 +9,7 @@
     (width (- (cdr extent) (car extent)))
     (old-line-width (ly:output-def-lookup layout 'line-width))
     (line-width (- old-line-width width))
-    (new-layout layout))
+    (new-layout (ly:output-def-clone layout)))
    ;(print "~a, ~a\n" old-line-width line-width)
    (ly:output-def-set-variable! new-layout 'line-width line-width)
    (interpret-markup new-layout props
malte@HOSTNAME$ lilypond_unstable -lDEBUG --ps problem_no-clone.ly &> problem_no-clone.log
malte@HOSTNAME$ lilypond_unstable -lDEBUG --ps problem_output-def-clone.ly &> problem_output-def-clone.log
malte@HOSTNAME$ grep -a Emmentaler-20 problem_no-clone.ps | head -n 5
%%DocumentSuppliedResources: font Emmentaler-20
%%BeginFont: Emmentaler-20
%%BeginResource: font Emmentaler-20
%%Title: (FontSet/Emmentaler-20)
%%BeginResource: FontSet (Emmentaler-20)
malte@HOSTNAME$ grep -a Emmentaler-20 problem_output-def-clone.ps
/helpEmmentaler-20 where {pop helpEmmentaler-20} if
malte@HOSTNAME$

Den ersten grop hab ich hier per head gekürzt, weil dann auch lange binär-Zeilen mit dem eingebetteten Font folgen ;)

Ein
diff -u problem_no-clone.log problem_output-def-clone.log
zeigt außer natürlich veränderten Ein- und Ausgabedateinamen keine Unterschiede auf.

Im Anhang findest du die .ly- und die resultierenden .log- und .ps-Dateien. Das Forum erlaubt für einzelne Anhänge nur eine kleinere Größe als für die Summe, deshalb kommen sie in zwei zips (das no-clone-zip enthält das no-clone-ps, alle anderen Dateien sind im anderen zip).

harm6

#6
Hallo Malte,

seltsamerweise bekomme ich jetzt auch den gs-Fehler.
Ich hab' aber keine Ahnung woran es liegt, frag doch mal auf der internationalen Liste.

Nichtsdestotrotz hier ein coding welches erstmal funktioniert:

#(define-markup-command (foo layout props arg1 arg2)(markup? ly:score?)
  (let* ((arg1-stil (interpret-markup layout props arg1))
         (arg1-lngth (interval-length (ly:stencil-extent arg1-stil X)))
         (line-width (ly:output-def-lookup layout 'line-width))
         (output-scale (ly:output-def-lookup layout 'output-scale))
         (score-line-width (* output-scale (- line-width arg1-lngth))))
    (ly:score-add-output-def!
      arg2
      #{ \layout { line-width = $score-line-width } #})
   
  (interpret-markup layout props
    (make-fill-line-markup (list arg1 (make-score-markup arg2))))))

\layout {
  ragged-right = ##f
  indent = 0
}

\markup \column {
  \concat {
    "Laaaaaaaaaaaaaaaaaaaaanger Text"
    "kurzer Text"
  }
  \foo
    "Laaaaaaaaaaaaaaaaaaaaanger Text"
    $#{ \score { { c'4 d' e' f' g'1 g'4 f' e' d' c'1 } } #}
  \foo
    "kurzer Text"
    $#{ \score { { c'4 d' e' f' g'1 g'4 f' e' d' c'1 } } #}
}


Die Eingabe ist allerdings unbequemer.

Gruß,
  Harm

EDIT überflüssigen ly-code entfernt


harm6

Zitat von: harmNichtsdestotrotz hier ein coding welches erstmal funktioniert:
[...]
Bevor ich hier weitermache, warte ich auf Rückmeldung, denn:
Zitat von: MalteWenn ich richtig verstehe, soll auf jeder Zeile immer genau ein Text und eine Notenzeile sein
ist zwar möglicherweise richtig aber nicht zwangsläufig.
Ehe ich also mehr Arbeit investiere ...


Gruß,
  Harm