Index: lily/grob.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/grob.cc,v
retrieving revision 1.168
diff -p -u -r1.168 grob.cc
--- lily/grob.cc	11 Feb 2006 11:35:18 -0000	1.168
+++ lily/grob.cc	12 May 2006 08:30:57 -0000
@@ -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 "
Index: lily/stencil-interpret.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/stencil-interpret.cc,v
retrieving revision 1.5
diff -p -u -r1.5 stencil-interpret.cc
--- lily/stencil-interpret.cc	6 Jan 2006 09:13:24 -0000	1.5
+++ lily/stencil-interpret.cc	12 May 2006 08:30:57 -0000
@@ -56,6 +56,22 @@ interpret_stencil_expression (SCM expr,
 
 	  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
 	{
 	  (*func) (func_arg,
Index: lily/stencil-scheme.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/stencil-scheme.cc,v
retrieving revision 1.53
diff -p -u -r1.53 stencil-scheme.cc
--- lily/stencil-scheme.cc	6 Jan 2006 09:13:24 -0000	1.53
+++ lily/stencil-scheme.cc	12 May 2006 08:30:57 -0000
@@ -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),
Index: lily/stencil.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/stencil.cc,v
retrieving revision 1.51
diff -p -u -r1.51 stencil.cc
--- lily/stencil.cc	19 Feb 2006 12:38:02 -0000	1.51
+++ lily/stencil.cc	12 May 2006 08:30:57 -0000
@@ -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
+   */
+  Real x = x_cen + off[X_AXIS] * x_cen;
+  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<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));
+
+  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)
 {
Index: lily/include/stencil.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/stencil.hh,v
retrieving revision 1.24
diff -p -u -r1.24 stencil.hh
--- lily/include/stencil.hh	6 Jan 2006 09:13:24 -0000	1.24
+++ lily/include/stencil.hh	12 May 2006 08:30:57 -0000
@@ -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);
 
Index: scm/define-grob-properties.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/define-grob-properties.scm,v
retrieving revision 1.162
diff -p -u -r1.162 define-grob-properties.scm
--- scm/define-grob-properties.scm	9 May 2006 02:15:57 -0000	1.162
+++ scm/define-grob-properties.scm	12 May 2006 08:30:58 -0000
@@ -352,6 +352,8 @@ quicker the slur attains it @code{height
      (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.")
Index: scm/define-markup-commands.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/define-markup-commands.scm,v
retrieving revision 1.146
diff -p -u -r1.146 define-markup-commands.scm
--- scm/define-markup-commands.scm	5 May 2006 22:56:06 -0000	1.146
+++ scm/define-markup-commands.scm	12 May 2006 08:30:58 -0000
@@ -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
Index: scm/output-ps.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/output-ps.scm,v
retrieving revision 1.168
diff -p -u -r1.168 output-ps.scm
--- scm/output-ps.scm	4 Apr 2006 10:18:59 -0000	1.168
+++ scm/output-ps.scm	12 May 2006 08:30:58 -0000
@@ -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))
Index: scm/output-svg.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/output-svg.scm,v
retrieving revision 1.37
diff -p -u -r1.37 output-svg.scm
--- scm/output-svg.scm	10 Feb 2006 09:57:07 -0000	1.37
+++ scm/output-svg.scm	12 May 2006 08:30:58 -0000
@@ -250,6 +250,16 @@
 		(map offset->point (ly:list->offsets '() coords))))
    ))
 
+;; rotate around given point
+(define (setrotation ang x y)
+  (format "<g transform=\"rotate(~a,~a,~a)\">"
+    (number->string ang)
+    (number->string x)
+    (number->string y)))
+
+(define (resetrotation ang x y)
+  "</g>")
+
 (define (round-filled-box breapth width depth height blot-diameter)
   (entity 'rect ""
 	  ;; The stroke will stick out.  To use stroke,
Index: scm/output-tex.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/output-tex.scm,v
retrieving revision 1.97
diff -p -u -r1.97 output-tex.scm
--- scm/output-tex.scm	6 Feb 2006 01:13:59 -0000	1.97
+++ scm/output-tex.scm	12 May 2006 08:30:58 -0000
@@ -34,6 +34,7 @@
 	    bezier-sandwich
 	    round-filled-box
 	    text
+	    rotate
 	    setcolor
 	    resetcolor
 	    polygon

