mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Remove unused path representation
This commit is contained in:
parent
f8f91e4207
commit
db2c4d21c9
|
@ -49,254 +49,6 @@ impl Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encoded collection of path elements.
|
|
||||||
#[derive(Clone, Default, Debug)]
|
|
||||||
pub struct Path {
|
|
||||||
tag_stream: Vec<u8>,
|
|
||||||
pathseg_stream: Vec<u8>,
|
|
||||||
n_path: u32,
|
|
||||||
n_pathseg: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Path {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn elements(&self) -> Elements {
|
|
||||||
Elements::new(&self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Elements<'a> {
|
|
||||||
tag_stream: &'a [u8],
|
|
||||||
points: &'a [[f32; 2]],
|
|
||||||
tag_ix: usize,
|
|
||||||
point_ix: usize,
|
|
||||||
next_element: Option<Element>,
|
|
||||||
close: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Elements<'a> {
|
|
||||||
fn new(path: &'a Path) -> Self {
|
|
||||||
let points: &'a [[f32; 2]] = bytemuck::cast_slice(&path.pathseg_stream);
|
|
||||||
let (point_ix, next_element) = match points.get(0) {
|
|
||||||
Some(&point) => (1, Some(Element::MoveTo(point.into()))),
|
|
||||||
None => (0, None),
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
tag_stream: &path.tag_stream,
|
|
||||||
points,
|
|
||||||
tag_ix: 0,
|
|
||||||
point_ix,
|
|
||||||
next_element,
|
|
||||||
close: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for Elements<'a> {
|
|
||||||
type Item = Element;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
// println!("n_points: {}", self.points.len());
|
|
||||||
// println!("tag_ix: {}, point_ix: {}, el: {:?}, close: {}", self.tag_ix, self.point_ix, self.next_element, self.close);
|
|
||||||
if self.close {
|
|
||||||
self.close = false;
|
|
||||||
return Some(Element::Close);
|
|
||||||
}
|
|
||||||
if let Some(next_el) = self.next_element.take() {
|
|
||||||
return Some(next_el);
|
|
||||||
}
|
|
||||||
let tag = *self.tag_stream.get(self.tag_ix)?;
|
|
||||||
self.tag_ix += 1;
|
|
||||||
let end = tag & 4 != 0;
|
|
||||||
let el = match tag & 3 {
|
|
||||||
1 => {
|
|
||||||
let p0 = *self.points.get(self.point_ix)?;
|
|
||||||
self.point_ix += 1;
|
|
||||||
Element::LineTo(p0.into())
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
let p0 = *self.points.get(self.point_ix)?;
|
|
||||||
let p1 = *self.points.get(self.point_ix + 1)?;
|
|
||||||
self.point_ix += 2;
|
|
||||||
Element::QuadTo(p0.into(), p1.into())
|
|
||||||
}
|
|
||||||
3 => {
|
|
||||||
let p0 = *self.points.get(self.point_ix)?;
|
|
||||||
let p1 = *self.points.get(self.point_ix + 1)?;
|
|
||||||
let p2 = *self.points.get(self.point_ix + 2)?;
|
|
||||||
self.point_ix += 3;
|
|
||||||
Element::CurveTo(p0.into(), p1.into(), p2.into())
|
|
||||||
}
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
if end {
|
|
||||||
// println!("END!");
|
|
||||||
if let Some(&p0) = self.points.get(self.point_ix) {
|
|
||||||
self.point_ix += 1;
|
|
||||||
self.next_element = Some(Element::MoveTo(p0.into()));
|
|
||||||
}
|
|
||||||
self.close = tag & 0x80 != 0;
|
|
||||||
}
|
|
||||||
Some(el)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PathBuilder<'a> {
|
|
||||||
tag_stream: &'a mut Vec<u8>,
|
|
||||||
// If we're never going to use the i16 encoding, it might be
|
|
||||||
// slightly faster to store this as Vec<u32>, we'd get aligned
|
|
||||||
// stores on ARM etc.
|
|
||||||
pathseg_stream: &'a mut Vec<u8>,
|
|
||||||
first_pt: [f32; 2],
|
|
||||||
state: State,
|
|
||||||
n_pathseg: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
enum State {
|
|
||||||
Start,
|
|
||||||
MoveTo,
|
|
||||||
NonemptySubpath,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> PathBuilder<'a> {
|
|
||||||
pub fn new(path: &'a mut Path) -> Self {
|
|
||||||
Self {
|
|
||||||
tag_stream: &mut path.tag_stream,
|
|
||||||
pathseg_stream: &mut path.pathseg_stream,
|
|
||||||
first_pt: [0.0, 0.0],
|
|
||||||
state: State::Start,
|
|
||||||
n_pathseg: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_inner(tags: &'a mut Vec<u8>, pathsegs: &'a mut Vec<u8>) -> PathBuilder<'a> {
|
|
||||||
PathBuilder {
|
|
||||||
tag_stream: tags,
|
|
||||||
pathseg_stream: pathsegs,
|
|
||||||
first_pt: [0.0, 0.0],
|
|
||||||
state: State::Start,
|
|
||||||
n_pathseg: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn move_to(&mut self, x: f32, y: f32) {
|
|
||||||
let buf = [x, y];
|
|
||||||
let bytes = bytemuck::bytes_of(&buf);
|
|
||||||
self.first_pt = buf;
|
|
||||||
if self.state == State::MoveTo {
|
|
||||||
let new_len = self.pathseg_stream.len() - 8;
|
|
||||||
self.pathseg_stream.truncate(new_len);
|
|
||||||
}
|
|
||||||
if self.state == State::NonemptySubpath {
|
|
||||||
if let Some(tag) = self.tag_stream.last_mut() {
|
|
||||||
*tag |= 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.pathseg_stream.extend_from_slice(bytes);
|
|
||||||
self.state = State::MoveTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn line_to(&mut self, x: f32, y: f32) {
|
|
||||||
if self.state == State::Start {
|
|
||||||
// should warn or error
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let buf = [x, y];
|
|
||||||
let bytes = bytemuck::bytes_of(&buf);
|
|
||||||
self.pathseg_stream.extend_from_slice(bytes);
|
|
||||||
self.tag_stream.push(9);
|
|
||||||
self.state = State::NonemptySubpath;
|
|
||||||
self.n_pathseg += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn quad_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
|
|
||||||
if self.state == State::Start {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let buf = [x1, y1, x2, y2];
|
|
||||||
let bytes = bytemuck::bytes_of(&buf);
|
|
||||||
self.pathseg_stream.extend_from_slice(bytes);
|
|
||||||
self.tag_stream.push(10);
|
|
||||||
self.state = State::NonemptySubpath;
|
|
||||||
self.n_pathseg += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cubic_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) {
|
|
||||||
if self.state == State::Start {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let buf = [x1, y1, x2, y2, x3, y3];
|
|
||||||
let bytes = bytemuck::bytes_of(&buf);
|
|
||||||
self.pathseg_stream.extend_from_slice(bytes);
|
|
||||||
self.tag_stream.push(11);
|
|
||||||
self.state = State::NonemptySubpath;
|
|
||||||
self.n_pathseg += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_path(&mut self) {
|
|
||||||
match self.state {
|
|
||||||
State::Start => return,
|
|
||||||
State::MoveTo => {
|
|
||||||
let new_len = self.pathseg_stream.len() - 8;
|
|
||||||
self.pathseg_stream.truncate(new_len);
|
|
||||||
self.state = State::Start;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
State::NonemptySubpath => (),
|
|
||||||
}
|
|
||||||
let len = self.pathseg_stream.len();
|
|
||||||
if len < 8 {
|
|
||||||
// can't happen
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let first_bytes = bytemuck::bytes_of(&self.first_pt);
|
|
||||||
if &self.pathseg_stream[len - 8..len] != first_bytes {
|
|
||||||
self.pathseg_stream.extend_from_slice(first_bytes);
|
|
||||||
self.tag_stream.push(0x80 | 13);
|
|
||||||
self.n_pathseg += 1;
|
|
||||||
} else {
|
|
||||||
if let Some(tag) = self.tag_stream.last_mut() {
|
|
||||||
*tag |= 0x80 | 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.state = State::Start;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finish(&mut self) {
|
|
||||||
if self.state == State::MoveTo {
|
|
||||||
let new_len = self.pathseg_stream.len() - 8;
|
|
||||||
self.pathseg_stream.truncate(new_len);
|
|
||||||
}
|
|
||||||
if let Some(tag) = self.tag_stream.last_mut() {
|
|
||||||
*tag |= 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finish encoding a path.
|
|
||||||
///
|
|
||||||
/// Encode this after encoding path segments.
|
|
||||||
pub fn path(&mut self) {
|
|
||||||
self.finish();
|
|
||||||
// maybe don't encode if path is empty? might throw off sync though
|
|
||||||
self.tag_stream.push(0x10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the number of path segments.
|
|
||||||
///
|
|
||||||
/// This is the number of path segments that will be written by the
|
|
||||||
/// path stage; use this for allocating the output buffer.
|
|
||||||
///
|
|
||||||
/// Also note: it takes `self` for lifetime reasons.
|
|
||||||
pub fn n_pathseg(self) -> u32 {
|
|
||||||
self.n_pathseg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rect {
|
impl Rect {
|
||||||
pub fn elements(&self) -> impl Iterator<Item = Element> + Clone {
|
pub fn elements(&self) -> impl Iterator<Item = Element> + Clone {
|
||||||
let elements = [
|
let elements = [
|
||||||
|
|
|
@ -49,5 +49,4 @@ pub struct PersistentBrush {
|
||||||
|
|
||||||
struct PersistentBrushData {
|
struct PersistentBrushData {
|
||||||
brush: Brush,
|
brush: Brush,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,14 @@ pub struct Builder<'a> {
|
||||||
|
|
||||||
impl<'a> Builder<'a> {
|
impl<'a> Builder<'a> {
|
||||||
/// Creates a new builder for constructing a scene.
|
/// Creates a new builder for constructing a scene.
|
||||||
fn new(scene: &'a mut SceneData, resources: ResourceData<'a>) -> Self {
|
fn new(scene: &'a mut SceneData, mut resources: ResourceData<'a>) -> Self {
|
||||||
scene.clear();
|
scene.clear();
|
||||||
resources.clear();
|
resources.clear();
|
||||||
Self { scene, resources, layers: vec![] }
|
Self {
|
||||||
|
scene,
|
||||||
|
resources,
|
||||||
|
layers: vec![],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a transform matrix onto the stack.
|
/// Pushes a transform matrix onto the stack.
|
||||||
|
@ -173,7 +177,7 @@ impl<'a> Builder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Completes construction and finalizes the underlying scene.
|
/// Completes construction and finalizes the underlying scene.
|
||||||
pub fn finish(self) {
|
pub fn finish(mut self) {
|
||||||
while let Some(layer) = self.layers.pop() {
|
while let Some(layer) = self.layers.pop() {
|
||||||
self.end_clip(Some(layer));
|
self.end_clip(Some(layer));
|
||||||
}
|
}
|
||||||
|
@ -301,7 +305,9 @@ impl<'a> Builder<'a> {
|
||||||
let element = Clip {
|
let element = Clip {
|
||||||
blend: blend.unwrap_or(Blend::default()).pack(),
|
blend: blend.unwrap_or(Blend::default()).pack(),
|
||||||
};
|
};
|
||||||
self.scene.drawdata_stream.extend(bytemuck::bytes_of(&element));
|
self.scene
|
||||||
|
.drawdata_stream
|
||||||
|
.extend(bytemuck::bytes_of(&element));
|
||||||
self.scene.n_clip += 1;
|
self.scene.n_clip += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +316,9 @@ impl<'a> Builder<'a> {
|
||||||
let element = Clip {
|
let element = Clip {
|
||||||
blend: blend.unwrap_or(Blend::default()).pack(),
|
blend: blend.unwrap_or(Blend::default()).pack(),
|
||||||
};
|
};
|
||||||
self.scene.drawdata_stream.extend(bytemuck::bytes_of(&element));
|
self.scene
|
||||||
|
.drawdata_stream
|
||||||
|
.extend(bytemuck::bytes_of(&element));
|
||||||
// This is a dummy path, and will go away with the new clip impl.
|
// This is a dummy path, and will go away with the new clip impl.
|
||||||
self.scene.tag_stream.push(0x10);
|
self.scene.tag_stream.push(0x10);
|
||||||
self.scene.n_path += 1;
|
self.scene.n_path += 1;
|
||||||
|
@ -326,10 +334,11 @@ enum ResourceData<'a> {
|
||||||
impl ResourceData<'_> {
|
impl ResourceData<'_> {
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
match self {
|
match self {
|
||||||
Self::Fragment(res) {
|
Self::Fragment(res) => {
|
||||||
res.patches.clear();
|
res.patches.clear();
|
||||||
res.stops.clear();
|
res.stops.clear();
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue