►V Reference
On this page:
58.1.1 The Basic Visual Protocol
visual-path?
visual-target-path
gen:  visual
visual?
visual-id
visual-position
visual-with-position
58.1.2 Whole-Visual Affine Maps
affine-map
affine-map-visual?
affine-map-visual-content
affine-map-visual-map
58.1.3 The Affine-Visual Protocol
gen:  affine-visual
affine-visual?
visual-transform
visual-with-transform
visual-rotation
visual-scale
visual-with-rotation
visual-with-scale
58.1.4 The Opacity-Visual Protocol
opacity?
gen:  opacity-visual
opacity-visual?
visual-opacity
visual-with-opacity
58.1.5 The Stroke-Width-Visual Protocol
stroke-width?
gen:  stroke-width-visual
stroke-width-visual?
visual-stroke-width
visual-with-stroke-width
58.1.6 Fill-Color and Stroke-Color Visual Protocols
gen:  fill-color-visual
fill-color-visual?
visual-fill-color
visual-with-fill-color
gen:  stroke-color-visual
stroke-color-visual?
visual-stroke-color
visual-with-stroke-color
58.1.7 Group Visuals
group
group-visual?
group-visual-children
group-visual-with-children
9.3

58.1 Visual Protocols and Groups🔗ℹ

Use the basic protocol for identity and reference position. The optional protocols describe the updates a Visual supports; group supplies ordered composition rather than another leaf renderer. Positions are expressed in the containing coordinate system, so a child’s position is local to its group.

See also Shapes and Path Visuals, Relations and Live Layout.

    58.1.1 The Basic Visual Protocol

    58.1.2 Whole-Visual Affine Maps

    58.1.3 The Affine-Visual Protocol

    58.1.4 The Opacity-Visual Protocol

    58.1.5 The Stroke-Width-Visual Protocol

    58.1.6 Fill-Color and Stroke-Color Visual Protocols

    58.1.7 Group Visuals

58.1.1 The Basic Visual Protocol🔗ℹ

procedure

(visual-path? value) → boolean?

  value : any/c
Returns #t for a nonempty list of symbol identities used to address a nested built-in group child, such as '(scatter marker). The first symbol identifies a top-level Visual and each remaining symbol names one child.

procedure

(visual-target-path target) → visual-path?

  target : (or/c visual? symbol? visual-path?)
Converts a top-level Visual or symbol to its one-element path, and returns an existing nested path unchanged.

A symbol becomes a one-element path; an existing nested path is retained.

Examples:
> (visual-target-path 'marker)

'(marker)

> (visual-target-path '(scatter marker))

'(scatter marker)

generic interface

gen:visual : any/c

The generic interface for semantic Visual values. A structure type implements this interface with #:methods in its struct definition. It must implement visual-id, visual-position, and visual-with-position.

procedure

(visual? value) → boolean?

  value : any/c
Returns #t when value implements gen:visual.

procedure

(visual-id visual) → symbol?

  visual : visual?
Returns the stable identity of visual. Scene lookup and animation targeting use this symbol.

A custom Visual implementation must always return a symbol. Immutable update methods must preserve the symbol.

procedure

(visual-position visual) → vec2?

  visual : visual?
Returns the reference position of visual in its containing coordinate system. A top-level Visual uses world coordinates. A child of a group uses coordinates local to that group. For the built-in affine Visuals, the result is the translation component of the affine transform.

procedure

(visual-with-position visual position) → visual?

  visual : visual?
  position : vec2?
Returns a new Visual with position as its reference position in the same containing coordinate system. The result must preserve identity. Built-in Visuals also preserve geometry, style, rotation, scale, opacity, and child order when applicable.

Moving a model value preserves its identity without changing the original.

Examples:
> (define dot (circle #:id 'dot))
> (define shifted-dot (visual-with-position dot (vec2 2 1)))
> (visual-id shifted-dot)

'dot

> (visual-position dot)

(vec2 0 0)

A minimal position-only Visual can be defined as follows:

(struct marker (id position)
  #:transparent
  #:methods gen:visual
  [(define (visual-id value)
     (marker-id value))
   (define (visual-position value)
     (marker-position value))
   (define (visual-with-position value position)
     (struct-copy marker value [position position]))])

Such a Visual can use move-to, but it cannot use rotation or scale animations.

58.1.2 Whole-Visual Affine Maps🔗ℹ

procedure

(affine-map content map) → affine-map-visual?

  content : visual?
  map : affine2?
Wraps an affine Visual in a general affine map while preserving its stable identity. The Pict adapter applies map’s complete linear component to the semantic subtree; normal scene placement uses its mapped reference point. This makes a group shear or reflect as one coherent diagram.

The wrapper is itself an affine-visual?. It retains a canonical local copy of the subtree plus its full local-to-parent map, which lets ordinary group composition preserve the map and lets descendants remain addressable. This is the semantic bridge used by nested apply-affine requests.

procedure

(affine-map-visual? value) → boolean?

  value : any/c
Returns #t when value is a semantic affine-map wrapper.

procedure

(affine-map-visual-content visual) → visual?

  visual : affine-map-visual?
Returns the canonical local semantic content of visual. Its ordinary decomposed transform is neutral; affine-map-visual-map contains the complete local-to-parent placement.

procedure

(affine-map-visual-map visual) → affine2?

  visual : affine-map-visual?
Returns the current outer general affine map.

58.1.3 The Affine-Visual Protocol🔗ℹ

generic interface

gen:affine-visual : any/c

The optional generic interface for Visuals that support complete affine transforms. A structure type implementing this interface must provide visual-transform and visual-with-transform. It normally also implements gen:visual.

procedure

(affine-visual? value) → boolean?

  value : any/c
Returns #t when value implements gen:affine-visual.

procedure

(visual-transform visual) → affine-transform?

  visual : affine-visual?
Returns the complete affine transform of visual. Its translation must agree with visual-position. Custom implementations must return an affine-transform? value.

procedure

(visual-with-transform visual transform) → affine-visual?

  visual : affine-visual?
  transform : affine-transform?
Returns a new affine Visual with transform installed. A correct implementation preserves the Visual’s identity, geometry, style, child order, and opacity when those fields apply. The result’s visual-position, visual-rotation, and visual-scale results must agree with the installed transform.

procedure

(visual-rotation visual) → finite-real?

  visual : affine-visual?
Returns the counter-clockwise rotation of visual in radians.

procedure

(visual-scale visual) → vec2?

  visual : affine-visual?
Returns the positive x and y scale factors of visual.

procedure

(visual-with-rotation visual rotation) → affine-visual?

  visual : affine-visual?
  rotation : finite-real?
Returns a new affine Visual with rotation installed. Position, scale, geometry, style, and opacity are preserved.

procedure

(visual-with-scale visual scale) → affine-visual?

  visual : affine-visual?
  scale : scale-factor?
Returns a new affine Visual with scale installed. Position, rotation, geometry, style, child order, and opacity are preserved.

A built-in group or formula assembly accepts only a uniform scale, so its x and y components must be equal. Other built-in affine Visuals, including arrows and axes, accept non-uniform scale.

58.1.4 The Opacity-Visual Protocol🔗ℹ

procedure

(opacity? value) → boolean?

  value : any/c
Returns #t when value is a finite real number in the closed interval from 0 through 1. Exact and inexact values are accepted. Negative values, values greater than one, infinities, NaN values, and non-real values are rejected.

generic interface

gen:opacity-visual : any/c

The optional generic interface for Visuals that support global opacity. A structure type implementing this interface must provide visual-opacity and visual-with-opacity. It normally also implements gen:visual.

Opacity is semantic model data. Renderers should draw the Visual normally. The Pict adapter applies global opacity after it selects and runs a renderer.

procedure

(opacity-visual? value) → boolean?

  value : any/c
Returns #t when value implements gen:opacity-visual. Implementing this protocol does not require implementing gen:affine-visual.

procedure

(visual-opacity visual) → opacity?

  visual : opacity-visual?
Returns the global opacity of visual. A custom implementation must return a value accepted by opacity?. Animation and rendering adapters validate this result at their boundaries.

procedure

(visual-with-opacity visual opacity) → opacity-visual?

  visual : opacity-visual?
  opacity : opacity?
Returns a new opacity Visual with opacity installed. A correct implementation preserves Visual identity, reference position, geometry, affine transform, style, child order when applicable, and every other semantic field. It must return the requested opacity exactly.

The built-in circle, rectangle, path, arrow, axes, plain-text, formula, formula-assembly, and group Visuals implement this protocol.

A position-only custom Visual can implement opacity as follows:

(struct marker (id position opacity)
  #:transparent
  #:methods gen:visual
  [(define (visual-id value)
     (marker-id value))
   (define (visual-position value)
     (marker-position value))
   (define (visual-with-position value position)
     (struct-copy marker value [position position]))]
  #:methods gen:opacity-visual
  [(define (visual-opacity value)
     (marker-opacity value))
   (define (visual-with-opacity value opacity)
     (struct-copy marker value [opacity opacity]))])

58.1.5 The Stroke-Width-Visual Protocol🔗ℹ

procedure

(stroke-width? value) → boolean?

  value : any/c
Returns #t when value is a nonnegative finite real number. Exact and inexact values are accepted, including zero. Negative values, infinities, NaN values, and non-real values are rejected. This semantic domain is renderer-independent: alternate renderers may support widths outside the narrower range accepted by the default Pict backend.

generic interface

gen:stroke-width-visual : any/c

The optional generic interface for Visuals with one semantic cosmetic stroke width. A structure type implementing this interface must provide visual-stroke-width and visual-with-stroke-width. It normally also implements gen:visual.

The protocol is renderer-independent model data. Built-in renderers read the stored widths of the Visual types they support; third-party renderers decide how to interpret the width exposed by their own Visual implementations.

procedure

(stroke-width-visual? value) → boolean?

  value : any/c
Returns #t when value implements gen:stroke-width-visual. Implementing this protocol does not require implementing gen:affine-visual or gen:opacity-visual.

procedure

(visual-stroke-width visual) → (and/c finite-real? (>=/c 0))

  visual : stroke-width-visual?
Returns the cosmetic stroke width of visual. A custom implementation must return a value accepted by stroke-width?. Animation compilation validates this result before constructing a stroke-width transition.

procedure

(visual-with-stroke-width visual    
  stroke-width) → stroke-width-visual?
  visual : stroke-width-visual?
  stroke-width : (and/c finite-real? (>=/c 0))
Returns a new stroke-width Visual with stroke-width installed. A correct implementation preserves Visual identity and every semantic field other than stroke width, returns a Visual that still implements the protocol, and installs the requested width exactly, including exact/inexact numeric representation.

The built-in circle, rectangle, path, arrow, axes, number-line, and point-marker Visuals implement this protocol. Coordinate plots and filled areas that are themselves path Visuals participate without a separate plot-animation mechanism. A scatter-plot result is instead a top-level group; its nested point-marker children are not independent scene-state animation targets, so the scatter group does not implement this protocol. A callout’s callout-visual-connector-width is likewise separate frame-space connector style and is not controlled by stroke-width-to.

A position-only custom Visual can opt in independently of affine transforms and opacity:

(struct width-marker (id position stroke-width)
  #:transparent
  #:methods gen:visual
  [(define (visual-id value)
     (width-marker-id value))
   (define (visual-position value)
     (width-marker-position value))
   (define (visual-with-position value position)
     (struct-copy width-marker value [position position]))]
  #:methods gen:stroke-width-visual
  [(define (visual-stroke-width value)
     (width-marker-stroke-width value))
   (define (visual-with-stroke-width value stroke-width)
     (struct-copy width-marker value [stroke-width stroke-width]))])

58.1.6 Fill-Color and Stroke-Color Visual Protocols🔗ℹ

generic interface

gen:fill-color-visual : any/c

The optional interface for Visuals with a replaceable fill-color slot. A structure type implementing it provides visual-fill-color and visual-with-fill-color. A current slot value may be #f to mean no fill, but fill-paint interpolation requires the current value to satisfy paint?.

procedure

(fill-color-visual? value) → boolean?

  value : any/c
Returns #t when value implements gen:fill-color-visual.

procedure

(visual-fill-color visual) → any/c

  visual : fill-color-visual?
Returns the Visual’s fill style slot. Built-ins normally return a textual color, an rgba-color, a gradient or pattern paint, or #f. Animation compilation accepts a source for fill-color-to only when this result satisfies paint?.

procedure

(visual-with-fill-color visual color) → fill-color-visual?

  visual : fill-color-visual?
  color : paint?
Returns a Visual with color installed as its fill paint. Correct custom implementations preserve Visual identity and all other semantic fields and install the requested value exactly. For rgba-color endpoints, exactness includes the exact/inexact representation of every channel.

generic interface

gen:stroke-color-visual : any/c

The corresponding optional interface for a replaceable stroke-color slot. It provides visual-stroke-color and visual-with-stroke-color. A current #f stroke means no stroke and is not a color interpolation source.

procedure

(stroke-color-visual? value) → boolean?

  value : any/c
Returns #t when value implements gen:stroke-color-visual.

procedure

(visual-stroke-color visual) → any/c

  visual : stroke-color-visual?
Returns the Visual’s stroke style slot. stroke-color-to requires the current result to satisfy color-spec?.

procedure

(visual-with-stroke-color visual color) → stroke-color-visual?

  visual : stroke-color-visual?
  color : color-spec?
Returns a Visual with color installed as its stroke color while preserving identity and every unrelated semantic field. The requested style must be installed exactly, including exact/inexact channel representation for rgba-color values.

Circles, rectangles, paths, and point markers implement both protocols. Arrows, axes, and number lines implement the stroke-color protocol. A scatter-plot result is a group whose nested marker children are not independent scene-state targets, so the group itself implements neither color protocol. Callout callout-visual-connector-stroke is separate frame-space connector style and is not controlled by stroke-color-to. The protocols are independent of affine transforms, opacity, and stroke width, so third-party Visuals may opt into either one separately.

58.1.7 Group Visuals🔗ℹ

A group is a semantic composite. Its children are stored as ordinary Visual values, not as Picts. The child list is significant back-to-front order. Child positions are local to the group anchor.

All children must implement both gen:visual and gen:affine-visual. Circles, rectangles, paths, function graphs, parametric curves, data plots, arrows, axes, plain text, formulas, and groups all satisfy this requirement. A child may itself be a group. Direct siblings must have distinct identities, and a group identity may not occur anywhere below that group. The same child identity may be reused in separate nested branches; its complete Visual path identifies it unambiguously. A custom affine Visual is treated as one leaf because there is no public protocol for inspecting children hidden inside it.

procedure

(group children    
  #:id id    
  [#:center center    
  #:rotation rotation    
  #:scale scale    
  #:opacity opacity]) → group-visual?
  children : (listof (and/c visual? affine-visual?))
  id : symbol?
  center : vec2? = origin
  rotation : finite-real? = 0
  scale : scale-factor? = 1
  opacity : opacity? = 1
Creates a semantic group with children in significant back-to-front order. An empty list creates a valid empty group.

The center value places the group anchor in its containing coordinate system. At the top level this is a world-space point. In a parent group it is a local point. Each child’s existing reference position is interpreted in the group’s local coordinates.

The group scale may be a positive finite scalar or a positive vec2, but its normalized x and y components must be equal. This uniform-scale restriction lets parent transforms compose exactly with rotated children without introducing shear. The group may be rotated by any finite angle.

The group opacity is applied to the complete composed result. Child opacity is applied first, so opacity is inherited multiplicatively through nested groups.

The constructor rejects a non-affine child, a nonsymbol child identity, a repeated identity anywhere in the built-in group tree, or a descendant whose identity equals id. For a custom affine child, its reported position must agree with the translation in its reported affine transform.

Nested children are addressed by nonempty paths such as '(parent child) for scene-state lookup and compatible animation requests. Their identity remains local to the containing group, so a bare child symbol is not a top-level scene identity.

procedure

(group-visual? value) → boolean?

  value : any/c
Returns #t when value is a built-in group Visual.

procedure

(group-visual-children group)

 → (listof (and/c visual? affine-visual?))
  group : group-visual?
Returns the group’s children in significant back-to-front order. The returned Visuals use coordinates local to the group. The list is immutable model data.

Child order is available directly from the semantic group.

Examples:
> (define pair
    (group (list (circle #:id 'left) (rectangle #:id 'right))
           #:id 'pair))
> (map visual-id (group-visual-children pair))

'(left right)

procedure

(group-visual-with-children group children) → group-visual?

  group : group-visual?
  children : (listof (and/c visual? affine-visual?))
Returns a new group with children as its significant back-to-front child list. Identity, group transform, and opacity are preserved. The same child and identity validation as group is performed. The original group is unchanged.