2 text-interface.cc -- implement Text_interface
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 Jan Nieuwenhuizen <janneke@gnu.org>
10 #include "text-interface.hh"
13 #include "font-interface.hh"
17 #include "modified-font-metric.hh"
18 #include "output-def.hh"
19 #include "pango-font.hh"
23 replace_whitespace (string
*str
)
26 vsize n
= str
->size ();
32 // avoid the locale-dependent isspace
33 if (cur
== '\n' || cur
== '\t' || cur
== '\v')
36 vsize char_len
= utf8_char_len (cur
);
42 MAKE_SCHEME_CALLBACK (Text_interface
, interpret_string
, 3);
44 Text_interface::interpret_string (SCM layout_smob
,
48 LY_ASSERT_SMOB (Output_def
, layout_smob
, 1);
49 LY_ASSERT_TYPE (scm_is_string
, markup
, 3);
51 string str
= ly_scm2string (markup
);
52 Output_def
*layout
= unsmob_output_def (layout_smob
);
53 Font_metric
*fm
= select_encoded_font (layout
, props
);
55 replace_whitespace (&str
);
58 We want to use "glyph-string" in the SVG backend for all
59 music fonts (Emmentaler and Aybabtu) that pass through the
60 text interface. Here the font encoding is checked to see if
61 it matches one of the music font encodings. --pmccarty
63 SCM encoding
= ly_chain_assoc_get (ly_symbol2scm ("font-encoding"),
66 SCM music_encodings
= ly_lily_module_constant ("all-music-font-encodings");
68 if (scm_memq (encoding
, music_encodings
) != SCM_BOOL_F
)
69 return fm
->word_stencil (str
, true).smobbed_copy ();
71 return fm
->word_stencil (str
, false).smobbed_copy ();
74 MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Text_interface
, interpret_markup
, 3, 0,
75 "Convert a text markup into a stencil."
76 " Takes three arguments, @var{layout}, @var{props}, and @var{markup}.\n"
78 "@var{layout} is a @code{\\layout} block; it may be obtained from a grob with"
79 " @code{ly:grob-layout}. @var{props} is an alist chain, i.e. a list of"
80 " alists. This is typically obtained with"
81 " @code{(ly:grob-alist-chain grob (ly:output-def-lookup layout 'text-font-defaults))}."
82 " @var{markup} is the markup text to be processed.");
84 Text_interface::interpret_markup (SCM layout_smob
, SCM props
, SCM markup
)
86 if (scm_is_string (markup
))
87 return interpret_string (layout_smob
, props
, markup
);
88 else if (scm_is_pair (markup
))
90 SCM func
= scm_car (markup
);
91 SCM args
= scm_cdr (markup
);
92 if (!is_markup (markup
))
93 programming_error ("markup head has no markup signature");
95 return scm_apply_2 (func
, layout_smob
, props
, args
);
99 programming_error ("Object is not a markup. ");
100 scm_puts ("This object should be a markup: ", scm_current_error_port ());
101 scm_display (markup
, scm_current_error_port ());
102 scm_puts ("\n", scm_current_error_port ());
105 b
[X_AXIS
].set_empty ();
106 b
[Y_AXIS
].set_empty ();
108 Stencil
s (b
, SCM_EOL
);
109 return s
.smobbed_copy ();
113 MAKE_SCHEME_CALLBACK (Text_interface
, print
, 1);
115 Text_interface::print (SCM grob
)
117 Grob
*me
= unsmob_grob (grob
);
119 SCM t
= me
->get_property ("text");
120 SCM chain
= Font_interface::text_font_alist_chain (me
);
121 return interpret_markup (me
->layout ()->self_scm (), chain
, t
);
124 /* Ugh. Duplicated from Scheme. */
126 Text_interface::is_markup (SCM x
)
128 return (scm_is_string (x
)
131 != scm_object_property (scm_car (x
),
132 ly_symbol2scm ("markup-signature"))));
136 Text_interface::is_markup_list (SCM x
)
138 SCM music_list_p
= ly_lily_module_constant ("markup-list?");
139 return scm_is_true (scm_call_1 (music_list_p
, x
));
143 ADD_INTERFACE (Text_interface
,
144 "A Scheme markup text, see @ruser{Formatting text} and"
145 " @rextend{New markup command definition}.\n"
147 "There are two important commands:"
148 " @code{ly:text-interface::print}, which is a"
149 " grob callback, and"
150 " @code{ly:text-interface::interpret-markup}.",