diff options
| author | Micha White <botahamec@outlook.com> | 2023-02-13 00:40:32 -0500 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2023-02-13 00:40:32 -0500 |
| commit | 89c4981fad88c0ae8353f6e934c1ec10d51b0fd7 (patch) | |
| tree | 35e3161fb03ca72aa944b39b7f1f6c2ad6463adb /tvg | |
| parent | 861b467b95be55db3a42182b77dba944869bf49f (diff) | |
Support custom color encodings
Diffstat (limited to 'tvg')
| -rw-r--r-- | tvg/src/colors.rs | 29 | ||||
| -rw-r--r-- | tvg/src/lib.rs | 33 |
2 files changed, 56 insertions, 6 deletions
diff --git a/tvg/src/colors.rs b/tvg/src/colors.rs index 10bc41c..9f4e7e5 100644 --- a/tvg/src/colors.rs +++ b/tvg/src/colors.rs @@ -3,6 +3,8 @@ use std::io::{self, Read}; use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; use num_enum::TryFromPrimitive; +use crate::TvgError; + /// The color table encodes the palette for this file. /// /// It’s binary content is defined by the `color_encoding` field in the header. @@ -14,12 +16,14 @@ pub struct ColorTable<C: Color> { } impl<C: Color> ColorTable<C> { - /// Read in one encoding, and convert it to another + /// Read in one encoding, and convert it to another. If `encoding` is + /// [`ColorEncoding::Custom`], then return + /// [`TvgError::UnsupportedColorEncoding`]. pub fn read_from_encoding( reader: &mut impl Read, color_count: u32, encoding: ColorEncoding, - ) -> io::Result<Self> { + ) -> Result<Self, TvgError> { Ok(match encoding { ColorEncoding::Rgba8888 => (&ColorTable::<Rgba8888>::read(reader, color_count)?).into(), ColorEncoding::Rgb565 => (&ColorTable::<Rgb565>::read(reader, color_count)?).into(), @@ -28,6 +32,21 @@ impl<C: Color> ColorTable<C> { }) } + /// Read in one encoding, and convert it into another. If `encoding` is + /// [`ColorEncoding::Custom`], then use the given encoding. + pub fn read_from_encoding_with_custom<Custom: Color>( + reader: &mut impl Read, + color_count: u32, + encoding: ColorEncoding, + ) -> io::Result<Self> { + Ok(match encoding { + ColorEncoding::Rgba8888 => (&ColorTable::<Rgba8888>::read(reader, color_count)?).into(), + ColorEncoding::Rgb565 => (&ColorTable::<Rgb565>::read(reader, color_count)?).into(), + ColorEncoding::RgbaF32 => (&ColorTable::<RgbaF32>::read(reader, color_count)?).into(), + ColorEncoding::Custom => (&ColorTable::<Custom>::read(reader, color_count)?).into(), + }) + } + /// Parse a color table. fn read(reader: &mut impl Read, color_count: u32) -> io::Result<Self> { let mut colors = Vec::with_capacity(color_count as usize); @@ -117,7 +136,7 @@ pub trait Color: Sized { /// Each color value is encoded as a sequence of four bytes. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -struct Rgba8888 { +pub struct Rgba8888 { /// Red color channel between 0 and 100% intensity, mapped to byte values 0 /// to 255. red: u8, @@ -172,7 +191,7 @@ impl Color for Rgba8888 { /// Each color value is encoded as a sequence of 2 bytes. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -struct Rgb565 { +pub struct Rgb565 { /// Red color channel between 0 and 100% intensity, mapped to integer /// values 0 to 31. red: u8, @@ -224,7 +243,7 @@ impl Color for Rgb565 { /// Each color value is encoded as a sequence of 16 bytes. #[derive(Debug, Clone, Copy, PartialEq)] -struct RgbaF32 { +pub struct RgbaF32 { /// Red color channel, using 0.0 for 0% intensity and 1.0 for 100% /// intensity. red: f32, diff --git a/tvg/src/lib.rs b/tvg/src/lib.rs index 5cbe33c..011b5c7 100644 --- a/tvg/src/lib.rs +++ b/tvg/src/lib.rs @@ -11,7 +11,7 @@ mod commands; mod header; mod path; -pub use colors::Rgba16; +pub use colors::{Rgb565, Rgba16, Rgba8888, RgbaF32}; pub use header::SUPPORTED_VERSION; pub struct TvgFile<C: Color> { @@ -21,6 +21,7 @@ pub struct TvgFile<C: Color> { } impl<C: Color + std::fmt::Debug> TvgFile<C> { + /// Read a TinyVG file. pub fn read_from(reader: &mut impl Read) -> Result<Self, TvgError> { let header = TvgHeader::read(reader)?; let color_table = @@ -42,6 +43,34 @@ impl<C: Color + std::fmt::Debug> TvgFile<C> { commands: commands.into_boxed_slice(), }) } + + /// Read a TinyVG file. If a Custom color encoding if found, use the specified encoding. + pub fn read_with_custom_encoding<Custom: Color>( + reader: &mut impl Read, + ) -> Result<Self, TvgError> { + let header = TvgHeader::read(reader)?; + let color_table = ColorTable::read_from_encoding_with_custom::<Custom>( + reader, + header.color_count(), + header.color_encoding(), + )?; + + let mut commands = Vec::new(); + loop { + let command = Command::read(reader, &header)?; + commands.push(command.clone()); + + if command.is_end_of_document() { + break; + } + } + + Ok(Self { + header, + color_table, + commands: commands.into_boxed_slice(), + }) + } } #[derive(Debug, Error)] @@ -52,6 +81,8 @@ pub enum TvgError { UnsupportedVersion(u8), #[error("Found a coordinate range with an index of 3, which is invalid")] InvalidCoordinateRange, + #[error("Found a Custom color encoding, which is unsupported")] + UnsupportedColorEncoding, #[error("Found a command with an index of {}, which is invalid", .0)] InvalidCommand(u8), #[error("Found a style kind with an index of 3, which is invalid")] |
