+2005-02-04 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * Documentation/user/changing-defaults.itely (Text encoding):
+ rewrite.
+
+ * lily/pango-font.cc (physical_font_tab): new member. Store PSname
+ -> font_filename mapping.
+
+ * lily/pango-font-scheme.cc (LY_DEFINE): new file. New function
+ ly_pango_font_physical_fonts
+
+ * scm/framework-ps.scm (supplies-or-needs): extract names from
+ physical Pango_fonts.
+
+ * utf8.ly: new file.
+
2005-02-02 Han-Wen Nienhuys <hanwen@xs4all.nl>
* Documentation/user/changing-defaults.itely (Page layout): add
-@c -*- coding: latin-1; mode: texinfo; -*-
+@c -*- coding: utf-8; mode: texinfo; -*-
@node Changing defaults
@chapter Changing defaults
(self-alignment-X . 0)
(self-alignment-Y . 0)
(script-priority . 100)
- (font-encoding . number)
(font-size . -5)
(meta . ((interfaces . (finger-interface font-interface
text-script-interface text-interface
@itemize @bullet
@item @code{font-encoding}
-is a symbol that sets layout of the glyphs. Choices include @code{ec}
-for @TeX{} EC font encoding, @code{fetaBraces} for piano staff
-braces, @code{fetaMusic} the standard music font, including ancient
-glyphs, @code{fetaDynamic} for dynamic signs and @code{fetaNumber}
-for the number font.
+is a symbol that sets layout of the glyphs. This should only be set to
+select different types of non-text fonts, eg.
+
+@code{fetaBraces} for piano staff braces, @code{fetaMusic} the
+standard music font, including ancient glyphs, @code{fetaDynamic} for
+dynamic signs and @code{fetaNumber} for the number font.
@item @code{font-family}
is a symbol indicating the general class of the typeface. Supported are
@node Text encoding
@subsection Text encoding
-[FIXME: OBSOLETE, use UTF8 for input files.]
+LilyPond uses the Pango library to format multi-lingual texts. This
+means that any text, be it title, lyric text, or musical instruction
+contaning non-ASCII characters should be entered as Unicode.
+@lilypondfile[utf8.ly]
-Texts can be entered in different encodings. The encoding of the
-file can be set with @code{\encoding}.
+The @TeX{} backend does not handle encoding specially at all. Strings
+in the input are put in the output as-is. Extents of text items in the
+@TeX{} backend, are determined by reading a file created via the
+@file{texstr} backend,
@example
-\encoding "latin1"
+ lilypond -b texstr input/les-nereides.ly
+ latex les-nereides.texstr
@end example
-This command may be placed anywhere in the input file. The current
-encoding is passed as an extra argument to @code{\markup} commands,
-and is passed similarly to lyric syllables.
-
-If no @code{\encoding} has been specified, then the encoding is taken
-from the @code{\layout} block (or @code{\paper}, if @code{\layout}
-does not specify encoding). The variable @code{inputencoding} may be
-set to a string or symbol specifying the encoding, e.g.,
+The last command produces @file{les-nereides.textmetrics}, which is
+read when you execute
@example
-\layout @{
- inputencoding = "latin1"
-@}
+ lilypond -b tex input/les-nereides.ly
@end example
-Normal strings are unaffected by @code{\encoding}. This means that
-the following will usually not produce `Baßtuba' in the title.
-
-@example
-\header @{
- title = "Grazing cow"
- instrument = "Baßtuba"
-@}
-@end example
+Both @file{les-nereides.texstr} and @file{les-nereides.tex} need
+suitable LaTeX wrappers to load appropriate La@TeX{} packages for
+interpreting non-ASCII strings.
-@noindent
-Rather, you should say
-@example
-instrument = \markup @{ Baßtuba @}
-@end example
-
-@noindent
-or set @code{inputencoding} in the @code{\paper} block.
-
-There is a special encoding, called @code{TeX}. This encoding does not
-reencode text for the font used. Rather, it tries to guess the width
-of @TeX{} commands, such as @code{\"}. Strings encoded with @code{TeX}
-are passed to the output back-end verbatim.
+@seealso
-@cindex encoding
-@cindex @code{\encoding}
-@cindex inputencoding
-@cindex @TeX{} commands in strings
+@inputfileref{input/regression/,utf8.ly}
@node Nested scores
--- /dev/null
+\version "2.5.10"
+
+% Edit this file using a Unicode aware editor, such as GVIM, GEDIT, Emacs
+
+%{
+
+I installed some additional font packages to get this working.
+
+taipeifonts
+fonts-xorg-truetype
+ttfonts-ja
+fonts-arabic
+ttfonts-zh_CN
+fonts-ja
+fonts-hebrew
+
+%}
+
+\header {
+
+ texidoc = "Various scripts may be used for texts (like titles and
+lyrics) introduced by entering them in UTF-8 encoding, and using a
+Pango based backend. Depending on the fonts installed, this fragment
+will render Japanese, Hebrew and Cyrillic.
+
+"
+
+}
+
+
+japanese = \lyricsto "melody" \new Lyrics {
+
+ いろはにほへど ちりぬるを
+ わがよたれぞ つねならむ
+ うゐのおくやまけふこえて
+ あさきゆめみじ ゑひもせず
+
+ }
+
+
+bulgarian = \lyricsto "melody" \new Lyrics {
+
+ Жълтата дюля беше щастлива, че пухът, който цъфна, замръзна като гьон.
+
+}
+
+hebrew = \lyricsto "melody" \new Lyrics {
+זה כיף סתם לשמוע איך תנצח קרפד עץ טוב בגן.
+}
+
+% latin1 section start
+
+ <<
+ \context Voice = "melody" \relative {
+ c2 d e f g f e
+ }
+ \hebrew
+ \bulgarian
+
+ %% no support for TTF yet.
+
+% \japanese
+
+>>
Real last_size = -1e6;
int i = 0;
- String pango_description_string;
+ SCM pango_description_string = SCM_EOL;
for (; i < n; i++)
{
SCM entry = scm_c_vector_ref (font_vector, i);
{
size = scm_to_double (scm_car (entry));
pango_description_string
- = ly_scm2string (scm_cdr (entry));
+ = scm_cdr (entry);
}
#endif
}
Font_metric *fm = 0;
- if (pango_description_string != "")
+ if (scm_is_string (pango_description_string))
{
#if HAVE_PANGO_FT2
- PangoFontDescription *description
- = pango_font_description_from_string (pango_description_string.to_str0 ());
- return all_fonts_global->find_pango_font (description,
- requested / size,
- output_scale (layout));
+ return find_pango_font (layout,
+ pango_description_string,
+ requested / size);
#else
error ("Trying to retrieve pango font without HAVE_PANGO_FT2.");
#endif
SCM robust_list_ref(int i, SCM l);
SCM alist_to_hashq (SCM);
+SCM ly_alist_vals (SCM alist);
+SCM ly_hash2alist (SCM tab);
/* inserts at front, removing dublicates */
inline SCM ly_assoc_front_x(SCM alist, SCM key, SCM val)
DECLARE_UNSMOB (Output_def, output_def);
-Font_metric *find_scaled_font (Output_def *od,
- Font_metric *f, Real magnification);
+Font_metric* find_pango_font (Output_def *layout, SCM descr, Real factor);
+Font_metric *find_scaled_font (Output_def *od, Font_metric *f, Real magnification);
Output_def *scale_output_def (Output_def *def, Real scale);
+
Real output_scale (Output_def*);
#endif /* MUSIC_OUTPUT_DEF_HH */
PangoFontDescription *pango_description_;
PangoAttrList *attribute_list_;
Real scale_;
- SCM subfonts_;
-
+ SCM physical_font_tab_;
+
public:
+ SCM physical_font_tab () const;
Pango_font (PangoFT2FontMap *,
Direction leftright,
PangoFontDescription *,
Stencil text_stencil (String) const;
Stencil pango_item_string_stencil (PangoItem*, String, Real) const;
- virtual SCM sub_fonts () const;
virtual void derived_mark () const;
};
}
return true;
}
+
+
+
+SCM
+ly_alist_vals (SCM alist)
+{
+ SCM x = SCM_EOL;
+ for (SCM p = alist; scm_is_pair (p); p = scm_cdr (p))
+ {
+ x = scm_cons (scm_cdar (p), x);
+ }
+ return x;
+}
+
+SCM
+ly_hash2alist (SCM tab)
+{
+ SCM func = ly_lily_module_constant ("hash-table->alist");
+ return scm_call_1 (func, tab);
+}
init_global_tweak_registry ();
init_fontconfig ();
init_freetype ();
+
+ is_pango_format_global = (output_backend_global != "tex"
+ && output_backend_global != "texstr");
+
all_fonts_global = new All_font_metrics (global_path.to_string ());
init_scheme_code_string += ")";
warranty ();
exit (0);
break;
+
case 'b':
output_backend_global = option_parser->optional_argument_str0_;
- is_pango_format_global = (output_backend_global != "tex"
- &&output_backend_global != "texstr");
break;
case 'f':
int
Object_key_undumper::print_smob (SCM s, SCM port, scm_print_state*)
{
+ (void) s;
scm_puts ("#<Object_key_undumper>", port);
return 1;
}
{
Output_def *b = unsmob_output_def (bp);
- SCM font_table = b->lookup_variable (ly_symbol2scm ("scaled-fonts"));
SCM_ASSERT_TYPE (b, bp, SCM_ARG1, __FUNCTION__, "paper");
- SCM ell = SCM_EOL;
- if (scm_hash_table_p (font_table) == SCM_BOOL_T)
+ SCM tab1 = b->lookup_variable (ly_symbol2scm ("scaled-fonts"));
+ SCM tab2 = b->lookup_variable (ly_symbol2scm ("pango-fonts"));
+
+ SCM alist1 = SCM_EOL;
+ if (scm_hash_table_p (tab1) == SCM_BOOL_T)
+ {
+ alist1 = scm_append (ly_alist_vals (ly_hash2alist (tab1)));
+
+ alist1 = ly_alist_vals (alist1);
+ }
+
+ SCM alist2 = SCM_EOL;
+ if (scm_hash_table_p (tab2) == SCM_BOOL_T)
{
- SCM func = ly_lily_module_constant ("hash-table->alist");
-
- for (SCM s = scm_call_1 (func, font_table); scm_is_pair (s);
- s = scm_cdr (s))
- {
- SCM entry = scm_car (s);
- for (SCM t = scm_cdr (entry); scm_is_pair (t); t = scm_cdr (t))
- {
- Font_metric *fm = unsmob_metrics (scm_cdar (t));
-
- if (dynamic_cast<Modified_font_metric*> (fm)
- || dynamic_cast<Pango_font*> (fm))
- ell = scm_cons (fm->self_scm (), ell);
- }
- }
+ // strip original-fonts/pango-font-descriptions
+ alist2 = scm_append (ly_alist_vals (ly_hash2alist (tab2)));
+
+ // strip size factors
+ alist2 = ly_alist_vals (alist2);
}
- return ell;
+
+ SCM alist = scm_append (scm_list_2 (alist1, alist2));
+ SCM font_list = SCM_EOL;
+ for (SCM s = alist; scm_is_pair (s); s = scm_cdr (s))
+ {
+ SCM entry = scm_car (s);
+
+ Font_metric *fm = unsmob_metrics (entry);
+
+ if (dynamic_cast<Modified_font_metric*> (fm)
+ || dynamic_cast<Pango_font*> (fm))
+ font_list = scm_cons (fm->self_scm (), font_list);
+ }
+
+ return font_list;
}
--- /dev/null
+/*
+ pango-font-scheme.cc -- implement Pango_font
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2004--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+
+#define PANGO_ENABLE_BACKEND // ugh, why necessary?
+
+#include <pango/pangoft2.h>
+
+#include "main.hh"
+#include "lookup.hh"
+#include "dimensions.hh"
+#include "pango-font.hh"
+#include "warn.hh"
+
+#if HAVE_PANGO_FT2
+#include "stencil.hh"
+
+
+LY_DEFINE (ly_pango_font_p, "ly:pango-font?",
+ 1, 0, 0,
+ (SCM f),
+ "Is @var{f} a pango font?")
+{
+ return scm_from_bool (dynamic_cast<Pango_font*> (unsmob_metrics (f)));
+}
+
+
+
+LY_DEFINE (ly_pango_font_physical_fonts, "ly:pango-font-physical-fonts",
+ 1, 0, 0,
+ (SCM f),
+ "Return alist of (PSNAME . FILENAME) tuples.")
+{
+ Pango_font *pf = dynamic_cast<Pango_font*> (unsmob_metrics (f));
+
+ SCM alist = SCM_EOL;
+ if (pf)
+ alist = ly_hash2alist (pf->physical_font_tab ());
+
+ return alist;
+}
+#endif
#include "lookup.hh"
#include "dimensions.hh"
#include "pango-font.hh"
+#include "warn.hh"
#if HAVE_PANGO_FT2
#include "stencil.hh"
PangoFontDescription *description,
Real output_scale)
{
- subfonts_ = SCM_EOL;
+ physical_font_tab_ = scm_c_make_hash_table (11);
PangoDirection pango_dir = (dir == RIGHT)
? PANGO_DIRECTION_LTR
: PANGO_DIRECTION_RTL;
void
Pango_font::register_font_file (String filename, String ps_name)
{
- subfonts_ = scm_cons (scm_makfrom0str (filename.to_str0 ()),
- subfonts_);
+ scm_hash_set_x (physical_font_tab_,
+ scm_makfrom0str (ps_name.to_str0()),
+ scm_makfrom0str (filename.to_str0()));
}
void
Pango_font::derived_mark () const
{
- scm_gc_mark (subfonts_);
+ scm_gc_mark (physical_font_tab_);
}
Stencil
char *filename = 0;
FcPatternGetString(fcpat, FC_FILE, 0, (FcChar8 **) &filename);
char const *ps_name = FT_Get_Postscript_Name (ftface);
- ((Pango_font *) this)->register_font_file (filename, ps_name);
- pango_fc_font_unlock_face (fcfont);
+
+ if (ps_name)
+ {
+ ((Pango_font *) this)->register_font_file (filename, ps_name);
+ pango_fc_font_unlock_face (fcfont);
- SCM expr = scm_list_4 (ly_symbol2scm ("glyph-string"),
- scm_makfrom0str (ps_name),
- scm_from_double (size),
- ly_quote_scm (glyph_exprs));
+ SCM expr = scm_list_4 (ly_symbol2scm ("glyph-string"),
+ scm_makfrom0str (ps_name),
+ scm_from_double (size),
+ ly_quote_scm (glyph_exprs));
- Stencil item_stencil (b, expr);
+ return Stencil (b, expr);
+ }
+ else
+ {
+ warning (_ ("FreeType face has no PostScript font name."));
+ return Stencil();
+ }
+}
- return item_stencil;
+SCM
+Pango_font::physical_font_tab () const
+{
+ return physical_font_tab_;
}
Stencil
+
Pango_font::text_stencil (String str) const
{
GList *items = pango_itemize (context_,
return dest;
}
-SCM
-Pango_font::sub_fonts () const
-{
- return subfonts_;
-}
SCM
Pango_font::font_file_name () const
return SCM_BOOL_F;
}
-LY_DEFINE (ly_pango_font_p, "ly:pango-font?",
- 1, 0, 0,
- (SCM f),
- "Is @var{f} a pango font?")
-{
- return scm_from_bool (dynamic_cast<Pango_font*> (unsmob_metrics (f)));
-}
-
#endif
#include "output-def.hh"
#include "modified-font-metric.hh"
#include "pango-font.hh"
+#include "all-font-metrics.hh"
+
Real
output_scale (Output_def *od)
return scm_to_double (od->lookup_variable (ly_symbol2scm ("outputscale")));
}
-
SCM
get_font_table (Output_def *def)
{
}
return font_table;
}
-
+SCM
+get_pango_font_table (Output_def *def)
+{
+ SCM font_table = def->lookup_variable (ly_symbol2scm ("pango-fonts"));
+ if (scm_hash_table_p (font_table) != SCM_BOOL_T)
+ {
+ font_table = scm_c_make_hash_table (11);
+ def->set_variable (ly_symbol2scm ("pango-fonts"), font_table);
+ }
+ return font_table;
+}
/* TODO: should add nesting for Output_def here too. */
Font_metric *
Real lookup_mag = m / output_scale (mod);
SCM font_table = get_font_table (mod);
- SCM sizes = scm_hashq_ref (font_table, f->self_scm (), SCM_BOOL_F);
- if (sizes != SCM_BOOL_F)
- {
- SCM met = scm_assoc (scm_make_real (lookup_mag), sizes);
- if (scm_is_pair (met))
- return unsmob_metrics (scm_cdr (met));
- }
- else
- sizes = SCM_EOL;
+ SCM sizes = scm_hashq_ref (font_table, f->self_scm (), SCM_EOL);
+ SCM handle = scm_assoc (scm_make_real (lookup_mag), sizes);
+ if (scm_is_pair (handle))
+ return unsmob_metrics (scm_cdr (handle));
SCM val = Modified_font_metric::make_scaled_font_metric (f, lookup_mag);
return unsmob_metrics (val);
}
+Font_metric*
+find_pango_font (Output_def *layout, SCM descr, Real factor)
+{
+ if (layout->parent_)
+ return find_pango_font (layout->parent_, descr, factor);
+
+ SCM table = get_pango_font_table (layout);
+ SCM sizes = scm_hash_ref (table, descr, SCM_EOL);
+ SCM size_key = scm_from_double (factor);
+ SCM handle = scm_assoc (size_key, sizes);
+ if (scm_is_pair (handle))
+ {
+ return unsmob_metrics (scm_cdr (handle));
+ }
+
+ PangoFontDescription *description
+ = pango_font_description_from_string (scm_i_string_chars (descr));
+ Font_metric *fm = all_fonts_global->find_pango_font (description,
+ factor,
+ output_scale (layout));
+
+ sizes = scm_acons (size_key, fm->self_scm(), sizes);
+ scm_hash_set_x (table, descr, sizes);
+
+ return fm;
+}
+
/* TODO: this is a nasty interface. During formatting,
the Output_def should be scaled to the output_scale_
specified in the toplevel Output_def. */
%type <outputdef> output_def_body output_def_head
%type <outputdef> output_def paper_block
+%type <scm> assignment_id
%type <scm> Music_list
%type <scm> chord_body_elements
%type <scm> chord_item chord_items chord_separator new_chord
/*
DECLARATIONS
*/
+assignment_id:
+ STRING { $$ = $1; }
+ | LYRICS_STRING { $$ = $1; }
+ ;
+
assignment:
- STRING '=' identifier_init {
+ assignment_id '=' identifier_init {
if (! is_regular_identifier ($1))
{
@1.warning (_ ("Identifier should have alphabetic characters only"));
$$ = all;
scm_gc_unprotect_object (voice->self_scm ());
}
- | LYRICSTO {
+ | LYRICSTO simple_string {
THIS->lexer_->push_lyric_state ();
- } simple_string Music {
+ } Music {
THIS->lexer_->pop_state ();
Music *music = $4;
- SCM name = $3;
+ SCM name = $2;
$$ = make_lyric_combine_music (name, music);
scm_gc_unprotect_object (music->self_scm ());
}
(display (list font fontname)))
(define-font plain fontname scaling)))
+
(apply string-append
(map (lambda (x) (font-load-command x))
(filter (lambda (x) (not (ly:pango-font? x)))
(ly:outputter-dump-stencil outputter page)
(ly:outputter-dump-string outputter "} stop-system \nshowpage\n"))
+
(define (supplies-or-needs paper load-fonts?)
- (let* ((fonts (ly:paper-fonts paper)))
+ (define (extract-names font)
+ (if (ly:pango-font? font)
+ (map car (ly:pango-font-physical-fonts font))
+ (list (ly:font-name font))))
+
+ (let* ((fonts (ly:paper-fonts paper))
+ (names (apply append (map extract-names fonts)))
+ )
+
(apply string-append
(map (lambda (f)
(format
(if load-fonts?
"%%DocumentSuppliedResources: font ~a\n"
"%%DocumentNeededResources: font ~a\n")
- (ly:font-name f)))
- fonts))))
+ f))
+ names))))
(define (eps-header paper bbox load-fonts?)
(string-append "%!PS-Adobe-2.0 EPSF-2.0\n"
(all-font-names
(map
(lambda (font)
- (if (string? (ly:font-file-name font))
- (list (ly:font-file-name font))
- (ly:font-sub-fonts font)))
-
+ (cond
+ ((string? (ly:font-file-name font)) (list (ly:font-file-name font)))
+ ((ly:pango-font? font)
+ (map cdr (ly:pango-font-physical-fonts font)))
+ (else (ly:font-sub-fonts font))))
+
fonts))
+
(font-names
(uniq-list
(sort (apply append all-font-names) string<?)))