From dc1af73a4a34799c3e5492b32d0ea148a856b5bf Mon Sep 17 00:00:00 2001 From: Neil Puttock Date: Sat, 1 Aug 2009 00:06:45 +0100 Subject: [PATCH] New markup commands \left-brace and \right-brace. * add a binary search function to lily-library.scm * add markup command \left-brace, using binary search to select a fetaBraces glyph based on y-extent comparison with scaled point size * add markup command \right-brace: a \left-brace rotate 180 degrees * add exported function ly:otf-glyph-count and use in \left-brace to remove hard-coded value for upper range in binary search * fix potential null dereference in ly:otf-font-glyph-info * add regression tests for exercising new commands and invalid point sizes --- input/regression/markup-brace-warning.ly | 17 +++++++ input/regression/markup-braces.ly | 15 ++++++ lily/open-type-font-scheme.cc | 43 ++++++++++++------ scm/define-markup-commands.scm | 58 ++++++++++++++++++++++++ scm/lily-library.scm | 17 ++++++- 5 files changed, 136 insertions(+), 14 deletions(-) create mode 100644 input/regression/markup-brace-warning.ly create mode 100644 input/regression/markup-braces.ly diff --git a/input/regression/markup-brace-warning.ly b/input/regression/markup-brace-warning.ly new file mode 100644 index 0000000000..2646a798ae --- /dev/null +++ b/input/regression/markup-brace-warning.ly @@ -0,0 +1,17 @@ +\version "2.13.4" + +#(ly:set-option 'warning-as-error #f) + +\header { + texidoc = "If @code{\\left-brace} or @code{\\right-brace} cannot +find a match for the given point size, it should default +gracefully to either @code{brace0} or @code{brace575} and display +a warning. +" +} + +\markup { + % warning message expected; should default to 10.5 pt for + % global-staff-size = 20 + \left-brace #10 +} diff --git a/input/regression/markup-braces.ly b/input/regression/markup-braces.ly new file mode 100644 index 0000000000..2ef0406a06 --- /dev/null +++ b/input/regression/markup-braces.ly @@ -0,0 +1,15 @@ +\version "2.13.4" + +\header { + texidoc = "The markup command @code{\\left-brace} selects a +@code{fetaBraces} glyph based on point size, using a binary search. +@code{\\right-brace} is simply a @code{\\left-brace} rotated 180 +degrees. +" +} + +\markup { + \left-brace #30 + \hspace #2 + \right-brace #40 +} diff --git a/lily/open-type-font-scheme.cc b/lily/open-type-font-scheme.cc index 2d33394fc8..3ce37b6ef7 100644 --- a/lily/open-type-font-scheme.cc +++ b/lily/open-type-font-scheme.cc @@ -15,6 +15,7 @@ LY_DEFINE (ly_font_sub_fonts, "ly:font-sub-fonts", 1, 0, 0, " names of the subfonts within @var{font}.") { LY_ASSERT_SMOB (Font_metric, font, 1); + Font_metric *fm = unsmob_metrics (font); return fm->sub_fonts (); } @@ -26,9 +27,11 @@ LY_DEFINE (ly_otf_font_glyph_info, "ly:otf-font-glyph-info", 2, 0, 0, { Modified_font_metric *fm = dynamic_cast (unsmob_metrics (font)); - Open_type_font *otf = dynamic_cast (fm->original_font ()); + Open_type_font *otf = fm + ? dynamic_cast (fm->original_font ()) + : dynamic_cast (unsmob_metrics (font)); - SCM_ASSERT_TYPE (otf, font, SCM_ARG1, __FUNCTION__, "OTF font-metric"); + SCM_ASSERT_TYPE (otf, font, SCM_ARG1, __FUNCTION__, "OpenType font"); LY_ASSERT_TYPE (scm_is_string, glyph, 2); SCM sym = scm_string_to_symbol (glyph); @@ -42,11 +45,11 @@ LY_DEFINE (ly_otf_font_table_data, "ly:otf-font-table-data", 2, 0, 0, { Modified_font_metric *fm = dynamic_cast (unsmob_metrics (font)); - - Open_type_font *otf = fm ? dynamic_cast (fm->original_font ()) + Open_type_font *otf = fm + ? dynamic_cast (fm->original_font ()) : dynamic_cast (unsmob_metrics (font)); - SCM_ASSERT_TYPE (otf, font, SCM_ARG1, __FUNCTION__, "Open type font"); + SCM_ASSERT_TYPE (otf, font, SCM_ARG1, __FUNCTION__, "OpenType font"); LY_ASSERT_TYPE (scm_is_string, tag, 2); char ctag [5] = " "; @@ -65,25 +68,39 @@ LY_DEFINE (ly_otf_font_p, "ly:otf-font?", 1, 0, 0, { Modified_font_metric *fm = dynamic_cast (unsmob_metrics (font)); - - Open_type_font *otf = fm ? dynamic_cast (fm->original_font ()) + Open_type_font *otf = fm + ? dynamic_cast (fm->original_font ()) : dynamic_cast (unsmob_metrics (font)); return scm_from_bool (otf); } -LY_DEFINE (ly_otf_glyph_list, "ly:otf-glyph-list", - 1, 0, 0, (SCM font), - "Return a list of glyph names for @var{font}.") +LY_DEFINE (ly_otf_glyph_count, "ly:otf-glyph-count", 1, 0, 0, + (SCM font), + "Return the the number of glyphs in @var{font}.") { Modified_font_metric *fm = dynamic_cast (unsmob_metrics (font)); + Open_type_font *otf = fm + ? dynamic_cast (fm->original_font ()) + : dynamic_cast (unsmob_metrics (font)); + + SCM_ASSERT_TYPE (otf, font, SCM_ARG1, __FUNCTION__, "OpenType font"); - Open_type_font *otf = fm ? dynamic_cast (fm->original_font ()) + return scm_from_int ((int) otf->count ()); +} + +LY_DEFINE (ly_otf_glyph_list, "ly:otf-glyph-list", 1, 0, 0, + (SCM font), + "Return a list of glyph names for @var{font}.") +{ + Modified_font_metric *fm + = dynamic_cast (unsmob_metrics (font)); + Open_type_font *otf = fm + ? dynamic_cast (fm->original_font ()) : dynamic_cast (unsmob_metrics (font)); + SCM_ASSERT_TYPE (otf, font, SCM_ARG1, __FUNCTION__, "OpenType font"); - SCM_ASSERT_TYPE (otf, font, SCM_ARG1, __FUNCTION__, "OTF font"); return otf->glyph_list (); - } diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm index e953774466..4a91542260 100644 --- a/scm/define-markup-commands.scm +++ b/scm/define-markup-commands.scm @@ -2598,6 +2598,64 @@ figured bass notation. (make-with-dimensions-markup '(-0.55 . 2.9) '(0.4 . 2.4) (make-postscript-markup eyeglassesps)))) +(define-builtin-markup-command (left-brace layout props size) + (number?) + other + () + " +A feta brace in point size @var{size}. + +@lilypond[verbatim,quote] +\\markup { + \\left-brace #35 + \\hspace #2 + \\left-brace #45 +} +@end lilypond" + (let* ((font (ly:paper-get-font layout + (cons '((font-encoding . fetaBraces) + (font-name . #f)) + props))) + (glyph-count (1- (ly:otf-glyph-count font))) + (scale (ly:output-def-lookup layout 'output-scale)) + (scaled-size (/ (ly:pt size) scale)) + (glyph (lambda (n) + (ly:font-get-glyph font (string-append "brace" + (number->string n))))) + (get-y-from-brace (lambda (brace) + (interval-length + (ly:stencil-extent (glyph brace) Y)))) + (find-brace (binary-search 0 glyph-count get-y-from-brace scaled-size)) + (glyph-found (glyph find-brace))) + + (if (or (null? (ly:stencil-expr glyph-found)) + (< scaled-size (interval-length (ly:stencil-extent (glyph 0) Y))) + (> scaled-size (interval-length + (ly:stencil-extent (glyph glyph-count) Y)))) + (begin + (ly:warning (_ "no brace found for point size ~S ") size) + (ly:warning (_ "defaulting to ~S pt") + (/ (* scale (interval-length + (ly:stencil-extent glyph-found Y))) + (ly:pt 1))))) + glyph-found)) + +(define-builtin-markup-command (right-brace layout props size) + (number?) + other + () + " +A feta brace in point size @var{size}, rotated 180 degrees. + +@lilypond[verbatim,quote] +\\markup { + \\right-brace #45 + \\hspace #2 + \\right-brace #35 +} +@end lilypond" + (interpret-markup layout props (markup #:rotate 180 #:left-brace size))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; the note command. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/scm/lily-library.scm b/scm/lily-library.scm index d1cce2a84c..adb2bdfdc8 100644 --- a/scm/lily-library.scm +++ b/scm/lily-library.scm @@ -545,12 +545,27 @@ possibly turned off." (reverse matches)) ;;;;;;;;;;;;;;;; -; other +;; other + (define (sign x) (if (= x 0) 0 (if (< x 0) -1 1))) +(define-public (binary-search start end getter target-val) + (_i "Find the index between @var{start} and @var{end} (an integer) +which will produce the closest match to @var{target-val} when +applied to function @var{getter}.") + (if (<= end start) + start + (let* ((compare (quotient (+ start end) 2)) + (get-val (getter compare))) + (cond + ((< target-val get-val) + (set! end (1- compare))) + ((< get-val target-val) + (set! start (1+ compare)))) + (binary-search start end getter target-val)))) (define-public (car< a b) (< (car a) (car b))) -- 2.39.2