diff options
-rw-r--r-- | input/regression/stencil-scale.ly | 23 | ||||
-rw-r--r-- | lily/include/stencil.hh | 1 | ||||
-rw-r--r-- | lily/stencil-interpret.cc | 16 | ||||
-rw-r--r-- | lily/stencil-scheme.cc | 17 | ||||
-rw-r--r-- | lily/stencil.cc | 11 | ||||
-rw-r--r-- | scm/define-markup-commands.scm | 30 | ||||
-rw-r--r-- | scm/define-stencil-commands.scm | 5 | ||||
-rw-r--r-- | scm/output-ps.scm | 7 | ||||
-rw-r--r-- | scm/output-svg.scm | 7 |
9 files changed, 115 insertions, 2 deletions
diff --git a/input/regression/stencil-scale.ly b/input/regression/stencil-scale.ly new file mode 100644 index 0000000000..03cfd2e19c --- /dev/null +++ b/input/regression/stencil-scale.ly @@ -0,0 +1,23 @@ +\version "2.13.38" + +\header { + texidoc = "Stencils can be scaled using @code{ly:stencil-scale}. +Negative values will flip or mirror the stencil without changing its origin; this +may result in collisions unless the scaled stencil is realigned (e.g., the time +signature in this test)." +} + +\relative c' { + \override Staff.Clef #'stencil = + #(lambda (grob) + (ly:stencil-scale (ly:clef::print grob) 1 -1)) + \override Staff.TimeSignature #'stencil = + #(lambda (grob) + (ly:stencil-aligned-to + (ly:stencil-scale (ly:time-signature::print grob) -2 1) + X LEFT)) + \override MultiMeasureRestText #'stencil = + #(lambda (grob) + (ly:stencil-scale (ly:text-interface::print grob) 2 1.6)) + R1\fermataMarkup +} diff --git a/lily/include/stencil.hh b/lily/include/stencil.hh index fe13d583e4..ed0a5c96c9 100644 --- a/lily/include/stencil.hh +++ b/lily/include/stencil.hh @@ -79,6 +79,7 @@ public: void rotate_degrees_absolute (Real, Offset); void align_to (Axis a, Real x); void translate_axis (Real, Axis); + void scale (Real, Real); Interval extent (Axis) const; Box extent_box () const; diff --git a/lily/stencil-interpret.cc b/lily/stencil-interpret.cc index 509c89aba4..6985f2bbf0 100644 --- a/lily/stencil-interpret.cc +++ b/lily/stencil-interpret.cc @@ -88,6 +88,22 @@ interpret_stencil_expression (SCM expr, return; } + else if (head == ly_symbol2scm ("scale-stencil")) + { + SCM args = scm_cadr (expr); + SCM x_scale = scm_car (args); + SCM y_scale = scm_cadr (args); + Offset unscaled = o.scale (Offset (1 / scm_to_double (x_scale), + 1 / scm_to_double (y_scale))); + + (*func) (func_arg, scm_list_3 (ly_symbol2scm ("setscale"), x_scale, + y_scale)); + interpret_stencil_expression (scm_caddr (expr), func, func_arg, + unscaled); + (*func) (func_arg, scm_list_1 (ly_symbol2scm ("resetscale"))); + + return; + } else { (*func) (func_arg, diff --git a/lily/stencil-scheme.cc b/lily/stencil-scheme.cc index f6ac03b3c2..5c859251ef 100644 --- a/lily/stencil-scheme.cc +++ b/lily/stencil-scheme.cc @@ -390,3 +390,20 @@ LY_DEFINE (ly_all_stencil_expressions, "ly:all-stencil-expressions", { return all_stencil_heads (); } + +LY_DEFINE (ly_stencil_scale, "ly:stencil-scale", + 3, 0, 0, (SCM stil, SCM x, SCM y), + "Scale @var{stil} using the horizontal and vertical scaling" + " factors @var{x} and @var{y}.") +{ + Stencil *s = unsmob_stencil (stil); + LY_ASSERT_SMOB (Stencil, stil, 1); + LY_ASSERT_TYPE (scm_is_number, x, 2); + LY_ASSERT_TYPE (scm_is_number, y, 3); + + SCM new_s = s->smobbed_copy (); + Stencil *q = unsmob_stencil (new_s); + + q->scale (scm_to_double (x), scm_to_double (y)); + return new_s; +} diff --git a/lily/stencil.cc b/lily/stencil.cc index 74af9a0ab4..02f7f89b12 100644 --- a/lily/stencil.cc +++ b/lily/stencil.cc @@ -189,6 +189,17 @@ Stencil::translate_axis (Real x, Axis a) } void +Stencil::scale (Real x, Real y) +{ + expr_ = scm_list_3 (ly_symbol2scm ("scale-stencil"), + scm_list_2 (scm_from_double (x), + scm_from_double (y)), + expr_); + dim_[X_AXIS] *= x; + dim_[Y_AXIS] *= y; +} + +void Stencil::add_stencil (Stencil const &s) { expr_ = scm_list_3 (ly_symbol2scm ("combine-stencil"), s.expr_, expr_); diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm index d6c992e537..9f86121e16 100644 --- a/scm/define-markup-commands.scm +++ b/scm/define-markup-commands.scm @@ -3368,6 +3368,36 @@ when @var{label} is not found." y-ext))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; scaling +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-markup-command (scale layout props factor-pair arg) + (number-pair? markup?) + #:category graphic + " +@cindex scaling markup +@cindex mirroring markup + +Scale @var{arg}. @var{factor-pair} is a pair of numbers +representing the scaling-factor in the X and Y axes. +Negative values may be used to produce mirror images. + +@lilypond[verbatim,quote] +\\markup { + \\line { + \\scale #'(2 . 1) + stretched + \\scale #'(1 . -1) + mirrored + } +} +@end lilypond" + (let ((stil (interpret-markup layout props arg)) + (sx (car factor-pair)) + (sy (cdr factor-pair))) + (ly:stencil-scale stil sx sy))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Markup list commands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/scm/define-stencil-commands.scm b/scm/define-stencil-commands.scm index 07f3463828..bbb2ac2a9f 100644 --- a/scm/define-stencil-commands.scm +++ b/scm/define-stencil-commands.scm @@ -46,15 +46,15 @@ defined in the output modules (output-*.scm)" repeat-slash resetcolor resetrotation + resetscale round-filled-box setcolor setrotation + setscale text unknown url-link utf-8-string - white-dot - white-text zigzag-line )) @@ -68,6 +68,7 @@ are used internally in lily/stencil-interpret.cc." combine-stencil delay-stencil-evaluation rotate-stencil + scale-stencil translate-stencil )) diff --git a/scm/output-ps.scm b/scm/output-ps.scm index 723a616369..ac7cc53d44 100644 --- a/scm/output-ps.scm +++ b/scm/output-ps.scm @@ -303,3 +303,10 @@ thickness (convert-path-exps exps) (if fill? "fill" "")))) + +(define (setscale x y) + (ly:format "gsave ~4l scale\n" + (list x y))) + +(define (resetscale) + "grestore\n") diff --git a/scm/output-svg.scm b/scm/output-svg.scm index 2388195528..9b1b250f77 100644 --- a/scm/output-svg.scm +++ b/scm/output-svg.scm @@ -615,6 +615,9 @@ (define (resetrotation ang x y) "</g>\n") +(define (resetscale) + "</g>\n") + (define (round-filled-box breapth width depth height blot-diameter) (entity 'rect "" @@ -642,6 +645,10 @@ (ly:format "<g transform=\"rotate(~4f, ~4f, ~4f)\">\n" (- ang) x (- y))) +(define (setscale x y) + (ly:format "<g transform=\"scale(~4f, ~4f)\">\n" + x y)) + (define (text font string) (dispatch `(fontify ,font ,(entity 'tspan (string->entities string))))) |