Jump to content

Using path expressions to override stencils: Difference between revisions

From LilyPond wiki
Import snippet from LSR
 
(No difference)

Latest revision as of 22:41, 26 October 2025

The stencil expression path can be used to override stencils for any printed object. The advantage of using path instead of embedded-ps is that path is supported by both the PostScript and SVG backends, and uses the same syntax.

There are six commands available to use in a path expression, and all commands use prefix notation. The six commands are moveto, rmoveto, lineto, rlineto, curveto, and rcurveto. Note that the commands that begin with r are the relative variants of the other three commands.

The commands moveto, rmoveto, lineto, and rlineto take 2 arguments; they are the X and Y coordinates for the destination point.

The commands curveto and rcurveto create cubic Bézier curves, and take 6 arguments; the first two are the X and Y coordinates for the first control point, the second two are the X and Y coordinates for the second control point, and the last two are the X and Y coordinates for the destination point.

In addition this snippet shows how to create a filled stencil using path, and adds a scheme function to automatically resize custom stencils when individual staves are resized.

\version "2.24.0"

%% http://lsr.di.unimi.it/LSR/Item?id=623

%{
  Note: since SVG path data needs an "M" or "m" at the
  beginning to start a new subpath, every path expression
  must begin with "rmoveto" (or "moveto") to work with the
  SVG backend.
%}

customClefStencilOne =
  #(ly:make-stencil
    `(path 0.2
	  (rmoveto 0 0
	    rcurveto 0 0.75 1 0.75 1 0
	    rcurveto 0 -0.75 -1 -0.75 -1 0
	    rcurveto -1 0 -1 1.5 -0.5 1.5
	    rmoveto 0.5 -1.5
	    rcurveto -1 0 -1 -1.5 -0.5 -1.5
	    rmoveto 0.5 1.5
	    rmoveto 1 0
	    rcurveto 2.5 0 2.5 4 4 4
	    rmoveto -4 -4
	    rcurveto 2.5 0 2.5 -4 4 -4))
     (cons -0.5 1)
     (cons -3 5))
  
% a filled custom stencil
customClefStencilTwo = 
  #(ly:make-stencil
    ;; path line thickness is set to 0.1 
    `(path 0.1
      ;; path coordinates
	  (moveto 0 0
	    curveto 0 1 0.7 2.5 1.5 1.5
            lineto 1.5 -3
            closepath)
          ;; path cap style
          round
          ;; path join style
          round
          ;; path filled?  #t or #f
          #t)
     ;; horizontal extent
     (cons 0 1.5)
     ;; vertical extent
     (cons -3 2))

% scheme function to automatically resize a custom stencil 
% when an individual staff is resized (uses font-size)
scaleCustomClefStencilTwo =
#(lambda (grob)
  (let* ((sz (ly:grob-property grob 'font-size 0.0))
           (mult (magstep sz)))
    (ly:stencil-scale
      customClefStencilTwo
      mult mult)))
  
customClefOne = \override Staff.Clef.stencil = \customClefStencilOne
customClefTwo = \override Staff.Clef.stencil = \scaleCustomClefStencilTwo
normalClefs = \revert Staff.Clef.stencil

music =
\relative c' {
  \customClefOne
  \clef "alto"
  c1 g1
  \customClefTwo
  \clef "bass"
  c1 g1
  \normalClefs
  \clef "treble"
  c1 g1
  \clef "alto"
  c1 g1
}
<<
\new Staff \with {
    fontSize = #-3
    \override StaffSymbol.staff-space = #(magstep -3)
    \override StaffSymbol.thickness = #(magstep -3)
}
\music

\new Staff 
\music

\new Staff \with {
    fontSize = #2
    \override StaffSymbol.staff-space = #(magstep 2)
    \override StaffSymbol.thickness = #(magstep 2)
}
\music
>>