AS TE R renders document objects by calling generic function read-aloud. Primary methods1 can be defined on this function for objects that appear in the document model described in Section 2.1.
The body of such a read-aloud method consists of AFL statements that set AFL state and execute audio events. For instance, the read-aloud method for object string is:
(defmethod read-aloud ((text string))
"Render a string."
(afl:send-text text))
Here is a slightly more complex example:
(defmethod read-aloud ((article article ))
"Abbreviated read-aloud method for article. "
(when (title article) (read-aloud (title article )))
(read-aloud (body article)))
Function read-aloud, as described so far, can produce only one view of a document it can render it in only one way. To enable different views of the same object, we now introduce the notion of rendering rules and styles. This makes function read-aloud more involved.
A rendering rule associates a name with a set of actions that are to be executed when an instance of a given object type is rendered. The format of a rendering rule is
The body of the rule consists of AFL statements that modify AFL state and execute audio events it is the same as the body of an instance of method read-aloud.
Named rendering rules permit the user to define several rules for the same object, but now, a mechanism is needed to determine which rule to use when rendering instances of an object O. At any time, only one rendering rule is active for object O, and this active rule is used by read-aloud.
Rules can be activated and deactivated interactively by executing (activate-rule <object-name> <rule-name>) and (deactivate-rule <object-name>)
Each rule presents a different audio view of the object. AS TE R provides a collection of default rendering rules (in the form of primary methods on read-aloud) that are used when no rule has been explicitly activated for a particular object type.
Within the body of a rendering rule, we recommend that sub-objects be rendered only by calling function read-aloud. This ensures that if a listener activates a new rendering rule for an object O, then all instances of O will be rendered using this rule. For example, after activating a rendering rule for fractions, a summation that contains a fraction as the summand gets rendered as expected, i.e., the summation is rendered as before, but the fraction in the summand is rendered using the newly activated rule. Of course, a rendering rule is free to activate and deactivate other rules. Note, however, that this will hard-wire a particular type of rendering into such a rule.
Activating rendering rules provides a convenient mechanism for obtaining different views of a single object type. However, this is cumbersome when changing how several object types are rendered we will have to explicitly activate a different rule for each object type. This is obviated by the introduction of rendering styles.
A rendering style style-1 is the collection of rendering rules named style-1, each of which renders a different object type. AS TE R maintains a list of active styles in the order in which they were activated. Initially, this list contains only style default, which specifies a default rendering for all objects.
The user can execute
to add style-1 to the front of the list of active styles. This effectively activates all rules that appear in style-1 when rendering an object, AS TE R uses the most recently activated style that defines a rule for that object.
Style style-1 can be deactivated by executing
A listener can create a new rendering style simply by defining rendering rules for one or more object types. The style need not provide rules for all the known object types rules for the remaining objects are taken from previously active styles. Thus, we might define rules in style descriptive for summations, integrals and coproducts. If descriptive is now activated, and style simple is the next most-recently activated style, AS TE R uses rendering rules from simple for all other objects. Typically, the list of active styles is:
(use-special-patterns descriptive simple default)
If no rule has been explicitly activated for an object type O, then the active rule for O is provided by the most recently activated style that defines a rendering rule for O or one of its superclasses. Thus, in the above example, if the list of active styles is descriptive, simple, default, the active rule for an integral is descriptive. If we now want to have all objects rendered using this list of active styles but would like integrals rendered using rule simple, then we would execute
The ability to obtain different views of an object is a very useful learning aid. It gives the listener a chance to obtain different perspectives of complex expressions. Further, this system of rendering rules and styles has proven very useful in experimenting with different ways of rendering mathematics.
Rendering rules can be used in many interesting ways. For instance, defining and activating the following rule for paragraphs provides a thumb-nail view of a document.
(def-reading-rule (paragraph quiet) nil)
The body of this rule is empty, so the contents of paragraphs are not rendered. When this rule is activated, only the titles of the sectional units will be spoken.
The rendering rule in Figure 4.1 on page 101 renders only the displayed math from a document. Activating this rule allows the listener to locate an equation of interest quickly. The user can now reactivate the normal rendering rule for paragraphs and listen to the entire paragraph that contains the math expression. This is like flicking through the pages of a book until something of interest is located and then reading the relevant content.