From 8cf69a467ad7650f5ca9da6fe2dfd4c7c088b239 Mon Sep 17 00:00:00 2001 From: Jay Anderson Date: Sat, 30 Jan 2016 22:45:32 -0700 Subject: [PATCH] Issue 1388: Initial work to support opentype font features. --- configure.ac | 2 +- input/regression/font-features.ly | 22 ++++++++++++++++ lily/font-interface.cc | 1 + lily/font-metric.cc | 4 ++- lily/include/font-metric.hh | 4 ++- lily/include/modified-font-metric.hh | 2 +- lily/include/pango-font.hh | 4 ++- lily/modified-font-metric.cc | 8 +++--- lily/pango-font.cc | 14 +++++++++- lily/text-interface.cc | 38 +++++++++++++++++++++++++++- scm/define-grob-properties.scm | 1 + 11 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 input/regression/font-features.ly diff --git a/configure.ac b/configure.ac index 8f2f61abf8..d2ec5ec956 100644 --- a/configure.ac +++ b/configure.ac @@ -260,7 +260,7 @@ AC_MSG_RESULT($rpath_b) HOST_ARCH=`$CC -dumpmachine` AC_SUBST(HOST_ARCH) -STEPMAKE_PANGO_FT2(pangoft2, REQUIRED, 1.6.0) +STEPMAKE_PANGO_FT2(pangoft2, REQUIRED, 1.38.0) STEPMAKE_FONTCONFIG(fontconfig, REQUIRED, 2.4.0) STEPMAKE_FREETYPE2(freetype2, REQUIRED, 2.1.10) diff --git a/input/regression/font-features.ly b/input/regression/font-features.ly new file mode 100644 index 0000000000..ed01c1fbb0 --- /dev/null +++ b/input/regression/font-features.ly @@ -0,0 +1,22 @@ +\version "2.19.60" + +\header +{ + texidoc = "Exercise font features. Requires a font that supports the + features. This ensures no errors using the interface." +} + +% Comparison between caps styles +\markup { Hello } +\markup { HELLO } +\markup { \caps Hello } +\markup { \fontCaps Hello } +% True small caps +\markup { \override #'(font-features . ("smcp")) Hello } + +% Comparison between number styles +\markup { 0123456789 } +\markup { \override #'(font-features . ("onum")) 0123456789 } + +% Multiple features +\markup { \override #'(font-features . ("onum" "smcp")) { Hello 0123456789 } } diff --git a/lily/font-interface.cc b/lily/font-interface.cc index de787fd852..5e5f18ceb3 100644 --- a/lily/font-interface.cc +++ b/lily/font-interface.cc @@ -72,4 +72,5 @@ ADD_INTERFACE (Font_interface, "font-series " "font-shape " "font-size " + "font-features " ); diff --git a/lily/font-metric.cc b/lily/font-metric.cc index c9daa95f3e..77f02df579 100644 --- a/lily/font-metric.cc +++ b/lily/font-metric.cc @@ -147,7 +147,9 @@ Font_metric::sub_fonts () const Stencil Font_metric::text_stencil (Output_def *state, - const string&, bool) const + const string&, + bool, + const string&) const { (void) state; diff --git a/lily/include/font-metric.hh b/lily/include/font-metric.hh index 7a388f86f3..429801db55 100644 --- a/lily/include/font-metric.hh +++ b/lily/include/font-metric.hh @@ -47,7 +47,9 @@ public: // Return stencil for given string. output_state may be modified to // record the font. virtual Stencil text_stencil (Output_def *output_state, - const string &text, bool music) const; + const string &text, + bool music, + const string &features_str) const; virtual string font_name () const; virtual size_t count () const; diff --git a/lily/include/modified-font-metric.hh b/lily/include/modified-font-metric.hh index 0f4223d4ba..7001680863 100644 --- a/lily/include/modified-font-metric.hh +++ b/lily/include/modified-font-metric.hh @@ -33,7 +33,7 @@ class Modified_font_metric : Preinit_Modified_font_metric, public Font_metric { public: - Stencil text_stencil (Output_def *output_state, const string&, bool) const; + Stencil text_stencil (Output_def *output_state, const string&, bool, const string&) const; Real get_magnification () const; static SCM make_scaled_font_metric (Font_metric *fm, Real magnification); diff --git a/lily/include/pango-font.hh b/lily/include/pango-font.hh index aaae077b76..5e804f7a8f 100644 --- a/lily/include/pango-font.hh +++ b/lily/include/pango-font.hh @@ -63,7 +63,9 @@ public: Stencil pango_item_string_stencil (PangoGlyphItem const *) const; virtual Stencil text_stencil (Output_def *output_state, - const string &text, bool music) const; + const string &text, + bool music, + const string &features_str) const; virtual void derived_mark () const; }; diff --git a/lily/modified-font-metric.cc b/lily/modified-font-metric.cc index d68db92c4b..a3beb4daef 100644 --- a/lily/modified-font-metric.cc +++ b/lily/modified-font-metric.cc @@ -113,12 +113,14 @@ Modified_font_metric::derived_mark () const Stencil Modified_font_metric::text_stencil (Output_def *state, - const string &text, bool feta) const + const string &text, + bool feta, + const string &features_str) const { Box b; if (Pango_font *pf = dynamic_cast (orig_)) { - Stencil stc = pf->text_stencil (state, text, feta); + Stencil stc = pf->text_stencil (state, text, feta, features_str); Box b = stc.extent_box (); @@ -127,7 +129,7 @@ Modified_font_metric::text_stencil (Output_def *state, return scaled; } - return Font_metric::text_stencil (state, text, feta); + return Font_metric::text_stencil (state, text, feta, features_str); } Font_metric * diff --git a/lily/pango-font.cc b/lily/pango-font.cc index 9fe6b78cb0..024d7b1d57 100644 --- a/lily/pango-font.cc +++ b/lily/pango-font.cc @@ -387,7 +387,9 @@ extern bool music_strings_to_paths; Stencil Pango_font::text_stencil (Output_def * /* state */, - const string &str, bool music_string) const + const string &str, + bool music_string, + const string &features_str) const { /* The text assigned to a PangoLayout is automatically divided @@ -395,6 +397,16 @@ Pango_font::text_stencil (Output_def * /* state */, Bidirectional Algorithm, if necessary. */ PangoLayout *layout = pango_layout_new (context_); + + if (!features_str.empty()) + { + PangoAttrList *list = pango_attr_list_new(); + PangoAttribute *features_attr = pango_attr_font_features_new(features_str.c_str()); + pango_attr_list_insert(list, features_attr); + pango_layout_set_attributes(layout, list); + pango_attr_list_unref(list); + } + pango_layout_set_text (layout, str.c_str (), -1); GSList *lines = pango_layout_get_lines (layout); diff --git a/lily/text-interface.cc b/lily/text-interface.cc index d930cdaa37..bad6d50281 100644 --- a/lily/text-interface.cc +++ b/lily/text-interface.cc @@ -92,8 +92,44 @@ Text_interface::interpret_string (SCM layout_smob, SCM_BOOL_F); SCM music_encodings = Lily::all_music_font_encodings; + 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).smobbed_copy (); + return fm->text_stencil (layout, str, is_music, features_str).smobbed_copy (); } static size_t markup_depth = 0; diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index fbcaa2b4bb..0acc741f1c 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -327,6 +327,7 @@ approximately 12% larger; 6@tie{}steps are exactly a factor@tie{}2 larger. If the context property @code{fontSize} is set, its value is added to this before the glyph is printed. Fractional values are allowed.") + (font-features ,list? "Opentype features.") (footnote ,boolean? "Should this be a footnote or in-note?") (footnote-music ,ly:music? "Music creating a footnote.") (footnote-text ,markup? "A footnote for the grob.") -- 2.39.2