geomotif.core.style
¶
color and layers: how a design is drawn, rather than what it is.
Geometry says where the ink goes. A :class:Style says which pen puts it
there -- a layer name, a color, a stroke width -- and it rides along in
:attr:Design.meta rather than in :class:~geomotif.Path, because none of it
changes the maths. A design keeps its styles through every transform, every
resample and every overlay, and drops them the moment you ask for the
coordinates alone.
Layers are the part that earns its keep. A pen plotter draws one pen at a
time, so a two-color drawing is two files or one file with two layers; the
SVG writer emits the groups Inkscape and vpype already understand, and the
DXF writer emits real DXF layers::
from geomotif import layer, save_svg, styled
from geomotif.motifs import Circle, Phyllotaxis
outline = styled(Circle(radius=100).build(), layer="pen1", stroke="black")
seeds = styled(Phyllotaxis().build(), layer="pen2", stroke="crimson")
save_svg(layer(outline, seeds), "two-pens.svg")
Nothing is required to have a style, and a design without one writes exactly the file it wrote before this module existed.
Classes:
| Name | Description |
|---|---|
Style |
How one stroke or one loose point is drawn. |
Functions:
| Name | Description |
|---|---|
styled |
Return |
styles_of |
Return one style per stroke, |
point_styles_of |
Return one style per loose point, |
layer_names |
Return the layers a design uses, in the order they first appear. |
by_layer |
Split a design into one sub-design per layer, styles and all. |
Style
dataclass
¶
Style(layer: str | None = None, stroke: str | None = None, width: float | None = None, fill: str | None = None)
How one stroke or one loose point is drawn.
Every field is optional and None means "not stated", which is not the
same as a default: an unstated color takes whatever the writer was told
to use, so a style that names only a layer still draws in the document's
own ink.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer
|
str
|
Which layer the geometry belongs on. SVG writes these as the labeled
groups Inkscape and |
None
|
stroke
|
str
|
Line color, as any CSS color string. DXF has no notion of an arbitrary color, so its writer maps the seven it can name and leaves the rest to the layer. |
None
|
width
|
float
|
Stroke width, in the units the writer is working in. Must be > 0. |
None
|
fill
|
str
|
Fill color for closed paths. Line art rarely wants one, which is why it is not the default. |
None
|
Methods:
| Name | Description |
|---|---|
merged |
Return this style with everything |
merged
¶
Return this style with everything other states laid over it.
Silence loses: a field other leaves at None keeps this style's
value, which is what makes styled composable -- setting a color
later must not quietly clear the layer set earlier.
Source code in src/geomotif/core/style.py
styled
¶
styled(design: Design, style: Style | None = None, *, layer: str | None = None, stroke: str | None = None, width: float | None = None, fill: str | None = None) -> Design
Return design with a style laid over every stroke and loose point.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
design
|
Design
|
What to style. Returned unchanged if nothing is actually stated. |
required |
style
|
Style
|
A whole style to apply. |
None
|
layer
|
str | None
|
Individual fields, applied over |
None
|
stroke
|
str | None
|
Individual fields, applied over |
None
|
width
|
str | None
|
Individual fields, applied over |
None
|
fill
|
str | None
|
Individual fields, applied over |
None
|
Returns:
| Type | Description |
|---|---|
Design
|
The same geometry, with styles merged over whatever it already carried -- so a second call that names a color keeps the layer the first one set. |
Source code in src/geomotif/core/style.py
styles_of
¶
Return one style per stroke, None where a stroke has none.
Always exactly as long as design.paths, whatever the metadata says, so
callers can zip the two without checking.
Source code in src/geomotif/core/style.py
point_styles_of
¶
Return one style per loose point, None where a point has none.
layer_names
¶
layer_names(design: Design) -> tuple[str, ...]
Return the layers a design uses, in the order they first appear.
First appearance rather than alphabetical: layer order is drawing order, and a plotter changes pens in the order the file lists them.
Source code in src/geomotif/core/style.py
by_layer
¶
Split a design into one sub-design per layer, styles and all.
Returns:
| Type | Description |
|---|---|
dict
|
Keyed by layer name, in first-appearance order, with |