Figure 2.11 Creating a complex figure, starting from the heart painter of figure 2.10.

[1] The picture language is based on the language Peter Henderson created to construct images like M.C. Escher's Square Limit woodcut (see Henderson 1982). The woodcut incorporates a repeated scaled pattern, similar to the arrangements drawn using the square_limit function in this section.
[2] Equivalently, we could write
const flipped_pairs =
    square_of_four(turn_upside_down, flip_vert, 
                   flip_horiz, identity);

[3] The function turn_upside_down rotates a painter by 180 degrees. Instead of turn_upside_down we could say compose(flip_vert, flip_horiz), using the compose function from exercise 1.42.
[4] The function frame_coord_map uses the vector operations described in exercise 2.46 below, which we assume have been implemented using some representation for vectors. Because of data abstraction, it doesn't matter what this vector representation is, so long as the vector operations behave correctly.
[5] The function segments_to_painter uses the representation for line segments described in exercise 2.48 below. It also uses the for_each function described in exercise 2.23.
[6] For example, the heart painter of figure 2.10 was constructed from a gray-level image. For each point in a given frame, the heart painter determines the point in the image that is mapped to it under the frame coordinate map, and shades it accordingly. By allowing different types of painters, we are capitalizing on the abstract data idea discussed in section 2.1.3, where we argued that a rational-number representation could be anything at all that satisfies an appropriate condition. Here we're using the fact that a painter can be implemented in any way at all, so long as it draws something in the designated frame. Section 2.1.3 also showed how pairs could be implemented as functions. Painters are our second example of a functional representation for data.
[7] In transform_painter, we make use of a slight extension of the syntax of function definition expressions, compared to section 1.3.2: The body of a function definition can be a block, not just a single return expression. Such function definition expressions have the following shape: \[ \texttt{(} \ \textit{parameters}\ \texttt{) => \{}\ \textit{statements}\ \texttt{\}} \]
[8] The function rotate90 is a pure rotation only for square frames, because it also stretches and shrinks the image to fit into the rotated frame.
[9] The diamond-shaped images in figure 2.10 were created with squash_inwards applied to heart.
[10] Section 3.3.4 describes one such language.
2.2.4 Example: A Picture Language