Upgrade to the Rust 2024 edition (#2367)

* Update to rust 2024 edition

* Fixes

* Clean up imports

* Cargo fmt again

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2025-03-13 01:29:12 +01:00
committed by GitHub
parent 927d7dd9b2
commit beb1c6ae64
253 changed files with 980 additions and 1371 deletions

View File

@@ -1,8 +1,8 @@
[package]
name = "bezier-rs"
version = "0.4.0"
rust-version = "1.79"
edition = "2021"
rust-version = "1.85"
edition = "2024"
authors = ["Graphite Authors <contact@graphite.rs>"]
description = "Computational geometry algorithms for Bézier segments and shapes useful in the context of 2D graphics"
license = "MIT OR Apache-2.0"

View File

@@ -1,7 +1,6 @@
use super::*;
use utils::format_point;
use std::fmt::Write;
use utils::format_point;
/// Functionality relating to core `Bezier` operations, such as constructors and `abs_diff_eq`.
impl Bezier {

View File

@@ -1,6 +1,5 @@
use crate::utils::{TValue, TValueType};
use super::*;
use crate::utils::{TValue, TValueType};
/// Functionality relating to looking up properties of the `Bezier` or points along the `Bezier`.
impl Bezier {

View File

@@ -69,7 +69,7 @@ impl Bezier {
/// - For a linear segment, the order of the points will be: `start`, `end`.
/// - For a quadratic segment, the order of the points will be: `start`, `handle`, `end`.
/// - For a cubic segment, the order of the points will be: `start`, `handle_start`, `handle_end`, `end`.
pub fn get_points(&self) -> impl Iterator<Item = DVec2> {
pub fn get_points(&self) -> impl Iterator<Item = DVec2> + use<> {
match self.handles {
BezierHandles::Linear => [self.start, self.end, DVec2::ZERO, DVec2::ZERO].into_iter().take(2),
BezierHandles::Quadratic { handle } => [self.start, handle, self.end, DVec2::ZERO].into_iter().take(3),

View File

@@ -7,11 +7,9 @@ mod transform;
use crate::consts::*;
use crate::utils;
pub use structs::*;
use glam::DVec2;
use std::fmt::{Debug, Formatter, Result};
pub use structs::*;
/// Representation of the handle point(s) in a bezier segment.
#[derive(Copy, Clone, PartialEq, Debug)]

View File

@@ -1,8 +1,7 @@
use super::*;
use crate::polynomial::Polynomial;
use crate::utils::{solve_cubic, solve_quadratic, TValue};
use crate::{to_symmetrical_basis_pair, SymmetricalBasis};
use crate::utils::{TValue, solve_cubic, solve_quadratic};
use crate::{SymmetricalBasis, to_symmetrical_basis_pair};
use glam::DMat2;
use std::ops::Range;
@@ -99,11 +98,7 @@ impl Bezier {
pub fn tangent(&self, t: TValue) -> DVec2 {
let t = self.t_value_to_parametric(t);
let tangent = self.non_normalized_tangent(t);
if tangent.length() > 0. {
tangent.normalize()
} else {
tangent
}
if tangent.length() > 0. { tangent.normalize() } else { tangent }
}
/// Find the `t`-value(s) such that the tangent(s) at `t` pass through the specified point.
@@ -147,11 +142,7 @@ impl Bezier {
let numerator = d.x * dd.y - d.y * dd.x;
let denominator = (d.x.powf(2.) + d.y.powf(2.)).powf(1.5);
if denominator.abs() < MAX_ABSOLUTE_DIFFERENCE {
0.
} else {
numerator / denominator
}
if denominator.abs() < MAX_ABSOLUTE_DIFFERENCE { 0. } else { numerator / denominator }
}
/// Returns two lists of `t`-values representing the local extrema of the `x` and `y` parametric curves respectively.
@@ -228,7 +219,7 @@ impl Bezier {
}
/// Returns an `Iterator` containing all possible parametric `t`-values at the given `x`-coordinate.
pub fn find_tvalues_for_x(&self, x: f64) -> impl Iterator<Item = f64> {
pub fn find_tvalues_for_x(&self, x: f64) -> impl Iterator<Item = f64> + use<> {
// Compute the roots of the resulting bezier curve
match self.handles {
BezierHandles::Linear => {

View File

@@ -1,9 +1,7 @@
use super::*;
use crate::compare::compare_points;
use crate::utils::{f64_compare, Cap, TValue};
use crate::utils::{Cap, TValue, f64_compare};
use crate::{AppendType, ManipulatorGroup, Subpath};
use glam::DMat2;
use std::f64::consts::PI;
@@ -476,11 +474,7 @@ impl Bezier {
error,
max_iterations,
});
if final_low_t != 1. {
[auto_arcs, arc_approximations].concat()
} else {
auto_arcs
}
if final_low_t != 1. { [auto_arcs, arc_approximations].concat() } else { auto_arcs }
}
ArcStrategy::FavorLargerArcs => self.approximate_curve_with_arcs(0., 1., error, max_iterations, false).0,
ArcStrategy::FavorCorrectness => self
@@ -620,9 +614,9 @@ impl Bezier {
#[cfg(test)]
mod tests {
use super::*;
use crate::EmptyId;
use crate::compare::{compare_arcs, compare_points};
use crate::utils::{Cap, TValue};
use crate::EmptyId;
#[test]
fn test_split() {
@@ -777,14 +771,18 @@ mod tests {
// Check that the reduce helper is correct
let (helper_curves, helper_t_values) = bezier.reduced_curves_and_t_values(None);
assert!(reduced_curves
.iter()
.zip(helper_curves.iter())
.all(|(bezier1, bezier2)| bezier1.abs_diff_eq(bezier2, MAX_ABSOLUTE_DIFFERENCE)));
assert!(reduced_curves
.iter()
.zip(helper_t_values.iter())
.all(|(curve, t_pair)| curve.abs_diff_eq(&bezier.trim(TValue::Parametric(t_pair[0]), TValue::Parametric(t_pair[1])), MAX_ABSOLUTE_DIFFERENCE)))
assert!(
reduced_curves
.iter()
.zip(helper_curves.iter())
.all(|(bezier1, bezier2)| bezier1.abs_diff_eq(bezier2, MAX_ABSOLUTE_DIFFERENCE))
);
assert!(
reduced_curves
.iter()
.zip(helper_t_values.iter())
.all(|(curve, t_pair)| curve.abs_diff_eq(&bezier.trim(TValue::Parametric(t_pair[0]), TValue::Parametric(t_pair[1])), MAX_ABSOLUTE_DIFFERENCE))
)
}
fn assert_valid_offset<PointId: crate::Identifier>(bezier: &Bezier, offset: &Subpath<PointId>, expected_distance: f64) {

View File

@@ -1,11 +1,9 @@
/// Comparison functions used for tests in the bezier module
#[cfg(test)]
use super::{CircleArc, Subpath};
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
#[cfg(test)]
use crate::utils::f64_compare;
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use glam::DVec2;
// Compare two f64s with some maximum absolute difference to account for floating point errors

View File

@@ -102,7 +102,7 @@ impl<const N: usize> Default for Polynomial<N> {
impl<const N: usize> Display for Polynomial<N> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let mut first = true;
for (index, coefficient) in self.coefficients.iter().enumerate().rev().filter(|(_, &coefficient)| coefficient != 0.) {
for (index, coefficient) in self.coefficients.iter().enumerate().rev().filter(|&(_, &coefficient)| coefficient != 0.) {
if first {
first = false;
} else {

View File

@@ -1,7 +1,6 @@
use super::*;
use crate::consts::*;
use crate::utils::format_point;
use glam::DVec2;
use std::fmt::Write;

View File

@@ -124,7 +124,6 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
mod tests {
use super::*;
use crate::utils::SubpathTValue;
use glam::DVec2;
fn set_up_open_subpath() -> Subpath<EmptyId> {

View File

@@ -4,13 +4,12 @@ mod manipulators;
mod solvers;
mod structs;
mod transform;
pub use core::*;
pub use structs::*;
use crate::Bezier;
pub use core::*;
use std::fmt::{Debug, Formatter, Result};
use std::ops::{Index, IndexMut};
pub use structs::*;
/// Structure used to represent a path composed of [Bezier] curves.
#[derive(Clone, PartialEq, Hash)]

View File

@@ -1,8 +1,7 @@
use super::*;
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use crate::utils::{compute_circular_subpath_details, is_rectangle_inside_other, line_intersection, SubpathTValue};
use crate::TValue;
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use crate::utils::{SubpathTValue, compute_circular_subpath_details, is_rectangle_inside_other, line_intersection};
use glam::{DAffine2, DMat2, DVec2};
use std::f64::consts::PI;
@@ -539,10 +538,9 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
#[cfg(test)]
mod tests {
use super::*;
use crate::Bezier;
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use crate::utils;
use crate::Bezier;
use glam::DVec2;
fn normalize_t(n: i64, t: f64) -> f64 {
@@ -629,44 +627,54 @@ mod tests {
let mut n = (subpath.len() as i64) - 1;
let t0 = 0.;
assert!(utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t0)),
linear_bezier.evaluate(TValue::Parametric(normalize_t(n, t0))),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t0)),
linear_bezier.evaluate(TValue::Parametric(normalize_t(n, t0))),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
let t1 = 0.25;
assert!(utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t1)),
linear_bezier.evaluate(TValue::Parametric(normalize_t(n, t1))),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t1)),
linear_bezier.evaluate(TValue::Parametric(normalize_t(n, t1))),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
let t2 = 0.50;
assert!(utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t2)),
quadratic_bezier.evaluate(TValue::Parametric(normalize_t(n, t2))),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t2)),
quadratic_bezier.evaluate(TValue::Parametric(normalize_t(n, t2))),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
let t3 = 0.75;
assert!(utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t3)),
quadratic_bezier.evaluate(TValue::Parametric(normalize_t(n, t3))),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t3)),
quadratic_bezier.evaluate(TValue::Parametric(normalize_t(n, t3))),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
let t4 = 1.;
assert!(utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t4)),
quadratic_bezier.evaluate(TValue::Parametric(1.)),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t4)),
quadratic_bezier.evaluate(TValue::Parametric(1.)),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
// Test closed subpath
@@ -674,20 +682,24 @@ mod tests {
n = subpath.len() as i64;
let t5 = 2. / 3.;
assert!(utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t5)),
cubic_bezier.evaluate(TValue::Parametric(normalize_t(n, t5))),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t5)),
cubic_bezier.evaluate(TValue::Parametric(normalize_t(n, t5))),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
let t6 = 1.;
assert!(utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t6)),
cubic_bezier.evaluate(TValue::Parametric(1.)),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
subpath.evaluate(SubpathTValue::GlobalParametric(t6)),
cubic_bezier.evaluate(TValue::Parametric(1.)),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
}
#[test]
@@ -737,35 +749,41 @@ mod tests {
let quadratic_1_intersections = quadratic_bezier_1.intersections(&line, None, None);
let subpath_intersections = subpath.intersections(&line, None, None);
assert!(utils::dvec2_compare(
cubic_bezier.evaluate(TValue::Parametric(cubic_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[0].0,
t: subpath_intersections[0].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
cubic_bezier.evaluate(TValue::Parametric(cubic_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[0].0,
t: subpath_intersections[0].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
assert!(utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[1].0,
t: subpath_intersections[1].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[1].0,
t: subpath_intersections[1].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
assert!(utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[1])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[2].0,
t: subpath_intersections[2].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[1])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[2].0,
t: subpath_intersections[2].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
}
#[test]
@@ -816,25 +834,29 @@ mod tests {
let quadratic_1_intersections = quadratic_bezier_1.intersections(&line, None, None);
let subpath_intersections = subpath.intersections(&line, None, None);
assert!(utils::dvec2_compare(
cubic_bezier.evaluate(TValue::Parametric(cubic_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[0].0,
t: subpath_intersections[0].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
cubic_bezier.evaluate(TValue::Parametric(cubic_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[0].0,
t: subpath_intersections[0].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
assert!(utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[1].0,
t: subpath_intersections[1].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[1].0,
t: subpath_intersections[1].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
}
#[test]
@@ -884,35 +906,41 @@ mod tests {
let quadratic_1_intersections = quadratic_bezier_1.intersections(&line, None, None);
let subpath_intersections = subpath.intersections(&line, None, None);
assert!(utils::dvec2_compare(
cubic_bezier.evaluate(TValue::Parametric(cubic_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[0].0,
t: subpath_intersections[0].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
cubic_bezier.evaluate(TValue::Parametric(cubic_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[0].0,
t: subpath_intersections[0].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
assert!(utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[1].0,
t: subpath_intersections[1].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[0])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[1].0,
t: subpath_intersections[1].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
assert!(utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[1])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[2].0,
t: subpath_intersections[2].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all());
assert!(
utils::dvec2_compare(
quadratic_bezier_1.evaluate(TValue::Parametric(quadratic_1_intersections[1])),
subpath.evaluate(SubpathTValue::Parametric {
segment_index: subpath_intersections[2].0,
t: subpath_intersections[2].1
}),
MAX_ABSOLUTE_DIFFERENCE
)
.all()
);
}
// TODO: add more intersection tests
@@ -924,19 +952,19 @@ mod tests {
let curve = Bezier::from_quadratic_dvec2(DVec2::new(189., 289.), DVec2::new(9., 286.), DVec2::new(45., 410.));
let curve_intersecting = Subpath::<EmptyId>::from_bezier(&curve);
assert_eq!(curve_intersecting.is_inside_subpath(&boundary_polygon, None, None), false);
assert!(!curve_intersecting.is_inside_subpath(&boundary_polygon, None, None));
let curve = Bezier::from_quadratic_dvec2(DVec2::new(115., 37.), DVec2::new(51.4, 91.8), DVec2::new(76.5, 242.));
let curve_outside = Subpath::<EmptyId>::from_bezier(&curve);
assert_eq!(curve_outside.is_inside_subpath(&boundary_polygon, None, None), false);
assert!(!curve_outside.is_inside_subpath(&boundary_polygon, None, None));
let curve = Bezier::from_cubic_dvec2(DVec2::new(210.1, 133.5), DVec2::new(150.2, 436.9), DVec2::new(436., 285.), DVec2::new(247.6, 240.7));
let curve_inside = Subpath::<EmptyId>::from_bezier(&curve);
assert_eq!(curve_inside.is_inside_subpath(&boundary_polygon, None, None), true);
assert!(curve_inside.is_inside_subpath(&boundary_polygon, None, None));
let line = Bezier::from_linear_dvec2(DVec2::new(101., 101.5), DVec2::new(150.2, 499.));
let line_inside = Subpath::<EmptyId>::from_bezier(&line);
assert_eq!(line_inside.is_inside_subpath(&boundary_polygon, None, None), true);
assert!(line_inside.is_inside_subpath(&boundary_polygon, None, None));
}
#[test]

View File

@@ -1,10 +1,7 @@
use super::Bezier;
use glam::{DAffine2, DVec2};
use std::{
fmt::{Debug, Formatter, Result},
hash::Hash,
};
use std::fmt::{Debug, Formatter, Result};
use std::hash::Hash;
/// An id type used for each [ManipulatorGroup].
pub trait Identifier: Sized + Clone + PartialEq + Hash + 'static {
@@ -113,7 +110,7 @@ impl<PointId: crate::Identifier> ManipulatorGroup<PointId> {
/// Are all handles at finite positions
pub fn is_finite(&self) -> bool {
self.anchor.is_finite() && self.in_handle.map_or(true, |handle| handle.is_finite()) && self.out_handle.map_or(true, |handle| handle.is_finite())
self.anchor.is_finite() && self.in_handle.is_none_or(|handle| handle.is_finite()) && self.out_handle.is_none_or(|handle| handle.is_finite())
}
/// Reverse directions of handles

View File

@@ -1,20 +1,14 @@
use std::vec;
use super::*;
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use crate::utils::{Cap, Join, SubpathTValue, TValue};
use glam::{DAffine2, DVec2};
use std::vec;
/// Helper function to ensure the index and t value pair is mapped within a maximum index value.
/// Allows for the point to be fetched without needing to handle an additional edge case.
/// - Ex. Via `subpath.iter().nth(index).evaluate(t);`
fn map_index_within_range(index: usize, t: f64, max_size: usize) -> (usize, f64) {
if max_size > 0 && index == max_size && t == 0. {
(index - 1, 1.)
} else {
(index, t)
}
if max_size > 0 && index == max_size && t == 0. { (index - 1, 1.) } else { (index, t) }
}
/// Functionality that transforms Subpaths, such as split, reduce, offset, etc.
@@ -549,10 +543,10 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
#[cfg(test)]
mod tests {
use super::{Cap, Join, ManipulatorGroup, Subpath};
use crate::EmptyId;
use crate::compare::{compare_points, compare_subpaths, compare_vec_of_points};
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use crate::utils::{SubpathTValue, TValue};
use crate::EmptyId;
use glam::DVec2;
fn set_up_open_subpath() -> Subpath<EmptyId> {

View File

@@ -38,7 +38,6 @@
*/
use crate::{Bezier, BezierHandles};
use glam::DVec2;
impl std::ops::Index<usize> for Bezier {

View File

@@ -1,6 +1,5 @@
use crate::consts::{MAX_ABSOLUTE_DIFFERENCE, STRICT_MAX_ABSOLUTE_DIFFERENCE};
use crate::{ManipulatorGroup, Subpath};
use glam::{BVec2, DMat2, DVec2};
use std::fmt::Write;
@@ -94,11 +93,7 @@ pub fn compute_abc_for_cubic_through_points(start_point: DVec2, point_on_curve:
/// Find the roots of the linear equation `ax + b`.
pub fn solve_linear(a: f64, b: f64) -> [Option<f64>; 3] {
// There exist roots when `a` is not 0
if a.abs() > MAX_ABSOLUTE_DIFFERENCE {
[Some(-b / a), None, None]
} else {
[None; 3]
}
if a.abs() > MAX_ABSOLUTE_DIFFERENCE { [Some(-b / a), None, None] } else { [None; 3] }
}
/// Find the roots of the linear equation `ax^2 + bx + c`.
@@ -310,7 +305,8 @@ pub fn format_point(svg: &mut String, prefix: &str, x: f64, y: f64) -> std::fmt:
#[cfg(test)]
mod tests {
use super::*;
use crate::{consts::MAX_ABSOLUTE_DIFFERENCE, Bezier, EmptyId};
use crate::consts::MAX_ABSOLUTE_DIFFERENCE;
use crate::{Bezier, EmptyId};
/// Compare vectors of `f64`s with a provided max absolute value difference.
fn f64_compare_vector(a: Vec<f64>, b: Vec<f64>, max_abs_diff: f64) -> bool {

View File

@@ -1,8 +1,8 @@
[package]
name = "dyn-any"
version = "0.3.1"
rust-version = "1.79"
edition = "2021"
rust-version = "1.85"
edition = "2024"
authors = ["Graphite Authors <contact@graphite.rs>"]
description = "An Any trait that works for arbitrary lifetimes"
license = "MIT OR Apache-2.0"

View File

@@ -1,7 +1,7 @@
[package]
name = "dyn-any-derive"
version = "0.3.0"
edition = "2021"
edition = "2024"
authors = ["Graphite Authors <contact@graphite.rs>"]
description = "#[derive(DynAny)]"

View File

@@ -5,7 +5,7 @@ extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, GenericParam, Lifetime, LifetimeParam, TypeParamBound};
use syn::{DeriveInput, GenericParam, Lifetime, LifetimeParam, TypeParamBound, parse_macro_input};
/// Derives an implementation for the [`DynAny`] trait.
///
@@ -62,7 +62,7 @@ fn replace_lifetimes(generics: &syn::Generics, replacement: &str) -> Vec<proc_ma
GenericParam::Type(t) => {
let mut t = t.clone();
t.bounds.iter_mut().for_each(|bond| {
if let TypeParamBound::Lifetime(ref mut t) = bond {
if let TypeParamBound::Lifetime(t) = bond {
*t = Lifetime::new(replacement, Span::call_site())
}
});

View File

@@ -187,7 +187,6 @@ macro_rules! impl_slice {
mod slice {
use super::*;
use core::slice::*;
impl_slice!(Iter, IterMut, Chunks, ChunksMut, RChunks, RChunksMut, Windows);
@@ -249,24 +248,24 @@ impl From<()> for Box<dyn DynAny<'static>> {
}
#[cfg(feature = "alloc")]
use alloc::{
borrow::Cow,
boxed::Box,
collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque},
string::String,
vec::Vec,
};
use alloc::borrow::Cow;
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::cell::{Cell, RefCell, UnsafeCell};
use core::iter::Empty;
use core::marker::{PhantomData, PhantomPinned};
use core::mem::{ManuallyDrop, MaybeUninit};
use core::num::Wrapping;
use core::ops::Range;
use core::pin::Pin;
use core::sync::atomic::*;
use core::{
cell::{Cell, RefCell, UnsafeCell},
iter::Empty,
marker::{PhantomData, PhantomPinned},
mem::{ManuallyDrop, MaybeUninit},
num::Wrapping,
ops::Range,
pin::Pin,
time::Duration,
};
use core::time::Duration;
impl_type!(
Option<T>, Result<T, E>, Cell<T>, UnsafeCell<T>, RefCell<T>, MaybeUninit<T>,
@@ -286,10 +285,9 @@ impl_type!(
);
#[cfg(feature = "std")]
use std::{
collections::{HashMap, HashSet},
sync::*,
};
use std::collections::{HashMap, HashSet};
#[cfg(feature = "std")]
use std::sync::*;
#[cfg(feature = "std")]
impl_type!(Once, Mutex<T>, RwLock<T>, HashSet<T>, HashMap<K, V>);

View File

@@ -1,8 +1,8 @@
[package]
name = "math-parser"
version = "0.0.0"
rust-version = "1.79"
edition = "2021"
rust-version = "1.85"
edition = "2024"
authors = ["Graphite Authors <contact@graphite.rs>"]
description = "Parser for Graphite style mathematics expressions"
license = "MIT OR Apache-2.0"

View File

@@ -1,10 +1,9 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use criterion::{Criterion, black_box, criterion_group, criterion_main};
use math_parser::ast;
use math_parser::context::EvalContext;
macro_rules! generate_benchmarks {
($( $input:expr ),* $(,)?) => {
($( $input:expr_2021 ),* $(,)?) => {
fn parsing_bench(c: &mut Criterion) {
$(
c.bench_function(concat!("parse ", $input), |b| {

View File

@@ -1,9 +1,9 @@
use std::{collections::HashMap, f64::consts::PI};
use crate::value::{Number, Value};
use lazy_static::lazy_static;
use num_complex::{Complex, ComplexFloat};
use std::collections::HashMap;
use std::f64::consts::PI;
use crate::value::{Number, Value};
type FunctionImplementation = Box<dyn Fn(&[Value]) -> Option<Value> + Send + Sync>;
lazy_static! {
pub static ref DEFAULT_FUNCTIONS: HashMap<&'static str, FunctionImplementation> = {

View File

@@ -1,9 +1,6 @@
use std::{
collections::HashMap,
ops::{Deref, DerefMut},
};
use crate::value::Value;
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
//TODO: editor integration, implement these traits for whatever is needed, maybe merge them if needed
pub trait ValueProvider {

View File

@@ -1,12 +1,9 @@
use crate::ast::{Literal, Node};
use crate::constants::DEFAULT_FUNCTIONS;
use crate::context::{EvalContext, FunctionProvider, ValueProvider};
use crate::value::{Number, Value};
use thiserror::Error;
use crate::{
ast::{Literal, Node},
constants::DEFAULT_FUNCTIONS,
context::{EvalContext, FunctionProvider, ValueProvider},
value::{Number, Value},
};
#[derive(Debug, Error)]
pub enum EvalError {
#[error("Missing value: {0}")]
@@ -49,14 +46,12 @@ impl Node {
#[cfg(test)]
mod tests {
use crate::{
ast::{BinaryOp, Literal, Node, UnaryOp},
context::{EvalContext, ValueMap},
value::Value,
};
use crate::ast::{BinaryOp, Literal, Node, UnaryOp};
use crate::context::{EvalContext, ValueMap};
use crate::value::Value;
macro_rules! eval_tests {
($($name:ident: $expected:expr => $expr:expr),* $(,)?) => {
($($name:ident: $expected:expr_2021 => $expr:expr_2021),* $(,)?) => {
$(
#[test]
fn $name() {

View File

@@ -21,16 +21,14 @@ pub fn evaluate(expression: &str) -> Result<(Result<Value, EvalError>, Unit), Pa
#[cfg(test)]
mod tests {
use value::Number;
use ast::Unit;
use super::*;
use ast::Unit;
use value::Number;
const EPSILON: f64 = 1e-10_f64;
macro_rules! test_end_to_end{
($($name:ident: $input:expr => ($expected_value:expr, $expected_unit:expr)),* $(,)?) => {
($($name:ident: $input:expr_2021 => ($expected_value:expr_2021, $expected_unit:expr_2021)),* $(,)?) => {
$(
#[test]
fn $name() {

View File

@@ -1,21 +1,15 @@
use std::num::{ParseFloatError, ParseIntError};
use crate::ast::{BinaryOp, Literal, Node, UnaryOp, Unit};
use crate::context::EvalContext;
use crate::value::{Complex, Number, Value};
use lazy_static::lazy_static;
use num_complex::ComplexFloat;
use pest::{
iterators::{Pair, Pairs},
pratt_parser::{Assoc, Op, PrattParser},
Parser,
};
use pest::Parser;
use pest::iterators::{Pair, Pairs};
use pest::pratt_parser::{Assoc, Op, PrattParser};
use pest_derive::Parser;
use std::num::{ParseFloatError, ParseIntError};
use thiserror::Error;
use crate::{
ast::{BinaryOp, Literal, Node, UnaryOp, Unit},
context::EvalContext,
value::{Complex, Number, Value},
};
#[derive(Parser)]
#[grammar = "./grammer.pest"] // Point to the grammar file
struct ExprParser;
@@ -321,7 +315,7 @@ fn parse_expr(pairs: Pairs<Rule>) -> Result<(Node, NodeMetadata), ParseError> {
mod tests {
use super::*;
macro_rules! test_parser {
($($name:ident: $input:expr => $expected:expr),* $(,)?) => {
($($name:ident: $input:expr_2021 => $expected:expr_2021),* $(,)?) => {
$(
#[test]
fn $name() {

View File

@@ -1,8 +1,6 @@
use std::f64::consts::PI;
use num_complex::ComplexFloat;
use crate::ast::{BinaryOp, UnaryOp};
use num_complex::ComplexFloat;
use std::f64::consts::PI;
pub type Complex = num_complex::Complex<f64>;

View File

@@ -1,9 +1,9 @@
[package]
name = "path-bool"
version = "0.1.0"
rust-version = "1.81"
rust-version = "1.85"
authors = ["Graphite Authors <contact@graphite.rs>", "Adam Platkevič"]
edition = "2021"
edition = "2024"
keywords = [
"bezier",
"curve",

View File

@@ -1,4 +1,4 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use criterion::{Criterion, black_box, criterion_group, criterion_main};
use path_bool::*;
pub fn criterion_benchmark(c: &mut Criterion) {

View File

@@ -1,4 +1,4 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use criterion::{Criterion, black_box, criterion_group, criterion_main};
use glam::DVec2;
use path_bool::*;

View File

@@ -24,7 +24,7 @@ pub(crate) use util::*;
pub use intersection_path_segment::path_segment_intersection;
#[cfg(feature = "parsing")]
pub use parsing::path_data::{path_from_path_data, path_to_path_data};
pub use path_boolean::{path_boolean, BooleanError, FillRule, PathBooleanOperation, EPS};
pub use path_boolean::{BooleanError, EPS, FillRule, PathBooleanOperation, path_boolean};
pub use path_segment::PathSegment;
#[cfg(test)]

View File

@@ -1,6 +1,6 @@
use crate::path::{path_from_commands, path_to_commands, Path};
use crate::path_command::{AbsolutePathCommand, PathCommand, RelativePathCommand};
use crate::BooleanError;
use crate::path::{Path, path_from_commands, path_to_commands};
use crate::path_command::{AbsolutePathCommand, PathCommand, RelativePathCommand};
use glam::DVec2;
use regex::Regex;

View File

@@ -7,7 +7,7 @@ pub(crate) mod path_segment;
use glam::DVec2;
#[cfg(feature = "parsing")]
use crate::path_command::{to_absolute_commands, AbsolutePathCommand, PathCommand};
use crate::path_command::{AbsolutePathCommand, PathCommand, to_absolute_commands};
use crate::path_segment::PathSegment;
pub type Path = Vec<PathSegment>;
@@ -107,7 +107,7 @@ where
let start = seg.start();
let mut commands = Vec::new();
if last_point.map_or(true, |lp| !start.abs_diff_eq(lp, eps)) {
if last_point.is_none_or(|lp| !start.abs_diff_eq(lp, eps)) {
if last_point.is_some() {
commands.push(PathCommand::Absolute(AbsolutePathCommand::Z));
}

View File

@@ -1,10 +1,9 @@
use crate::aabb::{bounding_box_max_extent, bounding_boxes_overlap, Aabb};
use crate::aabb::{Aabb, bounding_box_max_extent, bounding_boxes_overlap};
use crate::epsilons::Epsilons;
use crate::line_segment::{line_segment_intersection, line_segments_intersect};
use crate::line_segment_aabb::line_segment_aabb_intersect;
use crate::math::lerp;
use crate::path_segment::PathSegment;
use glam::DVec2;
#[derive(Clone)]

View File

@@ -21,11 +21,7 @@ pub fn line_segment_intersection([p1, p2]: LineSegment, [p3, p4]: LineSegment, e
let s = (c.x * b.y - c.y * b.x) / denom;
let t = (a.x * c.y - a.y * c.x) / denom;
if (-eps..=1. + eps).contains(&s) && (-eps..=1. + eps).contains(&t) {
Some((s, t))
} else {
None
}
if (-eps..=1. + eps).contains(&s) && (-eps..=1. + eps).contains(&t) { Some((s, t)) } else { None }
}
pub fn line_segments_intersect(seg1: LineSegment, seg2: LineSegment, eps: f64) -> bool {

View File

@@ -9,13 +9,12 @@
//! The implementations in this module closely follow the SVG path specification,
//! making it suitable for use in vector graphics applications.
use crate::EPS;
use crate::aabb::{Aabb, bounding_box_around_point, expand_bounding_box, extend_bounding_box, merge_bounding_boxes};
use crate::math::{lerp, vector_angle};
use glam::{DMat2, DMat3, DVec2};
use std::f64::consts::{PI, TAU};
use crate::aabb::{bounding_box_around_point, expand_bounding_box, extend_bounding_box, merge_bounding_boxes, Aabb};
use crate::math::{lerp, vector_angle};
use crate::EPS;
/// Represents a segment of a path in a 2D space, based on the SVG path specification.
///
/// This enum closely follows the path segment types defined in the SVG 2 specification.
@@ -155,11 +154,7 @@ impl PathSegment {
let b = 6. * b;
let numerator = a.x * b.y - a.y * b.x;
let denominator = a.length_squared() * a.length();
if denominator == 0. {
0.
} else {
numerator / denominator
}
if denominator == 0. { 0. } else { numerator / denominator }
}
PathSegment::Quadratic(start, control, end) => {
// First derivative
@@ -168,11 +163,7 @@ impl PathSegment {
let b = 2. * (start - 2. * control + end);
let numerator = a.x * b.y - a.y * b.x;
let denominator = a.length_squared() * a.length();
if denominator == 0. {
0.
} else {
numerator / denominator
}
if denominator == 0. { 0. } else { numerator / denominator }
}
PathSegment::Arc(..) => self.arc_segment_to_cubics(0.001)[0].start_curvature(),
}

View File

@@ -63,7 +63,7 @@ new_key_type! {
//
// SPDX-License-Identifier: MIT
use crate::aabb::{bounding_box_around_point, bounding_box_max_extent, merge_bounding_boxes, Aabb};
use crate::aabb::{Aabb, bounding_box_around_point, bounding_box_max_extent, merge_bounding_boxes};
use crate::epsilons::Epsilons;
use crate::intersection_path_segment::{path_segment_intersection, segments_equal};
use crate::path::Path;
@@ -72,9 +72,8 @@ use crate::path_segment::PathSegment;
#[cfg(feature = "logging")]
use crate::path_to_path_data;
use crate::quad_tree::QuadTree;
use glam::DVec2;
use slotmap::{new_key_type, SlotMap};
use slotmap::{SlotMap, new_key_type};
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet, VecDeque};
use std::fmt::Display;
@@ -1090,7 +1089,11 @@ fn compute_dual(minor_graph: &MinorGraph) -> Result<DualGraph, BooleanError> {
let (key, _) = *areas.iter().max_by_key(|(_, area)| ((area.abs() * 1000.) as u64)).unwrap();
*key
} else {
*windings.iter().find(|(&_, winding)| (winding < &0) ^ reverse_winding).expect("No outer face of a component found.").0
*windings
.iter()
.find(|&&(&_, ref winding)| (winding < &0) ^ reverse_winding)
.expect("No outer face of a component found.")
.0
};
#[cfg(feature = "logging")]
dbg!(outer_face_key);
@@ -1338,7 +1341,7 @@ fn get_selected_faces<'a>(predicate: &'a impl Fn(u8) -> bool, flags: &'a HashMap
flags.iter().filter_map(|(key, &flag)| predicate(flag).then_some(*key))
}
fn walk_faces<'a>(faces: &'a [DualVertexKey], edges: &SlotMap<DualEdgeKey, DualGraphHalfEdge>, vertices: &SlotMap<DualVertexKey, DualGraphVertex>) -> impl Iterator<Item = PathSegment> + 'a {
fn walk_faces<'a>(faces: &'a [DualVertexKey], edges: &SlotMap<DualEdgeKey, DualGraphHalfEdge>, vertices: &SlotMap<DualVertexKey, DualGraphVertex>) -> impl Iterator<Item = PathSegment> + use<'a> {
let face_set: HashSet<_> = faces.iter().copied().collect();
// TODO: Try using a binary search to avoid the hashset construction
let is_removed_edge = |edge: &DualGraphHalfEdge| face_set.contains(&edge.incident_vertex) == face_set.contains(&edges[edge.twin.unwrap()].incident_vertex);

View File

@@ -1,6 +1,5 @@
use crate::path_boolean::{self, FillRule, PathBooleanOperation};
use crate::path_data::{path_from_path_data, path_to_path_data};
use core::panic;
use glob::glob;
use image::{DynamicImage, GenericImageView, RgbaImage};

View File

@@ -9,7 +9,7 @@ syn = "2.0.87"
[package]
name = "rawkit"
version = "0.1.0"
edition = "2021"
edition = "2024"
authors = ["Graphite Authors <contact@graphite.rs>"]
description = "A library to extract images from camera raw files"
license = "MIT OR Apache-2.0"

View File

@@ -1,7 +1,7 @@
[package]
name = "rawkit-proc-macros"
version = "0.1.0"
edition = "2021"
edition = "2024"
authors = ["Graphite Authors <contact@graphite.rs>"]
description = "Procedural macros for Rawkit"
license = "MIT OR Apache-2.0"

View File

@@ -1,9 +1,8 @@
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use toml::{Table, Value};
use quote::{ToTokens, quote};
use std::fs;
use std::path::Path;
use toml::{Table, Value};
enum CustomValue {
String(String),

View File

@@ -24,7 +24,7 @@ pub fn tag_derive(input: TokenStream) -> TokenStream {
let new_name = format_ident!("_{}", name);
let gen = quote! {
let r#gen = quote! {
struct #new_name {
#( #struct_idents: <#struct_types as Tag>::Output ),*
}
@@ -39,5 +39,5 @@ pub fn tag_derive(input: TokenStream) -> TokenStream {
}
};
gen.into()
r#gen.into()
}

View File

@@ -1,9 +1,8 @@
use crate::tiff::Ifd;
use crate::tiff::file::TiffRead;
use crate::tiff::tags::SonyDataOffset;
use crate::tiff::Ifd;
use crate::{RawImage, SubtractBlack, Transform};
use bitstream_io::{BitRead, BitReader, Endianness, BE};
use bitstream_io::{BE, BitRead, BitReader, Endianness};
use std::io::{Read, Seek};
pub fn decode_a100<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage {
@@ -63,11 +62,7 @@ fn ljpeg_diff<R: Read + Seek, E: Endianness>(huff: &[u16], file: &mut BitReader<
let diff = read_n_bits_from_file(length, file) as i32;
if length == 0 || (diff & (1 << (length - 1))) == 0 {
diff - (1 << length) - 1
} else {
diff
}
if length == 0 || (diff & (1 << (length - 1))) == 0 { diff - (1 << length) - 1 } else { diff }
}
fn sony_arw_load_raw<R: Read + Seek>(width: usize, height: usize, file: &mut BitReader<R, BE>) -> Option<Vec<u16>> {

View File

@@ -3,7 +3,6 @@ use crate::tiff::tags::{BitsPerSample, CfaPattern, CfaPatternDim, Compression, I
use crate::tiff::values::CurveLookupTable;
use crate::tiff::{Ifd, TiffError};
use crate::{RawImage, SubtractBlack, Transform};
use rawkit_proc_macros::Tag;
use std::io::{Read, Seek};

View File

@@ -2,7 +2,6 @@ use crate::tiff::file::TiffRead;
use crate::tiff::tags::{BitsPerSample, BlackLevel, CfaPattern, CfaPatternDim, Compression, ImageLength, ImageWidth, RowsPerStrip, StripByteCounts, StripOffsets, Tag, WhiteBalanceRggbLevels};
use crate::tiff::{Ifd, TiffError};
use crate::{RawImage, SubtractBlack, Transform};
use rawkit_proc_macros::Tag;
use std::io::{Read, Seek};

View File

@@ -7,17 +7,15 @@ pub mod processing;
pub mod tiff;
use crate::metadata::identify::CameraModel;
use processing::{Pixel, PixelTransform, RawPixel, RawPixelTransform};
use rawkit_proc_macros::Tag;
use std::io::{Read, Seek};
use thiserror::Error;
use tiff::file::TiffRead;
use tiff::tags::{Compression, ImageLength, ImageWidth, Orientation, StripByteCounts, SubIfd, Tag};
use tiff::values::Transform;
use tiff::{Ifd, TiffError};
use std::io::{Read, Seek};
use thiserror::Error;
pub(crate) const CHANNELS_IN_RGB: usize = 3;
pub(crate) type Histogram = [[usize; 0x2000]; CHANNELS_IN_RGB];

View File

@@ -1,7 +1,6 @@
use crate::tiff::file::TiffRead;
use crate::tiff::tags::{Make, Model, Tag};
use crate::tiff::{Ifd, TiffError};
use rawkit_proc_macros::Tag;
use std::io::{Read, Seek};

View File

@@ -1,7 +1,7 @@
use crate::{Pixel, RawImage, CHANNELS_IN_RGB};
use crate::{CHANNELS_IN_RGB, Pixel, RawImage};
impl RawImage {
pub fn convert_to_rgb_fn(&self) -> impl Fn(Pixel) -> [u16; CHANNELS_IN_RGB] {
pub fn convert_to_rgb_fn(&self) -> impl Fn(Pixel) -> [u16; CHANNELS_IN_RGB] + use<> {
let Some(camera_to_rgb) = self.camera_to_rgb else { todo!() };
move |pixel: Pixel| {

View File

@@ -1,8 +1,8 @@
use crate::{Histogram, Image, Pixel, CHANNELS_IN_RGB};
use crate::{CHANNELS_IN_RGB, Histogram, Image, Pixel};
use std::f64::consts::E;
impl Image<u16> {
pub fn gamma_correction_fn(&self, histogram: &Histogram) -> impl Fn(Pixel) -> [u16; CHANNELS_IN_RGB] {
pub fn gamma_correction_fn(&self, histogram: &Histogram) -> impl Fn(Pixel) -> [u16; CHANNELS_IN_RGB] + use<> {
let percentage = self.width * self.height;
let mut white = 0;

View File

@@ -1,4 +1,4 @@
use crate::{Histogram, Pixel, PixelTransform, RawImage, CHANNELS_IN_RGB};
use crate::{CHANNELS_IN_RGB, Histogram, Pixel, PixelTransform, RawImage};
impl RawImage {
pub fn record_histogram_fn(&self) -> RecordHistogram {

View File

@@ -1,7 +1,7 @@
use crate::{RawImage, RawPixel, SubtractBlack};
impl RawImage {
pub fn scale_to_16bit_fn(&self) -> impl Fn(RawPixel) -> u16 {
pub fn scale_to_16bit_fn(&self) -> impl Fn(RawPixel) -> u16 + use<> {
let black_level = match self.black {
SubtractBlack::CfaGrid(x) => x,
_ => unreachable!(),

View File

@@ -1,7 +1,7 @@
use crate::{RawImage, RawPixel};
impl RawImage {
pub fn scale_white_balance_fn(&self) -> impl Fn(RawPixel) -> u16 {
pub fn scale_white_balance_fn(&self) -> impl Fn(RawPixel) -> u16 + use<> {
let Some(mut white_balance) = self.white_balance else { todo!() };
if white_balance[1] == 0. {

View File

@@ -2,7 +2,7 @@ use crate::RawPixel;
use crate::{RawImage, SubtractBlack};
impl RawImage {
pub fn subtract_black_fn(&self) -> impl Fn(RawPixel) -> u16 {
pub fn subtract_black_fn(&self) -> impl Fn(RawPixel) -> u16 + use<> {
match self.black {
SubtractBlack::CfaGrid(black_levels) => move |pixel: RawPixel| pixel.value.saturating_sub(black_levels[2 * (pixel.row % 2) + (pixel.column % 2)]),
_ => todo!(),

View File

@@ -4,11 +4,10 @@ mod types;
pub mod values;
use file::TiffRead;
use tags::Tag;
use num_enum::{FromPrimitive, IntoPrimitive};
use std::fmt::Display;
use std::io::{Read, Seek};
use tags::Tag;
use thiserror::Error;
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, IntoPrimitive)]

View File

@@ -1,6 +1,5 @@
use super::types::{Array, ConstArray, TagType, TypeByte, TypeIfd, TypeLong, TypeNumber, TypeOrientation, TypeSRational, TypeSShort, TypeShort, TypeSonyToneCurve, TypeString};
use super::{Ifd, TagId, TiffError, TiffRead};
use std::io::{Read, Seek};
pub trait SimpleTag {

View File

@@ -1,8 +1,7 @@
use std::io::{Read, Seek};
use super::file::TiffRead;
use super::values::{CurveLookupTable, Rational, Transform};
use super::{Ifd, IfdTagType, TiffError};
use std::io::{Read, Seek};
pub struct TypeAscii;
pub struct TypeByte;
@@ -41,11 +40,7 @@ impl PrimitiveType for TypeAscii {
fn read_primitive<R: Read + Seek>(_: IfdTagType, file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
let value = file.read_ascii()?;
if value.is_ascii() {
Ok(value)
} else {
Err(TiffError::InvalidValue)
}
if value.is_ascii() { Ok(value) } else { Err(TiffError::InvalidValue) }
}
}

View File

@@ -1,15 +1,14 @@
// Only compile this file if the feature "rawkit-tests" is enabled
#![cfg(feature = "rawkit-tests")]
use rawkit::RawImage;
use image::codecs::png::{CompressionType, FilterType, PngEncoder};
use image::{ColorType, ImageEncoder};
use libraw::Processor;
use rawkit::RawImage;
use rayon::prelude::*;
use std::collections::HashMap;
use std::fmt::Write;
use std::fs::{create_dir, metadata, read_dir, File};
use std::fs::{File, create_dir, metadata, read_dir};
use std::io::{BufWriter, Cursor, Read};
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -338,10 +337,10 @@ fn extract_data_from_dng_images() {
}
fn extract_data_from_dng_image(path: &Path) {
use rawkit::tiff::Ifd;
use rawkit::tiff::file::TiffRead;
use rawkit::tiff::tags::{ColorMatrix2, Make, Model};
use rawkit::tiff::values::ToFloat;
use rawkit::tiff::Ifd;
use std::io::{BufReader, Write};
let reader = BufReader::new(File::open(path).unwrap());