GraphicsState.java
package com.varnernet.gerb4j;
import java.awt.geom.Point2D;
/**
* Immutable snapshot of the Gerber graphics state.
*
* <p>Per Ucamco specification page 15, the state saved/restored on block entry/exit (AB, SR)
* includes:
*
* <ul>
* <li>Current point (X, Y)
* <li>Current aperture selection (Dnn)
* <li>Polarity (LP)
* <li>Mirroring (LM)
* <li>Rotation (LR)
* <li>Scaling (LS)
* </ul>
*
* <p>Note: Aperture <em>definitions</em> (AD, AB) are global and are <strong>not</strong> part of
* the graphics state. {@code PlotState} has been removed — {@link InterpolationMode} is the
* canonical interpolation-mode type and is tracked separately.
*
* @param currentPoint the current point
* @param currentApertureId the current aperture ID
* @param polarity the polarity
* @param mirroring the mirroring
* @param rotation the rotation
* @param scaling the scaling
*/
public record GraphicsState(Point2D currentPoint, String currentApertureId, Polarity polarity, Mirror mirroring,
Double rotation, Double scaling) {
/**
* Create a snapshot with all given values.
*/
public GraphicsState(
final Point2D currentPoint,
final String currentApertureId,
final Polarity polarity,
final Mirror mirroring,
final Double rotation,
final Double scaling) {
this.currentPoint =
currentPoint != null ? new Point2D.Double(currentPoint.getX(), currentPoint.getY()) : null;
this.currentApertureId = currentApertureId;
this.polarity = polarity != null ? polarity : Polarity.DARK;
this.mirroring = mirroring != null ? mirroring : Mirror.NONE;
this.rotation = rotation;
this.scaling = scaling;
}
/**
* Create a default (power-on) graphics state.
*/
public GraphicsState() {
this(null, null, Polarity.DARK, Mirror.NONE, null, null);
}
/**
* Copy constructor — produces an independent snapshot.
*
* @param other the graphics state to copy
*/
public GraphicsState(final GraphicsState other) {
this(
other.currentPoint,
other.currentApertureId,
other.polarity,
other.mirroring,
other.rotation,
other.scaling);
}
// ── Accessors ─────────────────────────────────────────────────────────────
/**
* Current pen position, or {@code null} if not yet set.
*
* @return a defensive copy of the current point, or {@code null}
*/
@Override
public Point2D currentPoint() {
return currentPoint != null
? new Point2D.Double(currentPoint.getX(), currentPoint.getY())
: null;
}
@Override
public String toString() {
return String.format(
"GraphicsState[point=%s, aperture=%s, polarity=%s, mirror=%s, rot=%s, scale=%s]",
currentPoint, currentApertureId, polarity, mirroring, rotation, scaling);
}
}