Re: ps changes betweeen 2.7.29 and 2.8.2 broke tabloid booklet
Graham Percival <[EMAIL PROTECTED]> wrote on Sun, 14 May 2006 at 21:08:21 -0700 in <[EMAIL PROTECTED]>: > >I expect this relates to binary font encodings and psbook/psnup. What > >if you pdf2ps the lilypond-produced pdf file and use that as your > >starting point for psbook? > > It works fine with this solution. > > > Still, it would be nice to track down this bug. Yeah... the problem here is it kind of depends on your idea of a bug. I find it a bit frustrating because even if it is fixed in ghostscript, I expect it will still cause my printer to crash... I think Han-Wen's position is that if LilyPond generates legitimate postscript, then things are OK, even if several popular postscript interpreters have trouble with it. > http://percival-music.ca/bar.ps ... > Current file position is 4968 > AFPL Ghostscript 8.51: Unrecoverable error, exit code 1 So, this is in the middle of the Emmentaler-14 font. i.e. this is an opentype font issue. In a perfect world, we'd discover there was a fontforge bug in the generation of the opentype fonts, but I don't think we're really in that world. But perhaps someone here is active in fontforge development and knows if the issue has been raised? --jhawk ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: ps changes betweeen 2.7.29 and 2.8.2 broke tabloid booklet
On 14-May-06, at 7:57 PM, John Hawkinson wrote: Argh. Well, this teaches me to reply to one email before reading the rest. :) Christian Conkle on lilypond-user reported a similar failure, Yes; that prompted me to investigate, and I discovered that my previously-working system failed. Graham Percival <[EMAIL PROTECTED]> wrote on Thu, 11 May 2006 at 03:24:36 -0700 in <[EMAIL PROTECTED]>: 1) use lilypond-book to produce normal ps and pdf. (well, normal-looking; I know little about under-the-hood ps stuff) 2) run this: psbook $1.ps | psnup -2 -ptabloid -Pletter | ps2pdf -sPAPERSIZE=11x17 - tab-$1.pdf With 2.8.2, the final ps2pdf fails I expect this relates to binary font encodings and psbook/psnup. What if you pdf2ps the lilypond-produced pdf file and use that as your starting point for psbook? It works fine with this solution. Still, it would be nice to track down this bug. The original file (works with ps2pdf) is http://percival-music.ca/op2.ps and after psbook $1.ps | psnup -2 -ptabloid -Pletter > bar.ps(no longer works) http://percival-music.ca/bar.ps and here's the error message: Error: /rangecheck in --get-- Operand stack: names --nostringval-- 1 6147 --nostringval-- 37 Execution stack: %interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- --nostringval-- Dictionary stack: --dict:1124/1686(ro)(G)-- --dict:0/20(G)-- --dict:81/200(L)-- --dict:53/72(ro)(G)-- --dict:10/30(L)-- Current allocation mode is local Last OS error: 2 Current file position is 4968 AFPL Ghostscript 8.51: Unrecoverable error, exit code 1 Cheers, - Graham ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Getting the height of a system.
On Sun, 14 May 2006 20:40, Han-Wen Nienhuys wrote: > Joe Neeman schreef: > > We discussed this a bit a long time ago but I'm getting close to actually > > implementing something so I thought I'd bring it up again. > > > > Getting the Y-extent of a system is potentially destructive, causing all > > sorts of non-undoable caching and possibly suiciding of grobs. So I need > > to do make a copy of the system before I can get its Y-extent. > > > > The problem is that there are a large number of possible lines in a > > score. To copy a system, I need to do a full grob substitution for every > > grob in that system. If each bar could be in up to N possible lines, I > > need to do N full copies of the entire score and N full grob > > substitutions in the > > object_alist_. If we can fit up to K bars to a line then N is > > approximately K(K-1)/2. In the scores I typically work with, N would be > > around 50-60 so this is getting pretty expensive. > > It's much worse than that, because the cost of the substitution is > actually proportional to the number grobs in the "long" System, i.e. the > length of the entire score. It would be much much better if you could > make your algorithm compute the system heights of a complete line > breaking configuration. I think this could be even more expensive because my page breaker looks at a _lot_ of different line breaking configurations. On the score I have been using for coverage tests (Haydn op 76, no 3, 1st violin part), the page breaker tests more than 4000 different line breaking configurations so this is already much more expensive than doing it for 50-60 copies of the score. > Also, it's not completely possible to compute the height of an isolated > system: some grobs (notably spanners like slur) look at the next system > to decide how to format across line breaks. Would it be acceptable to skip those cases? This would be a good point to mention that I don't really need the exact height of the system -- just an approximation. The current approximation I am using (setting a score-wide system-height) is _very_ crude but it works pretty well as long as there are no RemoveEmptyStaffContexts or very high notes. > > > So I propose the following instead. I don't know a great deal (yet) about > > the C++ internals of grobs so I'd appreciate knowing if this is > > unworkable before I spend lots of time trying to implement it. > > > > 1) add a virtual Grob *save () and virtual void restore (Grob*) function > > to every C++ Grob subclass. save() would be a bit like clone except that > > it copies the object_alist_ and, for example, broken_intos_ in the case > > of a Spanner. > > Grob *copy = me->save (); > > // make some changes to me > > me->restore (copy); > > and you end up with the same grob you started with. > > > > 2) save every grob in the score > > > > 3) for each possible system, using the original grobs, > > - work out the Y-extent > > - restore () every grob in that system > > > > The advantage is that we avoid fiddling around with the object_alist_ > > because this clone is never used -- it exists only to save the state of > > the score before we mess it up with calling Y-extent. We also only have > > to make one copy of the system and restore it N times instead of making N > > copies. > > Sounds like a possiblity, but have you also considered break alignments? > It's not only the object_alist_ (and property_alist_, as that too will > change), but also other pointers like original_. I hadn't, but it's just a matter of copying a few more bits of data, right? > > Secondly, although it will be nicely portable, it also sounds like a lot > of work. Isn't it a lot easier to simply do a fork() and let the OS > clean up after us? Perhaps if the vertical spacing is completely > working, we can consider doing the full-blown copy and restore. Also, > for large scores, fork() is an interesting option, as we could get some > benefit from using SMP. But then the OS would have to deal with copying the data and it can only do that in page-sized chunks. So wouldn't this just increase the amount of stuff that gets copied? Getting a bit OT, the gomp project was recently checked in for GCC 4.2 [http://gcc.gnu.org/wiki/GCC 4.2 Projects]. If you want to introduce parallelism, it might be a worthwhile thing to wait for since it is portable and _much_ easier to use than either fork() or pthreads. There is actually another possibility that I've only just thought of so it's pretty half-baked: Add an approximate-Y-extent to each grob that 1) leaves the grob constant (in particular no caching) 2) ignores anything in the object_alist_ that doesn't have a system. Then we could even get away with not doing any break-substitutions (until it's time to typeset things, of course) with something like: Real System::guess_line_height (Column_x_positions col) { set_bound (LEFT, col.cols_[0]); set_bound (RIGHT, col.cols_.back ()); for (vsize i = 0;
Re: ps changes betweeen 2.7.29 and 2.8.2 broke tabloid booklet
Argh. Well, this teaches me to reply to one email before reading the rest. Christian Conkle on lilypond-user reported a similar failure, and made me wonder if the patch I had posted had caused a behavior change. But since you're having the same problem without my patch, evidently not. Graham Percival <[EMAIL PROTECTED]> wrote on Thu, 11 May 2006 at 03:24:36 -0700 in <[EMAIL PROTECTED]>: > I produce tabloid booklets of my music (fold tabloid sheet in half to > get letter-sized pages). The method I use to produce them currently > does not work; it worked in 2.7.29. I'm not certain if any ps changes > went into 2.9 but not 2.8.2. There were significant changes to font handling around 2.7.38. > 1) use lilypond-book to produce normal ps and pdf. (well, > normal-looking; I know little about under-the-hood ps stuff) > 2) run this: > psbook $1.ps | psnup -2 -ptabloid -Pletter | ps2pdf -sPAPERSIZE=11x17 - > tab-$1.pdf > > With 2.8.2, the final ps2pdf fails I expect this relates to binary font encodings and psbook/psnup. What if you pdf2ps the lilypond-produced pdf file and use that as your starting point for psbook? > spark:~/aaa/opus/op2/out gperciva$ ps2pdf -sPAPERSIZE=11x17 foo.ps > foo.pdf > Error: /rangecheck in --get-- ... > Last OS error: 2 > Current file position is 4968 > AFPL Ghostscript 8.51: Unrecoverable error, exit code 1 This means the error is around character position 4968 of the file. So you might go there (in emacs, C-u 4968 C-f) and look around... --jhawk ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Implementation of music streams
2006/5/15, Erik Sandberg <[EMAIL PROTECTED]>: On 5/14/06, Han-Wen Nienhuys <[EMAIL PROTECTED]> wrote: > 2006/5/14, Erik Sandberg <[EMAIL PROTECTED]>: > > What should be the value of the 'unique field of a CreateContext event? > > When writing, the 'unique field to be written is determined by the file writer. OK, so file writers have direct listeners to all contexts then? (I've implemented it previously using the events_below dispatcher, which is more convenient) I agree it would be nice to get rid of unique. Sorry, I think we're miscommunicating something. Can you explain what the value unique is used for? AFAICS, it's only used for reading and writing streams, and isn't per se necessary inside the context tree. -- Han-Wen Nienhuys [EMAIL PROTECTED] http://www.xs4all.nl/~hanwen ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Implementation of music streams
On 5/14/06, Han-Wen Nienhuys <[EMAIL PROTECTED]> wrote: 2006/5/14, Erik Sandberg <[EMAIL PROTECTED]>: > What should be the value of the 'unique field of a CreateContext event? When writing, the 'unique field to be written is determined by the file writer. OK, so file writers have direct listeners to all contexts then? (I've implemented it previously using the events_below dispatcher, which is more convenient) I agree it would be nice to get rid of unique. There are however some problems, mainly that the writer needs to figure out which context that the CreateContext event created. The problem can be solved in an unclean way (e.g. look up all child contexts in the context->int map and see which one that isn't already in the lookup), question is what's the Right Way to do it. Hm. One way that feels quite OK is to keep CreateContext as it is, but remove the unique field, and then let newly created contexts signal their creation with a AnnounceContext event, which only contains a reference to the context itself. The AnnounceContext event has no semantics and will not be part of the output file. Instead, only those who are interested in accessing the new context directly (i.e. the one who sent the CreateContext event initially, and the file writer) will listen to the AnnounceContext event. There will be problems if a CreateContext triggers another CreateContext event before the first one reaches the file writer; this is a clear strength of the unique system. But I'm too tired to think about that now. (chronology: 1. CreateContext event is created and dispatched. 2. event arrives to parent context, which creates new context. 3. event arrives to file writer, which must associate the event with the newly created context. other listeners may exist between 2 and 3, which may want to create new contexts; in that case the file writer may receive CreateContext and AnnounceContext events in a strange order). (sorry if I write confusing text. I'm going to sleep now) Erik ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Implementation of music streams
2006/5/14, Erik Sandberg <[EMAIL PROTECTED]>: > > There's a problem with that: Context creation is triggered by stream > > events, which tell which unique value to use for the new context. So > > the unique value needs to be there before the context has been > > created. > > I don't understand this argument. What should be the value of the 'unique field of a CreateContext event? When writing, the 'unique field to be written is determined by the file writer. When reading, the field indicating the context where any event has to go is as int. This int is mapped to a Context* by a separate lookup table. As you noticed before, nobody looks at the unique field, which suggests to me that it is superfluous. -- Han-Wen Nienhuys [EMAIL PROTECTED] http://www.xs4all.nl/~hanwen ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Bleeding edge documentation
Graham Percival <[EMAIL PROTECTED]> writes: > Chapter 11 (scheme stuff) has been extensively changed. Is any of the > material in 11.6 still accurate / relevant / useful? > http://percival-music.ca/Documentation/user/lilypond/OLD-STUFF.html 11.1.1 Overview of music functions The parser and location arguments may be explained here. pair? is the type predicate for pairs of anything, not just numbers. Maybe it could be mentionned that the list is not exhaustive. 11.1.2 Simple substitution functions tempoMark: a string argument can be written without the sharp. This looks cleaner: \tempoMark "Allegro" #3.0 Also it's usual, for instance in the case of markup commands, to have the integer argument before the other. Otherwise, if the string is very long, the number would be lost after. tempoMark = #(define-music-function (parser location padding marktext) (number? string?) ... \tempoMark #3.0 "Allegro" 11.2.1 Input variables and Scheme #(define (nopc) (ly:set-option 'point-and-click #f)) ... #(nopc) This example could be used in the Music function section, to introduce void music functions. The style is more consistent using a \nopc music function instead of a #(nopc) scheme form. noPointAndClick = #(define-music-function (parser location) () (ly:set-option 'point-and-click #f) (make-music 'SequentialMusic 'void #t)) .. \noPointAndClick %% disable point and click A music function has to return a music expression: that's why the form that is returned is the (make-music ...). With its 'void property set to #t, the parser is told to actually disregard this returned music expression. Thus, the important part of the void music function is the processing done by the function, not the music expression that is returned. 11.3.1 Displaying music expressions Perhaps, the output of the \displayMusic example could be explained a bit. The output, left verbatim first, may be reformatted to show how properties and their values are paired: (make-music 'SequentialMusic 'elements (list (make-music 'EventChord 'elements (list (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1 1) 'pitch (ly:make-pitch 0 0 0)) (make-music 'AbsoluteDynamicEvent 'text "f") - A { ... } music sequence has the name SequentialMusic, and its inner expressions are stored as a list in its 'elements property; - a note is represented as an EventChord expression, containing a NoteEvent object (storing the duration and pitch properties) and the ornementations, here an AbsoluteDynamicEvent with a "f" text property. Between that section and the following one, the functions used to access and set music properties may be introduced. someNote = c' \displayMusic \someNote % ==> (make-music % 'EventChord % 'elements % (list (make-music % 'NoteEvent % 'duration % (ly:make-duration 2 0 1 1) % 'pitch % (ly:make-pitch 0 0 0 The NoteEvent object is the first object of the 'elements property of someNote. (The `display-scheme-music' function is the function used by \displayMusic to display the scheme representation of a music expression) #(display-scheme-music (first (ly:music-property someNote 'elements))) % ==> (make-music % 'NoteEvent % 'duration % (ly:make-duration 2 0 1 1) % 'pitch % (ly:make-pitch 0 0 0)) Then, the note pitch is accessed thourgh the 'pitch property of the NoteEvent object: #(display-scheme-music (ly:music-property (first (ly:music-property someNote 'elements)) 'pitch)) % ==> (ly:make-pitch 0 0 0) The note pitch can be changed, by setting this 'pitch property: #(set! (ly:music-property (first (ly:music-property someNote 'elements)) 'pitch) (ly:make-pitch 0 1 0)) ;; set the pitch to d'. \displayLilyMusic \someNote % ==> d' 11.3.3 Adding articulation to notes (example) I don't know where you got this example from, but there are mistakes. `cons' is used to add an element to a list The wording is poor: cons does not modify the existing list. Maybe that should be precised, for instance: (without modifying the original list). 11.4.1 Markup construction in Scheme "One can not feed the #:line, #:center, or #:column) commands with a variable or the result of a function call." This sentence should more general, we're talking here about commands accepting markup-list arguments, eg. #:line, #:center-align or #:column (but there are others, like #:fill-line). nicolas ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: lilypond ./ChangeLog Documentation/user/advance...
On 14-May-06, at 7:07 AM, Mats Bengtsson wrote: Sorry to be picky: Not at all; thanks a lot! Fixed in CVS. - Graham ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
New attempt on tuplets/percent repeats
Hi, Here's a patch that massively refactors tuplets and percent repeats. Highlights: - tuplets are now signalled by start/stop events. - each percent/slash is signalled by an individual event, whose repeat-count property tells whether it should be numbered (this moves some decisions from engraver to iterator) The diffs of some files are huge, so I'm sending the new files instead. I think it's a bit out of place to merge percent_repeat and double_percent_repeat into one engraver. Some next steps that would be nice are: - move handling of double percent repeats to slash_engraver (or possibly to a new double_percent_engraver, but imho they are similar enough to share engraver) - handle percent_repeat with start/stop event - create different event types for percent event, slash event and double percent event. These are however not very related to music streams. Erik /* new-chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver source file of the GNU LilyPond music typesetter (c) 2000--2006 Han-Wen Nienhuys <[EMAIL PROTECTED]>, Erik Sandberg <[EMAIL PROTECTED]> */ #include "score-engraver.hh" #include "bar-line.hh" #include "global-context.hh" #include "international.hh" #include "item.hh" #include "misc.hh" #include "percent-repeat-iterator.hh" #include "repeated-music.hh" #include "score-context.hh" #include "side-position-interface.hh" #include "spanner.hh" #include "warn.hh" #include "translator.icc" /* * TODO: Create separate Double_percent_repeat_engraver? * Or, at least move double percent handling to Slash_repeat_engraver */ class Percent_repeat_engraver : public Engraver { void typeset_perc (); public: TRANSLATOR_DECLARATIONS (Percent_repeat_engraver); protected: Music *percent_event_; /// moment (global time) where percent started. Moment stop_mom_; Moment start_mom_; enum Repeat_sign_type { UNKNOWN, MEASURE, DOUBLE_MEASURE, }; Repeat_sign_type repeat_sign_type_; Spanner *percent_; Spanner *percent_counter_; protected: virtual void finalize (); virtual bool try_music (Music *); void stop_translation_timestep (); void start_translation_timestep (); void process_music (); }; Percent_repeat_engraver::Percent_repeat_engraver () { percent_ = 0; percent_counter_ = 0; percent_event_ = 0; } bool Percent_repeat_engraver::try_music (Music *m) { if (m->is_mus_type ("percent-event") && !percent_event_) { Moment body_length = m->get_length (); Moment meas_len (robust_scm2moment (get_property ("measureLength"), Moment (1))); if (meas_len == body_length) { repeat_sign_type_ = MEASURE; start_mom_ = now_mom (); stop_mom_ = now_mom () + body_length; get_global_context ()->add_moment_to_process (stop_mom_); } else if (Moment (2) * meas_len == body_length) { repeat_sign_type_ = DOUBLE_MEASURE; start_mom_ = now_mom () + meas_len; stop_mom_ = now_mom () + body_length; /* never used */ get_global_context ()->add_moment_to_process (start_mom_); } else return false; percent_event_ = m; return true; } return false; } void Percent_repeat_engraver::process_music () { if (percent_event_ && now_mom ().main_part_ == start_mom_.main_part_) { if (repeat_sign_type_ == MEASURE) { if (percent_) typeset_perc (); percent_ = make_spanner ("PercentRepeat", percent_event_->self_scm ()); Grob *col = unsmob_grob (get_property ("currentCommandColumn")); percent_->set_bound (LEFT, col); SCM count = percent_event_->get_property ("repeat-count"); if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))) { percent_counter_ = make_spanner ("PercentRepeatCounter", percent_event_->self_scm ()); SCM text = scm_number_to_string (count, scm_from_int (10)); percent_counter_->set_property ("text", text); percent_counter_->set_bound (LEFT, col); Side_position_interface::add_support (percent_counter_, percent_); percent_counter_->set_parent (percent_, Y_AXIS); } else percent_counter_ = 0; } else if (repeat_sign_type_ == DOUBLE_MEASURE) { Item *double_percent = make_item ("DoublePercentRepeat", percent_event_->self_scm ()); SCM count = percent_event_->get_property ("repeat-count"); if (count != SCM_EOL && to_boolean (get_property ("countPercentRepeats"))) { Item *double_percent_counter = make_item ("DoublePercentRepeatCounter", percent_event_->self_scm()); SCM text = scm_number_to_string
Re: Implementation of music streams
On 5/14/06, Han-Wen Nienhuys <[EMAIL PROTECTED]> wrote: Erik Sandberg schreef: >> > This step is now finished, patch attached. You can notice some >> > additional stuff that has been added as well, which currently is >> > unused but will be used in future patches. You will notice that this >> > patch makes lily spit out lots of Junking Event messages, which are >> > harmless. > > so I may apply the patch then? I would like to look over it one more time. OK, tell me when you're done (nothing has changed since the patch I sent in the root of this thread). > There's a problem with that: Context creation is triggered by stream > events, which tell which unique value to use for the new context. So > the unique value needs to be there before the context has been > created. I don't understand this argument. What should be the value of the 'unique field of a CreateContext event? For reading the stream, you need a map mapping, of course. why? unique ints are unique enough for me. Erik ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: lilypond ./ChangeLog Documentation/user/advance...
Graham Percival wrote: Index: lilypond/Documentation/user/tweaks.itely diff -u lilypond/Documentation/user/tweaks.itely:1.9 lilypond/Documentation/user/tweaks.itely:1.10 --- lilypond/Documentation/user/tweaks.itely:1.9Wed May 10 04:37:14 2006 +++ lilypond/Documentation/user/tweaks.itelySun May 14 01:53:54 2006 ... + +We cannot list every object, but here is a list of the most +common objects. + [EMAIL PROTECTED] @columnfractions .33 .66 [EMAIL PROTECTED] Object type @tab Object name [EMAIL PROTECTED] Text @tab @code{TextScript} [EMAIL PROTECTED] Dynamics @tab @code{DynamicLineSpanner} [EMAIL PROTECTED] Ties @tab @code{Tie} [EMAIL PROTECTED] Slurs@tab @code{Slur} [EMAIL PROTECTED] Articulation @tab @code{Script} [EMAIL PROTECTED] Fingering@tab @code{Fingering} [EMAIL PROTECTED] Rehearsal marks @tab @code{RehearsalMark} [EMAIL PROTECTED] multitable Sorry to be picky: - It seems like a mix of singular/plural. Why not also "Articulations" and "Fingerings" to be more consequent? - "Text" is a very generic term. One way to clarify what we mean could be to say Text e.g. c^"text" to avoid confusion with text marks, lyrics, titling or whatever other texts that can appear in a score. - If it fits into the table, why not say "Rehearsal/Text marks"? /Mats ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Getting the height of a system.
Han-Wen Nienhuys schreef: 3) for each possible system, using the original grobs, - work out the Y-extent - restore () every grob in that system The advantage is that we avoid fiddling around with the object_alist_ because this clone is never used -- it exists only to save the state of the score before we mess it up with calling Y-extent. We also only have to make one copy of the system and restore it N times instead of making N copies. I don't think that this will really help. Inside the grobs, the object_alist_ will contain grob_arrays, which are considered 'private data' to each grob, and hence need to be copied completely before each new System formatting step. This is expensive, as the length of the grob_arrays is proportional to the entire score. -- Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen LilyPond Software Design -- Code for Music Notation http://www.lilypond-design.com ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Getting the height of a system.
Joe Neeman schreef: We discussed this a bit a long time ago but I'm getting close to actually implementing something so I thought I'd bring it up again. Getting the Y-extent of a system is potentially destructive, causing all sorts of non-undoable caching and possibly suiciding of grobs. So I need to do make a copy of the system before I can get its Y-extent. The problem is that there are a large number of possible lines in a score. To copy a system, I need to do a full grob substitution for every grob in that system. If each bar could be in up to N possible lines, I need to do N full copies of the entire score and N full grob substitutions in the object_alist_. If we can fit up to K bars to a line then N is approximately K(K-1)/2. In the scores I typically work with, N would be around 50-60 so this is getting pretty expensive. It's much worse than that, because the cost of the substitution is actually proportional to the number grobs in the "long" System, i.e. the length of the entire score. It would be much much better if you could make your algorithm compute the system heights of a complete line breaking configuration. Also, it's not completely possible to compute the height of an isolated system: some grobs (notably spanners like slur) look at the next system to decide how to format across line breaks. So I propose the following instead. I don't know a great deal (yet) about the C++ internals of grobs so I'd appreciate knowing if this is unworkable before I spend lots of time trying to implement it. 1) add a virtual Grob *save () and virtual void restore (Grob*) function to every C++ Grob subclass. save() would be a bit like clone except that it copies the object_alist_ and, for example, broken_intos_ in the case of a Spanner. Grob *copy = me->save (); // make some changes to me me->restore (copy); and you end up with the same grob you started with. 2) save every grob in the score 3) for each possible system, using the original grobs, - work out the Y-extent - restore () every grob in that system The advantage is that we avoid fiddling around with the object_alist_ because this clone is never used -- it exists only to save the state of the score before we mess it up with calling Y-extent. We also only have to make one copy of the system and restore it N times instead of making N copies. Sounds like a possiblity, but have you also considered break alignments? It's not only the object_alist_ (and property_alist_, as that too will change), but also other pointers like original_. Secondly, although it will be nicely portable, it also sounds like a lot of work. Isn't it a lot easier to simply do a fork() and let the OS clean up after us? Perhaps if the vertical spacing is completely working, we can consider doing the full-blown copy and restore. Also, for large scores, fork() is an interesting option, as we could get some benefit from using SMP. -- Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen LilyPond Software Design -- Code for Music Notation http://www.lilypond-design.com ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: system-count bugfix
Joe Neeman schreef: On Sun, 14 May 2006 02:07, Han-Wen Nienhuys wrote: Joe Neeman schreef: { Output_def *l = pscore_->layout (); - Real extent = scm_to_double (l->c_variable ("system-height")); + Real extent = robust_scm2double (l->c_variable ("system-height"), 12.0); Real padding = scm_to_double (l->c_variable ("between-system-padding")); Real space = scm_to_double (l->c_variable ("between-system-space")); bool ragged_right = to_boolean (pscore_->layout ()->c_variable ("ragged-right")); Is ok, but wouldn't it be fitting to print a warning somewher about the need to define system-height if using constrained page breaking? I thought it would be better just to provide a sane default and only involve the user when it needs to be changed. But maybe ly/paper-defaults.ly would be a better place for this? yes, but the robust_() call is better in any case. -- Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen LilyPond Software Design -- Code for Music Notation http://www.lilypond-design.com ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Implementation of music streams
Erik Sandberg schreef: > This step is now finished, patch attached. You can notice some > additional stuff that has been added as well, which currently is > unused but will be used in future patches. You will notice that this > patch makes lily spit out lots of Junking Event messages, which are > harmless. so I may apply the patch then? I would like to look over it one more time. There's a problem with that: Context creation is triggered by stream events, which tell which unique value to use for the new context. So the unique value needs to be there before the context has been created. I don't understand this argument. For reading the stream, you need a map mapping, of course. -- Han-Wen Nienhuys - [EMAIL PROTECTED] - http://www.xs4all.nl/~hanwen LilyPond Software Design -- Code for Music Notation http://www.lilypond-design.com ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel
Re: Implementation of music streams
"Erik Sandberg" <[EMAIL PROTECTED]> writes: > OK, unique in the sense of eq? seems sensible. you mean in the sense of eqv?. http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%25_idx_216 (eq? 2 2) ===> unspecified (eq? #\A #\A) ===> unspecified (let ((n (+ 2 3))) (eq? n n)) ===> unspecified ___ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel