From a1b73185eae2f07dfee3cfcac0a6f11a15075ffe Mon Sep 17 00:00:00 2001 From: Marc Hohl Date: Wed, 20 Jun 2012 09:14:29 +0200 Subject: [PATCH] Issue 1320: Scheme bar line interface (part 1/2: recoding) --- lily/auto-beam-engraver.cc | 1 - lily/bar-engraver.cc | 1 - lily/bar-line.cc | 456 +--------------------- lily/clef-engraver.cc | 1 - lily/cue-clef-engraver.cc | 1 - lily/custos-engraver.cc | 1 - lily/grob-scheme.cc | 13 + lily/hairpin.cc | 4 +- lily/include/bar-line.hh | 11 - lily/include/span-bar.hh | 47 --- lily/key-engraver.cc | 1 - lily/mark-engraver.cc | 1 - lily/span-bar-engraver.cc | 9 +- lily/span-bar-stub-engraver.cc | 2 - lily/span-bar.cc | 251 ------------ lily/staff-spacing.cc | 4 +- lily/vertical-align-engraver.cc | 1 - lily/volta-engraver.cc | 1 - scm/bar-line.scm | 650 ++++++++++++++++++++++++++++++++ scm/define-grob-interfaces.scm | 52 +++ scm/lily-library.scm | 4 + scm/lily.scm | 1 + scm/output-lib.scm | 62 +-- 23 files changed, 731 insertions(+), 844 deletions(-) delete mode 100644 lily/include/span-bar.hh delete mode 100644 lily/span-bar.cc create mode 100644 scm/bar-line.scm diff --git a/lily/auto-beam-engraver.cc b/lily/auto-beam-engraver.cc index 87ab20e524..fe9c94ae54 100644 --- a/lily/auto-beam-engraver.cc +++ b/lily/auto-beam-engraver.cc @@ -17,7 +17,6 @@ along with LilyPond. If not, see . */ -#include "bar-line.hh" #include "beaming-pattern.hh" #include "beam.hh" #include "context.hh" diff --git a/lily/bar-engraver.cc b/lily/bar-engraver.cc index 63f5e83384..b2594a2cb8 100644 --- a/lily/bar-engraver.cc +++ b/lily/bar-engraver.cc @@ -18,7 +18,6 @@ along with LilyPond. If not, see . */ -#include "bar-line.hh" #include "context.hh" #include "score-engraver.hh" #include "warn.hh" diff --git a/lily/bar-line.cc b/lily/bar-line.cc index 0cd0339235..fe4406956c 100644 --- a/lily/bar-line.cc +++ b/lily/bar-line.cc @@ -18,463 +18,11 @@ */ #include "bar-line.hh" - -#include "all-font-metrics.hh" -#include "font-interface.hh" -#include "line-interface.hh" -#include "lookup.hh" -#include "output-def.hh" #include "paper-column.hh" -#include "staff-symbol-referencer.hh" - -MAKE_SCHEME_CALLBACK (Bar_line, calc_bar_extent, 1) -SCM -Bar_line::calc_bar_extent (SCM smob) -{ - Interval result; - Grob *me = unsmob_grob (smob); - if (Grob *staff = Staff_symbol_referencer::get_staff_symbol (me)) - { - result = staff->extent (staff, Y_AXIS); - - /* Due to rounding problems, bar lines extending to the outermost edges - of the staff lines appear wrongly in on-screen display - (and, to a lesser extent, in print) - they stick out a pixel. - The solution is to extend bar lines only to the middle - of the staff line - unless they have different colors, - when it would be undesirable. - */ - SCM bar_line_color = me->get_property ("color"); - SCM staff_color = staff->get_property ("color"); - Real radius = Staff_symbol_referencer::staff_radius (me); - if (bar_line_color == staff_color && radius) - result *= (1 - 0.5 * (Staff_symbol_referencer::line_thickness (me) / radius)); - } - return ly_interval2scm (result); -} - -Interval -Bar_line::bar_y_extent (Grob *me, Grob *refpoint) -{ - Interval iv = robust_scm2interval (me->get_property ("bar-extent"), Interval ()); - - iv.translate (me->relative_coordinate (refpoint, Y_AXIS)); - return iv; -} bool Bar_line::non_empty_barline (Grob *me) { - return has_interface (me) && !me->extent (me, X_AXIS).is_empty (); -} - -MAKE_SCHEME_CALLBACK (Bar_line, print, 1); -SCM -Bar_line::print (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - SCM s = me->get_property ("glyph-name"); - SCM extent = me->get_property ("bar-extent"); - - if (scm_is_string (s) && is_number_pair (extent)) - { - string str = ly_scm2string (s); - Interval ex = ly_scm2interval (extent); - if (ex.length () > 0) - { - Stencil result = compound_barline (me, str, ex, false); - - return result.smobbed_copy (); - } - } - return SCM_EOL; + return me->internal_has_interface (ly_symbol2scm ("bar-line-interface")) + && !me->extent (me, X_AXIS).is_empty (); } - -Stencil -Bar_line::compound_barline (Grob *me, string str, Interval const &extent, - bool rounded) -{ - Real kern = robust_scm2double (me->get_property ("kern"), 1); - Real thinkern = robust_scm2double (me->get_property ("thin-kern"), 1); - Real hair = robust_scm2double (me->get_property ("hair-thickness"), 1); - Real fatline = robust_scm2double (me->get_property ("thick-thickness"), 1); - - Real staffline = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); - Real staff_space = Staff_symbol_referencer::staff_space (me); - - kern *= staffline; - thinkern *= staffline; - hair *= staffline; - fatline *= staffline; - - Stencil thin = simple_barline (me, hair, extent, rounded); - Stencil thick = simple_barline (me, fatline, extent, rounded); - Stencil dot = Font_interface::get_default_font (me)->find_by_name ("dots.dot"); - - int lines = Staff_symbol_referencer::line_count (me); - Real dist - = ((lines & 1 || lines == 0) - ? 1 - : (staff_space < 2 ? 2 : .5)) * staff_space; - Stencil colon (dot); - colon.translate_axis (dist, Y_AXIS); - colon.add_stencil (dot); - colon.translate_axis (-dist / 2, Y_AXIS); - - Real const h = extent.length (); - Stencil m; - - if (str == "||:") - str = "|:"; - - if (str == "|S" || str == "S|") - str = "S"; - - if (str == "") - { - Stencil empty = Lookup::blank (Box (Interval (0, 0), extent)); - return empty; - } - else if (str == "|") - return thin; - else if (str == ".") - return thick; - else if (str == "|." || (h == 0 && str == ":|")) - { - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - } - else if (str == ".|" || (h == 0 && str == "|:")) - { - m.add_at_edge (X_AXIS, RIGHT, thick, 0); - m.add_at_edge (X_AXIS, RIGHT, thin, kern); - } - else if (str == ":|") - { - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - m.add_at_edge (X_AXIS, LEFT, colon, kern); - } - else if (str == "|:") - { - m.add_at_edge (X_AXIS, RIGHT, thick, 0); - m.add_at_edge (X_AXIS, RIGHT, thin, kern); - m.add_at_edge (X_AXIS, RIGHT, colon, kern); - } - else if (str == ":|:") - { - m.add_at_edge (X_AXIS, LEFT, thick, thinkern); - m.add_at_edge (X_AXIS, LEFT, colon, kern); - m.add_at_edge (X_AXIS, RIGHT, thick, kern); - m.add_at_edge (X_AXIS, RIGHT, colon, kern); - } - else if (str == ":|.|:") - { - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - m.add_at_edge (X_AXIS, LEFT, colon, kern); - m.add_at_edge (X_AXIS, RIGHT, thin, kern); - m.add_at_edge (X_AXIS, RIGHT, colon, kern); - } - else if (str == ":|.:") - { - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - m.add_at_edge (X_AXIS, LEFT, colon, kern); - m.add_at_edge (X_AXIS, RIGHT, colon, kern); - } - else if (str == ".|.") - { - m.add_at_edge (X_AXIS, LEFT, thick, thinkern); - m.add_at_edge (X_AXIS, RIGHT, thick, kern); - } - else if (str == "|.|") - { - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - m.add_at_edge (X_AXIS, RIGHT, thin, kern); - } - else if (str == "||") - { - /* - should align to other side? this never appears - on the system-start? - m.add_at_edge (X_AXIS, RIGHT, thin, 0); - m.add_at_edge (X_AXIS, RIGHT, thin, thinkern); - */ - m.add_at_edge (X_AXIS, LEFT, thin, thinkern); - m.add_at_edge (X_AXIS, RIGHT, thin, thinkern); - } - else if (str.find ("S") != NPOS || str == "|._.|") - { - // Handle all varsegno stuff - Stencil segno; - segno.add_at_edge (X_AXIS, LEFT, thin, thinkern); - segno.add_at_edge (X_AXIS, RIGHT, thin, thinkern); - segno.add_stencil (Font_interface::get_default_font (me)->find_by_name ("scripts.varsegno")); - - if (str == "S") - m.add_stencil (segno); - else if (str == "S|:" || str == ".S|:") - { - m.add_at_edge (X_AXIS, RIGHT, thick, 0); - m.add_at_edge (X_AXIS, RIGHT, thin, kern); - m.add_at_edge (X_AXIS, RIGHT, colon, kern); - m.add_at_edge (X_AXIS, LEFT, segno, thinkern); - } - else if (str == ":|S" || str == ":|S.") - { - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - m.add_at_edge (X_AXIS, LEFT, colon, kern); - m.add_at_edge (X_AXIS, RIGHT, segno, thinkern); - } - else if (str == ":|S|:" || str == ":|S.|:") - { - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - m.add_at_edge (X_AXIS, LEFT, colon, kern); - m.add_at_edge (X_AXIS, RIGHT, segno, thinkern); - m.add_at_edge (X_AXIS, RIGHT, thick, thinkern); - m.add_at_edge (X_AXIS, RIGHT, thin, kern); - m.add_at_edge (X_AXIS, RIGHT, colon, kern); - } - else if (str == "|._.|") // :|S|: or :|S.|: without segno and colon - { - // get the width of the segno sign - Real segno_width = segno.extent (X_AXIS).length (); - m.add_at_edge (X_AXIS, LEFT, thick, 0); - m.add_at_edge (X_AXIS, LEFT, thin, kern); - m.add_at_edge (X_AXIS, RIGHT, thick, segno_width + 2 * thinkern); - m.add_at_edge (X_AXIS, RIGHT, thin, kern); - } - // end varsegno block - } - else if (str == ":") - { - if (Grob *staff = Staff_symbol_referencer::get_staff_symbol (me)) - { - Interval staff_extent = staff->extent (staff, Y_AXIS); - - /* - assume staff lines are disposed equally at unit space; - put a dot into each space within extent (may extend staff_extent). - - staff_extent is an interval of two integers or two half-integers; - in the former case dots are to be placed at half-integers, - in the latter at integers. - - these integers are not exact due to staff line thickness. - */ - int const pos = int (rint (staff_extent.at (UP) * 2)); - Real const correction = pos & 1 ? 0.0 : 0.5; - - for (int i = int (rint (extent.at (DOWN) + (0.5 - correction))), - e = int (rint (extent.at (UP) + (0.5 - correction))); - i < e; - ++i) - { - Stencil d (dot); - - d.translate_axis (i + correction, Y_AXIS); - m.add_stencil (d); - } - } - } - else if (str == "dashed") - m = dashed_bar_line (me, extent, hair); - else if (str == "'") - m = tick_bar_line (me, extent.at (UP), rounded); - else if (str == "kievan") - { - me->set_property ("layer", scm_from_int (1)); - m.add_stencil (Font_interface::get_default_font (me)->find_by_name ("scripts.barline.kievan")); - m = *unsmob_stencil (scm_call_1 (ly_lily_module_constant ("stencil-whiteout"), m.smobbed_copy ())); - } - return m; -} - -Stencil -Bar_line::simple_barline (Grob *me, - Real w, - Interval const &extent, - bool rounded) -{ - Real blot - = rounded - ? me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")) - : 0.0; - - return Lookup::round_filled_box (Box (Interval (0, w), extent), blot); -} - -Stencil -Bar_line::tick_bar_line (Grob *me, Real h, bool rounded) -{ - Real th = Staff_symbol_referencer::staff_space (me) / 2; - Real line_thick = Staff_symbol_referencer::line_thickness (me); - - Real blot - = rounded - ? me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")) - : 0.0; - - return Lookup::round_filled_box (Box (Interval (0, line_thick), - Interval (h - th, h + th)), blot); -} - -Stencil -Bar_line::dashed_bar_line (Grob *me, Interval const &extent, Real thick) -{ - Real dash_size - = 1.0 - robust_scm2double (me->get_property ("gap"), 0.3); - /* - this is a tad complex for what we want to achieve, but with a - simple line, the round blotting interferes with staff line - connections. - */ - Real ss = Staff_symbol_referencer::staff_space (me); - Real const h = extent.length (); - int dashes = int (rint (h / ss)); - - /* - there are two concerns: - 1. one dash plus one space should be one staff space - 2. the line should begin and end with half a dash - - both can be satisfied, if the extent is (roughly) an integer - multiple of staff space. - */ - if (fabs (h / ss - dashes) < 0.1) - { - Real blot - = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")); - - Real const half_dash = dash_size / 2; - Stencil bar; - - for (int i = 0; i <= dashes; ++i) - { - Real top_y = extent.at (DOWN) - + (i == dashes ? h : (i + half_dash) * ss); - Real bot_y = extent.at (DOWN) + (i ? (i - half_dash) * ss : 0.0); - - bar.add_stencil (Lookup::round_filled_box (Box (Interval (0, thick), - Interval (bot_y, top_y)), - blot)); - } - return bar; - } - else - { - /* - We have to scale the dashing so it starts and ends with half a - dash exactly. - */ - Real total_dash_size = h / dashes; - Real factor = (dash_size - thick) / ss; - - SCM at = scm_list_n (ly_symbol2scm ("dashed-line"), - scm_from_double (thick), - scm_from_double (factor * total_dash_size), - scm_from_double ((1 - factor) * total_dash_size), - scm_from_double (0), - scm_from_double (h), - scm_from_double (factor * total_dash_size * 0.5), - SCM_UNDEFINED); - - Box box; - box.add_point (Offset (0, 0)); - box.add_point (Offset (0, h)); - - Stencil s (box, at); - s.translate (Offset (thick / 2, extent.at (DOWN))); - return s; - } - return Stencil (); -} - -MAKE_SCHEME_CALLBACK (Bar_line, calc_anchor, 1) -SCM -Bar_line::calc_anchor (SCM smob) -{ - Grob *me = unsmob_grob (smob); - Real kern = robust_scm2double (me->get_property ("kern"), 1); - Real staffline = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); - string str = robust_scm2string (me->get_property ("glyph-name"), ""); - - /* we put the anchor in the center of the barline, unless we are - a repeat bar, in which case we put the anchor in the center of - the barline without the dots. */ - Interval ext = me->extent (me, X_AXIS); - if (ext.is_empty ()) - return scm_from_double (0); - - Real anchor = ext.center (); - - Stencil dot = Font_interface::get_default_font (me)->find_by_name ("dots.dot"); - Real dot_width = dot.extent (X_AXIS).length () + kern * staffline; - if (str == "|:") - anchor -= dot_width / 2; - else if (str == ":|") - anchor += dot_width / 2; - - return scm_from_double (anchor); -} - -ADD_INTERFACE (Bar_line, - "Bar line.\n" - "\n" - "Print a special bar symbol. It replaces the regular bar" - " symbol with a special symbol. The argument @var{bartype}" - " is a string which specifies the kind of bar line to print." - " Options are @code{|}, @code{:|}, @code{|:}, @code{:|:}, @code{:|.|:}," - " @code{:|.:}, @code{.}, @code{||}, @code{|.}, @code{.|}, @code{.|.}," - " @code{|.|}, @code{:}, @code{dashed}, @code{'} and @code{S}.\n" - "\n" - "These produce, respectively, a normal bar line, a right repeat, a left repeat," - " a thick double repeat, a thin-thick-thin double repeat," - " a thin-thick double repeat, a thick bar, a double bar, a start bar," - " an end bar, a thick double bar, a thin-thick-thin bar," - " a dotted bar, a dashed bar, a tick as bar line and a segno bar.\n" - "\n" - "In addition, there is an option" - " @code{||:} which is equivalent to @code{|:} except at line" - " breaks, where it produces a double bar (@code{||}) at the" - " end of the line and a repeat sign (@code{|:}) at the" - " beginning of the new line.\n" - "\n" - "For segno, @code{S} produces a segno sign except at line breaks," - " where it produces a double bar (@code{||}) at the" - " end of the line and a segno sign at the beginning of the new line." - " @code{|S} is equivalent to @code{S} but produces a simple bar line" - " (@code{|}) instead of a double bar line (@code{||}) at line breaks." - " @code{S|} produces the segno sign at line breaks and starts the following" - " line without special bar lines.\n" - "\n" - "@code{S|:} and @code{:|S} are used for repeat/segno combinations that are" - " separated at line breaks. Alternatively, @code{.S|:} and @code{:|S.}" - " may be used which combine repeat signs and segno at the same line in" - " case of a line break. @code{:|S|:} is a combination of a left repeat" - " (@code{:|}), a segno (@code{S}) and a right repeat @code{|:} which" - " splits before the segno at line breaks; @code{:|S.|:} splits after" - " the segno sign.\n" - "\n" - "If @var{bartype} is set to @code{empty} then nothing is" - " printed, but a line break is allowed at that spot.\n" - "\n" - "@code{gap} is used for the gaps in dashed bar lines.", - - /* properties */ - "allow-span-bar " - "gap " - "kern " - "thin-kern " - "hair-thickness " - "has-span-bar " - "thick-thickness " - "glyph " - "glyph-name " - "bar-extent " - ); diff --git a/lily/clef-engraver.cc b/lily/clef-engraver.cc index 29fb3f0bdc..00c3457717 100644 --- a/lily/clef-engraver.cc +++ b/lily/clef-engraver.cc @@ -23,7 +23,6 @@ using namespace std; #include "item.hh" #include "context.hh" -#include "bar-line.hh" #include "staff-symbol-referencer.hh" #include "engraver.hh" #include "direction.hh" diff --git a/lily/cue-clef-engraver.cc b/lily/cue-clef-engraver.cc index c5d8ea6dba..dad382a27a 100644 --- a/lily/cue-clef-engraver.cc +++ b/lily/cue-clef-engraver.cc @@ -24,7 +24,6 @@ using namespace std; #include "item.hh" #include "context.hh" -#include "bar-line.hh" #include "staff-symbol-referencer.hh" #include "engraver.hh" #include "direction.hh" diff --git a/lily/custos-engraver.cc b/lily/custos-engraver.cc index c6ad98aa02..6b915f5cb4 100644 --- a/lily/custos-engraver.cc +++ b/lily/custos-engraver.cc @@ -19,7 +19,6 @@ */ #include "engraver.hh" -#include "bar-line.hh" #include "item.hh" #include "note-head.hh" #include "pitch.hh" diff --git a/lily/grob-scheme.cc b/lily/grob-scheme.cc index e56e02d27a..81ff7864ff 100644 --- a/lily/grob-scheme.cc +++ b/lily/grob-scheme.cc @@ -453,3 +453,16 @@ LY_DEFINE (ly_grob_chain_callback, "ly:grob-chain-callback", chain_callback (gr, proc, sym); return SCM_UNSPECIFIED; } + +LY_DEFINE (ly_grob_vertical_less_p, "ly:grob-verticalinternal_has_interface (ly_symbol2scm ("bar-line-interface")) && dynamic_cast (elts[i])->break_status_dir () == -1) { SCM hsb = elts[i]->get_property ("has-span-bar"); @@ -92,6 +91,7 @@ Hairpin::broken_bound_padding (SCM smob) span_bars[d] = unsmob_grob ((d == UP ? scm_car : scm_cdr) (hsb)); break; } + if (!span_bars[d]) return scm_from_double (0.0); } diff --git a/lily/include/bar-line.hh b/lily/include/bar-line.hh index 432cb0fd4a..8f7b1a24dd 100644 --- a/lily/include/bar-line.hh +++ b/lily/include/bar-line.hh @@ -28,17 +28,6 @@ class Bar_line public: DECLARE_GROB_INTERFACE (); - static Stencil dashed_bar_line (Grob *me, Interval const &extent, Real thick); - static Stencil tick_bar_line (Grob *me, Real h, bool rounded); - static Stencil compound_barline (Grob *, string, Interval const &extent, - bool rounded); - static Stencil simple_barline (Grob *, Real wid, Interval const &extent, - bool rounded); - static Interval bar_y_extent (Grob *, Grob *); static bool non_empty_barline (Grob *me); - - DECLARE_SCHEME_CALLBACK (calc_bar_extent, (SCM)); - DECLARE_SCHEME_CALLBACK (print, (SCM)); - DECLARE_SCHEME_CALLBACK (calc_anchor, (SCM)); }; #endif // BAR_LINE_HH diff --git a/lily/include/span-bar.hh b/lily/include/span-bar.hh deleted file mode 100644 index 6ae9dc175c..0000000000 --- a/lily/include/span-bar.hh +++ /dev/null @@ -1,47 +0,0 @@ -/* - This file is part of LilyPond, the GNU music typesetter. - - Copyright (C) 1997--2012 Han-Wen Nienhuys - - LilyPond is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - LilyPond is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with LilyPond. If not, see . -*/ - -#ifndef SPAN_BAR_HH -#define SPAN_BAR_HH - -#include "lily-proto.hh" -#include "grob-interface.hh" - -/** - This is a barline that is spanned across other bar lines. This is - the implementation of the long barlines that occur in orchestral - score and other multi-staff music. -*/ -class Span_bar -{ -public: - - DECLARE_GROB_INTERFACE (); - static Interval get_spanned_interval (Grob *); - static void add_bar (Grob *, Grob *); - static void evaluate_glyph (Grob *); - static void notify_grobs_of_my_existence (Grob *); - DECLARE_SCHEME_CALLBACK (width, (SCM smob)); - DECLARE_SCHEME_CALLBACK (print, (SCM)); - DECLARE_SCHEME_CALLBACK (calc_glyph_name, (SCM)); - DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM)); - DECLARE_SCHEME_CALLBACK (center_on_spanned_callback, (SCM element)); -}; - -#endif // SPAN_BAR_HH diff --git a/lily/key-engraver.cc b/lily/key-engraver.cc index 6f1d9a374e..5707b548b9 100644 --- a/lily/key-engraver.cc +++ b/lily/key-engraver.cc @@ -17,7 +17,6 @@ along with LilyPond. If not, see . */ -#include "bar-line.hh" #include "clef.hh" #include "context.hh" #include "engraver.hh" diff --git a/lily/mark-engraver.cc b/lily/mark-engraver.cc index 4f2cd630d2..25b19bd18a 100644 --- a/lily/mark-engraver.cc +++ b/lily/mark-engraver.cc @@ -23,7 +23,6 @@ using namespace std; #include "engraver.hh" #include "axis-group-interface.hh" -#include "bar-line.hh" #include "context.hh" #include "grob-array.hh" #include "international.hh" diff --git a/lily/span-bar-engraver.cc b/lily/span-bar-engraver.cc index dc22f90484..09c846f896 100644 --- a/lily/span-bar-engraver.cc +++ b/lily/span-bar-engraver.cc @@ -17,10 +17,9 @@ along with LilyPond. If not, see . */ -#include "bar-line.hh" #include "item.hh" -#include "span-bar.hh" #include "engraver.hh" +#include "pointer-group-interface.hh" /** @@ -54,7 +53,7 @@ void Span_bar_engraver::acknowledge_bar_line (Grob_info i) { int depth = i.origin_contexts (this).size (); - if (depth && !Span_bar::has_interface (i.grob ())) + if (depth && !i.grob ()->internal_has_interface (ly_symbol2scm ("span-bar-interface"))) { Item *it = dynamic_cast (i.grob ()); bars_.push_back (it); @@ -73,7 +72,7 @@ Span_bar_engraver::process_acknowledged () spanbar_->set_parent (bars_[0], X_AXIS); for (vsize i = 0; i < bars_.size (); i++) - Span_bar::add_bar (spanbar_, bars_[i]); + Pointer_group_interface::add_grob (spanbar_, ly_symbol2scm ("elements"), bars_[i]); make_spanbar_ = false; } } @@ -87,7 +86,7 @@ Span_bar_engraver::stop_translation_timestep () SCM vis = bars_[0]->internal_get_property (vissym); if (ly_is_equal (spanbar_->internal_get_property (vissym), vis)) spanbar_->set_property (vissym, vis); - Span_bar::notify_grobs_of_my_existence (spanbar_); + scm_call_1 (ly_lily_module_constant ("span-bar::notify-grobs-of-my-existence"), spanbar_->self_scm ()); spanbar_ = 0; } bars_.resize (0); diff --git a/lily/span-bar-stub-engraver.cc b/lily/span-bar-stub-engraver.cc index 11f1137f2f..10d97241bd 100644 --- a/lily/span-bar-stub-engraver.cc +++ b/lily/span-bar-stub-engraver.cc @@ -20,12 +20,10 @@ #include #include "align-interface.hh" -#include "bar-line.hh" #include "context.hh" #include "grob.hh" #include "item.hh" #include "pointer-group-interface.hh" -#include "span-bar.hh" #include "engraver.hh" /* diff --git a/lily/span-bar.cc b/lily/span-bar.cc deleted file mode 100644 index 5652313693..0000000000 --- a/lily/span-bar.cc +++ /dev/null @@ -1,251 +0,0 @@ -/* - This file is part of LilyPond, the GNU music typesetter. - - Copyright (C) 1997--2012 Han-Wen Nienhuys - - LilyPond is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - LilyPond is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with LilyPond. If not, see . -*/ - -#include "span-bar.hh" - -#include "font-interface.hh" -#include "dimensions.hh" -#include "output-def.hh" -#include "stencil.hh" -#include "warn.hh" -#include "axis-group-interface.hh" -#include "bar-line.hh" -#include "grob.hh" -#include "pointer-group-interface.hh" -#include "staff-symbol-referencer.hh" - -void -Span_bar::add_bar (Grob *me, Grob *b) -{ - Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), b); -} - -MAKE_SCHEME_CALLBACK (Span_bar, print, 1); - -/* Limitations/Bugs: - -(1) Elements from 'me->get_object ("elements")' must be -ordered according to their y coordinates relative to their common -axis group parent. Otherwise, the computation goes mad. - -(2) This method depends on bar_engraver not being removed from -staff context. If bar_engraver is removed, the size of the staff -lines is evaluated as 0, which results in a solid span bar line -with faulty y coordinate. */ - -/* This routine was originally by Juergen Reuter, but it was a on the - bulky side. Rewritten by Han-Wen. */ -SCM -Span_bar::print (SCM smobbed_me) -{ - Grob *me = unsmob_grob (smobbed_me); - extract_grob_set (me, "elements", elements); - Grob *refp = common_refpoint_of_array (elements, me, Y_AXIS); - - SCM glyph = me->get_property ("glyph-name"); - - /* glyph may not be a string, when ME is killed by Hara Kiri in - between. */ - if (!scm_is_string (glyph)) - return SCM_EOL; - - string glyph_string = ly_scm2string (glyph); - - /* compose span_bar_mol */ - vector extents; - vector make_span_bar; - Grob *model_bar = 0; - for (vsize i = elements.size (); i--;) - { - Grob *bar = elements[i]; - Interval ext = Bar_line::bar_y_extent (bar, refp); - if (Grob *staff = Staff_symbol_referencer::get_staff_symbol (bar)) - ext.unite (staff->extent (refp, Y_AXIS)); - if (ext.is_empty ()) - continue; - - extents.push_back (ext); - make_span_bar.push_back (to_boolean (bar->get_property ("allow-span-bar"))); - model_bar = bar; - } - - if (!model_bar) - model_bar = me; - - // Fixes problem with disappearing span bars when alignAboveContext is active - vector_sort (extents, Interval::left_less); - - Stencil span_bar; - for (vsize i = 1; i < extents.size (); i++) - { - Interval prev_extent = extents[i - 1]; - Interval ext = extents[i]; - if (!prev_extent.is_empty ()) - { - Interval l (prev_extent [UP], - ext[DOWN]); - - if (l.is_empty () || !make_span_bar[i]) - { - /* There is overlap between the bar lines. Do nothing. */ - } - else - { - Stencil interbar = Bar_line::compound_barline (model_bar, - glyph_string, - l, - false); - span_bar.add_stencil (interbar); - } - } - prev_extent = ext; - } - - span_bar.translate_axis (- me->relative_coordinate (refp, Y_AXIS), - Y_AXIS); - - return span_bar.smobbed_copy (); -} - -MAKE_SCHEME_CALLBACK (Span_bar, width, 1); -SCM -Span_bar::width (SCM smob) -{ - Grob *me = unsmob_grob (smob); - SCM gn = me->get_property ("glyph-name"); - if (!me->is_live ()) - return ly_interval2scm (Interval ()); - - string gl = ly_scm2string (gn); - - /* - urg. - */ - Stencil m - = Bar_line::compound_barline (me, gl, Interval (-20 PT, 20 PT), false); - - return ly_interval2scm (m.extent (X_AXIS)); -} - -MAKE_SCHEME_CALLBACK (Span_bar, before_line_breaking, 1); -SCM -Span_bar::before_line_breaking (SCM smob) -{ - Grob *me = unsmob_grob (smob); - extract_grob_set (me, "elements", elements); - if (elements.empty ()) - me->suicide (); - - return SCM_UNSPECIFIED; -} - -MAKE_SCHEME_CALLBACK (Span_bar, center_on_spanned_callback, 1); - -SCM -Span_bar::center_on_spanned_callback (SCM smob) -{ - Grob *me = unsmob_grob (smob); - Interval i (get_spanned_interval (me)); - - /* Bar_line::print delivers a barline of y-extent (-h/2, h/2), so - we have to translate ourselves to be in the center of the - interval that we span. */ - if (i.is_empty ()) - { - me->suicide (); - return scm_from_double (0.0); - } - - return scm_from_double (i.center ()); -} - -MAKE_SCHEME_CALLBACK (Span_bar, calc_glyph_name, 1); -SCM -Span_bar::calc_glyph_name (SCM smob) -{ - Grob *me = unsmob_grob (smob); - extract_grob_set (me, "elements", elements); - SCM gl = SCM_EOL; - for (vsize i = elements.size (); - i-- && !scm_is_string (gl);) - gl = elements[i]->get_property ("glyph-name"); - - if (!scm_is_string (gl)) - { - me->suicide (); - return SCM_UNSPECIFIED; - } - - string type = ly_scm2string (gl); - if (type == "|:" || type == "||:") - type = ".|"; - else if (type == ":|") - type = "|."; - else if (type == ":|:") - type = ".|."; - else if (type == ":|.|:") - type = "|.|"; - else if (type == ":|.:") - type = "|."; - else if (type == "S" || type == "S|" || type == "|S") - type = "||"; - else if (type == "S|:" || type == ".S|:") - type = ".|"; - else if (type == ":|S" || type == ":|S.") - type = "|."; - else if (type == ":|S|:" || type == ":|S.|:") - type = "|._.|"; - else if (type == "'") - type = ""; - - return ly_string2scm (type); -} - -void -Span_bar::notify_grobs_of_my_existence (Grob *me) -{ - extract_grob_set (me, "elements", elts); - vector sortable (elts.begin (), elts.end ()); - vector_sort (sortable, Grob::vertical_less); - for (vsize i = 0; i < sortable.size (); i++) - sortable[i]->set_property ("has-span-bar", - scm_cons (i != sortable.size () - 1 ? me->self_scm () : scm_from_bool (false), - i != 0 ? me->self_scm () : scm_from_bool (false))); -} - -Interval -Span_bar::get_spanned_interval (Grob *me) -{ - return ly_scm2interval (Axis_group_interface::generic_group_extent (me, Y_AXIS)); -} - -ADD_INTERFACE (Span_bar, - "A bar line that is spanned between other barlines. This" - " interface is used for bar lines that connect different" - " staves.", - - /* properties */ - "glyph-name " - "elements " - "pure-Y-common " - "pure-relevant-grobs " - "pure-relevant-items " - "pure-relevant-spanners " - ); - diff --git a/lily/staff-spacing.cc b/lily/staff-spacing.cc index d348b10fd7..49f42ea4a6 100644 --- a/lily/staff-spacing.cc +++ b/lily/staff-spacing.cc @@ -26,7 +26,6 @@ using namespace std; #include "paper-column.hh" #include "separation-item.hh" #include "warn.hh" -#include "bar-line.hh" #include "staff-symbol-referencer.hh" #include "note-column.hh" #include "stem.hh" @@ -75,7 +74,8 @@ Staff_spacing::bar_y_positions (Grob *bar_grob) { Interval bar_size; bar_size.set_empty (); - if (Bar_line::has_interface (bar_grob)) + + if (bar_grob->internal_has_interface (ly_symbol2scm ("bar-line-interface"))) { SCM glyph = bar_grob->get_property ("glyph-name"); Grob *staff_sym = Staff_symbol_referencer::get_staff_symbol (bar_grob); diff --git a/lily/vertical-align-engraver.cc b/lily/vertical-align-engraver.cc index 520a1225c4..97f14fdce0 100644 --- a/lily/vertical-align-engraver.cc +++ b/lily/vertical-align-engraver.cc @@ -20,7 +20,6 @@ #include "context.hh" #include "paper-column.hh" #include "align-interface.hh" -#include "span-bar.hh" #include "axis-group-interface.hh" #include "engraver.hh" #include "spanner.hh" diff --git a/lily/volta-engraver.cc b/lily/volta-engraver.cc index f4dc48bf64..882359621a 100644 --- a/lily/volta-engraver.cc +++ b/lily/volta-engraver.cc @@ -20,7 +20,6 @@ #include "engraver.hh" #include "axis-group-interface.hh" -#include "bar-line.hh" #include "context.hh" #include "grob-array.hh" #include "international.hh" diff --git a/scm/bar-line.scm b/scm/bar-line.scm new file mode 100644 index 0000000000..e000178837 --- /dev/null +++ b/scm/bar-line.scm @@ -0,0 +1,650 @@ +;;;; This file is part of LilyPond, the GNU music typesetter. +;;;; +;;;; Copyright (C) 2009--2012 Marc Hohl +;;;; +;;;; LilyPond is free software: you can redistribute it and/or modify +;;;; it under the terms of the GNU General Public License as published by +;;;; the Free Software Foundation, either version 3 of the License, or +;;;; (at your option) any later version. +;;;; +;;;; LilyPond is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with LilyPond. If not, see . + +;; helper functions + +(define (get-staff-symbol grob) + (if (grob::has-interface grob 'staff-symbol-interface) + grob + (ly:grob-object grob 'staff-symbol))) + +(define (layout-blot-diameter grob) + (let* ((layout (ly:grob-layout grob)) + (blot (ly:output-def-lookup layout 'blot-diameter))) + + blot)) + +(define (layout-line-thickness grob) + (let* ((layout (ly:grob-layout grob)) + (line-thickness (ly:output-def-lookup layout 'line-thickness))) + + line-thickness)) + +(define (staff-symbol-line-count grob) + (let ((line-count 0)) + + (if (ly:grob? grob) + (let ((line-pos (ly:grob-property grob 'line-positions '()))) + + (set! line-count (if (pair? line-pos) + (length line-pos) + (ly:grob-property grob 'line-count 0))))) + + line-count)) + +(define (staff-symbol-line-span grob) + (let ((line-pos (ly:grob-property grob 'line-positions '())) + (iv (cons 0.0 0.0))) + + (if (pair? line-pos) + (map (lambda (x) + (set! iv (cons (min (car iv) x) + (max (cdr iv) x)))) + line-pos) + (let ((line-count (ly:grob-property grob 'line-count 0))) + + (set! iv (cons (- 1 line-count) + (- line-count 1))))) + iv)) + +(define (staff-symbol-line-positions grob) + (let ((line-pos (ly:grob-property grob 'line-positions '()))) + + (if (not (pair? line-pos)) + (let* ((line-count (ly:grob-property grob 'line-count 0)) + (height (- line-count 1.0))) + + (set! line-pos (map (lambda (x) + (- height (* x 2))) + (iota line-count))))) + line-pos)) + +;; functions used by external routines + +(define-public (span-bar::notify-grobs-of-my-existence grob) + (let* ((elts (ly:grob-array->list (ly:grob-object grob 'elements))) + (sorted-elts (sort elts ly:grob-vertical (interval-length extent) 0)) + (bar-line::compound-bar-line grob glyph extent #f) + #f))) + +(define-public (bar-line::compound-bar-line grob glyph extent rounded) + (let* ((line-thickness (layout-line-thickness grob)) + (height (interval-length extent)) + (kern (* (ly:grob-property grob 'kern 1) line-thickness)) + (thinkern (* (ly:grob-property grob 'thin-kern 1) line-thickness)) + (hair (* (ly:grob-property grob 'hair-thickness 1) line-thickness)) + (fatline (* (ly:grob-property grob 'thick-thickness 1) line-thickness)) + (thin-stil (make-simple-bar-line grob hair extent rounded)) + (thick-stil (make-simple-bar-line grob fatline extent rounded)) + (colon-stil (make-colon-bar-line grob)) + (glyph (cond + ((not glyph) "") + ((string=? glyph "||:") "|:") + ;; bar-line::compound-bar-line is called only if + ;; height > 0, but just in case ... + ((and (string=? glyph ":|") + (zero? height)) "|.") + ((and (string=? glyph "|:") + (zero? height)) ".|") + (else glyph))) + (stencil (cond + ((string=? glyph "|") thin-stil) + ((string=? glyph ".") thick-stil) + ((string=? glyph "||") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + '() X LEFT thin-stil thinkern) + X RIGHT thin-stil thinkern)) + ((string=? glyph "|.") + (ly:stencil-combine-at-edge + thick-stil X LEFT thin-stil kern)) + ((string=? glyph ".|") + (ly:stencil-combine-at-edge + thick-stil X RIGHT thin-stil kern)) + ((string=? glyph "|:") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + thick-stil X RIGHT thin-stil kern) + X RIGHT colon-stil kern)) + ((string=? glyph ":|") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + thick-stil X LEFT thin-stil kern) + X LEFT colon-stil kern)) + ((string=? glyph ":|:") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + '() X LEFT thick-stil thinkern) + X LEFT colon-stil kern) + X RIGHT thick-stil kern) + X RIGHT colon-stil kern)) + ((string=? glyph ":|.|:") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + thick-stil X LEFT thin-stil kern) + X LEFT colon-stil kern) + X RIGHT thin-stil kern) + X RIGHT colon-stil kern)) + ((string=? glyph ":|.:") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + thick-stil X LEFT thin-stil kern) + X LEFT colon-stil kern) + X RIGHT colon-stil kern)) + ((string=? glyph ".|.") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + '() X LEFT thick-stil thinkern) + X RIGHT thick-stil kern)) + ((string=? glyph "|.|") + (ly:stencil-combine-at-edge + (ly:stencil-combine-at-edge + thick-stil X LEFT thin-stil kern) + X RIGHT thin-stil kern)) + ((string=? glyph ":") + (make-dotted-bar-line grob extent)) + ((or (string=? glyph "|._.|") + (string-contains glyph "S")) + (make-segno-bar-line grob glyph extent rounded)) + ((string=? glyph "'") + (make-tick-bar-line grob (interval-end extent) rounded)) + ((string=? glyph "dashed") + (make-dashed-bar-line grob extent hair)) + ((string=? glyph "kievan") + (make-kievan-bar-line grob)) + (else (make-empty-bar-line grob extent))))) + stencil)) + +(define-public (ly:bar-line::calc-anchor grob) + (let* ((line-thickness (layout-line-thickness grob)) + (kern (* (ly:grob-property grob 'kern 1) line-thickness)) + (glyph (ly:grob-property grob 'glyph-name "")) + (x-extent (ly:grob-extent grob grob X)) + (dot-width (+ (interval-length + (ly:stencil-extent + (ly:font-get-glyph + (ly:grob-default-font grob) + "dots.dot") + X)) + kern)) + (anchor 0.0)) + + (if (> (interval-length x-extent) 0) + (begin + (set! anchor (interval-center x-extent)) + (cond ((string=? glyph "|:") + (set! anchor (+ anchor (/ dot-width -2.0)))) + ((string=? glyph ":|") + (set! anchor (+ anchor (/ dot-width 2.0))))))) + anchor)) + +(define-public (bar-line::calc-glyph-name grob) + (let* ((glyph (ly:grob-property grob 'glyph)) + (dir (ly:item-break-dir grob)) + (result (assoc-get glyph bar-glyph-alist)) + (glyph-name (if (= dir CENTER) + glyph + (if (and result + (string? (index-cell result dir))) + (index-cell result dir) + #f)))) + glyph-name)) + +(define-public (bar-line::calc-break-visibility grob) + (let* ((glyph (ly:grob-property grob 'glyph)) + (result (assoc-get glyph bar-glyph-alist))) + + (if result + (vector (string? (car result)) #t (string? (cdr result))) + all-invisible))) + +;; which span bar belongs to a bar line? + +(define-public span-bar-glyph-alist + '(("|:" . ".|") + ("||:" . ".|") + (":|" . "|.") + (":|.:" . "|.") + (":|:" . ".|.") + (":|.|:" . "|.|") + (":|.|" . "|.") + ("S" . "||" ) + ("S|" . "||") + ("|S" . "||") + ("S|:" . ".|") + (".S|:" . ".|") + (":|S" . "|.") + (":|S." . "|.") + (":|S|:" . "|._.|") + (":|S.|:" . "|._.|") + ("kievan" . "") + ("'" . ""))) + +;; span bar callbacks + +(define-public (ly:span-bar::calc-glyph-name grob) + (let* ((elts (ly:grob-object grob 'elements)) + (pos (1- (ly:grob-array-length elts))) + (glyph '())) + + (while (and (eq? glyph '()) + (> pos -1)) + (begin (set! glyph (ly:grob-property (ly:grob-array-ref elts pos) + 'glyph-name)) + (set! pos (1- pos)))) + (if (eq? glyph '()) + (begin (ly:grob-suicide! grob) + (set! glyph ""))) + (assoc-get glyph span-bar-glyph-alist glyph))) + +(define-public (ly:span-bar::width grob) + (let ((width (cons 0 0))) + + (if (grob::is-live? grob) + (let* ((glyph (ly:grob-property grob 'glyph-name)) + (stencil (bar-line::compound-bar-line grob glyph (cons -1 1) #f))) + + (set! width (ly:stencil-extent stencil X)))) + width)) + +(define-public (ly:span-bar::before-line-breaking grob) + (let ((elts (ly:grob-object grob 'elements))) + + (if (zero? (ly:grob-array-length elts)) + (ly:grob-suicide! grob)))) + +;; The method used in the following routine depends on bar_engraver +;; not being removed from staff context. If bar_engraver is removed, +;; the size of the staff lines is evaluated as 0, which results in a +;; solid span bar line with faulty y coordinate. +;; +;; This routine was originally by Juergen Reuter, but it was a on the +;; bulky side. Rewritten by Han-Wen. Ported from c++ to Scheme by Marc Hohl. +(define-public (ly:span-bar::print grob) + (let* ((elts-array (ly:grob-object grob 'elements)) + (refp (ly:grob-common-refpoint-of-array grob elts-array Y)) + (elts (reverse (sort (ly:grob-array->list elts-array) + ly:grob-vertical (interval-length ext) 0) + (begin + (set! extents (append extents (list ext))) + (set! model-bar bar) + (set! make-span-bars + (append make-span-bars + (list (ly:grob-property bar 'allow-span-bar #t)))))))))) + elts) + ;; if there is no bar grob, we use the callback argument + (if (not model-bar) + (set! model-bar grob)) + ;; we discard the first entry in make-span-bars, because its corresponding + ;; bar line is the uppermost and therefore not connected to another bar line + (if (pair? make-span-bars) + (set! make-span-bars (cdr make-span-bars))) + ;; the span bar reaches from the lower end of the upper staff + ;; to the upper end of the lower staff - when allow-span-bar is #t + (reduce (lambda (curr prev) + (let ((l (cons 0 0)) + (allow-span-bar (car make-span-bars))) + + (set! make-span-bars (cdr make-span-bars)) + (if (> (interval-length prev) 0) + (begin + (set! l (cons (cdr prev) (car curr))) + (if (or (zero? (interval-length l)) + (not allow-span-bar)) + (begin + ;; there is overlap between the bar lines + ;; or 'allow-span-bar = #f. + ;; Do nothing. + ) + (set! span-bar + (ly:stencil-add span-bar + (bar-line::compound-bar-line + model-bar + glyph + l + #f)))))) + curr)) + "" extents) + (set! span-bar (ly:stencil-translate-axis + span-bar + (- (ly:grob-relative-coordinate grob refp Y)) + Y)))) + span-bar)) diff --git a/scm/define-grob-interfaces.scm b/scm/define-grob-interfaces.scm index 5ce9690167..8d9c457037 100644 --- a/scm/define-grob-interfaces.scm +++ b/scm/define-grob-interfaces.scm @@ -36,6 +36,50 @@ note)." "The line between note heads for a pitch range." '(gap note-heads thickness)) +(ly:add-interface + 'bar-line-interface + "Print a special bar symbol. It replaces the regular bar +symbol with a special symbol. The argument @var{bartype} +is a string which specifies the kind of bar line to print. +Options are @code{|}, @code{:|}, @code{|:}, @code{:|:}, @code{:|.|:}, +@code{:|.:}, @code{.}, @code{||}, @code{|.}, @code{.|}, @code{.|.}, +@code{|.|}, @code{:}, @code{dashed}, @code{'} and @code{S}. + +These produce, respectively, a normal bar line, a right repeat, a left repeat, +a thick double repeat, a thin-thick-thin double repeat, +a thin-thick double repeat, a thick bar, a double bar, a start bar, +an end bar, a thick double bar, a thin-thick-thin bar, +a dotted bar, a dashed bar, a tick as bar line and a segno bar. + +In addition, there is an option +@code{||:} which is equivalent to @code{|:} except at line +breaks, where it produces a double bar (@code{||}) at the +end of the line and a repeat sign (@code{|:}) at the +beginning of the new line. + +For segno, @code{S} produces a segno sign except at line breaks, +where it produces a double bar (@code{||}) at the +end of the line and a segno sign at the beginning of the new line. +@code{|S} is equivalent to @code{S} but produces a simple bar line +(@code{|}) instead of a double bar line (@code{||}) at line breaks. +@code{S|} produces the segno sign at line breaks and starts the following +line without special bar lines. + +@code{S|:} and @code{:|S} are used for repeat/segno combinations that are +separated at line breaks. Alternatively, @code{.S|:} and @code{:|S.} +may be used which combine repeat signs and segno at the same line in +case of a line break. @code{:|S|:} is a combination of a left repeat +(@code{:|}), a segno (@code{S}) and a right repeat @code{|:} which +splits before the segno at line breaks; @code{:|S.|:} splits after +the segno sign. + +If @var{bartype} is set to @code{empty} then nothing is +printed, but a line break is allowed at that spot. + +@code{gap} is used for the gaps in dashed bar lines." + '(allow-span-bar bar-extent gap glyph glyph-name has-span-bar + hair-thickness kern thin-kern thick-thickness)) + (ly:add-interface 'bass-figure-interface "A bass figure text." @@ -212,6 +256,14 @@ interesting enough to maintain a hara-kiri staff." "Supports setting of spacing variables." '(spacing-increment shortest-duration-space)) +(ly:add-interface + 'span-bar-interface + "A bar line that is spanned between other barlines. + This interface is used for bar lines that connect different + staves." + '(glyph-name elements pure-Y-common pure-relevant-grobs + pure-relevant-items pure-relevant-spanners)) + (ly:add-interface 'stanza-number-interface "A stanza number, to be put in from of a lyrics line." diff --git a/scm/lily-library.scm b/scm/lily-library.scm index 91ece1e476..ec1097a32b 100644 --- a/scm/lily-library.scm +++ b/scm/lily-library.scm @@ -652,6 +652,10 @@ right (@var{dir}=+1)." (define (other-axis a) (remainder (+ a 1) 2)) +(define-public (interval-scale iv factor) + (cons (* (car iv) factor) + (* (cdr iv) factor))) + (define-public (interval-widen iv amount) (cons (- (car iv) amount) (+ (cdr iv) amount))) diff --git a/scm/lily.scm b/scm/lily.scm index 190670045c..5a6b5f388d 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -408,6 +408,7 @@ messages into errors.") "font.scm" "encoding.scm" + "bar-line.scm" "flag-styles.scm" "fret-diagrams.scm" "tablature.scm" diff --git a/scm/output-lib.scm b/scm/output-lib.scm index 01e429cd19..af55cc8fde 100644 --- a/scm/output-lib.scm +++ b/scm/output-lib.scm @@ -358,68 +358,8 @@ and duration-log @var{log}." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Bar lines. +;; neighbor-interface routines -;; -;; How should a bar line behave at a break? -(define bar-glyph-alist - '((":|:" . (":|" . "|:")) - (":|.|:" . (":|" . "|:")) - (":|.:" . (":|" . "|:")) - ("||:" . ("||" . "|:")) - ("dashed" . ("dashed" . '())) - ("|" . ("|" . ())) - ("|s" . (() . "|")) - ("|:" . ("|" . "|:")) - ("|." . ("|." . ())) - - ;; hmm... should we end with a bar line here? - (".|" . ("|" . ".|")) - (":|" . (":|" . ())) - ("||" . ("||" . ())) - (".|." . (".|." . ())) - ("|.|" . ("|.|" . ())) - ("" . ("" . "")) - (":" . (":" . "")) - ("." . ("." . ())) - ("'" . ("'" . ())) - ("empty" . (() . ())) - ("brace" . (() . "brace")) - ("bracket" . (() . "bracket")) - - ;; segno bar lines - ("S" . ("||" . "S")) - ("|S" . ("|" . "S")) - ("S|" . ("S" . ())) - (":|S" . (":|" . "S")) - (":|S." . (":|S" . ())) - ("S|:" . ("S" . "|:")) - (".S|:" . ("|" . "S|:")) - (":|S|:" . (":|" . "S|:")) - (":|S.|:" . (":|S" . "|:")) - - ;; ancient bar lines - ("kievan" . ("kievan" . "")))) - -(define-public (bar-line::calc-glyph-name grob) - (let* ((glyph (ly:grob-property grob 'glyph)) - (dir (ly:item-break-dir grob)) - (result (assoc-get glyph bar-glyph-alist)) - (glyph-name (if (= dir CENTER) - glyph - (if (and result - (string? (index-cell result dir))) - (index-cell result dir) - #f)))) - glyph-name)) - -(define-public (bar-line::calc-break-visibility grob) - (let* ((glyph (ly:grob-property grob 'glyph)) - (result (assoc-get glyph bar-glyph-alist))) - - (if result - (vector (string? (car result)) #t (string? (cdr result))) - all-invisible))) (define-public (shift-right-at-line-begin g) "Shift an item to the right, but only at the start of the line." -- 2.39.2