+2006-05-14 Erlend Aasland <erlenda@gmail.com>
+
+ * 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 <gpermus@gmail.com>
* Documentation/user/music-glossary.itely: French correction.
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");
"meta "
"minimum-X-extent "
"minimum-Y-extent "
+ "rotation "
"springs-and-rods "
"staff-symbol "
"stencil "
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);
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
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),
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<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));
+
+ 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)
{
(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.")
(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
;; 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)
;; 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))
(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))
(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 (* -1 ang))
+ (number->string x)
+ (number->string (* -1 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,