diff options
| author | Micha White <botahamec@outlook.com> | 2024-08-15 20:16:32 -0400 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2024-08-15 20:16:32 -0400 |
| commit | db9aa9f1bf49e8bede384b9ceb1e1fb82b522799 (patch) | |
| tree | 0d60727acf481f59b42ef0f74ed07c16ec562bcf /tvg/src/path.rs | |
| parent | f8a80039c74332e2101a177ef3fde31ef2077224 (diff) | |
Delete stuff
Diffstat (limited to 'tvg/src/path.rs')
| -rw-r--r-- | tvg/src/path.rs | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/tvg/src/path.rs b/tvg/src/path.rs deleted file mode 100644 index a576eb8..0000000 --- a/tvg/src/path.rs +++ /dev/null @@ -1,320 +0,0 @@ -use std::io::Read; - -use byteorder::ReadBytesExt; -use num_enum::TryFromPrimitive; -use raise::yeet; - -use crate::{commands::Point, header::TvgHeader, read_unit, read_varuint, Decode, TvgError}; - -/// Returns an error if the padding isn't zero -fn check_padding(padding: u8) -> Result<(), TvgError> { - if padding != 0 { - yeet!(TvgError::NonZeroPadding(padding)) - } - - Ok(()) -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)] -#[repr(u8)] -pub(crate) enum Sweep { - Right = 0, - Left = 1, -} - -/// An instruction to move a hypothetical "pen". -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)] -#[repr(u8)] -enum InstructionKind { - /// A straight line is drawn from the current point to a new point. - Line = 0, - /// A straight horizontal line is drawn from the current point to a new x - /// coordinate. - HorizontalLine = 1, - /// A straight vertical line is drawn from the current point to a new y - /// coordiante. - VerticalLine = 2, - /// A cubic Bézier curve is drawn from the current point to a new point. - CubicBezier = 3, - /// A circle segment is drawn from current point to a new point. - ArcCircle = 4, - /// An ellipse segment is drawn from current point to a new point. - ArcEllipse = 5, - /// The path is closed, and a straight line is drawn to the starting point. - ClosePath = 6, - /// A quadratic Bézier curve is drawn from the current point to a new point. - QuadraticBezier = 7, -} - -#[derive(Debug, Clone, Copy)] -pub(crate) enum InstructionData { - /// The line instruction draws a straight line to the position. - Line { - /// The end point of the line. - position: Point, - }, - /// The horizontal line instruction draws a straight horizontal line to a - /// given x coordinate. - HorizontalLine { - /// The new x coordinate. - x: f64, - }, - /// The vertical line instruction draws a straight vertical line to a given - /// y coordinate. - VerticalLine { - /// The new y coordinate. - y: f64, - }, - /// The cubic bezier instruction draws a Bézier curve with two control - /// points. - /// - /// The curve is drawn between the current location and `point_1` with - /// `control_0` being the first control point and `control_1` being the - /// second one. - CubicBezier { - /// The first control point. - control_0: Point, - /// The second control point. - control_1: Point, - /// The end point of the Bézier curve. - point_1: Point, - }, - /// Draws a circle segment between the current and the target point. - /// - /// The `radius` field determines the radius of the circle. If the distance - /// between the current point and `target` is larger than `radius`, the - /// distance is used as the radius. - ArcCircle { - /// If `true`, the large portion of the circle segment is drawn. - large_arc: bool, - /// Determines if the circle segment is left- or right bending. - sweep: Sweep, - /// The radius of the circle. - radius: f64, - /// The end point of the circle segment. - target: Point, - }, - /// Draws an ellipse segment between the current and the target point. - /// - /// The `radius_x` and `radius_y` fields determine the both radii of the - /// ellipse. If the distance between the current point and target is not - /// enough to fit any ellipse segment between the two points, `radius_x` - /// and `radius_y` are scaled uniformly so that it fits exactly. - ArcEllipse { - /// If `true`, the large portion of the ellipse segment is drawn. - large_arc: bool, - /// Determines if the ellipse segment is left- or right bending. - sweep: Sweep, - /// The radius of the ellipse segment in the horizontal direction. - radius_x: f64, - /// The radius of the ellipse segment in the vertical direction. - radius_y: f64, - /// The rotation of the ellipse in mathematical negative direction, in - /// degrees. - rotation: f64, - /// The end point of the ellipse segment. - target: Point, - }, - /// A straight line is drawn to the start location of the current segment. - /// This instruction doesn’t have additional data encoded. - ClosePath, - /// The quadratic bezier instruction draws a Bézier curve with a single - /// control point. - /// - /// The curve is drawn between the current location and `point_1` with - /// control being the control point. - QuadraticBezier { - /// The control point. - control: Point, - /// The end point of the Bézier curve. - target: Point, - }, -} - -impl InstructionData { - fn read( - reader: &mut impl Read, - header: &TvgHeader, - kind: InstructionKind, - ) -> Result<Self, TvgError> { - match kind { - InstructionKind::Line => Self::read_line(reader, header), - InstructionKind::HorizontalLine => Self::read_horizontal_line(reader, header), - InstructionKind::VerticalLine => Self::read_vertical_line(reader, header), - InstructionKind::CubicBezier => Self::read_cubic_bezier(reader, header), - InstructionKind::ArcCircle => Self::read_arc_circle(reader, header), - InstructionKind::ArcEllipse => Self::read_arc_ellipse(reader, header), - InstructionKind::ClosePath => Ok(Self::ClosePath), - InstructionKind::QuadraticBezier => Self::read_quadratic_bezier(reader, header), - } - } - - fn read_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - Ok(Self::Line { - position: Point::read(reader, header)?, - }) - } - - fn read_horizontal_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - Ok(Self::HorizontalLine { - x: read_unit(reader, header)?, - }) - } - - fn read_vertical_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - Ok(Self::VerticalLine { - y: read_unit(reader, header)?, - }) - } - - fn read_cubic_bezier(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - Ok(Self::CubicBezier { - control_0: Point::read(reader, header)?, - control_1: Point::read(reader, header)?, - point_1: Point::read(reader, header)?, - }) - } - - fn read_arc_header( - reader: &mut impl Read, - header: &TvgHeader, - ) -> Result<(bool, Sweep), TvgError> { - // large_arc and sweep are stored in the same byte - let byte = reader.read_u8()?; - let large_arc = (byte & 1) != 0; - let sweep = match byte & 2 { - 0 => Sweep::Left, - _ => Sweep::Right, - }; - - check_padding((byte & 0b1111_1100) >> 2)?; - - Ok((large_arc, sweep)) - } - - fn read_arc_circle(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - let (large_arc, sweep) = Self::read_arc_header(reader, header)?; - let radius = read_unit(reader, header)?; - let target = Point::read(reader, header)?; - - Ok(Self::ArcCircle { - large_arc, - sweep, - radius, - target, - }) - } - - fn read_arc_ellipse(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - let (large_arc, sweep) = Self::read_arc_header(reader, header)?; - let radius_x = read_unit(reader, header)?; - let radius_y = read_unit(reader, header)?; - let rotation = read_unit(reader, header)?; - let target = Point::read(reader, header)?; - - Ok(Self::ArcEllipse { - large_arc, - sweep, - radius_x, - radius_y, - rotation, - target, - }) - } - - fn read_quadratic_bezier(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - Ok(Self::QuadraticBezier { - control: Point::read(reader, header)?, - target: Point::read(reader, header)?, - }) - } -} - -#[derive(Debug, Clone)] -pub(crate) struct Instruction { - /// The width of the line the "pen" makes, if it makes one at all. - pub(crate) line_width: Option<f64>, - /// The arguments to the instruction. - pub(crate) data: InstructionData, -} - -impl Instruction { - fn read(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { - let byte = reader.read_u8()?; - let instruction_kind = - InstructionKind::try_from_primitive(byte & 0b0000_0111).expect("invalid instruction"); - let has_line_width = (byte & 0b0001_0000) != 0; - - check_padding((byte & 0b0000_1000) >> 3)?; - check_padding((byte & 0b1110_0000) >> 5)?; - - let line_width = has_line_width - .then(|| read_unit(reader, header)) - .transpose()?; - let data = InstructionData::read(reader, header, instruction_kind)?; - - Ok(Self { line_width, data }) - } -} - -#[derive(Debug, Clone)] -pub(crate) struct Segment { - /// The starting point of the segment. - pub(crate) start: Point, - /// The list of instructions for tha segment. - pub(crate) instructions: Box<[Instruction]>, -} - -impl Segment { - fn read( - reader: &mut impl Read, - header: &TvgHeader, - segment_length: u32, - ) -> Result<Self, TvgError> { - let start = Point::read(reader, header)?; - - let mut instructions = Vec::with_capacity(segment_length as usize); - for _ in 0..segment_length { - instructions.push(Instruction::read(reader, header)?) - } - - Ok(Segment { - start, - instructions: instructions.into_boxed_slice(), - }) - } -} - -/// Paths describe instructions to create complex 2D graphics. -/// -/// Each path segment generates a shape by moving a ”pen” around. The path this -/// ”pen” takes is the outline of our segment. Each segment, the ”pen” starts -/// at a defined position and is moved by instructions. Each instruction will -/// leave the ”pen” at a new position. The line drawn by our ”pen” is the -/// outline of the shape. -#[derive(Debug, Clone)] -pub struct Path { - pub(crate) segments: Box<[Segment]>, -} - -impl Path { - pub(crate) fn read( - reader: &mut impl Read, - header: &TvgHeader, - segment_count: u32, - ) -> Result<Self, TvgError> { - let mut segment_lengths = Vec::with_capacity(segment_count as usize); - for _ in 0..segment_count { - segment_lengths.push(read_varuint(reader)? + 1); - } - - let mut segments = Vec::with_capacity(segment_count as usize); - for segment_length in segment_lengths { - segments.push(Segment::read(reader, header, segment_length)?); - } - - Ok(Self { - segments: segments.into_boxed_slice(), - }) - } -} |
