///|
// Data-container identities detect setter replacements even when equal data
// was supplied. The carrier independently copies values for mutation checks.
priv struct DiscreteLineSource {
data : @render.DiscreteLineHitData
line : Line2D?
x : LineData?
y : LineData?
}
///|
fn Axes::record_discrete_line(
self : Axes,
data : @render.DiscreteLineHitData,
) -> Unit {
let records = self.state.val.artist_hits
if records.is_empty() {
return
}
let record = records[records.length() - 1]
guard record.artist is Artist::Line(points, _) else { return }
for line in self.state.val.line_originals {
if physical_equal(line.points, points) {
record.discrete = Some({
data,
line: Some(line),
x: Some(line.x),
y: Some(line.y),
})
return
}
}
record.discrete = Some({ data, line: None, x: None, y: None, })
}
///|
// A filled stairs polygon shares the same copied path/datum carrier. Its
// validated boundary-edge map is not a second line stroke or a hit bbox.
fn Axes::record_discrete_face(
self : Axes,
data : @render.DiscreteLineHitData,
) -> Unit {
let records = self.state.val.artist_hits
if records.is_empty() {
return
}
let record = records[records.length() - 1]
if record.artist is Artist::Polygon(_, _) {
record.discrete = Some({ data, line: None, x: None, y: None, })
}
}
///|
fn discrete_same_original(first : LineData, second : LineData?) -> Bool {
match (first, second) {
(Numeric(a), Some(Numeric(b))) => physical_equal(a, b)
_ => false
}
}
///|
fn DiscreteLineSource::prepare(
self : DiscreteLineSource,
line : Line2D,
path : Array[@core.Point],
samples : Array[@core.Point]?,
) -> @render.DiscreteLineHitData? {
guard self.line is Some(original) else { return None }
if !physical_equal(line, original) ||
line.drawstyle != "default" ||
!discrete_same_original(line.x, self.x) ||
!discrete_same_original(line.y, self.y) ||
!self.data.matches_path(path) {
return None
}
guard samples is Some(current) else { return None }
if !self.data.matches_path(current) {
return None
}
match (line.x, line.y) {
(Numeric(xs), Numeric(ys)) =>
if self.data.matches_xy(xs, ys) {
Some(self.data)
} else {
None
}
_ => None
}
}
///|
fn prepared_discrete_line(
sources : Array[DiscreteLineSource],
line : Line2D,
path : Array[@core.Point],
samples : Array[@core.Point]?,
) -> @render.DiscreteLineHitData? {
for source in sources {
if source.line is Some(original) && physical_equal(original, line) {
return source.prepare(line, path, samples)
}
}
None
}