[gsharp-cvs] CVS update: gsharp/clim-patches.lisp gsharp/beaming.lisp gsharp/drawing.lisp gsharp/gsharp.asd gsharp/measure.lisp gsharp/score-pane.lisp

Robert Strandh rstrandh at common-lisp.net
Wed Dec 7 03:38:31 UTC 2005


Update of /project/gsharp/cvsroot/gsharp
In directory common-lisp.net:/tmp/cvs-serv24600

Modified Files:
	beaming.lisp drawing.lisp gsharp.asd measure.lisp 
	score-pane.lisp 
Added Files:
	clim-patches.lisp 
Log Message:
Gsharp can now do multiple beams, partial beams and fractional beams.
There are still some quirks, however:

  * there is an off-by-one-pixel error that sometimes makes the beam
    not attach to one of its stems;

  * I am still using the algorithm for a single beam to compute the
    beaming, even when there are multiple beams.  

Also fixed a bug that did not set the modified-p flag on an element
when the stem direction was explicitly altered as a result of a user
interaction.


Date: Wed Dec  7 04:38:27 2005
Author: rstrandh



Index: gsharp/beaming.lisp
diff -u gsharp/beaming.lisp:1.2 gsharp/beaming.lisp:1.3
--- gsharp/beaming.lisp:1.2	Mon Feb 16 17:08:00 2004
+++ gsharp/beaming.lisp	Wed Dec  7 04:38:27 2005
@@ -3,9 +3,9 @@
 ;;; The beaming function takes a list of the form:
 ;;; ((p1 x1) (p2 x2) ... (pn xn))
 ;;; where p1 through pn are staff positions (bottom line is 0, 
-;;; increas upwards by 1 for each half staff step) and x1 through xn
+;;; increas upwards by 1 for each staff step) and x1 through xn
 ;;; are x positions for the clusters given in the same unit as the
-;;; positions, i.e., half staff steps
+;;; positions, i.e., staff steps
 
 ;;; The result of the computation is a VALID BEAMING.  Such a beaming
 ;;; is represented as a list of two elements representing the left and
@@ -18,11 +18,13 @@
 ;;; representation makes it easy to transform the constellation by
 ;;; reflection.
 
-;;; Take two notes and compute the beam slant and beam position for the
-;;; beam connecting them. A position of zero means the bottom of the
-;;; staff. Positive integers count up 1/2 space so that C on a staff
-;;; with a G-clef gets to have number -2.  Negative numbers go the other
-;;; way. This procedure assumes that pos2 >= pos1.
+;;; Take two vertical positions and compute the beam slant and beam
+;;; position for the beam connecting them. A position of zero means
+;;; the bottom of the staff. Positive integers count up 1/2 space so
+;;; that C on a staff with a G-clef gets to have number -2.  Negative
+;;; numbers go the other way. This function assumes that pos2 >= pos1,
+;;; and that the two notes are sufficiently far apart that the slant
+;;; is going to be acceptably small. 
 (defun beaming-single-stemsup-rising-twonotes (pos1 pos2)
   (let ((d (- pos2 pos1))
 	(s1 (+ pos2 1))
@@ -96,11 +98,19 @@
 	       (t `((,s5 . -1) (,s7 .  0))))))))
 
 (defun reflect-pos (pos)
-  (list (- 8 (car pos)) (cadr pos)))
+  (destructuring-bind (p x b) pos
+    (list (- 8 p) x b)))
 
 (defun reflect-bpos (pos)
   (cons (- 8 (car pos)) (- (cdr pos))))
 
+;;; take two points of the form (pos x b), where pos is a vertical
+;;; position (in staff-steps), x is a horizontal position (also in
+;;; staff-steps), and b is the number of beams at that position and
+;;; compute a valid beaming for the two points.  To do so, first call
+;;; the function passed as an argument on the two vertical positions.
+;;; If the slant thus obtained is too high, repeat with a slightly
+;;; higher vertical position of the first point.
 (defun beaming-two-points (p1 p2 fun)
   (let* ((beaming (funcall fun (car p1) (car p2)))
 	 (left (car beaming))
@@ -114,8 +124,18 @@
 	(progn (incf (car p1)) (beaming-two-points p1 p2 fun))
 	beaming)))
 
-;;; main entry
+;;; main entry 
 
+;;; Take a list of the form ((p1 x1 b1) (p2 x2 b2) ... (pn xn bn)),
+;;; (where pi is a vertical position, xi is a horizontal position
+;;; (both measured in staff-steps), and bi is the number of stems at
+;;; that position), a stem direction, and a function to compute a
+;;; valid slant of two notes sufficiently far apart, compute a valid
+;;; beaming.  First reflect the positions vertically and horizontally
+;;; until the last note is higher than the first and the stems are up.
+;;; Then compute a valid beaming using only the first and last
+;;; elements of the list.  Finally, move the beaming up vertically
+;;; until each stem it as least 2.5 staff steps long.
 (defun beaming-general (positions stem-direction fun)
   (let* ((first (car positions))
 	 (last (car (last positions)))
@@ -130,12 +150,11 @@
 		  (right (cadr beaming))
 		  (y1 (+ (car left) (* 0.5 (cdr left))))
 		  (y2 (+ (car right) (* 0.5 (cdr right))))
+		  (slope (/ (- y2 y1) (- x2 x1)))
 		  (minstem (reduce #'min positions
 				   :key (lambda (pos)
-					  (- (+ y1 (* (- (cadr pos) x1)
-						      (/ (- y2 y1)
-							 (- x2 x1))))
-					     (car pos)))))
+					  (destructuring-bind (p x b) pos
+					    (- (+ y1 (* (- x x1) slope)) p (* 2 (1- b)))))))
 		  (increment (* 2 (ceiling (/ (max 0 (- 5 minstem)) 2)))))
 	     `((,(+ (car left) increment) . ,(cdr left))
 	       (,(+ (car right) increment) . ,(cdr right))))))))


Index: gsharp/drawing.lisp
diff -u gsharp/drawing.lisp:1.51 gsharp/drawing.lisp:1.52
--- gsharp/drawing.lisp:1.51	Tue Dec  6 17:36:03 2005
+++ gsharp/drawing.lisp	Wed Dec  7 04:38:27 2005
@@ -578,7 +578,12 @@
 	     (x-positions (mapcar (lambda (element)
 				    (/ (final-absolute-element-xoffset element) (score-pane:staff-step 1)))
 				  elements))
-	     (beaming (beaming-single (mapcar #'list positions x-positions) stem-direction)))
+	     (nb-beams (mapcar (lambda (element)
+				 (max (lbeams element) (rbeams element)))
+			       elements))
+	     (beaming (beaming-single (mapcar #'list positions x-positions nb-beams) stem-direction))
+	     (max-nb-beams (reduce #'max nb-beams))
+	     (min-nb-beams (reduce #'min nb-beams)))
 	(destructuring-bind ((ss1 . offset1) (ss2 . offset2)) beaming
 	  (let* ((y1 (+ ss1 (* 1/2 offset1)))
 		 (y2 (+ ss2 (* 1/2 offset2)))
@@ -600,14 +605,72 @@
 	    (if (eq stem-direction :up)
 		(score-pane:with-notehead-right-offsets (right up)
 		  (declare (ignore up))
-		  (score-pane:draw-beam pane
-					(+ (final-absolute-element-xoffset (car elements)) right) ss1 offset1
-					(+ (final-absolute-element-xoffset (car (last elements))) right) ss2 offset2))
+		  (loop repeat min-nb-beams
+			for ss from 0 by 2
+			for offset from 0
+			do (score-pane:draw-beam pane
+						 (+ (final-absolute-element-xoffset (car elements)) right) (- ss1 ss) (+ offset1 offset)
+						 (+ (final-absolute-element-xoffset (car (last elements))) right) (- ss2 ss) (+ offset2 offset)))
+		  (let ((region +nowhere+))
+		    (loop for beams from (1+ min-nb-beams) to max-nb-beams
+			  for ss from (* 2 min-nb-beams) by 2
+			  for offset from min-nb-beams
+			  do (loop for (e1 e2) on elements
+				   do (when (not (null e2))
+					(cond ((and (>= (rbeams e1) beams) (>= (lbeams e2) beams))
+					       (setf region 
+						     (region-union region
+								   (make-rectangle* (+ (final-absolute-element-xoffset e1) right) -10000
+										    (+ (final-absolute-element-xoffset e2) right) 10000))))
+					      ((>= (rbeams e1) beams)
+					       (setf region
+						     (region-union region 
+								   (make-rectangle* (+ (final-absolute-element-xoffset e1) right) -10000
+										    (+ (final-absolute-element-xoffset e1) right (score-pane:staff-step 2)) 10000))))
+					      ((>= (lbeams e2) beams)
+					       (setf region
+						     (region-union region 
+								   (make-rectangle* (+ (final-absolute-element-xoffset e2) right (score-pane:staff-step -2)) -10000
+										    (+ (final-absolute-element-xoffset e2) right) 10000))))
+					      (t nil))))
+			     (with-drawing-options (pane :clipping-region region)
+			       (score-pane:draw-beam pane
+						     (+ (final-absolute-element-xoffset (car elements)) right) (- ss1 ss) (+ offset1 offset)
+						     (+ (final-absolute-element-xoffset (car (last elements))) right) (- ss2 ss) (+ offset2 offset))))))
 		(score-pane:with-notehead-left-offsets (left down)
 		  (declare (ignore down))
-		  (score-pane:draw-beam pane
-					(+ (final-absolute-element-xoffset (car elements)) left) ss1 offset1
-					(+ (final-absolute-element-xoffset (car (last elements))) left) ss2 offset2))))
+		  (loop repeat min-nb-beams
+			for ss from 0 by 2
+			for offset from 0
+			do (score-pane:draw-beam pane
+						 (+ (final-absolute-element-xoffset (car elements)) left) (+ ss1 ss) (- offset1 offset)
+						 (+ (final-absolute-element-xoffset (car (last elements))) left) (+ ss2 ss) (- offset2 offset)))
+		  (let ((region +nowhere+))
+		    (loop for beams from (1+ min-nb-beams) to max-nb-beams
+			  for ss from (* 2 min-nb-beams) by 2
+			  for offset from min-nb-beams
+			  do (loop for (e1 e2) on elements
+				   do (when (not (null e2))
+					(cond ((and (>= (rbeams e1) beams) (>= (lbeams e2) beams))
+					       (setf region 
+						     (region-union region
+								   (make-rectangle* (+ (final-absolute-element-xoffset e1) left) -10000
+										    (+ (final-absolute-element-xoffset e2) left) 10000))))
+					      ((>= (rbeams e1) beams)
+					       (setf region
+						     (region-union region 
+								   (make-rectangle* (+ (final-absolute-element-xoffset e1) left) -10000
+										    (+ (final-absolute-element-xoffset e1) left (score-pane:staff-step 2)) 10000))))
+					      ((>= (lbeams e2) beams)
+					       (setf region
+						     (region-union region 
+								   (make-rectangle* (+ (final-absolute-element-xoffset e2) left (score-pane:staff-step -2)) -10000
+										    (+ (final-absolute-element-xoffset e2) left) 10000))))
+					      (t nil))))
+			     (with-drawing-options (pane :clipping-region region)
+			       (score-pane:draw-beam pane
+						     (+ (final-absolute-element-xoffset (car elements)) left) (+ ss1 ss) (- offset1 offset)
+						     (+ (final-absolute-element-xoffset (car (last elements))) left) (+ ss2 ss) (- offset2 offset))))))))
 	  (loop for element in elements do
 		(draw-element pane element nil))))))
 


Index: gsharp/gsharp.asd
diff -u gsharp/gsharp.asd:1.4 gsharp/gsharp.asd:1.5
--- gsharp/gsharp.asd:1.4	Tue Nov 29 20:37:39 2005
+++ gsharp/gsharp.asd	Wed Dec  7 04:38:27 2005
@@ -22,6 +22,7 @@
 
 (gsharp-defsystem (:gsharp :depends-on (:mcclim :flexichain))
    "packages"
+   "clim-patches"
    "esa"
    "utilities"
    "gf"


Index: gsharp/measure.lisp
diff -u gsharp/measure.lisp:1.19 gsharp/measure.lisp:1.20
--- gsharp/measure.lisp:1.19	Tue Nov 29 20:37:40 2005
+++ gsharp/measure.lisp	Wed Dec  7 04:38:27 2005
@@ -78,6 +78,10 @@
   (declare (ignore dots))
   (mark-modified element))
 
+(defmethod (setf stem-direction) :after (direction (element relement))
+  (declare (ignore direction))
+  (mark-modified element))
+
 (defmethod note-position ((note note))
   (let ((clef (clef (staff note))))
     (+ (- (pitch note)


Index: gsharp/score-pane.lisp
diff -u gsharp/score-pane.lisp:1.17 gsharp/score-pane.lisp:1.18
--- gsharp/score-pane.lisp:1.17	Tue Nov  8 06:16:12 2005
+++ gsharp/score-pane.lisp	Wed Dec  7 04:38:27 2005
@@ -612,8 +612,9 @@
       (multiple-value-bind (left right) (stem-offsets *font*)
 	(let* ((xx1 (+ x1 left))
 	       (xx2 (+ x2 right))
-	       (y1 (- (floor (staff-step (+ staff-step-1 (* 1/2 offset1))))))
-	       (y2 (- (floor (staff-step (+ staff-step-2 (* 1/2 offset2))))))
+	       (offset (round (staff-step 1/3)))
+	       (y1 (- (+ (staff-step staff-step-1) (* offset1 offset))))
+	       (y2 (- (+ (staff-step staff-step-2) (* offset2 offset))))
 	       (slope (abs (/ (- y2 y1) (- xx2 xx1))))
 	       (thickness (/ (staff-line-distance *font*) 2))
 	       (medium (sheet-medium pane)))




More information about the Gsharp-cvs mailing list