Remove unused path representation

This commit is contained in:
Chad Brokaw 2022-04-11 06:14:58 -04:00
parent f8f91e4207
commit db2c4d21c9
3 changed files with 15 additions and 255 deletions

View file

@ -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 {
pub fn elements(&self) -> impl Iterator<Item = Element> + Clone {
let elements = [

View file

@ -49,5 +49,4 @@ pub struct PersistentBrush {
struct PersistentBrushData {
brush: Brush,
}

View file

@ -45,10 +45,14 @@ pub struct Builder<'a> {
impl<'a> Builder<'a> {
/// 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();
resources.clear();
Self { scene, resources, layers: vec![] }
Self {
scene,
resources,
layers: vec![],
}
}
/// Pushes a transform matrix onto the stack.
@ -173,7 +177,7 @@ impl<'a> Builder<'a> {
}
/// Completes construction and finalizes the underlying scene.
pub fn finish(self) {
pub fn finish(mut self) {
while let Some(layer) = self.layers.pop() {
self.end_clip(Some(layer));
}
@ -301,7 +305,9 @@ impl<'a> Builder<'a> {
let element = Clip {
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;
}
@ -310,7 +316,9 @@ impl<'a> Builder<'a> {
let element = Clip {
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.
self.scene.tag_stream.push(0x10);
self.scene.n_path += 1;
@ -326,10 +334,11 @@ enum ResourceData<'a> {
impl ResourceData<'_> {
fn clear(&mut self) {
match self {
Self::Fragment(res) {
Self::Fragment(res) => {
res.patches.clear();
res.stops.clear();
}
_ => {}
}
}
}