]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/accidental.cc
Issue 5167/6: Changes: show \markup xxx = ... \etc assignments
[lilypond.git] / lily / accidental.cc
index daf5b68b185d44caaf857694f056400c2b971605..4343c2dc5a9bf75e473b4d31c7b8a454b3910f2e 100644 (file)
 /*
-  accidental.cc -- implement Accidental_interface
+  This file is part of LilyPond, the GNU music typesetter.
 
-  (c) 2001--2003 Han-Wen Nienhuys
-  
- */
-#include "font-interface.hh"
-#include "item.hh"
-#include "molecule.hh"
-#include "accidental-interface.hh"
-#include "paper-def.hh"
+  Copyright (C) 2001--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
-/*
-  TODO: insert support for smaller cautionaries, tie-break-reminders.
-  Either here or in new-accidental-engraver.
+  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.
 
-  'accidentals should go, for a single 'accidental property -- see
-  accidental-placement.cc
+  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 <http://www.gnu.org/licenses/>.
 */
 
-
-Molecule
-parenthesize (Grob*me, Molecule m)
+#include "accidental-interface.hh"
+#include "font-interface.hh"
+#include "international.hh"
+#include "item.hh"
+#include "output-def.hh"
+#include "paper-column.hh"
+#include "pitch.hh"
+#include "stencil.hh"
+#include "system.hh"
+#include "skyline-pair.hh"
+
+Stencil
+parenthesize (Grob *me, Stencil m)
 {
-  Molecule open = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-leftparen"));
-  Molecule close = Font_interface::get_default_font (me)->find_by_name (String ("accidentals-rightparen"));
-  m.add_at_edge (X_AXIS, LEFT, Molecule (open), 0,0);
-  m.add_at_edge (X_AXIS, RIGHT, Molecule (close), 0,0);
+  Font_metric *font
+    = Font_interface::get_default_font (me);
+  Stencil open
+    = font->find_by_name ("accidentals.leftparen");
+  Stencil close
+    = font->find_by_name ("accidentals.rightparen");
+
+  m.add_at_edge (X_AXIS, LEFT, Stencil (open), 0);
+  m.add_at_edge (X_AXIS, RIGHT, Stencil (close), 0);
 
   return m;
 }
 
-
-MAKE_SCHEME_CALLBACK (Accidental_interface,after_line_breaking,1);
+MAKE_SCHEME_CALLBACK (Accidental_interface, horizontal_skylines, 1);
 SCM
-Accidental_interface::after_line_breaking (SCM smob)
+Accidental_interface::horizontal_skylines (SCM smob)
 {
-  Grob *me  = unsmob_grob (smob);
-  Grob *tie = unsmob_grob (me->get_grob_property ("tie"));
-
-  if (tie && !tie->original_)
+  Grob *me = unsmob<Grob> (smob);
+  if (!me->is_live ())
+    return Skyline_pair ().smobbed_copy ();
+
+  Stencil *my_stencil = unsmob<Stencil> (me->get_property ("stencil"));
+  if (!my_stencil)
+    return Skyline_pair ().smobbed_copy ();
+
+  Skyline_pair *sky =
+    unsmob<Skyline_pair>
+      (Stencil::skylines_from_stencil
+        (my_stencil->smobbed_copy (), 0.0, Y_AXIS));
+
+  SCM alist = me->get_property ("glyph-name-alist");
+  SCM alt = me->get_property ("alteration");
+  string glyph_name = robust_scm2string (ly_assoc_get (alt, alist, SCM_BOOL_F),
+                                                       "");
+  if (glyph_name == "accidentals.flat"
+      || glyph_name == "accidentals.flatflat")
     {
-      me->suicide ();
+      // a bit more padding for the right of the stem
+      // we raise the stem horizontally to a bit less than the average
+      // horizontal "height" of the entire glyph. This will bring flats
+      // closer to doubleflats, which looks better (MS opinion).
+      // this should work for all fonts where the flat is not
+      // completely bizarre
+      Real left = my_stencil->extent (X_AXIS)[LEFT];
+      Real right = my_stencil->extent (X_AXIS)[RIGHT] * 0.375;
+      Real down = my_stencil->extent (Y_AXIS)[DOWN];
+      Real up = my_stencil->extent (Y_AXIS)[UP];
+      vector<Box> boxes;
+      boxes.push_back (Box (Interval (left, right), Interval (down, up)));
+      Skyline merge_with_me (boxes, Y_AXIS, RIGHT);
+      (*sky)[RIGHT].merge (merge_with_me);
     }
-  return SCM_UNSPECIFIED;
+  return sky->smobbed_copy ();
 }
 
-Array<Box>
-Accidental_interface::accurate_boxes (Grob *a,Grob**common)
+MAKE_SCHEME_CALLBACK (Accidental_interface, height, 1);
+SCM
+Accidental_interface::height (SCM smob)
 {
-  Box b;
-  b[X_AXIS] = a->extent (a, X_AXIS);
-  b[Y_AXIS] = a->extent (a, Y_AXIS);
-
-  Array<Box> boxes;
-  
-  bool parens = false;
-  if (to_boolean (a->get_grob_property ("cautionary")))
-    {
-      SCM cstyle = a->get_grob_property ("cautionary-style");
-      parens = gh_equal_p (cstyle, ly_symbol2scm ("parentheses"));
+  Grob *me = unsmob<Grob> (smob);
+  Grob *tie = unsmob<Grob> (me->get_object ("tie"));
 
-    }
+  if (tie
+      && !to_boolean (me->get_property ("forced"))
+      && to_boolean (me->get_property ("hide-tied-accidental-after-break")))
+    return ly_interval2scm (Interval ());
 
-  SCM accs = a->get_grob_property ("accidentals");
-  SCM scm_style = a->get_grob_property ("style");
-  if (!gh_symbol_p (scm_style)
-      && !parens
-      && scm_ilength (accs) == 1)
-    {
-      if (gh_scm2int (gh_car (accs)) == -1)
-       {
-         Box stem = b;
-         Box bulb = b;
-
-         /*
-           we could make the stem thinner, but that places the flats
-           really close.
-         */
-         stem[X_AXIS][RIGHT] *= .5;
-         bulb[Y_AXIS][UP] *= .35;
-
-         boxes.push (bulb);
-         boxes.push (stem);
-       }
-      /*
-       TODO: add support for natural, double flat.
-       */
-    }
+  return Grob::stencil_height (smob);
+}
 
-  if (!boxes.size())
-    boxes.push (b);
+MAKE_SCHEME_CALLBACK (Accidental_interface, remove_tied, 1);
+SCM
+Accidental_interface::remove_tied (SCM smob)
+{
+  Grob *me = unsmob<Grob> (smob);
+  Grob *tie = unsmob<Grob> (me->get_object ("tie"));
 
-  Offset o (a->relative_coordinate (common[X_AXIS],  X_AXIS),
-           a->relative_coordinate (common[Y_AXIS],  Y_AXIS));
-  for(int i = boxes.size(); i--;)
-    {
-      boxes[i].translate(o);
-    }
-  
-  return boxes;
+  if (tie
+      && !to_boolean (me->get_property ("forced"))
+      && (to_boolean (me->get_property ("hide-tied-accidental-after-break"))
+          || !tie->original()))
+    me->suicide ();
+
+  return SCM_UNSPECIFIED;
 }
 
-/*
- * Some styles do not provide all flavours of accidentals, e.g. there
- * is currently no sharp accidental in vaticana style.  In these cases
- * this function falls back to one of the other styles.
- */
-String
-Accidental_interface::get_fontcharname(String style, int alteration)
+MAKE_SCHEME_CALLBACK (Accidental_interface, print, 1);
+SCM
+Accidental_interface::print (SCM smob)
 {
-  if (style == "hufnagel")
-    switch (alteration)
-      {
-      case -2: return "-2";
-      case -1: return "hufnagel-1";
-      case 0: return "vaticana0";
-      case 1: return "mensural1";
-      case 2: return "2";
-      }
-  if (style == "medicaea")
-    switch (alteration)
-      {
-      case -2: return "-2";
-      case -1: return "medicaea-1";
-      case 0: return "vaticana0";
-      case 1: return "mensural1";
-      case 2: return "2";
-      }
-  if (style == "vaticana")
-    switch (alteration)
-      {
-      case -2: return "-2";
-      case -1: return "vaticana-1";
-      case 0: return "vaticana0";
-      case 1: return "mensural1";
-      case 2: return "2";
-      }
-  if (style == "mensural")
-    switch (alteration)
-      {
-      case -2: return "-2";
-      case -1: return "mensural-1";
-      case 0: return "vaticana0";
-      case 1: return "mensural1";
-      case 2: return "2";
-      }
-  if (style == "neo_mensural")
-    style = ""; // currently same as default
-  if (style == "default")
-    style = "";
-  return style + to_string (alteration);
+  Grob *me = unsmob<Grob> (smob);
+
+  return get_stencil (me);
 }
 
-MAKE_SCHEME_CALLBACK (Accidental_interface,brew_molecule,1);
 SCM
-Accidental_interface::brew_molecule (SCM smob)
+Accidental_interface::get_stencil (Grob *me)
 {
-  Grob *me = unsmob_grob (smob);
-  bool smaller = false;
-  bool parens = false;
+  Font_metric *fm = Font_interface::get_default_font (me);
 
-  bool caut  = to_boolean (me->get_grob_property ("cautionary"));
-  if (caut)
-    {
-      SCM cstyle = me->get_grob_property ("cautionary-style");
-      parens = gh_equal_p (cstyle, ly_symbol2scm ("parentheses"));
-      smaller = gh_equal_p (cstyle, ly_symbol2scm ("smaller"));
-    }
+  SCM alist = me->get_property ("glyph-name-alist");
+  SCM alt = me->get_property ("alteration");
+  SCM glyph_name = ly_assoc_get (alt, alist, SCM_BOOL_F);
+  Stencil mol;
 
-  SCM scm_style = me->get_grob_property ("style");
-  String style;
-  if (gh_symbol_p (scm_style))
+  if (!scm_is_string (glyph_name))
     {
-      style = ly_symbol2string (scm_style);
+      me->warning (_f ("Could not find glyph-name for alteration %s",
+                       ly_scm_write_string (alt).c_str ()));
+      mol = fm->find_by_name ("noteheads.s1cross");
     }
   else
-    {
-      /*
-       preferably no name for the default style.
-      */
-      style = "";
-    }
+    mol = fm->find_by_name (ly_scm2string (glyph_name));
 
-  Font_metric *fm = 0;
-  if (smaller)
+  if (to_boolean (me->get_property ("restore-first")))
     {
-      SCM ac = Font_interface::font_alist_chain (me);
-      ac = gh_cons (gh_cons (gh_cons
-                            (ly_symbol2scm ("font-relative-size"),
-                             scm_int2num (-1)), SCM_EOL),
-                   ac);
-      fm = select_font (me->get_paper (), ac);
-    }
-  else
-    fm = Font_interface::get_default_font (me);
+      /*
+        this isn't correct for ancient accidentals, but they don't
+        use double flats/sharps anyway.
+        */
+      Stencil acc (fm->find_by_name ("accidentals.natural"));
 
-  Molecule mol;
-  for (SCM s = me->get_grob_property ("accidentals");
-       gh_pair_p (s); s = gh_cdr (s))
-    {
-      int alteration = gh_scm2int (gh_car (s));
-      String font_char = get_fontcharname (style, alteration);
-      Molecule acc (fm->find_by_name ("accidentals-" + font_char));
-
-      if (acc.empty_b())
-       {
-         me->warning (_f ("accidental `%s' not found", font_char));
-       }
+      if (acc.is_empty ())
+        me->warning (_ ("natural alteration glyph not found"));
       else
-       {
-         mol.add_at_edge (X_AXIS,  RIGHT, acc, 0.1,0);
-       }
+        mol.add_at_edge (X_AXIS, LEFT, acc, 0.1);
     }
 
-  if (parens)
-    mol = parenthesize (me, mol); 
+  if (to_boolean (me->get_property ("parenthesized")))
+    mol = parenthesize (me, mol);
 
-  return mol.smobbed_copy();
+  return mol.smobbed_copy ();
 }
 
-
-
-ADD_INTERFACE (Accidental_interface, "accidental-interface",
-             "a single accidental",
-              "cautionary cautionary-style style tie accidentals");
+ADD_INTERFACE (Accidental_interface,
+               "A single accidental.",
+
+               /* properties */
+               "alteration "
+               "avoid-slur "
+               "forced "
+               "glyph-name-alist "
+               "glyph-name "
+               "hide-tied-accidental-after-break "
+               "parenthesized "
+               "restore-first "
+               "tie "
+              );