]> git.donarmstrong.com Git - lilypond.git/blob - lily/stem-info.cc
release: 1.1.67
[lilypond.git] / lily / stem-info.cc
1 /*
2   stem-info.cc -- implement Stem_info
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Jan Nieuwenhuizen <janneke@gnu.org>
7
8 */
9
10 #include "proto.hh"
11 #include "misc.hh"
12 #include "debug.hh"
13 #include "dimension-cache.hh"
14
15 #include "align-element.hh"
16 #include "stem.hh"
17 #include "paper-def.hh"
18 #include "lookup.hh"
19 #include "stem-info.hh"
20 #include "beam.hh"
21 #include "staff-symbol.hh"
22
23 Stem_info::Stem_info ()
24 {
25 }
26 /*
27   FIXME: y dims should not be in internote.
28  */
29
30 Stem_info::Stem_info (Stem*s, int mult)
31 {
32   mult_i_ =mult;
33   stem_l_ = s;
34   x_ = stem_l_->hpos_f ();
35   dir_ = stem_l_->dir_;
36   SCM bd = stem_l_->remove_elt_property (beam_dir_scm_sym);
37   
38   beam_dir_ = gh_scm2int (SCM_CDR(bd));
39   interstaff_f_ = 0;
40
41   Paper_def* paper_l = stem_l_->paper_l ();
42   Real internote_f = stem_l_->staff_line_leading_f ()/2;
43   Real interbeam_f = paper_l->interbeam_f (mult_i_);
44   Real beam_f = paper_l->beam_thickness_f ();
45          
46   {
47       static int i = 1;
48       DOUT << "******" << i++ << "******\n" 
49            << "begin_f: " << stem_l_->stem_begin_f () * dir_ 
50            << "\nchord_f/i: " << stem_l_->chord_start_f () * dir_ / internote_f << '\n';
51   }
52
53   // strangely enough, dim(chord_start_f) == pt (and not internote!)
54   idealy_f_ = stem_l_->chord_start_f () / internote_f;
55
56   // calculate using dim(y) == pt
57   idealy_f_ *= internote_f;
58
59   // for simplicity, we calculate as if dir == UP
60   idealy_f_ *= beam_dir_;
61
62   bool grace_b = stem_l_->get_elt_property (grace_scm_sym) != SCM_BOOL_F;
63
64   int stem_max = (int)rint(paper_l->get_var ("stem_max"));
65   String type_str = grace_b ? "grace_" : "";
66   Real min_stem_f = paper_l->get_var (type_str + "minimum_stem_length"
67                                       + to_str (mult_i_ <? stem_max)) * internote_f;
68   Real stem_f = paper_l->get_var (type_str + "stem_length"
69                                   + to_str (mult_i_ <? stem_max))* internote_f;
70
71   if (!beam_dir_ || (beam_dir_ == dir_))
72     /* normal beamed stem */
73     {
74       if (mult_i_)
75         {
76           idealy_f_ += beam_f;
77           idealy_f_ += (mult_i_ - 1) * interbeam_f;
78         }
79       miny_f_ = idealy_f_;
80       maxy_f_ = INT_MAX;
81
82       idealy_f_ += stem_f;
83       miny_f_ += min_stem_f;
84
85       /*
86         lowest beam of (UP) beam must never be lower than second staffline
87
88         Hmm, reference (Wanske?)
89
90         Although this (additional) rule is probably correct,
91         I expect that highest beam (UP) should also never be lower
92         than middle staffline, just as normal stems.
93         
94       */
95       if (!grace_b)
96         {
97           //highest beam of (UP) beam must never be lower than middle staffline
98           miny_f_ = miny_f_ >? 0;
99           //lowest beam of (UP) beam must never be lower than second staffline
100           miny_f_ = miny_f_ >? (- 2 * internote_f - beam_f
101                                 + (mult_i_ > 0) * beam_f + interbeam_f * (mult_i_ - 1));
102         }
103     }
104   else
105     /* knee */
106     {
107       idealy_f_ -= beam_f;
108       // idealy_f_ -= (mult_i_ - 1) * interbeam_f;
109       // idealy_f_ += (mult_i_ - stem_l_->flag_i_ >? 0) * interbeam_f;
110       maxy_f_ = idealy_f_;
111       miny_f_ = -INT_MAX;
112
113       idealy_f_ -= stem_f;
114       maxy_f_ -= min_stem_f;
115     }
116
117   // set dim(y) == internote
118   idealy_f_ /= internote_f;
119   miny_f_ /= internote_f;
120   maxy_f_ /= internote_f;
121
122   DOUT << "dir_: " << dir_ << '\n';
123   DOUT << "mult_i_: " << mult_i_ << '\n';
124   DOUT << "idealy_f_: " << idealy_f_ << '\n';
125   DOUT << "miny_f_: " << miny_f_ << '\n';
126   DOUT << "maxy_f_: " << maxy_f_ << '\n';
127
128   idealy_f_ = maxy_f_ <? idealy_f_;
129   idealy_f_ = miny_f_ >? idealy_f_;
130
131   // interstaff beam
132   Beam* beam_l = stem_l_->beam_l_;
133   
134   Dimension_cache *common = stem_l_->common_group (beam_l, Y_AXIS);
135   Align_element * align = dynamic_cast<Align_element*> (common->element_l ());
136   if (align && align->axis() == Y_AXIS)
137     {
138       if (align->threshold_interval_[MIN] != 
139           align->threshold_interval_[MAX])
140         warning (_ ("minVerticalAlign != maxVerticalAlign: interstaff beams/slurs may be broken"));
141
142       interstaff_f_ = align->threshold_interval_[MIN] / internote_f;
143
144       Dimension_cache * beam_refpoint = beam_l->dim_cache_[Y_AXIS];
145       Dimension_cache * stem_refpoint = stem_l_->dim_cache_[Y_AXIS];
146
147       while (beam_refpoint->parent_l_ != common)
148         beam_refpoint = beam_refpoint->parent_l_;
149       while (stem_refpoint->parent_l_ != common)
150         stem_refpoint = stem_refpoint->parent_l_;
151
152
153       int beam_prio =
154         align->get_priority (dynamic_cast<Score_element*> (beam_refpoint->element_l ()));
155       int stem_prio =
156         align->get_priority (dynamic_cast<Score_element*> (stem_refpoint->element_l ()));
157
158       /*
159         our staff is lower -> interstaff_f_ *= -1
160        */
161       if (beam_prio < stem_prio)
162         interstaff_f_ *= -1;
163       
164       idealy_f_ += interstaff_f_ * beam_dir_;
165       miny_f_ += interstaff_f_ * beam_dir_;
166       maxy_f_ += interstaff_f_ * beam_dir_;
167     }
168 }
169