Jump to content

Skew Markup with a given angle

From LilyPond wiki

This is a more sophisticated and versatile version of LSR 1166
Now the skewing angle is an input parameter for the procedure.
A boolean parameter decides if the orginal height should be preserved

\version "2.24.0"

%% this is a more sophisticated version of LSR 1166
%% thanks to Arnold from the German forum
%% https://lilypondforum.de/index.php/topic,1216.0.html

\paper { tagline = #f }

%{
% LSR workaround:
#(set! paper-alist (cons '("snippet" . (cons (* 170 mm) (* 75 mm))) paper-alist))
\paper {
  #(set-paper-size "snippet")
  tagline = ##f
  #(include-special-characters)
  indent = #0
}
%}

#(define-markup-command (skew layout props arg ang type)
   ;; skewes the input markup at a certain angle, stencil vanishes at 90 degrees
   ;; takes three arguments
   ;; arg: markup to skew
   ;; ang: skewing angle degrees
   ;; type: true/false
   ;; if true the original height is preserved, otherwise it decreases with cos ang
   (markup?  number? boolean?)
   (let* ((deg-rad-factor (/ PI 180))
          (par type)
          (half-ang (* 0.5 ang))
          (sin-part (sin (* deg-rad-factor half-ang)))
          (cos-part (cos (* deg-rad-factor half-ang)))
          (px (- cos-part sin-part))
          (py (+ cos-part sin-part))
          ; Overall Matrix: xx = 1.0    xy
          ;                 yx = 0.0    yy
          (xy (if par (tan (* deg-rad-factor ang))
                  (sin (* deg-rad-factor ang))))
          (yy (if par 1.0 (cos (* deg-rad-factor ang))))
          ; input markup's stencil and extent
          (stil (interpret-markup layout props arg))
          (ext-x (ly:stencil-extent stil X))
          (ext-y (ly:stencil-extent stil Y))
          (xo1 (car ext-x))
          (xo2 (cdr ext-x))
          (yo1 (car ext-y))
          (yo2 (cdr ext-y))
          ; four edge points transformed by that matrix
          (xp1 (+ xo1 (* xy yo1)))
          (yp13 (* yy yo1))
          (xp2 (+ xo1 (* xy yo2)))
          (yp24 (* yy yo2))
          (xp3 (+ xo2 (* xy yo1)))
          (xp4 (+ xo2 (* xy yo2)))
          ; new extent
          (xmin (min xp1 xp2 xp3 xp4))
          (xmax (max xp1 xp2 xp3 xp4))
          (ymin (min yp13 yp24))
          (ymax (max yp13 yp24))
          (stil-2
           (if par (ly:stencil-scale stil 1.0 (/ 1.0 (cos (* deg-rad-factor ang)))) stil))
          (stil-3 (ly:stencil-rotate-absolute stil-2 45.0 0.0 0.0))
          (stil-4 (ly:stencil-scale stil-3 px py))
          (stil-5 (ly:stencil-rotate-absolute stil-4 (- -45.0 half-ang) 0.0 0.0)))
     ;      (write-me "degrad " deg-rad-factor)
     ;      (write-me "180/PI " (/ PI 180))
     (ly:stencil-outline stil-5
                         (make-filled-box-stencil (cons xmin xmax) (cons ymin ymax)))))

hello = \markup \override #'(box-padding . 0.0) \with-color #darkgreen \box
\with-color #black \fontsize #6 "Hello world!"

\markup \line {
  \left-column {
    "Text"
    \vspace #.2
    \hello
  }
  \left-column {
    "Text skewed 45 deg ##t"
    \vspace #.2
    \skew  \hello #45 ##t
  }
  \left-column {
    "Text skewed 45 deg ##f"
    \vspace #.2
    \skew  \hello #45 ##f
  }
}

\markup \vspace #1

\markup \line {
  \left-column {
    "Text"
    \vspace #.2
    \hello
  }
  \left-column {
    "Text skewed -70 deg ##t"
    \vspace #.2
    \skew  \hello #-70 ##t
  }
  \left-column {
    "Text skewed -30 deg ##f"
    \vspace #.2
    \skew  \hello #-30 ##f
  }
}