Closed rpspringuel closed 9 years ago
To develop a little bit: TeX has its own complex line-breaking algorithm, so we can't just do things at line level easily, though there are some experiments to do it in Lua, but it's really not mature enough, and it will make everything noticeably slower. So let's not count on it and do what we can.
What I propose is the following solution:
Do you see what I mean?
Note that this won't work in the case where a line breaks in the middle of a syllable and the lowest note is not well placed, but as it will fix 90% of the cases, it's already a good improvement. But if you or I work on it, it would be good to make gregorio also pass lowest note to each glyph, so that we can refine the algorithm later at glyph level, in order to avoid the case I described before.
Some discussions I was having today about the Gregorio inspired the following idea:
This would require two passes through LuaTeX to get the spacing correct, but that's already a fairly normal operation for TeX users (for instance, to get cross references right).
I think this is similar to what @eroux proposed above, but would be entirely done in the TeX.
Yes, I'm also thinking about this solution, but it's quite a lot of work too... For instance: how do you know what to write to the aux file? I don't think you can get a line per line information in the aux file simply... It would certainly require some pass in a lua callback too, or do you have something else in mind? But anyway, having two pass for this feature is no problem, so if it works that way, let's do it.
I'd probably go this way for implementation:
First, we define two counters scorecounter
and linecounter
which track the score and lines within the score (i.e. the second counter is a sub-counter of the first). We also have a tracking variable current_line_space
which tracks the lowest note encountered so far in this line.
At the beginning of each line (for instance, when drawing the staff lines or the clef that starts each line) go through the following steps:
linecounter=0
), write the value of current_line_space
to scorecounter_linecounter_space
in the aux file. This represents the needed space for the line we just ended.linecounter
.current_line_space
to 0.scorecounter_linecounter_space
which was loaded when the previous run's aux file was loaded at the beginning of the run (this is automatic). Default to 0 when the variable is not found.Basically, I can detect the beginning of each line from processes that are already done on a line by line bases (printing staff lines or the clef at the beginning of each line). That tells me when to write to the aux file. By then continually monitoring the amount of space needed for a line and resetting that tracking information whenever I write to the aux file, I can know what to write to the aux file. Combine the two (along with a counter system to track which information goes with which line) and I should be able to write information to the aux file on a line by line basis and retrieve it accordingly.
Quoting you:
Basically, I can detect the beginning of each line from processes that are already done on a line by line bases (printing staff lines or the clef at the beginning of each line).
I admit I'd be curious to know how... Can you show a minimal example of this?
Perhaps detect is the wrong word. Rather I'd piggy back on the code that draws the lines by inserting code which would do the above. A quick glance at the code tells me that's in localleftbox
, so I'd probably prefix the contents of that box with the necessary code. I'll work on a short example when I get the chance.
I'm affraid you'll be a bit surprised by the result... but let's give it a try, I might be!
@henryso there is something you could do here that would be very useful: making the \greglyph
macro aware of the highest and lowest level of what it typesets (including signs). This could be by adding \greglyphhighestlevel{x}
and \greglyphlowestlevel{y}
in the #5
th argument of \greglyph
or by adding two new arguments... It would be straightforward if it was only the notes, but I think you're the person knowing best the C code on signs heights, and it's the most difficult part... What do you think?
I can do it. Which way (argument #5
or additional arguments) would work best for you?
Let's start with additional arguments to #5
and you ca define \greglyph(highest|below)level
to macros that just don't do anything, we'll complete them later
Choral signs generally pass the height of the note. If the note is on a line and it's a high choral sign, it passes the height of the note + 2. How should I adjust the height for choral signs?
Should I even account for signs at all? Wouldn't it be cleaner to instrument the sign macros to maintain the computation in TeX?
Also, I intend to only create one macro which takes two arguments. Let me know if that's a bad idea.
The idea of instrumenting sign macros is interesting, this would be less intrusive indeed!
Or for having one macro.
Changes for this are in #440, ready for review. However, #440 piggybacks on #439, so merging #440 would merge the changes from #439 as well.
As mentioned above, I am only passing the low/high pitches to the new macro, called \GreGlyphHeights
(to follow the convention in #383).
@rpspringuel Did you have any luck using localleftbox
to reset things at the beginning of a line?
I actually haven't had a chance to try yet.
@eroux Having a better understanding of what you want to implement, I understand better why you wanted to take signs into account for the min/max height calculation in gregorio. I will make this change. By the time the sign macros get to it, the attributes on the main glyph node would have already been set.
Before I go off the deep end with this implementation, please check what I've done so far in the https://github.com/gregorio-project/gregorio/tree/fix-59 branch and let me know if I'm on the right track.
The code is really rough at this point, though it seems to work in my limited testing.
This is not yet ready to be a pull request. I need to do cleanup, remove dead code, add better comments, document the changes, and test more. But I would really like at least a high level review to prevent needless meandering.
Note: there's additional discussion on this topic in #515, #517, and #518.
Should the default be the old uniform-line-height behavior or the new variable-line-height behavior?
the new one will be better for beginners and will make Gregorio easier, we should just document that it might have a performance impact.
I have to report, after testing, that the old line-height behavior is not actually uniform. It's controlled by values passed by gregorio (the executable), and gregorio is a bit inconsistent (or perhaps just plain wrong) about the values it passes on the first line and around forced line breaks. I suppose I should fix this as well, to make it truly uniform. Or should I just let sleeping dogs lie?
As of #520, the implementation is more-or-less complete. If you have time, please review and let me know if there's anything I should change.
The last remaining thing before I create a pull request for https://github.com/gregorio-project/gregorio/tree/fix-59 into master
is documentation.
I think it would be best to fix the old line height system, it will certainly still be used... That's all I see, you did a very good job!
Apparently the Solesmes scores only move the lyric text down only on lines where the a low element (note
a'
,a
,b'
, orb
) is present. Currently gregorio moves the lyrics down for the whole score when this happens. A user would like to be able to imitate the Solesmes behavior.This will probably require making two passes per line. The first to figure out what the lowest note on the line is, the second to actually set the lines. Perhaps the first pass populates two boxes (one for staff and neumes, the other for text), then the second can simply place them on the page. However, there might be alignment issues in this approach.