summaryrefslogtreecommitdiff
path: root/tvg/src/path.rs
diff options
context:
space:
mode:
authorMicha White <botahamec@outlook.com>2024-08-15 20:16:32 -0400
committerMicha White <botahamec@outlook.com>2024-08-15 20:16:32 -0400
commitdb9aa9f1bf49e8bede384b9ceb1e1fb82b522799 (patch)
tree0d60727acf481f59b42ef0f74ed07c16ec562bcf /tvg/src/path.rs
parentf8a80039c74332e2101a177ef3fde31ef2077224 (diff)
Delete stuff
Diffstat (limited to 'tvg/src/path.rs')
-rw-r--r--tvg/src/path.rs320
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(),
- })
- }
-}