From 68d7330f72a14a8df49c49ed1566179248096092 Mon Sep 17 00:00:00 2001 From: Erlend Aasland Date: Sun, 14 May 2006 14:06:37 +0000 Subject: [PATCH] Add rotation support --- ChangeLog | 21 +++++++++++++++++ lily/grob.cc | 10 ++++++++ lily/include/stencil.hh | 1 + lily/stencil-interpret.cc | 16 +++++++++++++ lily/stencil-scheme.cc | 19 +++++++++++++++ lily/stencil.cc | 38 ++++++++++++++++++++++++++++++ scm/define-grob-properties.scm | 2 ++ scm/define-markup-commands.scm | 6 +++++ scm/output-ps.scm | 43 +++++++++++++++++++++++----------- scm/output-svg.scm | 10 ++++++++ 10 files changed, 152 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4995fda109..e77cf7e79f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2006-05-14 Erlend Aasland + + * lily/include/stencil.hh + * lily/stencil.cc (rotation): new function. Makes it possible + to rotate a stencil around a given offset. + + * lily/grob.cc (get_print_stencil): add rotation support + + * lily/stencil-interpret.cc (interpret_stencil_expression): + add rotation support + + * lily/stencil-scheme.cc (ly:stencil-rotate): new function + + * scm/define-grob-properties.scm: add 'rotation property + + * scm/define-markup-commands.scm: add rotate markup command + + * scm/output-ps.scm: add rotation support in PostScript backend + + * scm/output-svg.scm: add rotation support in SVG backend + 2006-05-13 Graham Percival * Documentation/user/music-glossary.itely: French correction. diff --git a/lily/grob.cc b/lily/grob.cc index fc49f16d4d..d66bc37208 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -120,6 +120,15 @@ Grob::get_print_stencil () const retval = Stencil (m->extent_box (), expr); } + SCM rot = get_property ("rotation"); + if (rot != SCM_EOL) + { + Real angle = scm_to_double (scm_car (rot)); + Real x = scm_to_double (scm_cadr (rot)); + Real y = scm_to_double (scm_caddr (rot)); + + retval.rotate (angle, Offset (x, y)); + } /* color support... see interpret_stencil_expression () for more... */ SCM color = get_property ("color"); @@ -522,6 +531,7 @@ ADD_INTERFACE (Grob, "grob-interface", "meta " "minimum-X-extent " "minimum-Y-extent " + "rotation " "springs-and-rods " "staff-symbol " "stencil " diff --git a/lily/include/stencil.hh b/lily/include/stencil.hh index 0c9979d327..2211b8c661 100644 --- a/lily/include/stencil.hh +++ b/lily/include/stencil.hh @@ -73,6 +73,7 @@ public: Real minimum); void add_stencil (Stencil const &m); void translate (Offset); + void rotate (Real, Offset); void align_to (Axis a, Real x); void translate_axis (Real, Axis); diff --git a/lily/stencil-interpret.cc b/lily/stencil-interpret.cc index 52e9242d0b..e438734536 100644 --- a/lily/stencil-interpret.cc +++ b/lily/stencil-interpret.cc @@ -54,6 +54,22 @@ interpret_stencil_expression (SCM expr, interpret_stencil_expression (scm_caddr (expr), func, func_arg, o); (*func) (func_arg, scm_list_1 (ly_symbol2scm ("resetcolor"))); + return; + } + else if (head == ly_symbol2scm ("rotate-stencil")) + { + SCM args = scm_cadr (expr); + SCM angle = scm_car (args); + Offset tmp = o + robust_scm2offset (scm_cadr (args), Offset (0.0, 0.0)); + + SCM offset = ly_offset2scm (tmp); + SCM x = scm_car (offset); + SCM y = scm_cdr (offset); + + (*func) (func_arg, scm_list_4 (ly_symbol2scm ("setrotation"), angle, x, y)); + interpret_stencil_expression (scm_caddr (expr), func, func_arg, o); + (*func) (func_arg, scm_list_4 (ly_symbol2scm ("resetrotation"), angle, x, y)); + return; } else diff --git a/lily/stencil-scheme.cc b/lily/stencil-scheme.cc index 2619ffd25e..66f1825931 100644 --- a/lily/stencil-scheme.cc +++ b/lily/stencil-scheme.cc @@ -319,6 +319,25 @@ LY_DEFINE (ly_bracket, "ly:bracket", 0.95 * scm_to_double (t)).smobbed_copy (); } +LY_DEFINE (ly_rotate_stencil, "ly:stencil-rotate", + 4, 0, 0, (SCM stil, SCM angle, SCM x, SCM y), + "Return a @var{stil} rotated @var{angle} degrees around point (@var{x}, @var{y}).") +{ + Stencil *s = unsmob_stencil (stil); + SCM_ASSERT_TYPE (s, stil, SCM_ARG1, __FUNCTION__, "stencil"); + SCM_ASSERT_TYPE (scm_is_number (angle), angle, SCM_ARG2, __FUNCTION__, "number"); + SCM_ASSERT_TYPE (scm_is_number (x), x, SCM_ARG3, __FUNCTION__, "number"); + SCM_ASSERT_TYPE (scm_is_number (y), y, SCM_ARG4, __FUNCTION__, "number"); + Real a = scm_to_double (angle); + Real x_off = scm_to_double (x); + Real y_off = scm_to_double (y); + + SCM new_s = s->smobbed_copy (); + Stencil *q = unsmob_stencil (new_s); + q->rotate (a, Offset (x_off, y_off)); + return new_s; +} + LY_DEFINE (ly_filled_box, "ly:round-filled-box", 3, 0, 0, (SCM xext, SCM yext, SCM blot), diff --git a/lily/stencil.cc b/lily/stencil.cc index 2fad44274d..dd3bb2626e 100644 --- a/lily/stencil.cc +++ b/lily/stencil.cc @@ -78,6 +78,44 @@ Stencil::origin () const return origin_; } +/* + * Rotate this stencil around the point [x, y] + */ +void +Stencil::rotate (Real a, Offset off) +{ + const Real x_cen = extent (X_AXIS).center (); + const Real y_cen = extent (Y_AXIS).center (); + + /* + * Calculate the center of rotation + */ + const Real x = x_cen + off[X_AXIS] * x_cen; + const Real y = y_cen + off[Y_AXIS] * y_cen; + + /* + * Build scheme expression (processed in stencil-interpret.cc) + */ + expr_ = scm_list_n (ly_symbol2scm ("rotate-stencil"), + scm_list_2 (scm_from_double (a), + scm_cons (scm_from_double (x), scm_from_double (y))), + expr_, SCM_UNDEFINED); + + /* + * Calculate the new bounding box + */ + vector pts; + pts.push_back (Offset (-x_cen, -y_cen)); + pts.push_back (Offset (x_cen, -y_cen)); + pts.push_back (Offset (x_cen, y_cen)); + pts.push_back (Offset (-x_cen, y_cen)); + + const Offset rot = complex_exp (Offset (0, a * M_PI / 180.0)); + dim_.set_empty (); + for (vsize i = 0; i < pts.size (); i++) + dim_.add_point (pts[i] * rot + Offset (x_cen, y_cen)); +} + void Stencil::translate (Offset o) { diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index ba1def6f73..d59d4661c9 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -352,6 +352,8 @@ quicker the slur attains it @code{height-limit}.") (remove-first ,boolean? "Remove the first staff of a orchestral score?") (right-padding ,ly:dimension? "Space to insert between note and accidentals.") + (rotation ,list? "Number of degrees to rotate this object, and what point +to rotate around. #'(45 0 0) means rotate 45 degrees around the center of this object.") (same-direction-correction ,number? "Optical correction amount for stems that are placed in tight configurations. This amount is used for stems with the same direction to compensate for note-head to stem distance.") diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm index 8512d6d257..5eea907169 100644 --- a/scm/define-markup-commands.scm +++ b/scm/define-markup-commands.scm @@ -118,6 +118,12 @@ circle of diameter 0 (ie sharp corners)." (ly:round-filled-box xext yext blot)) +(define-markup-command (rotate layout props ang arg) (number? markup?) + "Rotate object with @var{ang} degrees around its center." + (let* ((stil (interpret-markup layout props arg))) + (ly:stencil-rotate stil ang 0 0))) + + (define-markup-command (whiteout layout props arg) (markup?) "Provide a white underground for @var{arg}" (let* ((stil (interpret-markup layout props diff --git a/scm/output-ps.scm b/scm/output-ps.scm index 2303bf2d02..d7c55df028 100644 --- a/scm/output-ps.scm +++ b/scm/output-ps.scm @@ -18,26 +18,27 @@ ;; JUNK this -- see lily.scm: ly:all-output-backend-commands #:export (unknown - blank + bezier-sandwich + char circle - dot + comment + dashed-line dashed-slur - char - setcolor - resetcolor + dot + draw-line + embedded-ps named-glyph - dashed-line - zigzag-line - comment - repeat-slash + no-origin placebox - bezier-sandwich - embedded-ps + polygon + repeat-slash + resetcolor + resetrotatino round-filled-box + setcolor + setrotation text - polygon - draw-line - no-origin)) + zigzag-line)) (use-modules (guile) @@ -247,6 +248,13 @@ ;; restore color from stack (define (resetcolor) "setrgbcolor\n") +;; reset rotation +(define (resetrotation ang x y) + (format "~a translate ~a rotate ~a translate\n" + (numbers->string4 (list x y)) + (number->string (* -1 ang)) + (numbers->string4 (list (* -1 x) (* -1 y))))) + (define (round-filled-box left right bottom top blotdiam) (let* ((halfblot (/ blotdiam 2)) (x (- halfblot left)) @@ -262,6 +270,13 @@ (format #f "currentrgbcolor ~a setrgbcolor\n" (numbers->string4 (list r g b)))) +;; rotation around given point +(define (setrotation ang x y) + (format "~a translate ~a rotate ~a translate\n" + (numbers->string4 (list x y)) + (number->string ang) + (numbers->string4 (list (* -1 x) (* -1 y))))) + (define (text font s) ;; (ly:warning (_ "TEXT backend-command encountered in Pango backend")) ;; (ly:warning (_ "Arguments: ~a ~a"" font str)) diff --git a/scm/output-svg.scm b/scm/output-svg.scm index fbf458a7a4..786a37ca17 100644 --- a/scm/output-svg.scm +++ b/scm/output-svg.scm @@ -250,6 +250,16 @@ (map offset->point (ly:list->offsets '() coords)))) )) +;; rotate around given point +(define (setrotation ang x y) + (format "" + (number->string (* -1 ang)) + (number->string x) + (number->string (* -1 y)))) + +(define (resetrotation ang x y) + "") + (define (round-filled-box breapth width depth height blot-diameter) (entity 'rect "" ;; The stroke will stick out. To use stroke, -- 2.39.5