Using path expressions to override stencils: Difference between revisions

m New category
mNo edit summary
 
Line 1: Line 1:
The stencil expression <code>path</code> can be used to override stencils for any printed object. The advantage of using <code>path</code> instead of <code>embedded-ps</code> is that <code>path</code> is supported by both the PostScript and SVG backends, and uses the same syntax.
The stencil expression <code>path</code> can be used to override stencils for any printed object. The advantage of using <code>path</code> instead of <code>embedded-ps</code> is that <code>path</code> is supported by both the PostScript and SVG backends of LilyPond, and uses the same syntax.


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


The commands <code>moveto, rmoveto, lineto,</code> and <code>rlineto</code> take 2 arguments; they are the X and Y coordinates for the destination point.
The commands <code>moveto</code>, <code>rmoveto</code>, <code>lineto</code>, and <code>rlineto</code> take two arguments; they are the X- and Y-coordinates for the destination point.


The commands <code>curveto</code> and <code>rcurveto</code> 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.
The commands <code>curveto</code> and <code>rcurveto</code> create cubic Bézier curves and take six 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 <code>path,</code> and adds a scheme function to automatically resize custom stencils when individual staves are resized.
This snippet also shows how to create a ‘filled’ stencil using <code>path</code>, adding a Scheme function to automatically resize custom stencils when individual staves are resized.
 
Note that replacing the stencil of a grob doesn't change its dimensions.  In case you experience strange spacing you have to adjust the <code>X-extent</code> and <code>Y-extent</code> properties.  If you experience cropping, you might use the <code>\with-true-dimensions</code> trick shown below.
 
See also snippet [[Generate special note head shapes]].


<lilypond version="2.24">
<lilypond version="2.24">
%% http://lsr.di.unimi.it/LSR/Item?id=623
%{
%{
   Note: since SVG path data needs an "M" or "m" at the
   Note: since SVG path data needs an "M" or "m" instruction at
   beginning to start a new subpath, every path expression
   the beginning to start a new subpath, every path expression
   must begin with "rmoveto" (or "moveto") to work with the
   must begin with "rmoveto" (or "moveto") to work with the SVG
   SVG backend.
   backend.
%}
%}


customClefStencilOne =
customClefStencilOne =
  #(ly:make-stencil
#(ly:make-stencil
    `(path 0.2
  '(path 0.2
  (rmoveto 0 0
        (rmoveto 0 0
    rcurveto 0 0.75 1 0.75 1 0
          rcurveto 0 0.75 1 0.75 1 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
          rcurveto -1 0 -1 1.5 -0.5 1.5
    rmoveto 0.5 -1.5
          rmoveto 0.5 -1.5
    rcurveto -1 0 -1 -1.5 -0.5 -1.5
          rcurveto -1 0 -1 -1.5 -0.5 -1.5
    rmoveto 0.5 1.5
          rmoveto 0.5 1.5
    rmoveto 1 0
          rmoveto 1 0
    rcurveto 2.5 0 2.5 4 4 4
          rcurveto 2.5 0 2.5 4 4 4
    rmoveto -4 -4
          rmoveto -4 -4
    rcurveto 2.5 0 2.5 -4 4 -4))
          rcurveto 2.5 0 2.5 -4 4 -4))
    (cons -0.5 1)
  (cons -0.5 1)
    (cons -3 5))
  (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  
% A filled custom stencil.
% when an individual staff is resized (uses font-size)
customClefStencilTwo =
#(ly:make-stencil
  ;; Set path line thickness to 0.1.
  '(path
    ;; Set path line thickness.
    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
    ;; Is path filled?  `#t` or `#f`.
    #t)
  ;; Horizontal extent.
  (cons 0 1.5)
  ;; Vertical extent.
  (cons -3 2))
 
% A Scheme function to automatically resize a custom stencil
% when an individual staff is resized (uses `font-size`).
scaleCustomClefStencilTwo =
scaleCustomClefStencilTwo =
#(lambda (grob)
#(lambda (grob)
  (let* ((sz (ly:grob-property grob 'font-size 0.0))
  (let* ((sz (ly:grob-property grob 'font-size 0.0))
          (mult (magstep sz)))
          (mult (magstep sz)))
    (ly:stencil-scale
    (ly:stencil-scale customClefStencilTwo mult mult)))
      customClefStencilTwo
 
      mult mult)))
 
customClefOne = \override Staff.Clef.stencil = \customClefStencilOne
customClefOne = \override Staff.Clef.stencil = \customClefStencilOne
customClefTwo = \override Staff.Clef.stencil = \scaleCustomClefStencilTwo
customClefTwo = \override Staff.Clef.stencil = \scaleCustomClefStencilTwo
normalClefs = \revert Staff.Clef.stencil
normalClefs = \revert Staff.Clef.stencil


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


\new Staff  
\markup \with-true-dimensions % work around a cropping issue
\music
\score {
  <<
    \new Staff \with {
      fontSize = #-3
      \override StaffSymbol.staff-space = #(magstep -3)
      \override StaffSymbol.thickness = #(magstep -3)
    } \music
 
    \new Staff \music


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


[[Category:Tweaks and overrides]]
[[Category:Really cool]]
[[Category:Scheme]]
[[Category:Scheme]]
[[Category:Symbols and glyphs]]
[[Category:Symbols and glyphs]]
[[Category:Really cool]]
[[Category:Tweaks and overrides]]
[[Category:Snippet]]
[[Category:Snippet]]