Autor Thema: Verständnisfrage: Zusammenhänge im Layout  (Gelesen 2252 mal)

xr

  • Member
Verständnisfrage: Zusammenhänge im Layout
« am: Sonntag, 26. Februar 2017, 09:04 »
Hallo,

ich versuche mir einen Überblick über die Zusammenhänge im Lilypond Layout zu verschaffen. Dafür habe ich mal eine Tabelle erstellt, die eine Übersicht der Spalten und Zeilen im Layout geben soll.

Zitat
System
NonMusicalPaperColumn
NonMusicalPaperColumn
PaperColumnPaperColumnPaperColumn
VerticalAlignmentVerticalAxisGroupgrobs, zB StemStub NoteSpacing NoteColumngrobsgrobs
VerticalAxisGroupgrobs, zB NoteColumn BarLine StaffSpacing PhrasingSlurgrobsgrobs
VerticalAxisGroupgrobs, zB LyricText LyricSpacegrobsgrobs
VerticalAxisGroupgrobsgrobsgrobs

Beschreibung:
  • Der oberste Grob ist der Grob System, der alle Reihen und Spalten enthält
  • Die oberste Reihe unterhalb des Systems enthält Grobs wie: ( #<Grob NonMusicalPaperColumn > #<Grob PaperColumn > #<Grob SystemStartBar > #<Grob SpacingSpanner > #<Grob VerticalAlignment > #<Grob BreakAlignment > )
  • Die Spalten unterhalb einer PaperColumn enthalten alle musikalischen Elemente: Noten, Lyrics, Slurs, Markups
  • Das VerticalAlignment enthält alle VerticalAxisGroups
  • Jede VerticalAxisGroup enthält Grobs einer bestimmten Art: z.B. LyricText und LyricSpace

Wäre es richtig, zu sagen, dass Lilyponds Notensatz eine große Tabelle ist, jedes Element also eine Zelle ist? Und manche Elemente auch aus der Zelle hinausragen oder andere Elemente überlappen dürfen?

Der Zusammenhang von VerticalAxisGroup, VerticalAlignment und NonMusicalPaperColumn
Der Y-Parent von VerticalAxisGroups ist VerticalAlignment
Der X-Parent von VerticalAxisGroups und VerticalAlignment ist jeweils eine NonMusicalPaperColumn

Meine Frage ist: Ist die NonMusicalPaperColumn für beide die selbe? Oder wie muss ich mir das vorstellen?

Gruß und herzlichen Dank für Anmerkungen im Voraus,
Xaver

Tool aus der Snippet Repository, um sich die Hierarchie von Grobs anzeigen zu lassen:
http://lsr.di.unimi.it/LSR/Item?id=622

harm6

  • Member
Re: Verständnisfrage: Zusammenhänge im Layout
« Antwort #1 am: Sonntag, 26. Februar 2017, 10:15 »
Zitat
Wäre es richtig, zu sagen, dass Lilyponds Notensatz eine große Tabelle ist, jedes Element also eine Zelle ist? Und manche Elemente auch aus der Zelle hinausragen oder andere Elemente überlappen dürfen?

Ich muß gestehen, daß ich hier nur eingeschränkt Bescheid weiß. Mit den übergeordneten grobs wie #<Grob NonMusicalPaperColumn > #<Grob PaperColumn > #<Grob SystemStartBar > #<Grob SpacingSpanner > #<Grob VerticalAlignment > #<Grob BreakAlignment > beschäftige ich mich nur, wenn ich muß. ;)
Aber es ist sicherlich richtig, daß es eine Hierarchie von Eltern/Kinder-grobs gibt, sowohl in X- als auch in Y-Achse. Manche sind auch "Container-grobs", sammeln und bündeln also andere. Z.B. kommen alle NoteHeads (aber auch andere grobs) in die NoteColumn, um ein simples Beispiel zu bringen.
Alle grobs werden letztlich durch engraver (und deren Zusammenspiel) auf Grundlage des musikalischen inputs (den man sich z.B. mit displayMusic anzeigen lassen kann) erstellt.

Deine Beschreibung erscheint mir erstmal einleuchtend zu sein.

Zitat
Der Y-Parent von VerticalAxisGroups ist VerticalAlignment
Der X-Parent von VerticalAxisGroups und VerticalAlignment ist jeweils eine NonMusicalPaperColumn

Meine Frage ist: Ist die NonMusicalPaperColumn für beide die selbe? Oder wie muss ich mir das vorstellen?

Lass es uns testen:
\new Staff \with {
\override VerticalAxisGroup.after-line-breaking =
  #(lambda (grob)
    (let*  ((x-par (ly:grob-parent grob X))        ;; -> NonMusicalPaperColumn
            (y-par (ly:grob-parent grob Y))        ;; -> VerticalAlignment
            (x-par-y-par (ly:grob-parent y-par X))) ;; -> NonMusicalPaperColumn
 
    (format
      #t
      "\nIs the X-parent of VerticalAxisGroup a NonMusicalPaperColumn?: ~a"
      (eq? (grob::name x-par) 'NonMusicalPaperColumn))
    (format
      #t
      "\nIs the X-parent of the Y-parent of VerticalAxisGroup a NonMusicalPaperColumn?: ~a"
      (eq? (grob::name x-par-y-par) 'NonMusicalPaperColumn))
     
    (format #t "\nAre the found NonMusicalPaperColumns equal?: ~a"
            (equal? x-par x-par-y-par))))
}
{ c'1 }
Also: ja.

Zitat
Tool aus der Snippet Repository, um sich die Hierarchie von Grobs anzeigen zu lassen:
http://lsr.di.unimi.it/LSR/Item?id=622

Hier noch zwei andere tools:

(1)
Mein eigenes 'look-up-for-parent'
Es geht rekursiv durch den parent-tree um ein bestimmtes grob zu finden, egal an welcher Position im tree es ist. Allerdings nur in der spezifizierten Richtung.
#(define (look-up-for-parent name-symbol axis grob)
"Return the parent of @var{grob}, specified by it's @var{name-symbol} in
axis @var{axis} or @var{grob}, if equal to the grob named @var{name-symbol}
already.
If not found, look up for the next parent."
 (let* ((parent (ly:grob-parent grob axis)))
 (cond
   ((not (ly:grob? parent))
    (ly:error
       (_"Perhaps typing error for \"~a\" or \"~a\" is not in the parent-tree.")
       name-symbol name-symbol))
   ((equal? name-symbol (grob::name grob)) grob)
   ((not (equal? name-symbol (grob::name parent)))
    (look-up-for-parent name-symbol axis parent))
   (else parent))))
   
{
\override NoteHead.after-line-breaking =
#(lambda (grob)
  (write (look-up-for-parent 'VerticalAxisGroup Y grob)))
 
c'1
}

(2)
David Nalesniks 'display-pointers'
Gibt eine Tabelle zurück, die zeigt welche Eltern/Kinder/interfaces angelegt sind.
#(define (grob-interface::info iface)
   (hashq-get-handle (ly:all-grob-interfaces) iface))

#(define (grob-interface::properties iface-info)
   (if iface-info (cadddr iface-info) '()))

#(define (grob-interface::pointers grob iface)
   (let* ((info (grob-interface::info iface))
          (props (grob-interface::properties info))
          (pointers
           (and (pair? props)
                (filter
                 (lambda (prop)
                   (let ((type (object-property prop 'backend-type?)))
                     (or (eq? type ly:grob?)
                         (eq? type ly:grob-array?))))
                 props))))
     (if pointers
         (map
          (lambda (p) (list p (ly:grob-object grob p)))
          pointers))))

#(define (grob::all-pointers grob)
   (let ((ifaces (ly:grob-interfaces grob)))
     
     (define (entry iface)
       (let ((pointers (grob-interface::pointers grob iface)))
         (if (pair? pointers)
             (list (list iface pointers))
             '())))
     
     (let loop ((ifaces ifaces) (result '()))
       (if (null? ifaces)
           result
           (loop (cdr ifaces)
             (append result (entry (car ifaces))))))))

#(define (display-pointers grob)
   (format #t "~%~y ~y~%"
     (grob::name grob)
     (grob::all-pointers grob)))
   
{
\override NoteHead.after-line-breaking =
#(lambda (grob)
  (display-pointers grob))
 
c'1
}


HTH,
  Harm

xr

  • Member
Re: Verständnisfrage: Zusammenhänge im Layout
« Antwort #2 am: Sonntag, 26. Februar 2017, 10:43 »
Herzlichen Dank für die schnelle Antwort!


Ich hatte mir auch schon ein Lookup geschrieben. Bei mir wird allerdings jede Richtung durchlaufen und das erste gefundene Ergebnis zurückgeliefert.
Mir schien bisher, dass man bei dem, was ich gesucht habe, nicht auf namensgleiche aber unterschiedliche Grobs stoßen konnte.

\version "2.18.2"


#(define (grob-name grob)
    (cdr (assoc 'name (ly:grob-property grob 'meta))))

#(define resume-search #t)
#(define (get-parent-in-hierarchie grob searchword)
     ;; goes up in hierarchie until it finds
     ;; a grob named searchword     
     (define result #f)
     
     (define (get-par grob)
     
         (define compare
             (lambda (x)
                 (and (ly:grob? x)
                      (equal? searchword (grob-name x)))))   

        (let* (
            (parx   (ly:grob-parent grob X))
            (pary   (ly:grob-parent grob Y))
            )
           
            ;(disp (list parx (compare parx) pary (compare pary)))

            (cond
                ((not(equal? result #f))                     
                     result )
                ((compare parx)
                    (set! result parx)
                    result)
                ((compare pary)
                    (set! result pary)
                    result)
                (else
                    (if (ly:grob? parx)
                        (get-par parx))
                    (if(ly:grob? pary)
                        (get-par pary)) 
                )
            )
        )
    )
    ;; the inner function gets called from here
    (let* (
        (result (get-par grob))
        )
        ;; check if we found something
        (if (ly:grob? result)
            result
            #f
        )
    )
)

{
\override NoteHead.after-line-breaking =
#(lambda (grob)
  (write (get-parent-in-hierarchie grob 'VerticalAxisGroup)))

c'1
}