]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix ly:stencil-rotate; add function to rotate about absolute coordinate
authorReinhold Kainhofer <reinhold@kainhofer.com>
Tue, 9 Sep 2008 23:37:34 +0000 (01:37 +0200)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Thu, 11 Sep 2008 19:24:24 +0000 (21:24 +0200)
input/regression/flags-in-scheme.ly
lily/include/stencil.hh
lily/stencil-scheme.cc
lily/stencil.cc

index 0707f84258c89be783b5d98107a010848eb9008f..5d9238a1cedcf0282e56f39fa2fcddfdef917c91 100644 (file)
@@ -26,7 +26,7 @@ testnotes = { \autoBeamOff c'8 d'16 c'32 d'64 \acciaccatura {c'8} d'64 c''8 d''1
          (stroke-style (ly:grob-property stem-grob 'stroke-style))
          (stencil (if (null? stroke-style) flag
                          (add-stroke-glyph flag stem-grob dir stroke-style ""))))
-    (ly:stencil-rotate stencil 180 -1 -1)))
+    (ly:stencil-rotate-absolute stencil 180 0 0)))
 
 {
   \override Score.RehearsalMark #'self-alignment-X = #LEFT
index 820771ef7fe4d772ac072410b50d3bbe4f8e807e..63318a38b8fd7244381db95e028bf362638c4741 100644 (file)
@@ -65,6 +65,7 @@ public:
   Stencil translated (Offset) const;
   void rotate (Real, Offset);
   void rotate_degrees (Real, Offset);
+  void rotate_degrees_absolute (Real, Offset);
   void align_to (Axis a, Real x);
   void translate_axis (Real, Axis);
 
index 2e407b629ce17b73760121fb1cf6a1159185806a..de39fca5c340ca19e20cfaf14a41e9b4a0d12761 100644 (file)
@@ -288,7 +288,8 @@ LY_DEFINE (ly_bracket, "ly:bracket",
 LY_DEFINE (ly_stencil_rotate, "ly:stencil-rotate",
           4, 0, 0, (SCM stil, SCM angle, SCM x, SCM y),
           "Return a stencil @var{stil} rotated @var{angle} degrees around"
-          " point (@var{x}, @var{y}).")
+          " the relative offset (@var{x}, @var{y}). E.g. an offset of"
+          " (-1, 1) will rotate the stencil around the left upper corner.")
 {
   Stencil *s = unsmob_stencil (stil);
   LY_ASSERT_SMOB (Stencil, stil, 1);
@@ -305,6 +306,26 @@ LY_DEFINE (ly_stencil_rotate, "ly:stencil-rotate",
   return new_s;
 }
 
+LY_DEFINE (ly_stencil_rotate_absolute, "ly:stencil-rotate-absolute",
+          4, 0, 0, (SCM stil, SCM angle, SCM x, SCM y),
+          "Return a stencil @var{stil} rotated @var{angle} degrees around"
+          " point (@var{x}, @var{y}), given in absolute coordinates.")
+{
+  Stencil *s = unsmob_stencil (stil);
+  LY_ASSERT_SMOB (Stencil, stil, 1);
+  LY_ASSERT_TYPE (scm_is_number, angle, 2);
+  LY_ASSERT_TYPE (scm_is_number, x, 3);
+  LY_ASSERT_TYPE (scm_is_number, y, 4);
+  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_degrees_absolute (a, Offset (x_off, y_off));
+  return new_s;
+}
+
 LY_DEFINE (ly_round_filled_box, "ly:round-filled-box",
           3, 0, 0,
           (SCM xext, SCM yext, SCM blot),
index 3b92b558007aa71ba77383e83cb709ddc1ce049f..ae06add090c07b8052d6ea5a2a1fbb635ddf63fd 100644 (file)
@@ -80,26 +80,26 @@ Stencil::rotate (Real a, Offset off)
 }
 
 /*
-  Rotate this stencil around the point RELATIVE_OFF.
+  Rotate this stencil around the point ABSOLUTE_OFF.
 
-  RELATIVE_OFF is measured in terms of the extent of the stencil, so
-  -1 = LEFT/DOWN edge, 1 = RIGHT/UP edge.
  */
 void
-Stencil::rotate_degrees (Real a, Offset relative_off)
+Stencil::rotate_degrees_absolute (Real a, Offset absolute_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 + relative_off[X_AXIS] * x_cen;
-  const Real y = y_cen + relative_off[Y_AXIS] * y_cen;
+  const Real x = absolute_off[X_AXIS];
+  const Real y = absolute_off[Y_AXIS];
 
   /*
    * Build scheme expression (processed in stencil-interpret.cc)
    */
+  /* TODO: by hanwenn 2008/09/10 14:38:56:
+   * in effect, this copies the underlying expression.  It might be a
+   * little bit nicer to mirror this in the api, ie. make a
+   *         Stencil::rotated()
+   * and have Stencil::rotate be an abbrev of
+   *         *this = rotated()
+   */
+
   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))),
@@ -108,16 +108,36 @@ Stencil::rotate_degrees (Real a, Offset relative_off)
   /*
    * Calculate the new bounding box
    */
+  Box shifted_box = extent_box ();
+  shifted_box.translate (-absolute_off);
+
   vector<Offset> 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));
+  pts.push_back (Offset (shifted_box.x ().at(LEFT), shifted_box.y ().at(DOWN)));
+  pts.push_back (Offset (shifted_box.x ().at(RIGHT), shifted_box.y ().at(DOWN)));
+  pts.push_back (Offset (shifted_box.x ().at(RIGHT), shifted_box.y ().at(UP)));
+  pts.push_back (Offset (shifted_box.x ().at(LEFT), shifted_box.y ().at(UP)));
 
   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));
+    dim_.add_point (pts[i] * rot + absolute_off);
+}
+
+/*
+  Rotate this stencil around the point RELATIVE_OFF.
+
+  RELATIVE_OFF is measured in terms of the extent of the stencil, so
+  -1 = LEFT/DOWN edge, 1 = RIGHT/UP edge.
+ */
+void
+Stencil::rotate_degrees (Real a, Offset relative_off)
+{
+  /*
+   * Calculate the center of rotation
+   */
+  const Real x = extent (X_AXIS).linear_combination (relative_off[X_AXIS]);
+  const Real y = extent (Y_AXIS).linear_combination (relative_off[Y_AXIS]);
+  rotate_degrees_absolute (a, Offset (x, y));
 }
 
 void