2 line-spanner.cc -- implement Line_spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2001 Jan Nieuwenhuizen <janneke@gnu.org>
12 #include "line-spanner.hh"
13 #include "paper-def.hh"
14 #include "paper-column.hh"
15 #include "staff-symbol-referencer.hh"
16 #include "font-interface.hh"
21 Line_spanner::line_atom (Grob
* me
, Real dx
, Real dy
)
23 SCM type
= me
->get_grob_property ("type");
24 Real staff_space
= Staff_symbol_referencer::staff_space (me
);
25 Real thick
= me
->paper_l ()->get_var ("stafflinethickness");
27 SCM s
= me
->get_grob_property ("line-thickness");
29 thick
*= gh_scm2double (s
);
31 // maybe these should be in line-thickness?
32 Real length
= staff_space
;
33 s
= me
->get_grob_property ("dash-length");
35 length
= gh_scm2double (s
) * staff_space
;
37 Real period
= 2 * length
+ thick
;
38 s
= me
->get_grob_property ("dash-period");
40 period
= gh_scm2double (s
) * staff_space
;
42 if (type
== ly_symbol2scm ("dotted-line"))
45 if (type
== ly_symbol2scm ("line"))
46 length
= period
+ thick
;
48 Real on
= length
- thick
;
49 Real off
= period
- on
;
51 SCM list
= gh_list (ly_symbol2scm ("dashed-line"),
52 gh_double2scm (thick
),
63 Line_spanner::line_molecule (Grob
* me
, Real dx
, Real dy
)
66 SCM type
= me
->get_grob_property ("type");
67 if (gh_symbol_p (type
)
68 && (type
== ly_symbol2scm ("line")
69 || type
== ly_symbol2scm ("dashed-line")
70 || type
== ly_symbol2scm ("dotted-line")
71 || (type
== ly_symbol2scm ("trill") && dy
!= 0)))
73 Box
b (Interval (0, dx
), Interval (0, dy
));
74 mol
= Molecule (b
, line_atom (me
, dx
, dy
));
76 else if (gh_symbol_p (type
)
77 && type
== ly_symbol2scm ("trill"))
79 SCM alist_chain
= Font_interface::font_alist_chain (me
);
80 SCM style_chain
= gh_list (gh_cons (ly_symbol2scm ("font-family"),
81 ly_symbol2scm ("music")),
84 Font_metric
*fm
= Font_interface::get_font (me
,
88 Molecule m
= fm
->find_by_name ("scripts-trill-element");
90 mol
.add_at_edge (X_AXIS
, RIGHT
, m
, 0);
91 while (m
.extent (X_AXIS
).length ()
92 && mol
.extent (X_AXIS
).length ()
93 + m
.extent (X_AXIS
).length () < dx
);
96 FIXME: should center element on x/y
98 mol
.translate_axis (m
.extent (X_AXIS
).length () / 2, X_AXIS
);
99 mol
.translate_axis (-(mol
.extent (Y_AXIS
)[DOWN
]
100 + mol
.extent (Y_AXIS
).length ())/2, Y_AXIS
);
106 Line_spanner::get_broken_offset (Grob
*me
, Direction dir
)
108 Spanner
*spanner
= dynamic_cast<Spanner
*> (me
);
109 Item
* bound
= spanner
->get_bound (dir
);
111 if (!bound
->break_status_dir ())
114 bound
->common_refpoint (Staff_symbol_referencer::staff_symbol_l (me
),
116 bound
->common_refpoint (Staff_symbol_referencer::staff_symbol_l (me
),
120 return Offset (abs (bound
->extent (common
[X_AXIS
], X_AXIS
)[-dir
]),
121 bound
->extent (common
[Y_AXIS
], Y_AXIS
).center ());
127 Line_spanner::broken_trend_offset (Grob
*me
, Direction dir
)
129 /* A broken line-spaner should maintain the same vertical trend
130 the unbroken line-spanner would have had.
133 if (Spanner
*mother
= dynamic_cast<Spanner
*> (me
->original_l_
))
135 for (int i
= dir
== LEFT
? 0 : mother
->broken_into_l_arr_
.size () - 1;
136 dir
== LEFT
? i
< mother
->broken_into_l_arr_
.size () : i
> 0;
137 dir
== LEFT
? i
++ : i
--)
139 if (mother
->broken_into_l_arr_
[i
- dir
] == me
)
141 Grob
*neighbour
= mother
->broken_into_l_arr_
[i
];
142 Offset neighbour_o
= get_broken_offset (neighbour
, dir
);
143 Offset me_o
= get_broken_offset (me
, -dir
);
144 // Hmm, why not return me_o[X], but recalc in brew_mol?
146 (neighbour_o
[Y_AXIS
]*me_o
[X_AXIS
]
147 - me_o
[Y_AXIS
]*neighbour_o
[X_AXIS
]) * dir
/
148 (me_o
[X_AXIS
] + neighbour_o
[X_AXIS
]));
158 Warning: this thing is a cross-staff object, so it should have empty Y-dimensions.
160 (If not, you risk that this is called from the staff-alignment
161 routine, via molecule_extent. At this point, the staves aren't
162 separated yet, so it doesn't work cross-staff.
166 MAKE_SCHEME_CALLBACK (Line_spanner
, brew_molecule
, 1);
168 Line_spanner::brew_molecule (SCM smob
)
170 Grob
*me
= unsmob_grob (smob
);
172 Spanner
*spanner
= dynamic_cast<Spanner
*> (me
);
173 Item
* bound_drul
[] = {
174 spanner
->get_bound (LEFT
),
176 spanner
->get_bound (RIGHT
)
179 Item
** bound
= bound_drul
+ 1;
181 Grob
*common
[] = { 0, 0 };
182 for (Axis a
= X_AXIS
; a
< NO_AXES
; a
= Axis (a
+ 1))
184 common
[a
] = bound
[LEFT
]->common_refpoint (bound
[RIGHT
], a
);
190 Real gap
= gh_scm2double (me
->get_grob_property ("gap"));
191 Real dist
; /*distance between points */
193 Offset
ofxy (gap
, 0); /*offset from start point to start of line*/
199 if (bound
[LEFT
]->break_status_dir () || bound
[RIGHT
]->break_status_dir ())
200 /* across line break */
202 Direction broken
= bound
[LEFT
]->break_status_dir () ? LEFT
: RIGHT
;
204 dxy
[X_AXIS
] = bound
[RIGHT
]->extent (common
[X_AXIS
], X_AXIS
)[LEFT
]
205 - bound
[LEFT
]->extent (common
[X_AXIS
], X_AXIS
)[RIGHT
];
207 dxy
+= broken_trend_offset (me
, broken
);
208 dxy
[X_AXIS
] -= 1 * gap
;
211 me
->relative_coordinate (common
[Y_AXIS
], Y_AXIS
));
214 bound
[-broken
]->relative_coordinate (common
[Y_AXIS
],
219 my_off
[Y_AXIS
] += dxy
[Y_AXIS
];
224 Real off
= gap
+ ((bound
[LEFT
]->extent (bound
[LEFT
], X_AXIS
).length ()*3)/4); // distance from center to start of line
225 dxy
[X_AXIS
] = bound
[RIGHT
]->extent (common
[X_AXIS
], X_AXIS
).center ()
226 - bound
[LEFT
]->extent (common
[X_AXIS
], X_AXIS
).center ();
227 dxy
[Y_AXIS
] = bound
[RIGHT
]->extent (common
[Y_AXIS
], Y_AXIS
).center ()
228 - bound
[LEFT
]->extent (common
[Y_AXIS
], Y_AXIS
).center ();
230 dist
= sqrt (dxy
[X_AXIS
]*dxy
[X_AXIS
]+dxy
[Y_AXIS
]*dxy
[Y_AXIS
]);
231 ofxy
= dxy
* (off
/dist
);
234 my_off
= Offset (me
->relative_coordinate (common
[X_AXIS
], X_AXIS
),
235 me
->relative_coordinate (common
[Y_AXIS
], Y_AXIS
));
237 his_off
= Offset (bound
[LEFT
]->relative_coordinate (common
[X_AXIS
],
239 bound
[LEFT
]->relative_coordinate (common
[Y_AXIS
],
244 Molecule line
= line_molecule (me
, dxy
[X_AXIS
], dxy
[Y_AXIS
]);
245 line
.translate_axis (bound
[LEFT
]->extent (bound
[LEFT
],
246 X_AXIS
).length ()/2, X_AXIS
);
247 line
.translate (ofxy
- my_off
+ his_off
);
248 return line
.smobbed_copy ();