+(define (make-parenthesis-stencil
+ y-extent half-thickness width angularity)
+ "Create a parenthesis stencil.
+@var{y-extent} is the Y extent of the markup inside the parenthesis.
+@var{half-thickness} is the half thickness of the parenthesis.
+@var{width} is the width of a parenthesis.
+The higher the value of number @var{angularity},
+the more angular the shape of the parenthesis."
+ (let* ((line-width 0.1)
+ ;; Horizontal position of baseline that end points run through.
+ (base-x
+ (if (< width 0)
+ (- width)
+ 0))
+ ;; X value farthest from baseline on outside of curve
+ (outer-x (+ base-x width))
+ ;; X extent of bezier sandwich centerline curves
+ (x-extent (ordered-cons base-x outer-x))
+ (bottom-y (interval-start y-extent))
+ (top-y (interval-end y-extent))
+
+ (lower-end-point (cons base-x bottom-y))
+ (upper-end-point (cons base-x top-y))
+
+ (outer-control-x (+ base-x (* 4/3 width)))
+ (inner-control-x (+ outer-control-x
+ (if (< width 0)
+ half-thickness
+ (- half-thickness))))
+
+ ;; Vertical distance between a control point
+ ;; and the end point it connects to.
+ (offset-index (- (* 0.6 angularity) 0.8))
+ (lower-control-y (interval-index y-extent offset-index))
+ (upper-control-y (interval-index y-extent (- offset-index)))
+
+ (lower-outer-control-point
+ (cons outer-control-x lower-control-y))
+ (upper-outer-control-point
+ (cons outer-control-x upper-control-y))
+ (upper-inner-control-point
+ (cons inner-control-x upper-control-y))
+ (lower-inner-control-point
+ (cons inner-control-x lower-control-y)))
+
+ (ly:make-stencil
+ (list 'bezier-sandwich
+ `(quote ,(list
+ ;; Step 4: curve through inner control points
+ ;; to lower end point.
+ upper-inner-control-point
+ lower-inner-control-point
+ lower-end-point
+ ;; Step 3: move to upper end point.
+ upper-end-point
+ ;; Step 2: curve through outer control points
+ ;; to upper end point.
+ lower-outer-control-point
+ upper-outer-control-point
+ upper-end-point
+ ;; Step 1: move to lower end point.
+ lower-end-point))
+ line-width)
+ (interval-widen x-extent (/ line-width 2))
+ (interval-widen y-extent (/ line-width 2)))))
+
+(define-public (parenthesize-stencil
+ stencil half-thickness width angularity padding)
+ "Add parentheses around @var{stencil}, returning a new stencil."
+ (let* ((y-extent (ly:stencil-extent stencil Y))
+ (lp (make-parenthesis-stencil
+ y-extent half-thickness (- width) angularity))
+ (rp (make-parenthesis-stencil
+ y-extent half-thickness width angularity)))
+ (set! stencil (ly:stencil-combine-at-edge lp X RIGHT stencil padding))
+ (set! stencil (ly:stencil-combine-at-edge stencil X RIGHT rp padding))
+ stencil))
+
+(define-public (make-line-stencil width startx starty endx endy)
+ "Make a line stencil of given linewidth and set its extents accordingly"
+ (let ((xext (cons (min startx endx) (max startx endx)))
+ (yext (cons (min starty endy) (max starty endy))))
+ (ly:make-stencil
+ (list 'draw-line width startx starty endx endy)
+ ; Since the line has rounded edges, we have to / can safely add half the
+ ; width to all coordinates!
+ (interval-widen xext (/ width 2))
+ (interval-widen yext (/ width 2)))))
+
+