<-- previous page     Table of Contents    Index    next page -->

User defined symbols

Mup provides the most common musical symbols, but there are various other symbols that have been used over the centuries. If Mup doesn't provide some specific symbol that you would like, you can define up to 160 of your own symbols, as well as override any of the builtin music symbols with your own versions. Most people will never need this facility, so feel free to skip past this section unless you feel you do need it.

To define your own symbols, the description of how to draw those symbols must be provided as PostScript code. On the one hand, that means that unless you can find someone else's definition of just what you want, you will need to understand PostScript at least well enough to define your own. On the other hand, this gives access to the full power of the PostScript language, which lets you define essentially any kind of symbol you want. The PostScript language is beyond the scope of this User's Guide, but there are many books and Internet resources to help you learn, if you are interested. You can also look at the output that Mup generates for examples. If you want something similar to an existing Mup symbol, looking at its definition is probably the best place to start.

A user defined symbol or override is put in "symbol" context. The general format of this context is as follows:

symbol "name"
	postscript = "PostScript code to draw the symbol"
	bbox = llx, lly, urx, ury
	ystemoffset = up, down

The three parameters can be supplied in any order, but only once each per symbol. The ystemoffset parameter is optional, and only used for symbols that will be used as note heads. This is described in more detail later. The name and the postscript and bbox parameters are mandatory.

The name for a user-defined symbol must include at least one letter, and can include letters, numbers, and underscores. It must be different than existing names for non-ASCII characters.

You can refer to user defined symbols just like the builtin symbols, using their name in a mussym statement, or in a text string using the name inside \( ). Adding an "sm" prefix to a name will result in a "small" version, just like with the builtin symbols.

In addition to naming and defining your own symbols, you can also override the definitions of existing music symbols. Suppose, for example. you want a different style of C clef. You can then supply a symbol context for "cclef" and provide your own PostScript.

A symbol definition applies to the entire file, no matter where in the file it is defined. If you try to define the same symbol more than once, a warning will be issued, and the last definition will be used. A user defined symbol must have its "symbol" context before it is referenced.

The symbols you define will become part of a PostScript Type 3 font. Symbols must be defined in a 1000 unit scale coordinate space, where 300 units equals one stepsize, with the symbol's "logical center" at (0, 0). Limitations of Type 3 fonts apply. For example. since PostScript does not allow using setrgbcolor or sethsbcolor after a setcachedevice operation in a BuildChar procedure, it is not possible to change the color of a symbol. The PostScript code will be written to the output exactly as it is, so you will have to provide any escaping needed by PostScript. The normal Mup text string escape rule of needing to put a backslash before a double quote inside a text string also applies. So, for example, suppose you wanted to output a PostScript style string containing a parenthesis inside double quotes. Since PostScript requires a parenthesis inside a string to be preceded by a backslash, the Mup input would require the backslash as well, and since Mup requires double quotes to be backslashed, that would need to be done. So Mup input of:

	postscript="(\"\(\")"

would result in:
	("\(")

being copied to the PostScript output. (Of course, that is not a good symbol definition; it is just intended to show needed escapes.) As with any Mup text string, the postscript string can be as many lines long as you wish. But note that the
postscript = "
part must all be on one line.

There isn't currently any good way to call a PostScript procedure from within a symbol definition. So if you have some some code that is common to several symbols, probably the best way to handle that is to define a Mup macro for the common code, and then use the macro in the postscript string:

define COMMONCODE  ....the common code.... @
postscript = "...some specific code " + `COMMONCODE` + " more specific code"

The bounding box lists four numbers, giving the (x,y) coordinates of the lower left and upper right corners of the smallest box that can contain the symbol. It is in the same units as the symbol itself: 300 units per stepsize. Normally you should define the bounding box to include a small amount of white space padding around what is actually drawn, typically about 100 units, so that if it is printed right next to another symbol, they won't touch. However, in the case of a symbol you want to use as a note head, you should not include any padding, so that stems will touch the note head.

If you want to use a user-defined symbol as a note head, you need to specify the "ystemoffset" parameter. If the symbol is not to be used as a note head, you should omit that. The ystemoffset is given as two numbers, the first for when the stem is up, the second for when it is down. They specify, in the same units as the symbol itself (300 units per stepsize), where on the y axis the stem should begin. Any note head should be defined with its vertical center at y of zero. So if you want the stem to start at the vertical center of the note, the ystemoffset would also be zero. A stepsize below the center of the note would be -300, a half stepsize above would be 150, etc. In the x dimension, the stem is always placed at the edge of the note, as given by the bbox.

If you need an "upside down" version of a note head, just name the upside version of the symbol with a "u" prefix on the name of the right side up version. Then you can use the normal u? convention in headshapes context, and Mup will take care of the rest.

Once defined, a user-defined symbol can be used just like the builtin symbols. There are only a few places where Mup uses some special knowledge of the characteristics of music symbols, but in those cases, if you redefine the symbol to have different characteristics, Mup may not place things quite as perfectly as you would like. One place where this might happen is if you redefine the symbol for flat, natural, or dblflat, to make them significantly different, since Mup tries very hard to pack accidentals as tightly as possible, based on some intimate knowledge of the shapes of the builtin versions.

Here is an example that shows both overriding a builtin symbol and defining a completely new symbol, and then using them.

// Override the builtin xnote to have thicker lines
symbol "xnote"
	bbox=-435, -365, 435, 375
	postscript="gsave
	  % normal xnote has 120 linewidth; we set to 300 here
	  1.15 1 scale 300 setlinewidth 1 setlinecap
	  -300 -300 moveto 300 300 lineto stroke
	  -300 300 moveto 300 -300 lineto stroke
	  grestore"
	ystemoffset=300, -300

// Define a smiley face symbol.
symbol "Smiley"
	bbox=-700, -700, 700, 700
	postscript="gsave
	  100 setlinewidth
	  % the face
	  0 0 600 0 360 arc stroke
	  % the mouth
	  0 0 300 -160 -20 arc stroke
	  % the eyes
	  -200 200 100 0 360 arc fill
	  200 200 100 0 360 arc fill
	  grestore"
	ystemoffset = 0, 0
	
headshapes
	// Set up to use the extra-thick xnote
	// for quarter or shorter, and Smiley for longer.
	"boldxnote" "xnote Smiley Smiley Smiley"
music

1: [hs "boldxnote"]...g;8b;d+;2g;
// You can use the user-defined symbol just like a builtin
mussym above 1: 1.5 "Smiley";
// You can apply size just like for a builtin
rom below 1: 2 "\(Smiley) \s(+5)\(Smiley) \s(+5)\(Smiley)";
bar

Picture of Mup output


   <-- previous page    Table of Contents    Index    next page -->