public class SurfaceVector

  1. Object
  2. SurfaceNode
  3. SurfaceVector

A retained vector drawing node: a small catalog of fill/stroke/text operations recorded in paint order and replayed natively by every platform renderer (SwiftUI Canvas on iOS, an in-process bitmap on Android, Codename One Graphics on desktop). It exists for the widgets the sealed template catalog cannot express – clocks, gauges, dials and similar custom art – without shipping pre-rendered images for every state.

Operations use a logical coordinate space (the view box passed to the constructor) that is scaled to the node’s laid-out bounds preserving aspect ratio and centered, so the same op list renders correctly at every widget size.

Angles: the clock convention

All angles in this class are degrees where 0 points up (12 o’clock) and positive angles advance clockwise – the natural convention for clock hands and gauge needles. Renderers convert internally to each platform’s native arc convention.

Rotation groups

Operations added between beginRotation(...) and endRotation() rotate together around a pivot. The angle is either fixed or read from the entry state map by key, which is what makes an analog clock cheap: publish the face layout once and drive the hands with per-entry state:

SurfaceVector face = new SurfaceVector(200, 200)
        .fillEllipse(100, 100, 96, 96, SurfaceColor.BACKGROUND)
        .strokeEllipse(100, 100, 96, 96, 4, SurfaceColor.LABEL)
        .beginRotation("hourAngle", 100, 100)
            .line(100, 100, 100, 52, 8, SurfaceColor.LABEL)
        .endRotation()
        .beginRotation("minuteAngle", 100, 100)
            .line(100, 100, 100, 24, 5, SurfaceColor.ACCENT)
        .endRotation()
        .fillEllipse(100, 100, 6, 6, SurfaceColor.ACCENT);
// one timeline entry per minute; the OS flips entries on schedule without waking the app
WidgetTimeline t = new WidgetTimeline().setContent(face);
for (int m = 0; m < 60; m++) {
    int totalMinutes = hourOfDay * 60 + minute + m;
    Map<String, Object> state = new HashMap<String, Object>();
    state.put("minuteAngle", Float.valueOf(totalMinutes % 60 * 6f));
    state.put("hourAngle", Float.valueOf(totalMinutes % 720 * 0.5f));
    t.addEntry(new Date(startOfMinute + m * 60000L), state);
}

A state-driven angle does not tick by itself – state is per timeline entry, so a clock publishes one entry per minute (as above) and the OS flips them on its own schedule.

Descriptors cap the total operation count at 512 per vector node; exceeding it fails at serialization time. Unbalanced beginRotation/endRotation pairs also fail at serialization time with IllegalStateException.

Constructors

public SurfaceVector(int viewBoxWidth, int viewBoxHeight)Creates a vector node with a logical coordinate space.

Methods

public SurfaceVector fillRect(float x, float y, float w, float h, SurfaceColor c)Fills an axis-aligned rectangle.
public SurfaceVector fillRoundRect(float x, float y, float w, float h, float corner, SurfaceColor c)Fills a rectangle with rounded corners.
public SurfaceVector fillEllipse(float cx, float cy, float rx, float ry, SurfaceColor c)Fills an ellipse.
public SurfaceVector fillArc(float cx, float cy, float rx, float ry, float startDeg, float sweepDeg, SurfaceColor c)Fills a pie slice: the elliptical arc between the two angles joined to the center.
public SurfaceVector strokeEllipse(float cx, float cy, float rx, float ry, float strokeWidth, SurfaceColor c)Strokes the outline of an ellipse.
public SurfaceVector strokeArc(float cx, float cy, float rx, float ry, float startDeg, float sweepDeg, float strokeWidth, SurfaceColor c)Strokes an open elliptical arc with round caps – the primitive for gauge tracks and progress rings.
public SurfaceVector line(float x1, float y1, float x2, float y2, float strokeWidth, SurfaceColor c)Draws a line with round caps.
public SurfaceVector fillPath(float[] xy, boolean close, SurfaceColor c)Fills a polygon built from x,y coordinate pairs.
public SurfaceVector strokePath(float[] xy, boolean close, float strokeWidth, SurfaceColor c)Strokes a poly-line built from x,y coordinate pairs, with round caps and joins.
public SurfaceVector text(String text, float x, float y, float fontSize, SurfaceFontWeight w, SurfaceColor c)Draws text anchored at the middle of x with its baseline at y.
public SurfaceVector beginRotation(float degrees, float pivotX, float pivotY)Opens a rotation group with a fixed angle: every op added until the matching endRotation() rotates by degrees (clock convention: clockwise positive) around the pivot.
public SurfaceVector beginRotation(String degreesStateKey, float pivotX, float pivotY)Opens a rotation group whose angle is read from the entry state map: the state value is a Number in degrees, clockwise positive.
public SurfaceVector endRotation()Closes the most recently opened rotation group.
public int getViewBoxWidth()Returns the logical view-box width.
public int getViewBoxHeight()Returns the logical view-box height.
public int getOpCount()Returns the number of recorded operations, rotation groups included.
public SurfaceVector setPadding(int all)Sets the same padding on all four sides.
public SurfaceVector setPadding(int top, int right, int bottom, int left)Sets the padding of each side individually.
public SurfaceVector setBackground(SurfaceColor background)Sets the background color of this node.
public SurfaceVector setCornerRadius(int radius)Sets the corner radius applied to the node’s background.
public SurfaceVector setAlignment(SurfaceAlignment alignment)Sets this node’s alignment within its parent.
public SurfaceVector setWeight(int weight)Sets the flexible-space weight of this node within a row or column.
public SurfaceVector setSize(int widthDips, int heightDips)Sets a fixed size for this node.
public SurfaceVector setAction(String actionId)Assigns a tap action to this node.
public SurfaceVector setAction(String actionId, Map<String, Object> params)Assigns a tap action with parameters to this node.

Inherited methods

Constructor details

SurfaceVector

public SurfaceVector(int viewBoxWidth, int viewBoxHeight)
Creates a vector node with a logical coordinate space. The view box is scaled to the node’s laid-out bounds preserving aspect ratio (centered); it also provides the node’s natural size in dips when no fixed size or weight applies.

Parameters

viewBoxWidth int
the logical width of the drawing coordinate space
viewBoxHeight int
the logical height of the drawing coordinate space

Method details

fillRect

public SurfaceVector fillRect(float x, float y, float w, float h, SurfaceColor c)
Fills an axis-aligned rectangle.

Parameters

x float
left edge in view-box units
y float
top edge in view-box units
w float
width in view-box units
h float
height in view-box units
c SurfaceColor
the fill color

Returns

this vector node, for chaining

fillRoundRect

public SurfaceVector fillRoundRect(float x, float y, float w, float h, float corner, SurfaceColor c)
Fills a rectangle with rounded corners.

Parameters

x float
left edge in view-box units
y float
top edge in view-box units
w float
width in view-box units
h float
height in view-box units
corner float
the corner radius in view-box units
c SurfaceColor
the fill color

Returns

this vector node, for chaining

fillEllipse

public SurfaceVector fillEllipse(float cx, float cy, float rx, float ry, SurfaceColor c)
Fills an ellipse.

Parameters

cx float
center x in view-box units
cy float
center y in view-box units
rx float
horizontal radius in view-box units
ry float
vertical radius in view-box units
c SurfaceColor
the fill color

Returns

this vector node, for chaining

fillArc

public SurfaceVector fillArc(float cx, float cy, float rx, float ry, float startDeg, float sweepDeg, SurfaceColor c)
Fills a pie slice: the elliptical arc between the two angles joined to the center. Angles use the clock convention (degrees, 0 = 12 o’clock, clockwise positive).

Parameters

cx float
center x in view-box units
cy float
center y in view-box units
rx float
horizontal radius in view-box units
ry float
vertical radius in view-box units
startDeg float
the start angle in clock degrees
sweepDeg float
the sweep in degrees, clockwise positive
c SurfaceColor
the fill color

Returns

this vector node, for chaining

strokeEllipse

public SurfaceVector strokeEllipse(float cx, float cy, float rx, float ry, float strokeWidth, SurfaceColor c)
Strokes the outline of an ellipse.

Parameters

cx float
center x in view-box units
cy float
center y in view-box units
rx float
horizontal radius in view-box units
ry float
vertical radius in view-box units
strokeWidth float
the stroke width in view-box units
c SurfaceColor
the stroke color

Returns

this vector node, for chaining

strokeArc

public SurfaceVector strokeArc(float cx, float cy, float rx, float ry, float startDeg, float sweepDeg, float strokeWidth, SurfaceColor c)
Strokes an open elliptical arc with round caps – the primitive for gauge tracks and progress rings. Angles use the clock convention (degrees, 0 = 12 o’clock, clockwise positive).

Parameters

cx float
center x in view-box units
cy float
center y in view-box units
rx float
horizontal radius in view-box units
ry float
vertical radius in view-box units
startDeg float
the start angle in clock degrees
sweepDeg float
the sweep in degrees, clockwise positive
strokeWidth float
the stroke width in view-box units
c SurfaceColor
the stroke color

Returns

this vector node, for chaining

line

public SurfaceVector line(float x1, float y1, float x2, float y2, float strokeWidth, SurfaceColor c)
Draws a line with round caps.

Parameters

x1 float
start x in view-box units
y1 float
start y in view-box units
x2 float
end x in view-box units
y2 float
end y in view-box units
strokeWidth float
the stroke width in view-box units
c SurfaceColor
the stroke color

Returns

this vector node, for chaining

fillPath

public SurfaceVector fillPath(float[] xy, boolean close, SurfaceColor c)
Fills a polygon built from x,y coordinate pairs. The path is implicitly closed for filling regardless of close.

Parameters

xy float[]
coordinate pairs x0, y0, x1, y1, ... in view-box units, at least three points
close boolean
whether the serialized path is marked closed (kept for renderer symmetry with strokePath)
c SurfaceColor
the fill color

Returns

this vector node, for chaining

strokePath

public SurfaceVector strokePath(float[] xy, boolean close, float strokeWidth, SurfaceColor c)
Strokes a poly-line built from x,y coordinate pairs, with round caps and joins.

Parameters

xy float[]
coordinate pairs x0, y0, x1, y1, ... in view-box units, at least two points
close boolean
whether the last point connects back to the first
strokeWidth float
the stroke width in view-box units
c SurfaceColor
the stroke color

Returns

this vector node, for chaining

text

public SurfaceVector text(String text, float x, float y, float fontSize, SurfaceFontWeight w, SurfaceColor c)
Draws text anchored at the middle of x with its baseline at y. The text supports ${key} interpolation from the entry state map, like SurfaceText.

Parameters

text String
the text, may embed ${key} placeholders
x float
the horizontal anchor (text centers on it) in view-box units
y float
the text baseline in view-box units
fontSize float
the font size in view-box units
w SurfaceFontWeight
the font weight
c SurfaceColor
the text color

Returns

this vector node, for chaining

beginRotation

public SurfaceVector beginRotation(float degrees, float pivotX, float pivotY)
Opens a rotation group with a fixed angle: every op added until the matching endRotation() rotates by degrees (clock convention: clockwise positive) around the pivot. Groups nest.

Parameters

degrees float
the rotation in degrees, clockwise positive
pivotX float
the pivot x in view-box units
pivotY float
the pivot y in view-box units

Returns

this vector node, for chaining

beginRotation

public SurfaceVector beginRotation(String degreesStateKey, float pivotX, float pivotY)
Opens a rotation group whose angle is read from the entry state map: the state value is a Number in degrees, clockwise positive. This is how clock hands and gauge needles animate – a per-entry timeline updates the angle without republishing the layout.

Parameters

degreesStateKey String
the state-map key holding the angle in degrees
pivotX float
the pivot x in view-box units
pivotY float
the pivot y in view-box units

Returns

this vector node, for chaining

endRotation

public SurfaceVector endRotation()
Closes the most recently opened rotation group.

Returns

this vector node, for chaining

getViewBoxWidth

public int getViewBoxWidth()
Returns the logical view-box width.

getViewBoxHeight

public int getViewBoxHeight()
Returns the logical view-box height.

getOpCount

public int getOpCount()
Returns the number of recorded operations, rotation groups included.

setPadding

public SurfaceVector setPadding(int all)
Sets the same padding on all four sides.

Parameters

all int
padding in dips

Returns

this node, for chaining

setPadding

public SurfaceVector setPadding(int top, int right, int bottom, int left)
Sets the padding of each side individually.

Parameters

top int
top padding in dips
right int
right padding in dips
bottom int
bottom padding in dips
left int
left padding in dips

Returns

this node, for chaining

setBackground

public SurfaceVector setBackground(SurfaceColor background)
Sets the background color of this node.

Parameters

background SurfaceColor
the background color

Returns

this node, for chaining

setCornerRadius

public SurfaceVector setCornerRadius(int radius)
Sets the corner radius applied to the node’s background. May render square on Android versions below 12.

Parameters

radius int
the corner radius in dips

Returns

this node, for chaining

setAlignment

public SurfaceVector setAlignment(SurfaceAlignment alignment)
Sets this node’s alignment within its parent. In a SurfaceBox all nine positions apply; in rows and columns only the cross-axis component is used.

Parameters

alignment SurfaceAlignment
the alignment

Returns

this node, for chaining

setWeight

public SurfaceVector setWeight(int weight)
Sets the flexible-space weight of this node within a row or column. Nodes with a weight share the leftover space of the parent proportionally; a weight of 0 (the default) sizes the node to its natural size.

Parameters

weight int
the relative weight, 0 for natural sizing

Returns

this node, for chaining

setSize

public SurfaceVector setSize(int widthDips, int heightDips)
Sets a fixed size for this node. A value of 0 (the default) keeps the natural size of the respective axis.

Parameters

widthDips int
fixed width in dips, 0 for natural width
heightDips int
fixed height in dips, 0 for natural height

Returns

this node, for chaining

setAction

public SurfaceVector setAction(String actionId)
Assigns a tap action to this node. Tapping the node opens (or foregrounds) the app and delivers the action id to the handler registered with Surfaces.setActionHandler(...). Note that small iOS home-screen widgets only honor the action of the root node.

Parameters

actionId String
the app-defined action identifier

Returns

this node, for chaining

setAction

public SurfaceVector setAction(String actionId, Map<String, Object> params)
Assigns a tap action with parameters to this node. The parameter map may contain String, Number and Boolean values and is delivered verbatim with the SurfaceActionEvent.

Parameters

actionId String
the app-defined action identifier
params Map<String, Object>
parameters delivered with the action, may be null

Returns

this node, for chaining