blob: 78adf7529e3b7e5f247a5fbfc6c9083f373c6636 [file] [log] [blame] [edit]
// Copyright 2023 The Vello authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
use {
bytemuck::{Pod, Zeroable},
std::{collections::BTreeSet, fmt},
vello_encoding::LineSoup,
};
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Pod, Zeroable)]
#[repr(C)]
pub struct LineEndpoint {
pub path_ix: u32,
// Coordinates in IEEE-754 32-bit float representation
pub x: u32,
pub y: u32,
}
impl LineEndpoint {
pub fn new(line: &LineSoup, start_or_end: bool) -> Self {
let (x, y) = if start_or_end {
(line.p0[0], line.p0[1])
} else {
(line.p1[0], line.p1[1])
};
Self {
path_ix: line.path_ix,
x: x.to_bits(),
y: y.to_bits(),
}
}
}
impl fmt::Debug for LineEndpoint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Point")
.field("path_ix", &self.path_ix)
.field("x", &f32::from_bits(self.x))
.field("y", &f32::from_bits(self.y))
.finish()
}
}
pub(crate) fn validate_line_soup(lines: &[LineSoup]) -> Vec<LineEndpoint> {
let mut points = BTreeSet::new();
for line in lines {
let pts = [
LineEndpoint::new(line, true),
LineEndpoint::new(line, false),
];
for p in pts {
if !points.remove(&p) {
points.insert(p);
}
}
}
if !points.is_empty() {
eprintln!("Unpaired points are present: {:#?}", points);
}
points.into_iter().collect()
}