X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Ftext-interface.cc;h=bad6d50281f626ccce966a8e15200b9a4f80ea8d;hb=8cf69a467ad7650f5ca9da6fe2dfd4c7c088b239;hp=936a7488e2810a001e42c8b87896e35c1a12f202;hpb=12e6948fe2fa0c73103748fd815a7c93fdc3677e;p=lilypond.git diff --git a/lily/text-interface.cc b/lily/text-interface.cc index 936a7488e2..bad6d50281 100644 --- a/lily/text-interface.cc +++ b/lily/text-interface.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1998--2012 Han-Wen Nienhuys + Copyright (C) 1998--2015 Han-Wen Nienhuys Jan Nieuwenhuizen LilyPond is free software: you can redistribute it and/or modify @@ -33,6 +33,7 @@ #include "program-option.hh" #include "international.hh" #include "warn.hh" +#include "lily-imports.hh" static void replace_special_characters (string &str, SCM props) @@ -76,7 +77,7 @@ Text_interface::interpret_string (SCM layout_smob, LY_ASSERT_TYPE (scm_is_string, markup, 3); string str = ly_scm2string (markup); - Output_def *layout = unsmob_output_def (layout_smob); + Output_def *layout = unsmob (layout_smob); Font_metric *fm = select_encoded_font (layout, props); replace_special_characters (str, props); @@ -89,12 +90,53 @@ Text_interface::interpret_string (SCM layout_smob, SCM encoding = ly_chain_assoc_get (ly_symbol2scm ("font-encoding"), props, SCM_BOOL_F); - SCM music_encodings = ly_lily_module_constant ("all-music-font-encodings"); + SCM music_encodings = Lily::all_music_font_encodings; - bool is_music = (scm_memq (encoding, music_encodings) != SCM_BOOL_F); - return fm->text_stencil (layout, str, is_music).smobbed_copy (); + SCM features = ly_chain_assoc_get (ly_symbol2scm ("font-features"), + props, + SCM_BOOL_F); + + // The font-features value is stored in a scheme list. This joins the entries + // with commas for processing with pango. + string features_str = string (); + if (scm_is_pair (features)) + { + bool first = true; + for (SCM s = features; scm_is_pair (s); s = scm_cdr (s)) + { + SCM feature = scm_car (s); + if (scm_is_string (feature)) + { + if (first) + { + first = false; + } + else + { + features_str += ","; + } + features_str += ly_scm2string (feature); + } + else + { + scm_misc_error (__FUNCTION__, "Found non-string in font-features list", SCM_EOL); + } + } + } + else if (!scm_is_false (features)) + { + scm_misc_error (__FUNCTION__, "Expecting a list for font-features value", SCM_EOL); + } + + bool is_music = scm_is_true (scm_memq (encoding, music_encodings)); + return fm->text_stencil (layout, str, is_music, features_str).smobbed_copy (); } +static size_t markup_depth = 0; + +void markup_up_depth (void *) { ++markup_depth; } +void markup_down_depth (void *) { --markup_depth; } + MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Text_interface, interpret_markup, 3, 0, "Convert a text markup into a stencil." " Takes three arguments, @var{layout}, @var{props}, and @var{markup}.\n" @@ -114,29 +156,21 @@ Text_interface::interpret_markup (SCM layout_smob, SCM props, SCM markup) SCM func = scm_car (markup); SCM args = scm_cdr (markup); - /* Use a hare/tortoise algorithm to detect whether we are in a cycle, - * i.e. whether we have already encountered the same markup in the - * current branch of the markup tree structure. */ - static vector encountered_markups; - size_t depth = encountered_markups.size (); - if (depth > 0) - { - int slow = depth / 2; - if (ly_is_equal (encountered_markups[slow], markup)) - { - string name = ly_symbol2string (scm_procedure_name (func)); - // TODO: Also print the arguments of the markup! - non_fatal_error (_f ("Cyclic markup detected: %s", name)); - return Stencil ().smobbed_copy (); - } - } - /* Check for non-terminating markups, e.g. recursive calls with * changing arguments */ SCM opt_depth = ly_get_option (ly_symbol2scm ("max-markup-depth")); size_t max_depth = robust_scm2int (opt_depth, 1024); - if (depth > max_depth) + + // Don't use SCM_F_DYNWIND_REWINDABLE since it may be expensive + // without any obvious use for retaining continuations into + // markup expansion + scm_dynwind_begin ((scm_t_dynwind_flags)0); + // scm_dynwind_rewind_handler (markup_up_depth, 0, SCM_F_WIND_EXPLICITLY); + markup_up_depth (0); + scm_dynwind_unwind_handler (markup_down_depth, 0, SCM_F_WIND_EXPLICITLY); + if (markup_depth > max_depth) { + scm_dynwind_end (); string name = ly_symbol2string (scm_procedure_name (func)); // TODO: Also print the arguments of the markup! non_fatal_error (_f ("Markup depth exceeds maximal value of %d; " @@ -144,9 +178,8 @@ Text_interface::interpret_markup (SCM layout_smob, SCM props, SCM markup) return Stencil ().smobbed_copy (); } - encountered_markups.push_back (markup); SCM retval = scm_apply_2 (func, layout_smob, props, args); - encountered_markups.pop_back (); + scm_dynwind_end (); return retval; } else @@ -164,7 +197,7 @@ MAKE_SCHEME_CALLBACK (Text_interface, print, 1); SCM Text_interface::print (SCM grob) { - Grob *me = unsmob_grob (grob); + Grob *me = unsmob (grob); SCM t = me->get_property ("text"); SCM chain = Font_interface::text_font_alist_chain (me); @@ -188,8 +221,7 @@ Text_interface::is_markup (SCM x) bool Text_interface::is_markup_list (SCM x) { - SCM music_list_p = ly_lily_module_constant ("markup-list?"); - return scm_is_true (scm_call_1 (music_list_p, x)); + return scm_is_true (Lily::markup_list_p (x)); } ADD_INTERFACE (Text_interface,