X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scm%2Fdefine-markup-commands.scm;h=d6c992e537e91894ee4f05946d11d52fe0634191;hb=f8159a57125bbf52e96cad584d6c3756a39d5fc9;hp=933bfb27fb356c8fd71d6e89cebc1485263fdc24;hpb=99dc90bbc369722cf4d3bb9f30b7288762f2167f;p=lilypond.git diff --git a/scm/define-markup-commands.scm b/scm/define-markup-commands.scm index 933bfb27fb..d6c992e537 100644 --- a/scm/define-markup-commands.scm +++ b/scm/define-markup-commands.scm @@ -1,14 +1,109 @@ -;;;; define-markup-commands.scm -- markup commands +;;;; This file is part of LilyPond, the GNU music typesetter. ;;;; -;;;; source file of the GNU LilyPond music typesetter -;;;; -;;;; (c) 2000--2009 Han-Wen Nienhuys +;;;; Copyright (C) 2000--2010 Han-Wen Nienhuys ;;;; Jan Nieuwenhuizen - - -;;; markup commands -;;; * each markup function should have a doc string with -;; syntax, description and example. +;;;; +;;;; LilyPond is free software: you can redistribute it and/or modify +;;;; it under the terms of the GNU General Public License as published by +;;;; the Free Software Foundation, either version 3 of the License, or +;;;; (at your option) any later version. +;;;; +;;;; LilyPond is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with LilyPond. If not, see . + +;;; +;;; Markup commands and markup-list commands definitions. +;;; +;;; Markup commands which are part of LilyPond, are defined +;;; in the (lily) module, which is the current module in this file, +;;; using the `define-markup-command' macro. +;;; +;;; Usage: +;;; +;;; (define-markup-command (command-name layout props args...) +;;; args-signature +;;; [ #:category category ] +;;; [ #:properties property-bindings ] +;;; documentation-string +;;; ..body..) +;;; +;;; with: +;;; command-name +;;; the name of the markup command +;;; +;;; layout and props +;;; arguments that are automatically passed to the command when it +;;; is interpreted. +;;; `layout' is an output def, which properties can be accessed +;;; using `ly:output-def-lookup'. +;;; `props' is a list of property settings which can be accessed +;;; using `chain-assoc-get' (more on that below) +;;; +;;; args... +;;; the command arguments. +;;; There is no limitation on the order of command arguments. +;;; However, markup functions taking a markup as their last +;;; argument are somewhat special as you can apply them to a +;;; markup list, and the result is a markup list where the +;;; markup function (with the specified leading arguments) has +;;; been applied to every element of the original markup list. +;;; +;;; Since replicating the leading arguments for applying a +;;; markup function to a markup list is cheap mostly for +;;; Scheme arguments, you avoid performance pitfalls by just +;;; using Scheme arguments for the leading arguments of markup +;;; functions that take a markup as their last argument. +;;; +;;; args-signature +;;; the arguments signature, i.e. a list of type predicates which +;;; are used to type check the arguments, and also to define the general +;;; argument types (markup, markup-list, scheme) that the command is +;;; expecting. +;;; For instance, if a command expects a number, then a markup, the +;;; signature would be: (number? markup?) +;;; +;;; category +;;; for documentation purpose, builtin markup commands are grouped by +;;; category. This can be any symbol. When documentation is generated, +;;; the symbol is converted to a capitalized string, where hyphens are +;;; replaced by spaces. +;;; +;;; property-bindings +;;; this is used both for documentation generation, and to ease +;;; programming the command itself. It is list of +;;; (property-name default-value) +;;; or (property-name) +;;; elements. Each property is looked-up in the `props' argument, and +;;; the symbol naming the property is bound to its value. +;;; When the property is not found in `props', then the symbol is bound +;;; to the given default value. When no default value is given, #f is +;;; used instead. +;;; Thus, using the following property bindings: +;;; ((thickness 0.1) +;;; (font-size 0)) +;;; is equivalent to writing: +;;; (let ((thickness (chain-assoc-get 'thickness props 0.1)) +;;; (font-size (chain-assoc-get 'font-size props 0))) +;;; ..body..) +;;; When a command `B' internally calls an other command `A', it may +;;; desirable to see in `B' documentation all the properties and +;;; default values used by `A'. In that case, add `A-markup' to the +;;; property-bindings of B. (This is used when generating +;;; documentation, but won't create bindings.) +;;; +;;; documentation-string +;;; the command documentation string (used to generate manuals) +;;; +;;; body +;;; the command body. The function is supposed to return a stencil. +;;; +;;; Each markup command definition shall have a documentation string +;;; with description, syntax and example. (use-modules (ice-9 regex)) @@ -23,10 +118,10 @@ ;; geometric shapes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (draw-line layout props dest) +(define-markup-command (draw-line layout props dest) (number-pair?) - graphic - ((thickness 1)) + #:category graphic + #:properties ((thickness 1)) " @cindex drawing lines within text @@ -44,10 +139,9 @@ A simple line. (y (cdr dest))) (make-line-stencil th 0 0 x y))) -(define-builtin-markup-command (draw-circle layout props radius thickness filled) +(define-markup-command (draw-circle layout props radius thickness filled) (number? number? boolean?) - graphic - () + #:category graphic " @cindex drawing circles within text @@ -63,12 +157,12 @@ optionally filled. @end lilypond" (make-circle-stencil radius thickness filled)) -(define-builtin-markup-command (triangle layout props filled) +(define-markup-command (triangle layout props filled) (boolean?) - graphic - ((thickness 0.1) - (font-size 0) - (baseline-skip 2)) + #:category graphic + #:properties ((thickness 0.1) + (font-size 0) + (baseline-skip 2)) " @cindex drawing triangles within text @@ -92,12 +186,12 @@ A triangle, either filled or empty. (cons 0 ex) (cons 0 (* .86 ex))))) -(define-builtin-markup-command (circle layout props arg) +(define-markup-command (circle layout props arg) (markup?) - graphic - ((thickness 1) - (font-size 0) - (circle-padding 0.2)) + #:category graphic + #:properties ((thickness 1) + (font-size 0) + (circle-padding 0.2)) " @cindex circling text @@ -118,10 +212,9 @@ thickness and padding around the markup. (m (interpret-markup layout props arg))) (circle-stencil m th pad))) -(define-builtin-markup-command (with-url layout props url arg) +(define-markup-command (with-url layout props url arg) (string? markup?) - graphic - () + #:category graphic " @cindex inserting URL links into text @@ -145,10 +238,9 @@ the PDF backend. (ly:stencil-add (ly:make-stencil url-expr xextent yextent) stil))) -(define-builtin-markup-command (beam layout props width slope thickness) +(define-markup-command (beam layout props width slope thickness) (number? number? number?) - graphic - () + #:category graphic " @cindex drawing beams within text @@ -174,41 +266,42 @@ Create a beam with the specified parameters. (cons (+ (- half) (car yext)) (+ half (cdr yext)))))) -(define-builtin-markup-command (underline layout props arg) +(define-markup-command (underline layout props arg) (markup?) - font - ((thickness 1)) + #:category font + #:properties ((thickness 1) (offset 2)) " @cindex underlining text Underline @var{arg}. Looks at @code{thickness} to determine line -thickness and y-offset. +thickness, and @code{offset} to determine line y-offset. @lilypond[verbatim,quote] -\\markup { - default - \\hspace #2 - \\override #'(thickness . 2) - \\underline { - underline - } +\\markup \\fill-line { + \\underline \"underlined\" + \\override #'(offset . 5) + \\override #'(thickness . 1) + \\underline \"underlined\" + \\override #'(offset . 1) + \\override #'(thickness . 5) + \\underline \"underlined\" } @end lilypond" - (let* ((thick (* (ly:output-def-lookup layout 'line-thickness) - thickness)) + (let* ((thick (ly:output-def-lookup layout 'line-thickness)) + (underline-thick (* thickness thick)) (markup (interpret-markup layout props arg)) (x1 (car (ly:stencil-extent markup X))) (x2 (cdr (ly:stencil-extent markup X))) - (y (* thick -2)) - (line (make-line-stencil thick x1 y x2 y))) + (y (* thick (- offset))) + (line (make-line-stencil underline-thick x1 y x2 y))) (ly:stencil-add markup line))) -(define-builtin-markup-command (box layout props arg) +(define-markup-command (box layout props arg) (markup?) - font - ((thickness 1) - (font-size 0) - (box-padding 0.2)) + #:category font + #:properties ((thickness 1) + (font-size 0) + (box-padding 0.2)) " @cindex enclosing text within a box @@ -229,10 +322,9 @@ thickness and padding around the markup. (m (interpret-markup layout props arg))) (box-stencil m th pad))) -(define-builtin-markup-command (filled-box layout props xext yext blot) +(define-markup-command (filled-box layout props xext yext blot) (number-pair? number-pair? number?) - graphic - () + #:category graphic " @cindex drawing solid boxes within text @cindex drawing boxes with rounded corners @@ -258,13 +350,13 @@ circle of diameter@tie{}0 (i.e., sharp corners). (ly:round-filled-box xext yext blot)) -(define-builtin-markup-command (rounded-box layout props arg) +(define-markup-command (rounded-box layout props arg) (markup?) - graphic - ((thickness 1) - (corner-radius 1) - (font-size 0) - (box-padding 0.5)) + #:category graphic + #:properties ((thickness 1) + (corner-radius 1) + (font-size 0) + (box-padding 0.5)) "@cindex enclosing text in a box with rounded corners @cindex drawing boxes with rounded corners around text Draw a box with rounded corners around @var{arg}. Looks at @code{thickness}, @@ -287,10 +379,9 @@ c,8. c16 c4 r (ly:stencil-add (rounded-box-stencil m th pad corner-radius) m))) -(define-builtin-markup-command (rotate layout props ang arg) +(define-markup-command (rotate layout props ang arg) (number? markup?) - align - () + #:category align " @cindex rotating text @@ -309,10 +400,9 @@ Rotate object with @var{ang} degrees around its center. (let* ((stil (interpret-markup layout props arg))) (ly:stencil-rotate stil ang 0 0))) -(define-builtin-markup-command (whiteout layout props arg) +(define-markup-command (whiteout layout props arg) (markup?) - other - () + #:category other " @cindex adding a white background to text @@ -327,10 +417,9 @@ Provide a white background for @var{arg}. @end lilypond" (stencil-whiteout (interpret-markup layout props arg))) -(define-builtin-markup-command (pad-markup layout props amount arg) +(define-markup-command (pad-markup layout props amount arg) (number? markup?) - align - () + #:category align " @cindex padding text @cindex putting space around text @@ -364,10 +453,9 @@ Add space around a markup object. ;; space ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (strut layout props) - () - other +(define-markup-command (strut layout props) () + #:category other " @cindex creating vertical spaces in text @@ -379,10 +467,10 @@ Create a box of the same height as the space in the current font." ))) ;; todo: fix negative space -(define-builtin-markup-command (hspace layout props amount) +(define-markup-command (hspace layout props amount) (number?) - align - () + #:category align + #:properties ((word-space)) " @cindex creating horizontal spaces in text @@ -397,19 +485,45 @@ Create an invisible object taking up horizontal space @var{amount}. three } @end lilypond" - (if (> amount 0) - (ly:make-stencil "" (cons 0 amount) '(-1 . 1)) - (ly:make-stencil "" (cons amount amount) '(-1 . 1)))) + (let ((corrected-space (- amount word-space))) + (if (> corrected-space 0) + (ly:make-stencil "" (cons 0 corrected-space) '(0 . 0)) + (ly:make-stencil "" (cons corrected-space corrected-space) '(0 . 0))))) + +;; todo: fix negative space +(define-markup-command (vspace layout props amount) + (number?) + #:category align + " +@cindex creating vertical spaces in text + +Create an invisible object taking up vertical space +of @var{amount} multiplied by 3. + +@lilypond[verbatim,quote] +\\markup { + \\center-column { + one + \\vspace #2 + two + \\vspace #5 + three + } +} +@end lilypond" + (let ((amount (* amount 3.0))) + (if (> amount 0) + (ly:make-stencil "" (cons 0 0) (cons 0 amount)) + (ly:make-stencil "" (cons 0 0) (cons amount amount))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; importing graphics. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (stencil layout props stil) +(define-markup-command (stencil layout props stil) (ly:stencil?) - other - () + #:category other " @cindex importing stencils into text @@ -437,10 +551,9 @@ Use a stencil as markup. #f))) -(define-builtin-markup-command (epsfile layout props axis size file-name) +(define-markup-command (epsfile layout props axis size file-name) (number? number? string?) - graphic - () + #:category graphic " @cindex inlining an Encapsulated PostScript image @@ -460,10 +573,9 @@ Inline an EPS image. The image is scaled along @var{axis} to (eps-file->stencil axis size file-name) )) -(define-builtin-markup-command (postscript layout props str) +(define-markup-command (postscript layout props str) (string?) - graphic - () + #:category graphic " @cindex inserting PostScript directly into text This inserts @var{str} directly into the output as a PostScript @@ -501,10 +613,141 @@ grestore str)) '(0 . 0) '(0 . 0))) -(define-builtin-markup-command (score layout props score) +(define-markup-command (path layout props thickness commands) (number? list?) + #:category graphic + #:properties ((line-cap-style 'round) + (line-join-style 'round) + (filled #f)) + " +@cindex paths, drawing +@cindex drawing paths +Draws a path with line thickness @var{thickness} according to the +directions given in @var{commands}. @var{commands} is a list of +lists where the @code{car} of each sublist is a drawing command and +the @code{cdr} comprises the associated arguments for each command. + +Line-cap styles and line-join styles may be customized by +overriding the @code{line-cap-style} and @code{line-join-style} +properties, respectively. Available line-cap styles are +@code{'butt}, @code{'round}, and @code{'square}. Available +line-join styles are @code{'miter}, @code{'round}, and +@code{'bevel}. + +The property @code{filled} specifies whether or not the path is +filled with color. + +There are seven commands available to use in the list +@code{commands}: @code{moveto}, @code{rmoveto}, @code{lineto}, +@code{rlineto}, @code{curveto}, @code{rcurveto}, and +@code{closepath}. Note that the commands that begin with @emph{r} +are the relative variants of the other three commands. + +The commands @code{moveto}, @code{rmoveto}, @code{lineto}, and +@code{rlineto} take 2 arguments; they are the X and Y coordinates +for the destination point. + +The commands @code{curveto} and @code{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. + +The @code{closepath} command takes zero arguments and closes the +current subpath in the active path. + +Note that a sequence of commands @emph{must} begin with a +@code{moveto} or @code{rmoveto} to work with the SVG output. + +@lilypond[verbatim,quote] +samplePath = + #'((moveto 0 0) + (lineto -1 1) + (lineto 1 1) + (lineto 1 -1) + (curveto -5 -5 -5 5 -1 0) + (closepath)) + +\\markup { + \\path #0.25 #samplePath +} +@end lilypond" + (let* ((half-thickness (/ thickness 2)) + (current-point '(0 . 0)) + (set-point (lambda (lst) (set! current-point lst))) + (relative? (lambda (x) + (string-prefix? "r" (symbol->string (car x))))) + ;; For calculating extents, we want to modify the command + ;; list so that all coordinates are absolute. + (new-commands (map (lambda (x) + (cond + ;; for rmoveto, rlineto + ((and (relative? x) (eq? 3 (length x))) + (let ((cp (cons + (+ (car current-point) + (second x)) + (+ (cdr current-point) + (third x))))) + (set-point cp) + (list (car cp) + (cdr cp)))) + ;; for rcurveto + ((and (relative? x) (eq? 7 (length x))) + (let* ((old-cp current-point) + (cp (cons + (+ (car old-cp) + (sixth x)) + (+ (cdr old-cp) + (seventh x))))) + (set-point cp) + (list (+ (car old-cp) (second x)) + (+ (cdr old-cp) (third x)) + (+ (car old-cp) (fourth x)) + (+ (cdr old-cp) (fifth x)) + (car cp) + (cdr cp)))) + ;; for moveto, lineto + ((eq? 3 (length x)) + (set-point (cons (second x) + (third x))) + (drop x 1)) + ;; for curveto + ((eq? 7 (length x)) + (set-point (cons (sixth x) + (seventh x))) + (drop x 1)) + ;; keep closepath for filtering; + ;; see `without-closepath'. + (else x))) + commands)) + ;; path-min-max does not accept 0-arg lists, + ;; and since closepath does not affect extents, filter + ;; out those commands here. + (without-closepath (filter (lambda (x) + (not (equal? 'closepath (car x)))) + new-commands)) + (extents (path-min-max + ;; set the origin to the first moveto + (list (list-ref (car without-closepath) 0) + (list-ref (car without-closepath) 1)) + without-closepath)) + (X-extent (cons (list-ref extents 0) (list-ref extents 1))) + (Y-extent (cons (list-ref extents 2) (list-ref extents 3))) + (command-list (fold-right append '() commands))) + + ;; account for line thickness + (set! X-extent (interval-widen X-extent half-thickness)) + (set! Y-extent (interval-widen Y-extent half-thickness)) + + (ly:make-stencil + `(path ,thickness `(,@',command-list) + ',line-cap-style ',line-join-style ,filled) + X-extent + Y-extent))) + +(define-markup-command (score layout props score) (ly:score?) - music - () + #:category music + #:properties ((baseline-skip)) " @cindex inserting music into text @@ -549,19 +792,20 @@ Inline an image of music. } } @end lilypond" - (let* ((output (ly:score-embedded-format score layout))) + (let ((output (ly:score-embedded-format score layout))) (if (ly:music-output? output) - (paper-system-stencil - (vector-ref (ly:paper-score-paper-systems output) 0)) + (stack-stencils Y DOWN baseline-skip + (map paper-system-stencil + (vector->list + (ly:paper-score-paper-systems output)))) (begin (ly:warning (_"no systems found in \\score markup, does it have a \\layout block?")) empty-stencil)))) -(define-builtin-markup-command (null layout props) - () - other +(define-markup-command (null layout props) () + #:category other " @cindex creating empty text objects @@ -578,10 +822,9 @@ An empty markup with extents of a single point. ;; basic formatting. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (simple layout props str) +(define-markup-command (simple layout props str) (string?) - font - () + #:category font " @cindex simple text strings @@ -600,10 +843,9 @@ the use of @code{\\simple} is unnecessary. @end lilypond" (interpret-markup layout props str)) -(define-builtin-markup-command (tied-lyric layout props str) +(define-markup-command (tied-lyric layout props str) (string?) - music - () + #:category music " @cindex simple text strings with tie characters @@ -635,14 +877,16 @@ Like simple-markup, but use tie characters for @q{~} tilde symbols. (make-simple-markup "")) ;; helper for justifying lines. -(define (get-fill-space word-count line-width text-widths) +(define (get-fill-space word-count line-width word-space text-widths) "Calculate the necessary paddings between each two adjacent texts. - The lengths of all texts are stored in @var{text-widths}. - The normal formula for the padding between texts a and b is: - padding = line-width/(word-count - 1) - (length(a) + length(b))/2 - The first and last padding have to be calculated specially using the - whole length of the first or last text. - Return a list of paddings." + The lengths of all texts are stored in @var{text-widths}. + The normal formula for the padding between texts a and b is: + padding = line-width/(word-count - 1) - (length(a) + length(b))/2 + The first and last padding have to be calculated specially using the + whole length of the first or last text. + All paddings are checked to be at least word-space, to ensure that + no texts collide. + Return a list of paddings." (cond ((null? text-widths) '()) @@ -651,23 +895,27 @@ Like simple-markup, but use tie characters for @q{~} tilde symbols. (cons (- (- (/ line-width (1- word-count)) (car text-widths)) (/ (car (cdr text-widths)) 2)) - (get-fill-space word-count line-width (cdr text-widths)))) + (get-fill-space word-count line-width word-space (cdr text-widths)))) ;; special case last padding ((= (length text-widths) 2) (list (- (/ line-width (1- word-count)) (+ (/ (car text-widths) 2) (car (cdr text-widths)))) 0)) (else - (cons - (- (/ line-width (1- word-count)) - (/ (+ (car text-widths) (car (cdr text-widths))) 2)) - (get-fill-space word-count line-width (cdr text-widths)))))) - -(define-builtin-markup-command (fill-line layout props args) + (let ((default-padding + (- (/ line-width (1- word-count)) + (/ (+ (car text-widths) (car (cdr text-widths))) 2)))) + (cons + (if (> word-space default-padding) + word-space + default-padding) + (get-fill-space word-count line-width word-space (cdr text-widths))))))) + +(define-markup-command (fill-line layout props args) (markup-list?) - align - ((text-direction RIGHT) - (word-space 1) - (line-width #f)) + #:category align + #:properties ((text-direction RIGHT) + (word-space 0.6) + (line-width #f)) "Put @var{markups} in a horizontal line of width @var{line-width}. The markups are spaced or flushed to fill the entire line. If there are no arguments, return an empty stencil. @@ -690,59 +938,64 @@ If there are no arguments, return an empty stencil. } @end lilypond" (let* ((orig-stencils (interpret-markup-list layout props args)) - (stencils - (map (lambda (stc) - (if (ly:stencil-empty? stc) - point-stencil - stc)) orig-stencils)) - (text-widths - (map (lambda (stc) - (if (ly:stencil-empty? stc) - 0.0 - (interval-length (ly:stencil-extent stc X)))) - stencils)) - (text-width (apply + text-widths)) - (word-count (length stencils)) - (prop-line-width (chain-assoc-get 'line-width props #f)) - (line-width (or line-width (ly:output-def-lookup layout 'line-width))) - (fill-space - (cond - ((= word-count 1) - (list - (/ (- line-width text-width) 2) - (/ (- line-width text-width) 2))) - ((= word-count 2) - (list - (- line-width text-width))) - (else - (get-fill-space word-count line-width text-widths)))) - (fill-space-normal - (map (lambda (x) - (if (< x word-space) - word-space - x)) - fill-space)) - - (line-stencils (if (= word-count 1) - (list - point-stencil - (car stencils) - point-stencil) - stencils))) - - (if (= text-direction LEFT) - (set! line-stencils (reverse line-stencils))) + (stencils + (map (lambda (stc) + (if (ly:stencil-empty? stc) + point-stencil + stc)) orig-stencils)) + (text-widths + (map (lambda (stc) + (if (ly:stencil-empty? stc) + 0.0 + (interval-length (ly:stencil-extent stc X)))) + stencils)) + (text-width (apply + text-widths)) + (word-count (length stencils)) + (line-width (or line-width (ly:output-def-lookup layout 'line-width))) + (fill-space + (cond + ((= word-count 1) + (list + (/ (- line-width text-width) 2) + (/ (- line-width text-width) 2))) + ((= word-count 2) + (list + (- line-width text-width))) + (else + (get-fill-space word-count line-width word-space text-widths)))) + + (line-contents (if (= word-count 1) + (list + point-stencil + (car stencils) + point-stencil) + stencils))) (if (null? (remove ly:stencil-empty? orig-stencils)) - empty-stencil - (stack-stencils-padding-list X - RIGHT fill-space-normal line-stencils)))) - -(define-builtin-markup-command (line layout props args) + empty-stencil + (begin + (if (= text-direction LEFT) + (set! line-contents (reverse line-contents))) + (set! line-contents + (stack-stencils-padding-list + X RIGHT fill-space line-contents)) + (if (> word-count 1) + ;; shift s.t. stencils align on the left edge, even if + ;; first stencil had negative X-extent (e.g. center-column) + ;; (if word-count = 1, X-extents are already normalized in + ;; the definition of line-contents) + (set! line-contents + (ly:stencil-translate-axis + line-contents + (- (car (ly:stencil-extent (car stencils) X))) + X))) + line-contents)))) + +(define-markup-command (line layout props args) (markup-list?) - align - ((word-space) - (text-direction RIGHT)) + #:category align + #:properties ((word-space) + (text-direction RIGHT)) "Put @var{args} in a horizontal line. The property @code{word-space} determines the space between markups in @var{args}. @@ -760,10 +1013,9 @@ determines the space between markups in @var{args}. word-space (remove ly:stencil-empty? stencils)))) -(define-builtin-markup-command (concat layout props args) +(define-markup-command (concat layout props args) (markup-list?) - align - () + #:category align " @cindex concatenating text @cindex ligatures in text @@ -855,11 +1107,11 @@ equivalent to @code{\"fi\"}. X))) (reverse (cons line lines))))))) -(define-builtin-markup-list-command (wordwrap-internal layout props justify args) +(define-markup-list-command (wordwrap-internal layout props justify args) (boolean? markup-list?) - ((line-width #f) - (word-space) - (text-direction RIGHT)) + #:properties ((line-width #f) + (word-space) + (text-direction RIGHT)) "Internal markup list command used to define @code{\\justify} and @code{\\wordwrap}." (wordwrap-stencils (remove ly:stencil-empty? (interpret-markup-list layout props args)) @@ -869,11 +1121,11 @@ equivalent to @code{\"fi\"}. (ly:output-def-lookup layout 'line-width)) text-direction)) -(define-builtin-markup-command (justify layout props args) +(define-markup-command (justify layout props args) (markup-list?) - align - ((baseline-skip) - wordwrap-internal-markup-list) + #:category align + #:properties ((baseline-skip) + wordwrap-internal-markup-list) " @cindex justifying text @@ -894,11 +1146,11 @@ Use @code{\\override #'(line-width . @var{X})} to set the line width; (stack-lines DOWN 0.0 baseline-skip (wordwrap-internal-markup-list layout props #t args))) -(define-builtin-markup-command (wordwrap layout props args) +(define-markup-command (wordwrap layout props args) (markup-list?) - align - ((baseline-skip) - wordwrap-internal-markup-list) + #:category align + #:properties ((baseline-skip) + wordwrap-internal-markup-list) "Simple wordwrap. Use @code{\\override #'(line-width . @var{X})} to set the line width, where @var{X} is the number of staff spaces. @@ -915,11 +1167,11 @@ the line width, where @var{X} is the number of staff spaces. (stack-lines DOWN 0.0 baseline-skip (wordwrap-internal-markup-list layout props #f args))) -(define-builtin-markup-list-command (wordwrap-string-internal layout props justify arg) +(define-markup-list-command (wordwrap-string-internal layout props justify arg) (boolean? string?) - ((line-width) - (word-space) - (text-direction RIGHT)) + #:properties ((line-width) + (word-space) + (text-direction RIGHT)) "Internal markup list command used to define @code{\\justify-string} and @code{\\wordwrap-string}." (let* ((para-strings (regexp-split @@ -942,11 +1194,11 @@ the line width, where @var{X} is the number of staff spaces. list-para-words))) (apply append para-lines))) -(define-builtin-markup-command (wordwrap-string layout props arg) +(define-markup-command (wordwrap-string layout props arg) (string?) - align - ((baseline-skip) - wordwrap-string-internal-markup-list) + #:category align + #:properties ((baseline-skip) + wordwrap-string-internal-markup-list) "Wordwrap a string. Paragraphs may be separated with double newlines. @lilypond[verbatim,quote] @@ -968,11 +1220,11 @@ the line width, where @var{X} is the number of staff spaces. (stack-lines DOWN 0.0 baseline-skip (wordwrap-string-internal-markup-list layout props #f arg))) -(define-builtin-markup-command (justify-string layout props arg) +(define-markup-command (justify-string layout props arg) (string?) - align - ((baseline-skip) - wordwrap-string-internal-markup-list) + #:category align + #:properties ((baseline-skip) + wordwrap-string-internal-markup-list) "Justify a string. Paragraphs may be separated with double newlines @lilypond[verbatim,quote] @@ -994,10 +1246,9 @@ the line width, where @var{X} is the number of staff spaces. (stack-lines DOWN 0.0 baseline-skip (wordwrap-string-internal-markup-list layout props #t arg))) -(define-builtin-markup-command (wordwrap-field layout props symbol) +(define-markup-command (wordwrap-field layout props symbol) (symbol?) - align - () + #:category align "Wordwrap the data which has been assigned to @var{symbol}. @lilypond[verbatim,quote] @@ -1028,10 +1279,9 @@ the line width, where @var{X} is the number of staff spaces. (wordwrap-string-markup layout props m) empty-stencil))) -(define-builtin-markup-command (justify-field layout props symbol) +(define-markup-command (justify-field layout props symbol) (symbol?) - align - () + #:category align "Justify the data which has been assigned to @var{symbol}. @lilypond[verbatim,quote] @@ -1062,10 +1312,9 @@ the line width, where @var{X} is the number of staff spaces. (justify-string-markup layout props m) empty-stencil))) -(define-builtin-markup-command (combine layout props arg1 arg2) +(define-markup-command (combine layout props arg1 arg2) (markup? markup?) - align - () + #:category align " @cindex merging text @@ -1094,10 +1343,10 @@ curly braces as an argument; the follow example will not compile: ;; ;; TODO: should extract baseline-skip from each argument somehow.. ;; -(define-builtin-markup-command (column layout props args) +(define-markup-command (column layout props args) (markup-list?) - align - ((baseline-skip)) + #:category align + #:properties ((baseline-skip)) " @cindex stacking text in a column @@ -1118,11 +1367,11 @@ in @var{args}. (stack-lines -1 0.0 baseline-skip (remove ly:stencil-empty? arg-stencils)))) -(define-builtin-markup-command (dir-column layout props args) +(define-markup-command (dir-column layout props args) (markup-list?) - align - ((direction) - (baseline-skip)) + #:category align + #:properties ((direction) + (baseline-skip)) " @cindex changing direction of text columns @@ -1159,10 +1408,10 @@ setting of the @code{direction} layout property. (let* ((aligned-mols (map (lambda (x) (ly:stencil-aligned-to x X align-dir)) mols))) (stack-lines -1 0.0 baseline aligned-mols))) -(define-builtin-markup-command (center-column layout props args) +(define-markup-command (center-column layout props args) (markup-list?) - align - ((baseline-skip)) + #:category align + #:properties ((baseline-skip)) " @cindex centering a column of text @@ -1179,10 +1428,10 @@ Put @code{args} in a centered column. @end lilypond" (general-column CENTER baseline-skip (interpret-markup-list layout props args))) -(define-builtin-markup-command (left-column layout props args) +(define-markup-command (left-column layout props args) (markup-list?) - align - ((baseline-skip)) + #:category align + #:properties ((baseline-skip)) " @cindex text columns, left-aligned @@ -1199,10 +1448,10 @@ Put @code{args} in a left-aligned column. @end lilypond" (general-column LEFT baseline-skip (interpret-markup-list layout props args))) -(define-builtin-markup-command (right-column layout props args) +(define-markup-command (right-column layout props args) (markup-list?) - align - ((baseline-skip)) + #:category align + #:properties ((baseline-skip)) " @cindex text columns, right-aligned @@ -1219,10 +1468,9 @@ Put @code{args} in a right-aligned column. @end lilypond" (general-column RIGHT baseline-skip (interpret-markup-list layout props args))) -(define-builtin-markup-command (vcenter layout props arg) +(define-markup-command (vcenter layout props arg) (markup?) - align - () + #:category align " @cindex vertically centering text @@ -1239,10 +1487,9 @@ Align @code{arg} to its Y@tie{}center. (let* ((mol (interpret-markup layout props arg))) (ly:stencil-aligned-to mol Y CENTER))) -(define-builtin-markup-command (center-align layout props arg) +(define-markup-command (center-align layout props arg) (markup?) - align - () + #:category align " @cindex horizontally centering text @@ -1261,10 +1508,9 @@ Align @code{arg} to its X@tie{}center. (let* ((mol (interpret-markup layout props arg))) (ly:stencil-aligned-to mol X CENTER))) -(define-builtin-markup-command (right-align layout props arg) +(define-markup-command (right-align layout props arg) (markup?) - align - () + #:category align " @cindex right aligning text @@ -1283,10 +1529,9 @@ Align @var{arg} on its right edge. (let* ((m (interpret-markup layout props arg))) (ly:stencil-aligned-to m X RIGHT))) -(define-builtin-markup-command (left-align layout props arg) +(define-markup-command (left-align layout props arg) (markup?) - align - () + #:category align " @cindex left aligning text @@ -1305,10 +1550,9 @@ Align @var{arg} on its left edge. (let* ((m (interpret-markup layout props arg))) (ly:stencil-aligned-to m X LEFT))) -(define-builtin-markup-command (general-align layout props axis dir arg) +(define-markup-command (general-align layout props axis dir arg) (integer? number? markup?) - align - () + #:category align " @cindex controlling general text alignment @@ -1346,10 +1590,9 @@ Align @var{arg} in @var{axis} direction to the @var{dir} side. (let* ((m (interpret-markup layout props arg))) (ly:stencil-aligned-to m axis dir))) -(define-builtin-markup-command (halign layout props dir arg) +(define-markup-command (halign layout props dir arg) (number? markup?) - align - () + #:category align " @cindex setting horizontal text alignment @@ -1385,10 +1628,9 @@ alignment accordingly. (let* ((m (interpret-markup layout props arg))) (ly:stencil-aligned-to m X dir))) -(define-builtin-markup-command (with-dimensions layout props x y arg) +(define-markup-command (with-dimensions layout props x y arg) (number-pair? number-pair? markup?) - other - () + #:category other " @cindex setting extent of text objects @@ -1396,10 +1638,9 @@ Set the dimensions of @var{arg} to @var{x} and@tie{}@var{y}." (let* ((m (interpret-markup layout props arg))) (ly:make-stencil (ly:stencil-expr m) x y))) -(define-builtin-markup-command (pad-around layout props amount arg) +(define-markup-command (pad-around layout props amount arg) (number? markup?) - align - () + #:category align "Add padding @var{amount} all around @var{arg}. @lilypond[verbatim,quote] @@ -1422,10 +1663,9 @@ Set the dimensions of @var{arg} to @var{x} and@tie{}@var{y}." (interval-widen x amount) (interval-widen y amount)))) -(define-builtin-markup-command (pad-x layout props amount arg) +(define-markup-command (pad-x layout props amount arg) (number? markup?) - align - () + #:category align " @cindex padding text horizontally @@ -1451,19 +1691,17 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction. (interval-widen x amount) y))) -(define-builtin-markup-command (put-adjacent layout props axis dir arg1 arg2) +(define-markup-command (put-adjacent layout props axis dir arg1 arg2) (integer? ly:dir? markup? markup?) - align - () + #:category align "Put @var{arg2} next to @var{arg1}, without moving @var{arg1}." (let ((m1 (interpret-markup layout props arg1)) (m2 (interpret-markup layout props arg2))) (ly:stencil-combine-at-edge m1 axis dir m2 0.0))) -(define-builtin-markup-command (transparent layout props arg) +(define-markup-command (transparent layout props arg) (markup?) - other - () + #:category other "Make @var{arg} transparent. @lilypond[verbatim,quote] @@ -1478,10 +1716,9 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction. (y (ly:stencil-extent m Y))) (ly:make-stencil "" x y))) -(define-builtin-markup-command (pad-to-box layout props x-ext y-ext arg) +(define-markup-command (pad-to-box layout props x-ext y-ext arg) (number-pair? number-pair? markup?) - align - () + #:category align "Make @var{arg} take at least @var{x-ext}, @var{y-ext} space. @lilypond[verbatim,quote] @@ -1504,10 +1741,9 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction. (interval-union x-ext x) (interval-union y-ext y)))) -(define-builtin-markup-command (hcenter-in layout props length arg) +(define-markup-command (hcenter-in layout props length arg) (number? markup?) - align - () + #:category align "Center @var{arg} horizontally within a box of extending @var{length}/2 to the left and right. @@ -1540,10 +1776,9 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction. ;; property ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (fromproperty layout props symbol) +(define-markup-command (fromproperty layout props symbol) (symbol?) - other - () + #:category other "Read the @var{symbol} from property settings, and produce a stencil from the markup contained within. If @var{symbol} is not defined, it returns an empty markup. @@ -1566,10 +1801,9 @@ returns an empty markup. (interpret-markup layout props m) empty-stencil))) -(define-builtin-markup-command (on-the-fly layout props procedure arg) +(define-markup-command (on-the-fly layout props procedure arg) (symbol? markup?) - other - () + #:category other "Apply the @var{procedure} markup command to @var{arg}. @var{procedure} should take a single argument." (let ((anonymous-with-signature (lambda (layout props arg) (procedure layout props arg)))) @@ -1578,10 +1812,9 @@ returns an empty markup. (list markup?)) (interpret-markup layout props (list anonymous-with-signature arg)))) -(define-builtin-markup-command (override layout props new-prop arg) +(define-markup-command (override layout props new-prop arg) (pair? markup?) - other - () + #:category other " @cindex overriding properties within text markup @@ -1613,10 +1846,9 @@ may be any property supported by @rinternals{font-interface}, ;; files ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (verbatim-file layout props name) +(define-markup-command (verbatim-file layout props name) (string?) - other - () + #:category other "Read the contents of file @var{name}, and include it verbatim. @lilypond[verbatim,quote] @@ -1637,10 +1869,9 @@ may be any property supported by @rinternals{font-interface}, ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (smaller layout props arg) +(define-markup-command (smaller layout props arg) (markup?) - font - () + #:category font "Decrease the font size relative to the current setting. @lilypond[verbatim,quote] @@ -1659,10 +1890,9 @@ may be any property supported by @rinternals{font-interface}, (interpret-markup layout props `(,fontsize-markup -1 ,arg))) -(define-builtin-markup-command (larger layout props arg) +(define-markup-command (larger layout props arg) (markup?) - font - () + #:category font "Increase the font size relative to the current setting. @lilypond[verbatim,quote] @@ -1676,10 +1906,9 @@ may be any property supported by @rinternals{font-interface}, (interpret-markup layout props `(,fontsize-markup 1 ,arg))) -(define-builtin-markup-command (finger layout props arg) +(define-markup-command (finger layout props arg) (markup?) - font - () + #:category font "Set @var{arg} as small numbers. @lilypond[verbatim,quote] @@ -1690,13 +1919,12 @@ may be any property supported by @rinternals{font-interface}, } @end lilypond" (interpret-markup layout - (cons '((font-size . -5) (font-encoding . fetaNumber)) props) + (cons '((font-size . -5) (font-encoding . fetaText)) props) arg)) -(define-builtin-markup-command (abs-fontsize layout props size arg) +(define-markup-command (abs-fontsize layout props size arg) (number? markup?) - font - () + #:category font "Use @var{size} as the absolute font size to display @var{arg}. Adjusts @code{baseline-skip} and @code{word-space} accordingly. @@ -1721,12 +1949,12 @@ Adjusts @code{baseline-skip} and @code{word-space} accordingly. props) arg))) -(define-builtin-markup-command (fontsize layout props increment arg) +(define-markup-command (fontsize layout props increment arg) (number? markup?) - font - ((font-size 0) - (word-space 1) - (baseline-skip 2)) + #:category font + #:properties ((font-size 0) + (word-space 1) + (baseline-skip 2)) "Add @var{increment} to the font-size. Adjusts @code{baseline-skip} accordingly. @@ -1744,10 +1972,9 @@ accordingly. (cons 'font-size (+ font-size increment))))) (interpret-markup layout (cons entries props) arg))) -(define-builtin-markup-command (magnify layout props sz arg) +(define-markup-command (magnify layout props sz arg) (number? markup?) - font - () + #:category font " @cindex magnifying text @@ -1775,10 +2002,9 @@ Use @code{\\fontsize} otherwise. (prepend-alist-chain 'font-size (magnification->font-size sz) props) arg)) -(define-builtin-markup-command (bold layout props arg) +(define-markup-command (bold layout props arg) (markup?) - font - () + #:category font "Switch to bold font-series. @lilypond[verbatim,quote] @@ -1791,10 +2017,9 @@ Use @code{\\fontsize} otherwise. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-series 'bold props) arg)) -(define-builtin-markup-command (sans layout props arg) +(define-markup-command (sans layout props arg) (markup?) - font - () + #:category font "Switch to the sans serif font family. @lilypond[verbatim,quote] @@ -1808,10 +2033,9 @@ Use @code{\\fontsize} otherwise. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-family 'sans props) arg)) -(define-builtin-markup-command (number layout props arg) +(define-markup-command (number layout props arg) (markup?) - font - () + #:category font "Set font family to @code{number}, which yields the font used for time signatures and fingerings. This font contains numbers and some punctuation; it has no letters. @@ -1823,12 +2047,11 @@ some punctuation; it has no letters. } } @end lilypond" - (interpret-markup layout (prepend-alist-chain 'font-encoding 'fetaNumber props) arg)) + (interpret-markup layout (prepend-alist-chain 'font-encoding 'fetaText props) arg)) -(define-builtin-markup-command (roman layout props arg) +(define-markup-command (roman layout props arg) (markup?) - font - () + #:category font "Set font family to @code{roman}. @lilypond[verbatim,quote] @@ -1846,10 +2069,9 @@ some punctuation; it has no letters. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-family 'roman props) arg)) -(define-builtin-markup-command (huge layout props arg) +(define-markup-command (huge layout props arg) (markup?) - font - () + #:category font "Set font size to +2. @lilypond[verbatim,quote] @@ -1862,10 +2084,9 @@ some punctuation; it has no letters. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-size 2 props) arg)) -(define-builtin-markup-command (large layout props arg) +(define-markup-command (large layout props arg) (markup?) - font - () + #:category font "Set font size to +1. @lilypond[verbatim,quote] @@ -1878,10 +2099,9 @@ some punctuation; it has no letters. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-size 1 props) arg)) -(define-builtin-markup-command (normalsize layout props arg) +(define-markup-command (normalsize layout props arg) (markup?) - font - () + #:category font "Set font size to default. @lilypond[verbatim,quote] @@ -1899,10 +2119,9 @@ some punctuation; it has no letters. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-size 0 props) arg)) -(define-builtin-markup-command (small layout props arg) +(define-markup-command (small layout props arg) (markup?) - font - () + #:category font "Set font size to -1. @lilypond[verbatim,quote] @@ -1915,10 +2134,9 @@ some punctuation; it has no letters. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-size -1 props) arg)) -(define-builtin-markup-command (tiny layout props arg) +(define-markup-command (tiny layout props arg) (markup?) - font - () + #:category font "Set font size to -2. @lilypond[verbatim,quote] @@ -1931,10 +2149,9 @@ some punctuation; it has no letters. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-size -2 props) arg)) -(define-builtin-markup-command (teeny layout props arg) +(define-markup-command (teeny layout props arg) (markup?) - font - () + #:category font "Set font size to -3. @lilypond[verbatim,quote] @@ -1947,10 +2164,9 @@ some punctuation; it has no letters. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-size -3 props) arg)) -(define-builtin-markup-command (fontCaps layout props arg) +(define-markup-command (fontCaps layout props arg) (markup?) - font - () + #:category font "Set @code{font-shape} to @code{caps} Note: @code{\\fontCaps} requires the installation and selection of @@ -1958,10 +2174,9 @@ fonts which support the @code{caps} font shape." (interpret-markup layout (prepend-alist-chain 'font-shape 'caps props) arg)) ;; Poor man's caps -(define-builtin-markup-command (smallCaps layout props arg) +(define-markup-command (smallCaps layout props arg) (markup?) - font - () + #:category font "Emit @var{arg} as small caps. Note: @code{\\smallCaps} does not support accented characters. @@ -2006,10 +2221,9 @@ Note: @code{\\smallCaps} does not support accented characters. (make-small-caps (string->list arg) (list) #f (list)) arg))) -(define-builtin-markup-command (caps layout props arg) +(define-markup-command (caps layout props arg) (markup?) - font - () + #:category font "Copy of the @code{\\smallCaps} command. @lilypond[verbatim,quote] @@ -2023,10 +2237,9 @@ Note: @code{\\smallCaps} does not support accented characters. @end lilypond" (interpret-markup layout props (make-smallCaps-markup arg))) -(define-builtin-markup-command (dynamic layout props arg) +(define-markup-command (dynamic layout props arg) (markup?) - font - () + #:category font "Use the dynamic font. This font only contains @b{s}, @b{f}, @b{m}, @b{z}, @b{p}, and @b{r}. When producing phrases, like @q{pi@`{u}@tie{}@b{f}}, the normal words (like @q{pi@`{u}}) should be @@ -2039,12 +2252,11 @@ done in a different font. The recommended font for this is bold and italic. } @end lilypond" (interpret-markup - layout (prepend-alist-chain 'font-encoding 'fetaDynamic props) arg)) + layout (prepend-alist-chain 'font-encoding 'fetaText props) arg)) -(define-builtin-markup-command (text layout props arg) +(define-markup-command (text layout props arg) (markup?) - font - () + #:category font "Use a text font instead of music symbol or music alphabet font. @lilypond[verbatim,quote] @@ -2063,10 +2275,9 @@ done in a different font. The recommended font for this is bold and italic. (interpret-markup layout (prepend-alist-chain 'font-encoding 'latin1 props) arg)) -(define-builtin-markup-command (italic layout props arg) +(define-markup-command (italic layout props arg) (markup?) - font - () + #:category font "Use italic @code{font-shape} for @var{arg}. @lilypond[verbatim,quote] @@ -2079,10 +2290,9 @@ done in a different font. The recommended font for this is bold and italic. @end lilypond" (interpret-markup layout (prepend-alist-chain 'font-shape 'italic props) arg)) -(define-builtin-markup-command (typewriter layout props arg) +(define-markup-command (typewriter layout props arg) (markup?) - font - () + #:category font "Use @code{font-family} typewriter for @var{arg}. @lilypond[verbatim,quote] @@ -2096,10 +2306,9 @@ done in a different font. The recommended font for this is bold and italic. (interpret-markup layout (prepend-alist-chain 'font-family 'typewriter props) arg)) -(define-builtin-markup-command (upright layout props arg) +(define-markup-command (upright layout props arg) (markup?) - font - () + #:category font "Set @code{font-shape} to @code{upright}. This is the opposite of @code{italic}. @@ -2119,10 +2328,9 @@ of @code{italic}. (interpret-markup layout (prepend-alist-chain 'font-shape 'upright props) arg)) -(define-builtin-markup-command (medium layout props arg) +(define-markup-command (medium layout props arg) (markup?) - font - () + #:category font "Switch to medium font-series (in contrast to bold). @lilypond[verbatim,quote] @@ -2141,10 +2349,9 @@ of @code{italic}. (interpret-markup layout (prepend-alist-chain 'font-series 'medium props) arg)) -(define-builtin-markup-command (normal-text layout props arg) +(define-markup-command (normal-text layout props arg) (markup?) - font - () + #:category font "Set all font related properties (except the size) to get the default normal text font, no matter what font was used earlier. @@ -2172,10 +2379,9 @@ normal text font, no matter what font was used earlier. ;; symbols. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (doublesharp layout props) - () - music +(define-markup-command (doublesharp layout props) () + #:category music "Draw a double sharp symbol. @lilypond[verbatim,quote] @@ -2185,10 +2391,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get 1 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (sesquisharp layout props) - () - music +(define-markup-command (sesquisharp layout props) () + #:category music "Draw a 3/2 sharp symbol. @lilypond[verbatim,quote] @@ -2198,10 +2403,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get 3/4 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (sharp layout props) - () - music +(define-markup-command (sharp layout props) () + #:category music "Draw a sharp symbol. @lilypond[verbatim,quote] @@ -2211,10 +2415,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get 1/2 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (semisharp layout props) - () - music +(define-markup-command (semisharp layout props) () + #:category music "Draw a semisharp symbol. @lilypond[verbatim,quote] @@ -2224,10 +2427,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get 1/4 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (natural layout props) - () - music +(define-markup-command (natural layout props) () + #:category music "Draw a natural symbol. @lilypond[verbatim,quote] @@ -2237,10 +2439,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get 0 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (semiflat layout props) - () - music +(define-markup-command (semiflat layout props) () + #:category music "Draw a semiflat symbol. @lilypond[verbatim,quote] @@ -2250,10 +2451,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get -1/4 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (flat layout props) - () - music +(define-markup-command (flat layout props) () + #:category music "Draw a flat symbol. @lilypond[verbatim,quote] @@ -2263,10 +2463,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get -1/2 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (sesquiflat layout props) - () - music +(define-markup-command (sesquiflat layout props) () + #:category music "Draw a 3/2 flat symbol. @lilypond[verbatim,quote] @@ -2276,10 +2475,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get -3/4 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (doubleflat layout props) - () - music +(define-markup-command (doubleflat layout props) () + #:category music "Draw a double flat symbol. @lilypond[verbatim,quote] @@ -2289,10 +2487,9 @@ normal text font, no matter what font was used earlier. @end lilypond" (interpret-markup layout props (markup #:musicglyph (assoc-get -1 standard-alteration-glyph-name-alist "")))) -(define-builtin-markup-command (with-color layout props color arg) +(define-markup-command (with-color layout props color arg) (color? markup?) - other - () + #:category other " @cindex coloring text @@ -2319,10 +2516,9 @@ Draw @var{arg} in color specified by @var{color}. ;; glyphs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (arrow-head layout props axis dir filled) +(define-markup-command (arrow-head layout props axis dir filled) (integer? ly:dir? boolean?) - graphic - () + #:category graphic "Produce an arrow head in specified direction and axis. Use the filled head if @var{filled} is specified. @lilypond[verbatim,quote] @@ -2350,10 +2546,9 @@ Use the filled head if @var{filled} is specified. props)) name))) -(define-builtin-markup-command (musicglyph layout props glyph-name) +(define-markup-command (musicglyph layout props glyph-name) (string?) - music - () + #:category music "@var{glyph-name} is converted to a musical symbol; for example, @code{\\musicglyph #\"accidentals.natural\"} selects the natural sign from the music font. See @ruser{The Feta font} for a complete listing of @@ -2378,10 +2573,9 @@ the possible glyphs. glyph)) -(define-builtin-markup-command (lookup layout props glyph-name) +(define-markup-command (lookup layout props glyph-name) (string?) - other - () + #:category other "Lookup a glyph by name. @lilypond[verbatim,quote] @@ -2397,10 +2591,9 @@ the possible glyphs. (ly:font-get-glyph (ly:paper-get-font layout props) glyph-name)) -(define-builtin-markup-command (char layout props num) +(define-markup-command (char layout props num) (integer?) - other - () + #:category other "Produce a single character. Characters encoded in hexadecimal format require the prefix @code{#x}. @@ -2433,10 +2626,9 @@ format require the prefix @code{#x}. (number->markletter-string vec (remainder n lst))) (make-string 1 (vector-ref vec n))))) -(define-builtin-markup-command (markletter layout props num) +(define-markup-command (markletter layout props num) (integer?) - other - () + #:category other "Make a markup letter for @var{num}. The letters start with A to@tie{}Z (skipping letter@tie{}I), and continue with double letters. @@ -2450,10 +2642,9 @@ format require the prefix @code{#x}. (ly:text-interface::interpret-markup layout props (number->markletter-string number->mark-letter-vector num))) -(define-builtin-markup-command (markalphabet layout props num) +(define-markup-command (markalphabet layout props num) (integer?) - other - () + #:category other "Make a markup letter for @var{num}. The letters start with A to@tie{}Z and continue with double letters. @@ -2504,7 +2695,7 @@ and continue with double letters. ; backward slashes might use slope and point in the other direction! (dy (* mag (if forward 0.4 -0.4))) (number-stencil (interpret-markup layout - (prepend-alist-chain 'font-encoding 'fetaNumber props) + (prepend-alist-chain 'font-encoding 'fetaText props) (number->string num))) (num-x (horizontal-slash-interval num forward (ly:stencil-extent number-stencil X) mag)) (center (interval-center (ly:stencil-extent number-stencil Y))) @@ -2528,11 +2719,11 @@ and continue with double letters. number-stencil)) -(define-builtin-markup-command (slashed-digit layout props num) +(define-markup-command (slashed-digit layout props num) (integer?) - other - ((font-size 0) - (thickness 1.6)) + #:category other + #:properties ((font-size 0) + (thickness 1.6)) " @cindex slashed digits @@ -2548,11 +2739,11 @@ figured bass notation. @end lilypond" (slashed-digit-internal layout props num #t font-size thickness)) -(define-builtin-markup-command (backslashed-digit layout props num) +(define-markup-command (backslashed-digit layout props num) (integer?) - other - ((font-size 0) - (thickness 1.6)) + #:category other + #:properties ((font-size 0) + (thickness 1.6)) " @cindex backslashed digits @@ -2569,39 +2760,43 @@ figured bass notation. (slashed-digit-internal layout props num #f font-size thickness)) ;; eyeglasses -(define eyeglassesps - "0.15 setlinewidth - -0.9 0 translate - 1.1 1.1 scale - 1.2 0.7 moveto - 0.7 0.7 0.5 0 361 arc - stroke - 2.20 0.70 0.50 0 361 arc - stroke - 1.45 0.85 0.30 0 180 arc - stroke - 0.20 0.70 moveto - 0.80 2.00 lineto - 0.92 2.26 1.30 2.40 1.15 1.70 curveto - stroke - 2.70 0.70 moveto - 3.30 2.00 lineto - 3.42 2.26 3.80 2.40 3.65 1.70 curveto - stroke") - -(define-builtin-markup-command (eyeglasses layout props) () other () +(define eyeglassespath + '((moveto 0.42 0.77) + (rcurveto 0 0.304 -0.246 0.55 -0.55 0.55) + (rcurveto -0.304 0 -0.55 -0.246 -0.55 -0.55) + (rcurveto 0 -0.304 0.246 -0.55 0.55 -0.55) + (rcurveto 0.304 0 0.55 0.246 0.55 0.55) + (closepath) + (moveto 2.07 0.77) + (rcurveto 0 0.304 -0.246 0.55 -0.55 0.55) + (rcurveto -0.304 0 -0.55 -0.246 -0.55 -0.55) + (rcurveto 0 -0.304 0.246 -0.55 0.55 -0.55) + (rcurveto 0.304 0 0.55 0.246 0.55 0.55) + (closepath) + (moveto 1.025 0.935) + (rcurveto 0 0.182 -0.148 0.33 -0.33 0.33) + (rcurveto -0.182 0 -0.33 -0.148 -0.33 -0.33) + (moveto -0.68 0.77) + (rlineto 0.66 1.43) + (rcurveto 0.132 0.286 0.55 0.44 0.385 -0.33) + (moveto 2.07 0.77) + (rlineto 0.66 1.43) + (rcurveto 0.132 0.286 0.55 0.44 0.385 -0.33))) + +(define-markup-command (eyeglasses layout props) + () + #:category other "Prints out eyeglasses, indicating strongly to look at the conductor. @lilypond[verbatim,quote] \\markup { \\eyeglasses } @end lilypond" (interpret-markup layout props - (make-with-dimensions-markup '(-0.61 . 3.22) '(0.2 . 2.41) - (make-postscript-markup eyeglassesps)))) + (make-override-markup '(line-cap-style . butt) + (make-path-markup 0.15 eyeglassespath)))) -(define-builtin-markup-command (left-brace layout props size) +(define-markup-command (left-brace layout props size) (number?) - other - () + #:category other " A feta brace in point size @var{size}. @@ -2640,10 +2835,9 @@ A feta brace in point size @var{size}. (ly:pt 1))))) glyph-found)) -(define-builtin-markup-command (right-brace layout props size) +(define-markup-command (right-brace layout props size) (number?) - other - () + #:category other " A feta brace in point size @var{size}, rotated 180 degrees. @@ -2662,11 +2856,11 @@ A feta brace in point size @var{size}, rotated 180 degrees. ;; TODO: better syntax. -(define-builtin-markup-command (note-by-number layout props log dot-count dir) +(define-markup-command (note-by-number layout props log dot-count dir) (number? number? number?) - music - ((font-size 0) - (style '())) + #:category music + #:properties ((font-size 0) + (style '())) " @cindex notes within text by log and dot-count @@ -2682,25 +2876,36 @@ Construct a note symbol, with stem. By using fractional values for @end lilypond" (define (get-glyph-name-candidates dir log style) (map (lambda (dir-name) - (format "noteheads.~a~a~a" dir-name (min log 2) - (if (and (symbol? style) - (not (equal? 'default style))) - (symbol->string style) - ""))) + (format "noteheads.~a~a" dir-name + (if (and (symbol? style) + (not (equal? 'default style))) + (select-head-glyph style (min log 2)) + (min log 2)))) (list (if (= dir UP) "u" "d") "s"))) (define (get-glyph-name font cands) (if (null? cands) - "" - (if (ly:stencil-empty? (ly:font-get-glyph font (car cands))) - (get-glyph-name font (cdr cands)) - (car cands)))) + "" + (if (ly:stencil-empty? (ly:font-get-glyph font (car cands))) + (get-glyph-name font (cdr cands)) + (car cands)))) - (let* ((font (ly:paper-get-font layout (cons '((font-encoding . fetaMusic)) props))) + (let* ((font (ly:paper-get-font layout (cons '((font-encoding . fetaMusic)) + props))) (size-factor (magstep font-size)) - (stem-length (* size-factor (max 3 (- log 1)))) - (head-glyph-name (get-glyph-name font (get-glyph-name-candidates (sign dir) log style))) + (stem-length (* size-factor (max 3 (- log 1)))) + (head-glyph-name + (let ((result (get-glyph-name font (get-glyph-name-candidates + (sign dir) log style)))) + (if (string-null? result) + ;; If no glyph name can be found, select default heads. Though + ;; this usually means an unsupported style has been chosen, it + ;; also prevents unrelated 'style settings from other grobs + ;; (e.g., TextSpanner and TimeSignature) leaking into markup. + (get-glyph-name font (get-glyph-name-candidates + (sign dir) log 'default)) + result))) (head-glyph (ly:font-get-glyph font head-glyph-name)) (attach-indices (ly:note-head::stem-attachment font head-glyph-name)) (stem-thickness (* size-factor 0.13)) @@ -2708,14 +2913,15 @@ Construct a note symbol, with stem. By using fractional values for (attach-off (cons (interval-index (ly:stencil-extent head-glyph X) (* (sign dir) (car attach-indices))) - (* (sign dir) ; fixme, this is inconsistent between X & Y. + (* (sign dir) ; fixme, this is inconsistent between X & Y. (interval-index (ly:stencil-extent head-glyph Y) (cdr attach-indices))))) (stem-glyph (and (> log 0) (ly:round-filled-box (ordered-cons (car attach-off) - (+ (car attach-off) (* (- (sign dir)) stem-thickness))) + (+ (car attach-off) + (* (- (sign dir)) stem-thickness))) (cons (min stemy (cdr attach-off)) (max stemy (cdr attach-off))) (/ stem-thickness 3)))) @@ -2734,11 +2940,15 @@ Construct a note symbol, with stem. By using fractional values for (string-append "flags." (if (> dir 0) "u" "d") (number->string log))) - (cons (+ (car attach-off) (if (< dir 0) stem-thickness 0)) stemy))))) - - ; If there is a flag on an upstem and the stem is short, move the dots to avoid the flag. - ; 16th notes get a special case because their flags hang lower than any other flags. - (if (and dots (> dir 0) (> log 2) (or (< dir 1.15) (and (= log 4) (< dir 1.3)))) + (cons (+ (car attach-off) (if (< dir 0) + stem-thickness 0)) + stemy))))) + + ;; If there is a flag on an upstem and the stem is short, move the dots + ;; to avoid the flag. 16th notes get a special case because their flags + ;; hang lower than any other flags. + (if (and dots (> dir 0) (> log 2) + (or (< dir 1.15) (and (= log 4) (< dir 1.3)))) (set! dots (ly:stencil-translate-axis dots 0.5 X))) (if flaggl (set! stem-glyph (ly:stencil-add flaggl stem-glyph))) @@ -2760,10 +2970,12 @@ Construct a note symbol, with stem. By using fractional values for (lambda (z) (inexact->exact (/ (log z) divisor))))) (define (parse-simple-duration duration-string) - "Parse the `duration-string', e.g. ''4..'' or ''breve.'', and return a (log dots) list." - (let ((match (regexp-exec (make-regexp "(breve|longa|maxima|[0-9]+)(\\.*)") duration-string))) + "Parse the `duration-string', e.g. ''4..'' or ''breve.'', +and return a (log dots) list." + (let ((match (regexp-exec (make-regexp "(breve|longa|maxima|[0-9]+)(\\.*)") + duration-string))) (if (and match (string=? duration-string (match:substring match 0))) - (let ((len (match:substring match 1)) + (let ((len (match:substring match 1)) (dots (match:substring match 2))) (list (cond ((string=? len "breve") -1) ((string=? len "longa") -2) @@ -2772,10 +2984,10 @@ Construct a note symbol, with stem. By using fractional values for (if dots (string-length dots) 0))) (ly:error (_ "not a valid duration string: ~a") duration-string)))) -(define-builtin-markup-command (note layout props duration dir) +(define-markup-command (note layout props duration dir) (string? number?) - music - (note-by-number-markup) + #:category music + #:properties (note-by-number-markup) " @cindex notes within text by string @@ -2800,10 +3012,9 @@ a shortened down stem. ;; translating. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (lower layout props amount arg) +(define-markup-command (lower layout props amount arg) (number? markup?) - align - () + #:category align " @cindex lowering text @@ -2821,10 +3032,10 @@ A negative @var{amount} indicates raising; see also @code{\\raise}. (ly:stencil-translate-axis (interpret-markup layout props arg) (- amount) Y)) -(define-builtin-markup-command (translate-scaled layout props offset arg) +(define-markup-command (translate-scaled layout props offset arg) (number-pair? markup?) - align - ((font-size 0)) + #:category align + #:properties ((font-size 0)) " @cindex translating text @cindex scaling text @@ -2847,10 +3058,9 @@ Translate @var{arg} by @var{offset}, scaling the offset by the (ly:stencil-translate (interpret-markup layout props arg) scaled))) -(define-builtin-markup-command (raise layout props amount arg) +(define-markup-command (raise layout props amount arg) (number? markup?) - align - () + #:category align " @cindex raising text @@ -2878,10 +3088,10 @@ and/or @code{extra-offset} properties. @end lilypond" (ly:stencil-translate-axis (interpret-markup layout props arg) amount Y)) -(define-builtin-markup-command (fraction layout props arg1 arg2) +(define-markup-command (fraction layout props arg1 arg2) (markup? markup?) - other - ((font-size 0)) + #:category other + #:properties ((font-size 0)) " @cindex creating text fractions @@ -2914,10 +3124,10 @@ Make a fraction of two markups. ;; empirical anyway (ly:stencil-translate-axis stack offset Y)))) -(define-builtin-markup-command (normal-size-super layout props arg) +(define-markup-command (normal-size-super layout props arg) (markup?) - font - ((baseline-skip)) + #:category font + #:properties ((baseline-skip)) " @cindex setting superscript in standard font size @@ -2935,11 +3145,11 @@ Set @var{arg} in superscript with a normal font size. (interpret-markup layout props arg) (* 0.5 baseline-skip) Y)) -(define-builtin-markup-command (super layout props arg) +(define-markup-command (super layout props arg) (markup?) - font - ((font-size 0) - (baseline-skip)) + #:category font + #:properties ((font-size 0) + (baseline-skip)) " @cindex superscript text @@ -2963,10 +3173,9 @@ Set @var{arg} in superscript. (* 0.5 baseline-skip) Y)) -(define-builtin-markup-command (translate layout props offset arg) +(define-markup-command (translate layout props offset arg) (number-pair? markup?) - align - () + #:category align " @cindex translating text @@ -2983,11 +3192,11 @@ is a pair of numbers representing the displacement in the X and Y axis. (ly:stencil-translate (interpret-markup layout props arg) offset)) -(define-builtin-markup-command (sub layout props arg) +(define-markup-command (sub layout props arg) (markup?) - font - ((font-size 0) - (baseline-skip)) + #:category font + #:properties ((font-size 0) + (baseline-skip)) " @cindex subscript text @@ -3012,10 +3221,10 @@ Set @var{arg} in subscript. (* -0.5 baseline-skip) Y)) -(define-builtin-markup-command (normal-size-sub layout props arg) +(define-markup-command (normal-size-sub layout props arg) (markup?) - font - ((baseline-skip)) + #:category font + #:properties ((baseline-skip)) " @cindex setting subscript in standard font size @@ -3038,10 +3247,9 @@ Set @var{arg} in subscript with a normal font size. ;; brackets. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (hbracket layout props arg) +(define-markup-command (hbracket layout props arg) (markup?) - graphic - () + #:category graphic " @cindex placing horizontal brackets around text @@ -3060,10 +3268,9 @@ Draw horizontal brackets around @var{arg}. (m (interpret-markup layout props arg))) (bracketify-stencil m X th (* 2.5 th) th))) -(define-builtin-markup-command (bracket layout props arg) +(define-markup-command (bracket layout props arg) (markup?) - graphic - () + #:category graphic " @cindex placing vertical brackets around text @@ -3080,14 +3287,60 @@ Draw vertical brackets around @var{arg}. (m (interpret-markup layout props arg))) (bracketify-stencil m Y th (* 2.5 th) th))) +(define-markup-command (parenthesize layout props arg) + (markup?) + #:category graphic + #:properties ((angularity 0) + (padding) + (size 1) + (thickness 1) + (width 0.25)) + " +@cindex placing parentheses around text + +Draw parentheses around @var{arg}. This is useful for parenthesizing +a column containing several lines of text. + +@lilypond[verbatim,quote] +\\markup { + \\line { + \\parenthesize { + \\column { + foo + bar + } + } + \\override #'(angularity . 2) { + \\parenthesize { + \\column { + bah + baz + } + } + } + } +} +@end lilypond" + (let* ((markup (interpret-markup layout props arg)) + (scaled-width (* size width)) + (scaled-thickness + (* (chain-assoc-get 'line-thickness props 0.1) + thickness)) + (half-thickness + (min (* size 0.5 scaled-thickness) + (* (/ 4 3.0) scaled-width))) + (padding (chain-assoc-get 'padding props half-thickness))) + (parenthesize-stencil + markup half-thickness scaled-width angularity padding))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Delayed markup evaluation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-builtin-markup-command (page-ref layout props label gauge default) +(define-markup-command (page-ref layout props label gauge default) (symbol? markup? markup?) - other - () + #:category other " @cindex referencing page numbers in text @@ -3139,10 +3392,10 @@ when @var{label} is not found." dy-top))))) (space-stil (cdr stils) (cons new-stil result)))))) -(define-builtin-markup-list-command (justified-lines layout props args) +(define-markup-list-command (justified-lines layout props args) (markup-list?) - ((baseline-skip) - wordwrap-internal-markup-list) + #:properties ((baseline-skip) + wordwrap-internal-markup-list) " @cindex justifying lines of text @@ -3153,10 +3406,10 @@ Use @code{\\override-lines #'(line-width . @var{X})} to set the line width; (interpret-markup-list layout props (make-wordwrap-internal-markup-list #t args)))) -(define-builtin-markup-list-command (wordwrap-lines layout props args) +(define-markup-list-command (wordwrap-lines layout props args) (markup-list?) - ((baseline-skip) - wordwrap-internal-markup-list) + #:properties ((baseline-skip) + wordwrap-internal-markup-list) "Like @code{\\wordwrap}, but return a list of lines instead of a single markup. Use @code{\\override-lines #'(line-width . @var{X})} to set the line width, where @var{X} is the number of staff spaces." @@ -3164,16 +3417,15 @@ where @var{X} is the number of staff spaces." (interpret-markup-list layout props (make-wordwrap-internal-markup-list #f args)))) -(define-builtin-markup-list-command (column-lines layout props args) +(define-markup-list-command (column-lines layout props args) (markup-list?) - ((baseline-skip)) + #:properties ((baseline-skip)) "Like @code{\\column}, but return a list of lines instead of a single markup. @code{baseline-skip} determines the space between each markup in @var{args}." - (space-lines (chain-assoc-get 'baseline-skip props) + (space-lines baseline-skip (interpret-markup-list layout props args))) -(define-builtin-markup-list-command (override-lines layout props new-prop args) +(define-markup-list-command (override-lines layout props new-prop args) (pair? markup-list?) - () "Like @code{\\override}, for markup lists." (interpret-markup-list layout (cons (list new-prop) props) args))