* Added feature to lilypond-book to write out \header texidoc string.
-1.3.113.jcn1
-============
-
* Reincluded simple FAQ in tarball.
-* Fixed lyrics with bar-enrgaver example (?).
+* Fixed lyrics with bar-enrgaver example.
* Renamed LyricVoice to LyricsVoice.
-1.3.112.jcn3
-============
+1.3.113.uu1
+===========
+
+* Checksums for AFM fonts: make sure that TFM and AFM files match.
+One FAQ less to be asked.
+
+* Made point-and-click switchable, default: off
+
+* Bugfix: don't make multimeasure rests from failed span-requests.
+
+* Bugfix: mark with string arguments, eg. letters..
+
+* Bugfix: direction of staccato dots.
+
+1.3.113
+=======
* Added stems to font for use in markup text.
Offset callbacks can be stacked. The callbacks will be executed in the
order that they were added.
-Width and height are similarly implemted using extent callbacks. There
+Width and height are similarly implemented using extent callbacks. There
can be only one callback for each axis. No callback (the 0 ptr) means:
"empty in this direction".
@file{/var/lib/texmf} and your current directory. A script automating
this has been included, see @file{buildscripts/clean-fonts.sh}.
-@subsection Dvips spews weird error messages!
-
-Warnings that look like
-
-@example
- dvips: Couldn't find figure file src:XX:YY; continuing
-@end example
-
-are harmless. Dvips does not yet grok the
-@uref{http://appel.lilypond.org/wiki?PointAndClick,
-PointAndClick} feature.
-
-
@node Installation
@section Installation
that the correct guile, guile-config, and libguile* in your PATH and
LD_LIBRARY_PATH (or @file{/etc/ld.so.conf}).
-@subsection I get all kinds of errors while compiling @file{parser.cc}
-
-LilyPond uses features of bison version 1.25. Please confirm that
-you are using a version 1.25 or better, that is @strong{GNU} bison
-@strong{1.25}. Don't forget to do "make clean" after installing it. Don't
-forget to remove the stale @file{bison.simple} as well.
-
-If the problem persists, then please send a bug report to the mailing list.
-
@subsection I upgraded by applying a patch, and now my configure/build breaks.
Patches don't include automatically generated files, i.e.
@node Grobs, , , Reference Manual
+This section is about Grobs (short for Graphical Objects), which are
+formatting objects used to create the final output. This material is
+normally the domain of LilyPond gurus, but occasionally, a normal user
+also has to deal with grobs.
+The most simple interaction with Grobs are when you use
+@code{\override}:
+
+@example
+ \property Voice.Stem \override #'direction = #1
+@end example
+
+This piece of lily input causes all stem objects to be stem-up
+henceforth. In effect, you are telling lilypond to extend the defintion
+of the "Stem" grob with the setting @code{direction := 1}. Of course
+there are many more ways of customizing Lily output, and since most of
+them involve Grobs in some form, this section explains some details of
+how grobs work.
+
+Types of grob?
+
+What is a grob?
+
+Where do they come from?
+
+How can you override?
+
+Items and Spanners?
+
+X and Y parents, offsets and extents.
+
+
+@node Molecule, , , Reference Manual
+
+The objective of any typesetting system is to put ink on paper in the
+right places. For LilyPond, this final stage is left to the TeX and the
+printer subsystem. For lily, the last stage in processing a score is
+outputting a description of what to put where. This description roughly
+looks like
+
+@example
+ PUT glyph AT (x,y)
+ PUT glyph AT (x,y)
+ PUT glyph AT (x,y)
+@end example
+
+you merely have to look at the tex output of lily to see this.
+Internally these instructions are encoded in Molecules:@footnote{At some
+point LilyPond also contained Atom-objects, but they have been replaced
+by Scheme expressions.}. A molecule is an object that combines
+dimension information (how large is this ?) with what-to-print-where.
+
+Conceptually, Molecules can be constructed from Scheme code, by
+translating a Molecule and by combining two molecules. In BNF notation:
+
+@example
+ Molecule = COMBINE Molecule Molecule
+ | TRANSLATE Offset Molecule
+ | GLYPH-DESCRIPTION
+ ;
+@end example
+
+(refer to the C++ code for more details). All visible,
+ie. non-transparent, grobs have a function to create Molecule.
PACKAGE_NAME=LilyPond
MAJOR_VERSION=1
MINOR_VERSION=3
-PATCH_LEVEL=113
-MY_PATCH_LEVEL=jcn3
+PATCH_LEVEL=114
+MY_PATCH_LEVEL=
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
pass
+def tfm_checksum (fn):
+ s = open (fn).read ()
+ s = s[ 12 * 2 : ]
+ cs_bytes = s[:4]
+
+ shift = 24
+ cs = 0
+ for b in cs_bytes:
+ cs = cs + (ord (b) << shift)
+ shift = shift - 8
+
+ return cs
+
def parse_logfile (fn):
(autolines, deps) = read_log_file (fn)
charmetrics = []
for filenm in files:
(g,m, deps) = parse_logfile (filenm)
+ cs = tfm_checksum (re.sub ('.log$', '.tfm', filenm))
afm = open (afmfile_nm, 'w')
+
+ afm.write ("TfmCheckSum %u\n" % cs)
+
write_afm_metric (afm, g,m)
write_tex_defs (open (texfile_nm, 'w'), g, m)
write_deps (open (depfile_nm, 'wb'), deps, [texfile_nm, afmfile_nm])
Adobe_font_metric::Adobe_font_metric (AFM_Font_info * fi)
{
+ checksum_ = 0;
font_inf_ = fi;
for (int i= 256; i--;)
SCM
-Adobe_font_metric::make_afm (AFM_Font_info *fi)
+Adobe_font_metric::make_afm (AFM_Font_info *fi, unsigned int checksum)
{
Adobe_font_metric * fm = new Adobe_font_metric (fi);
-
+ fm->checksum_ = checksum;
return fm->self_scm();
}
read_afm_file (String nm)
{
FILE *f = fopen (nm.ch_C() , "r");
+ char s[2048];
+ char *check_key = "TfmCheckSum";
+ fgets (s, sizeof (s), f);
+
+ unsigned int cs = 0;
+ if (strncmp (s, check_key, strlen (check_key)) == 0)
+ {
+ sscanf (s + strlen (check_key), "%ud", &cs);
+ }
+ else
+ {
+ rewind (f);
+ }
+
AFM_Font_info * fi;
int ok = AFM_parseFile (f, &fi, ~1);
}
fclose (f);
- return Adobe_font_metric::make_afm (fi);
+ return Adobe_font_metric::make_afm (fi, cs);
}
afm_p_dict_->set (sname,val);
- scm_unprotect_object (val);
+ scm_unprotect_object (val);
+
+
+ Adobe_font_metric *afm
+ = dynamic_cast<Adobe_font_metric*> (unsmob_metrics (val) );
+ Tex_font_metric * tfm = find_tfm (name);
+
+ if (tfm->info_.checksum != afm->checksum_)
+ {
+ String s = _("Font checksum mismatch");
+ s+= "\n";
+ s += " TFM: " + to_str ((int) tfm->info_.checksum);
+ s += " AFM: " + to_str ((int) afm->checksum_);
+ s += "\n";
+ s += _(" Rebuild all AFM files, and remove all .pk and .tfm files");
+
+ error (s);
+ }
}
return dynamic_cast<Adobe_font_metric*> (unsmob_metrics (val));
Key_change_req::do_equal_b (Request const * req) const
{
Key_change_req const * k = dynamic_cast<Key_change_req const*> (req);
- return k && scm_equal_p (get_mus_property ("pitch-alist"), k->get_mus_property ("pitch-alist"));
+ return k && scm_equal_p (get_mus_property ("pitch-alist"), k->get_mus_property ("pitch-alist")) == SCM_BOOL_T;
}
{
Mark_req const * other = dynamic_cast<Mark_req const*> (r);
return other && scm_equal_p (other->get_mus_property ("mark-label"),
- get_mus_property ("mark-label"));
+ get_mus_property ("mark-label")) == SCM_BOOL_T;
}
String str () const;
~Adobe_font_metric ();
- static SCM make_afm (AFM_Font_info*);
+ static SCM make_afm (AFM_Font_info*, unsigned);
+ unsigned int checksum_;
protected:
Array<int> ascii_to_metric_idx_;
Dictionary<int> name_to_metric_dict_;
extern void set_inclusion_names (Array<String>);
extern File_path global_path;
-extern Array<String> global_score_header_fields;
extern String default_outname_base_global;
extern String default_outname_suffix_global;
{
public:
bool outputting_comment_b_;
- ostream *os_;
+ ostream *os;
int nest_level;
/// to check linelen in output. TeX has limits.
int line_len_i_;
void break_line();
};
-class ostream;
-ostream *open_file_stream (String filename);
-void close_file_stream (ostream *os);
-
-
#endif // PAPER_STREAM_HH
String str () const;
-private:
- Tex_font_metric ();
+
Tfm_info info_;
Tfm_header header_;
Array<Tex_font_char_metric> char_metrics_;
Array<int> ascii_to_metric_idx_;
+private:
+ Tex_font_metric ();
};
p->rank_i_ = prev ? Paper_column::rank_i (prev) + 1 : 0;
-
-
me->set_grob_property ("columns", gh_cons (p->self_scm (), cs));
Axis_group_interface::add_element (me, p);
int default_count_global;
File_path global_path;
-Array<String> global_score_header_fields;
-
bool safe_global_b = false;
bool experimental_features_global_b = false;
bool dependency_global_b = false;
Long_option_init theopts[] = {
{_i ("EXT"), "output-format", 'f', _i ("use output format EXT (scm, ps, tex or as)")},
{0, "help", 'h', _i ("this help")},
- {_i ("FIELD"), "header", 'H', _i ("write header field to BASENAME.FIELD")},
{_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
{_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
{0, "dependencies", 'M', _i ("write Makefile dependencies for every input file")},
global_path.add (p);
#if !KPATHSEA
+ /*
+ Although kpathsea seems nice, it is not universally available
+ (GNU/Windows).
+
+ Compiling kpathsea seems not possible without
+ (compiling) a matching tex installation. Apart from the fact
+ that I cannot get kpathsea compiled for GNU/Windows, another
+ major problem is that TeX installations may be different on
+ different clients, so it wouldn't work anyway. While ugly,
+ this code is simple and effective.
+ -- jcn
+ */
+
/* Urg: GNU make's $(word) index starts at 1 */
int i = 1;
while (global_path.try_add (p + to_str (".") + to_str (i)))
case 'Q':
find_old_relative_b= true;
break;
- case 'H':
- global_score_header_fields.push (oparser_global_p->optional_argument_ch_C_);
- break;
case 'I':
global_path.push (oparser_global_p->optional_argument_ch_C_);
break;
}
}
SCM st = ly_symbol2scm (style.ch_C());
- text_p_->set_grob_property ("style", st);
+ text_p_->set_grob_property ("font-style", st);
}
}
{
if (scm_equal_p (sp->get_mus_property ("span-type"),
- ly_str02scm ("rest")))
+ ly_str02scm ("rest")) == SCM_BOOL_T)
{
if (sp->get_span_dir() == STOP)
{
free (c);
}
}
-
void
Paper_outputter::output_scope (Scope *scope, String prefix)
{
output_scheme (scm);
}
-void
-Paper_outputter::output_string (SCM str)
-{
- *stream_p_ << ly_scm2string (str);
-}
-void
-Paper_outputter::output_score_header_field (String filename, String key, String value)
-{
- if (filename != "-")
- filename += String (".") + key;
- progress_indication (_f ("writing header field %s to %s...",
- key,
- filename == "-" ? String ("<stdout>") : filename));
-
- ostream* os = open_file_stream (filename);
- *os << value;
- close_file_stream (os);
- progress_indication ("\n");
-}
void
-Paper_outputter::output_score_header_fields (Paper_def *paper)
+Paper_outputter::output_string (SCM str)
{
- if (global_score_header_fields.size ())
- {
- SCM fields = paper->scope_p_->to_alist ();
- String base = paper->base_output_str ();
- for (int i = 0; i < global_score_header_fields.size (); i++)
- {
- String key = paper->global_score_header_fields[i];
- SCM val = gh_assoc (ly_str02scm (key), fields);
- String s
- if (val != SCM_BOOL_F)
- s = ly_scm2string (val);
- output_score_header_field (base, key, s);
- }
- }
+ *stream_p_ << ly_scm2string (str);
}
return sol;
}
+
+
/*
urg. clean me
*/
outputter_l_->output_scheme (scm);
progress_indication ("\n");
-
- outputter_l_->output_score_header_fields (paper_l_);
-
// huh?
delete outputter_l_;
outputter_l_ = 0;
-
+
if (verbose_global_b)
ly_display_scm (scm_gc_stats ());
}
const int MAXLINELEN = 200;
-ostream*
-open_file_stream (String filename)
+Paper_stream::Paper_stream (String filename)
{
if (filename.length_i () && (filename != "-"))
os = new ofstream (filename.ch_C ());
else
+ // os = new ostream (cout.ostreambuf ());
os = new ostream (cout._strbuf);
if (!*os)
error (_f ("can't open file: `%s'", filename));
- return os;
+ nest_level = 0;
+ line_len_i_ = 0;
+ outputting_comment_b_=false;
}
-void
-close_file_stream (ostream* os)
+Paper_stream::~Paper_stream ()
{
*os << flush;
if (!*os)
exit_status_i_ = 1;
}
delete os;
-}
-
-Paper_stream::Paper_stream (String filename)
-{
- os_ = open_file_stream (filename);
- nest_level = 0;
- line_len_i_ = 0;
- outputting_comment_b_=false;
-}
-
-Paper_stream::~Paper_stream ()
-{
- close_file_stream (os_);
assert (nest_level == 0);
}
{
if (outputting_comment_b_)
{
- *os_ << *cp;
+ *os << *cp;
if (*cp == '\n')
{
outputting_comment_b_=false;
{
case '%':
outputting_comment_b_ = true;
- *os_ << *cp;
+ *os << *cp;
break;
case '{':
nest_level++;
- *os_ << *cp;
+ *os << *cp;
break;
case '}':
nest_level--;
- *os_ << *cp;
+ *os << *cp;
if (nest_level < 0)
{
- delete os_; // we want to see the remains.
+ delete os; // we want to see the remains.
assert (nest_level>=0);
}
if (nest_level == 0)
break;
- *os_ << '%';
+ *os << '%';
break_line ();
break;
case '\n':
break_line ();
break;
case ' ':
- *os_ << ' ';
+ *os << ' ';
if (line_len_i_ > MAXLINELEN)
break_line ();
break;
default:
- *os_ << *cp;
+ *os << *cp;
break;
}
}
//urg, for debugging only!!
- *os_ << flush;
+ *os << flush;
return *this;
}
void
Paper_stream::break_line ()
{
- *os_ << '\n';
- *os_ << to_str (' ', nest_level);
+ *os << '\n';
+ *os << to_str (' ', nest_level);
outputting_comment_b_ = false;
line_len_i_ = 0;
}
Articulation_req* l=script_req_l_arr_[i];
SCM alist = get_property ("scriptDefinitions");
- SCM list = scm_assoc (l->get_mus_property ("articulation-type"), alist);
+ SCM art = scm_assoc (l->get_mus_property ("articulation-type"), alist);
- if (list == SCM_BOOL_F)
+ if (art == SCM_BOOL_F)
{
String a = ly_scm2string (l->get_mus_property ("articulation-type"));
l->origin ()->warning (_f ("Don't know how to interpret articulation `%s'", a.ch_C()));
}
// todo -> use result of articulation-to-scriptdef directly as basic prop list.
Grob *p =new Item (get_property ("Script"));
- list = gh_cdr (list);
+ art = gh_cdr (art);
p->set_grob_property ("molecule",
- gh_car (list));
+ gh_car (art));
- list = gh_cdr(list);
- bool follow_staff = gh_scm2bool (gh_car (list));
- list = gh_cdr(list);
- SCM relative_stem_dir = gh_car (list);
- list = gh_cdr(list);
+ art = gh_cdr(art);
+ bool follow_staff = gh_scm2bool (gh_car (art));
+ art = gh_cdr(art);
+ SCM relative_stem_dir = gh_car (art);
+ art = gh_cdr(art);
SCM force_dir = l->get_mus_property ("direction");
- if (!isdir_b (force_dir))
- force_dir = gh_car (list);
- list = gh_cdr(list);
- SCM priority = gh_car (list);
-
+ if (isdir_b (force_dir) && to_dir (force_dir))
+ force_dir = gh_car (art);
- if (!isdir_b (force_dir)
- && to_dir (relative_stem_dir))
- p->set_grob_property ("side-relative-direction", relative_stem_dir);
- else
+ art = gh_cdr(art);
+ SCM priority = gh_car (art);
+
+
+ if (isdir_b (force_dir) && to_dir (force_dir))
p->set_grob_property ("direction", force_dir);
+ else if (to_dir (relative_stem_dir))
+ p->set_grob_property ("side-relative-direction", relative_stem_dir);
+
+
/*
FIXME: should figure this out in relation with basic props!
Side_position::get_direction (Grob*me)
{
SCM d = me->get_grob_property ("direction");
- if (isdir_b (d))
- return to_dir (d) ? to_dir (d) : DOWN;
+ if (isdir_b (d) && to_dir (d))
+ return to_dir (d);
- Direction relative_dir = UP;
+ Direction relative_dir = Direction (1);
SCM reldir = me->get_grob_property ("side-relative-direction"); // should use a lambda.
if (isdir_b (reldir))
{
|| bounds[LEFT]->line_l () != bounds[RIGHT]->line_l ())
{
programming_error ("bounds of spanner are invalid");
-#if 0
- /*
- lily crashes upon displaying this ...
-
- */
-
- gh_display (ly_str02scm ("\nspanner:mutable_property_alist_\n"));
- gh_display (mutable_property_alist_);
- gh_display (ly_str02scm ("\nspanner:immutable_property_alist_\n"));
- gh_display (immutable_property_alist_);
- gh_newline ();
-#endif
span_p->suicide ();
}
else
return spanned_drul_ [d];
}
+/*
+ Set the items that this spanner spans. If D == LEFT, we also set the
+ X-axis parent of THIS to S.
+*/
void
Spanner::set_bound(Direction d, Grob*s)
{
}
}
-
Spanner::Spanner (SCM s)
: Grob (s)
{
spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
}
-
Real
Spanner::spanner_length() const
{
Grob* p2 = unsmob_grob (gh_cdr (pair));
sp->set_bound (LEFT,p1);
sp->set_bound (RIGHT, p2);
-
- //extra precaution.
}
Begin3
Title: LilyPond
-Version: 1.3.113
-Entered-date: 29NOV00
+Version: 1.3.114
+Entered-date: 01DEC00
Description:
Keywords: music notation typesetting midi fonts engraving
Author: hanwen@cs.uu.nl (Han-Wen Nienhuys)
janneke@gnu.org (Jan Nieuwenhuizen)
Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys)
Primary-site: sunsite.unc.edu /pub/Linux/apps/sound/convert
- 1000k lilypond-1.3.113.tar.gz
+ 1000k lilypond-1.3.114.tar.gz
Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/
- 1000k lilypond-1.3.113.tar.gz
+ 1000k lilypond-1.3.114.tar.gz
Copying-policy: GPL
End
%define info yes
Name: lilypond
-Version: 1.3.113
+Version: 1.3.114
Release: 1
License: GPL
Group: Applications/Publishing
-Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.113.tar.gz
+Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.3.114.tar.gz
Summary: A program for printing sheet music.
URL: http://www.cs.uu.nl/~hanwen/lilypond
# Icon: lilypond-icon.gif
(Script . (
(molecule-callback . ,Script::brew_molecule)
(X-offset-callbacks . (,Side_position::centered_on_parent))
+ (after-line-breaking-callback . ,Script::after_line_breaking)
(meta . ,(element-description "Script" script-interface side-position-interface font-interface))
))
(debug-enable 'backtrace)
+
+(define point-and-click #f)
+
;;; library funtions
(use-modules (ice-9 regex))
(define (define-origin file line col)
; use this for column positions
+ (if point-and-click
(string-append "\\special{src:" (number->string line) ":"
(number->string col) " " file "}"
;; arg, the clueless take over the mailing list...
; "\\special{-****-These-warnings-are-harmless-***}"
; "\\special{-****-PLEASE-read-http://appel.lilypond.org/wiki/index.php3?PostProcessing-****}"
)
+ "")
; line numbers only:
;(string-append "\\special{src:" (number->string line) " " file "}")
)
- ; no origin info: return empty string
- ; ""
+
; no-origin not yet supported by Xdvi
(define (no-origin) "")