diff --git a/src/aztec/DetectorTest.rs b/src/aztec/DetectorTest.rs index 0ceb841..cd93c31 100644 --- a/src/aztec/DetectorTest.rs +++ b/src/aztec/DetectorTest.rs @@ -102,30 +102,14 @@ fn test_error_in_parameter_locator(data: &str) { clone(&matrix) }; copy.flip_coords( - (orientation_points - .get(error1) - .unwrap() - .x as i32) - .unsigned_abs(), - (orientation_points - .get(error1) - .unwrap() - .y as i32) - .unsigned_abs(), + (orientation_points.get(error1).unwrap().x as i32).unsigned_abs(), + (orientation_points.get(error1).unwrap().y as i32).unsigned_abs(), ); if error2 > error1 { // if error2 == error1, we only test a single error copy.flip_coords( - (orientation_points - .get(error2) - .unwrap() - .x as i32) - .unsigned_abs(), - (orientation_points - .get(error2) - .unwrap() - .y as i32) - .unsigned_abs(), + (orientation_points.get(error2).unwrap().x as i32).unsigned_abs(), + (orientation_points.get(error2).unwrap().y as i32).unsigned_abs(), ); } // dbg!(copy.to_string()); diff --git a/src/aztec/detector.rs b/src/aztec/detector.rs index 5abbff3..206a8b4 100644 --- a/src/aztec/detector.rs +++ b/src/aztec/detector.rs @@ -319,10 +319,10 @@ impl<'a> Detector<'_> { // Expand the square by .5 pixel in each direction so that we're on the border // between the white square and the black square - let pinax = point(pina.x as f32 + 0.5, pina.y as f32 - 0.5); - let pinbx = point(pinb.x as f32 + 0.5, pinb.y as f32 + 0.5); - let pincx = point(pinc.x as f32 - 0.5, pinc.y as f32 + 0.5); - let pindx = point(pind.x as f32 - 0.5, pind.y as f32 - 0.5); + let pinax = point(pina.x + 0.5, pina.y - 0.5); + let pinbx = point(pinb.x + 0.5, pinb.y + 0.5); + let pincx = point(pinc.x - 0.5, pinc.y + 0.5); + let pindx = point(pind.x - 0.5, pind.y - 0.5); // Expand the square so that its corners are the centers of the points // just outside the bull's eye. @@ -362,18 +362,10 @@ impl<'a> Detector<'_> { if !fnd { let cx: i32 = (self.image.getWidth() / 2) as i32; let cy: i32 = (self.image.getHeight() / 2) as i32; - point_a = self - .get_first_different(Point::from((cx + 7, cy - 7)), false, 1, -1) - .into(); - point_b = self - .get_first_different(Point::from((cx + 7, cy + 7)), false, 1, 1) - .into(); - point_c = self - .get_first_different(Point::from((cx - 7, cy + 7)), false, -1, 1) - .into(); - point_d = self - .get_first_different(Point::from((cx - 7, cy - 7)), false, -1, -1) - .into(); + point_a = self.get_first_different(Point::from((cx + 7, cy - 7)), false, 1, -1); + point_b = self.get_first_different(Point::from((cx + 7, cy + 7)), false, 1, 1); + point_c = self.get_first_different(Point::from((cx - 7, cy + 7)), false, -1, 1); + point_d = self.get_first_different(Point::from((cx - 7, cy - 7)), false, -1, -1); } // try { @@ -416,18 +408,10 @@ impl<'a> Detector<'_> { // This exception can be in case the initial rectangle is white // In that case we try to expand the rectangle. if !fnd { - point_a = self - .get_first_different(Point::from((cx + 7, cy - 7)), false, 1, -1) - .into(); - point_b = self - .get_first_different(Point::from((cx + 7, cy + 7)), false, 1, 1) - .into(); - point_c = self - .get_first_different(Point::from((cx - 7, cy + 7)), false, -1, 1) - .into(); - point_d = self - .get_first_different(Point::from((cx - 7, cy - 7)), false, -1, -1) - .into(); + point_a = self.get_first_different(Point::from((cx + 7, cy - 7)), false, 1, -1); + point_b = self.get_first_different(Point::from((cx + 7, cy + 7)), false, 1, 1); + point_c = self.get_first_different(Point::from((cx - 7, cy + 7)), false, -1, 1); + point_d = self.get_first_different(Point::from((cx - 7, cy - 7)), false, -1, -1); } // try { // Point[] cornerPoints = new WhiteRectangleDetector(image, 15, cx, cy).detect(); @@ -540,13 +524,7 @@ impl<'a> Detector<'_> { * @return true if the border of the rectangle passed in parameter is compound of white points only * or black points only */ - fn is_white_or_black_rectangle( - &self, - p1: &Point, - p2: &Point, - p3: &Point, - p4: &Point, - ) -> bool { + fn is_white_or_black_rectangle(&self, p1: &Point, p2: &Point, p3: &Point, p4: &Point) -> bool { let corr = 3.0; let p1 = Point::new( @@ -602,12 +580,12 @@ impl<'a> Detector<'_> { if d == 0.0 { return 0; } - let dx = (p2.x - p1.x) as f32 / d; - let dy = (p2.y - p1.y) as f32 / d; + let dx = (p2.x - p1.x) / d; + let dy = (p2.y - p1.y) / d; let mut error = 0; - let mut px = p1.x as f32; - let mut py = p1.y as f32; + let mut px = p1.x; + let mut py = p1.y; let color_model = self.image.get(p1.x as u32, p1.y as u32); @@ -639,20 +617,23 @@ impl<'a> Detector<'_> { * Gets the coordinate of the first point with a different color in the given direction */ fn get_first_different(&self, init: Point, color: bool, dx: i32, dy: i32) -> Point { - let mut point = init + Point::from((dx,dy)); + let mut point = init + Point::from((dx, dy)); - while self.is_valid_points(point) && self.image.get(point.x as u32, point.y as u32) == color { - point += Point::from((dx,dy)); + while self.is_valid_points(point) && self.image.get(point.x as u32, point.y as u32) == color + { + point += Point::from((dx, dy)); } - point -= Point::from((dx,dy)); + point -= Point::from((dx, dy)); - while self.is_valid_points(point) && self.image.get(point.x as u32, point.y as u32) == color { + while self.is_valid_points(point) && self.image.get(point.x as u32, point.y as u32) == color + { point.x += dx as f32; } point.x -= dx as f32; - while self.is_valid_points(point) && self.image.get(point.x as u32, point.y as u32) == color { + while self.is_valid_points(point) && self.image.get(point.x as u32, point.y as u32) == color + { point.y += dy as f32; } point.y -= dy as f32; @@ -685,7 +666,10 @@ impl<'a> Detector<'_> { } fn is_valid_points(&self, p: Point) -> bool { - p.x >= 0.0 && p.x < self.image.getWidth() as f32 && p.y >= 0.0 && p.y < self.image.getHeight() as f32 + p.x >= 0.0 + && p.x < self.image.getWidth() as f32 + && p.y >= 0.0 + && p.y < self.image.getHeight() as f32 } fn is_valid(&self, point: Point) -> bool { @@ -693,7 +677,7 @@ impl<'a> Detector<'_> { } fn distance_points(a: Point, b: Point) -> f32 { - Point::from(a).distance(b.into()) + a.distance(b) } fn distance(a: Point, b: Point) -> f32 { @@ -707,4 +691,4 @@ impl<'a> Detector<'_> { 4 * self.nb_layers + 2 * ((2 * self.nb_layers + 6) / 15) + 15 } } -} \ No newline at end of file +} diff --git a/src/common/character_set.rs b/src/common/character_set.rs index b65696c..b514224 100644 --- a/src/common/character_set.rs +++ b/src/common/character_set.rs @@ -28,16 +28,16 @@ use crate::Exceptions; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum CharacterSet { // Enum name is a Java encoding valid for java.lang and java.io - Cp437, //(new int[]{0,2}), - ISO8859_1, //(new int[]{1,3}, "ISO-8859-1"), - ISO8859_2, //(4, "ISO-8859-2"), - ISO8859_3, //(5, "ISO-8859-3"), - ISO8859_4, //(6, "ISO-8859-4"), - ISO8859_5, //(7, "ISO-8859-5"), + Cp437, //(new int[]{0,2}), + ISO8859_1, //(new int[]{1,3}, "ISO-8859-1"), + ISO8859_2, //(4, "ISO-8859-2"), + ISO8859_3, //(5, "ISO-8859-3"), + ISO8859_4, //(6, "ISO-8859-4"), + ISO8859_5, //(7, "ISO-8859-5"), // ISO8859_6, //(8, "ISO-8859-6"), - ISO8859_7, //(9, "ISO-8859-7"), + ISO8859_7, //(9, "ISO-8859-7"), // ISO8859_8, //(10, "ISO-8859-8"), - ISO8859_9, //(11, "ISO-8859-9"), + ISO8859_9, //(11, "ISO-8859-9"), // ISO8859_10, //(12, "ISO-8859-10"), // ISO8859_11, //(13, "ISO-8859-11"), ISO8859_13, //(15, "ISO-8859-13"), diff --git a/src/datamatrix/detector/zxing_cpp_detector/edge_tracer.rs b/src/datamatrix/detector/zxing_cpp_detector/edge_tracer.rs index a1c6743..186aa81 100644 --- a/src/datamatrix/detector/zxing_cpp_detector/edge_tracer.rs +++ b/src/datamatrix/detector/zxing_cpp_detector/edge_tracer.rs @@ -225,9 +225,9 @@ impl<'a> EdgeTracer<'_> { return Ok(StepResult::Found); } - pEdge = pEdge - dEdge; + pEdge -= dEdge; if self.blackAt(pEdge - self.d) { - pEdge = pEdge - self.d; + pEdge -= self.d; } // dbg!(pEdge); diff --git a/src/multi_use_multi_format_reader.rs b/src/multi_use_multi_format_reader.rs index efeec2a..16ecb18 100644 --- a/src/multi_use_multi_format_reader.rs +++ b/src/multi_use_multi_format_reader.rs @@ -14,223 +14,222 @@ * limitations under the License. */ - use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet}; - use crate::common::Result; - use crate::{ - aztec::AztecReader, datamatrix::DataMatrixReader, maxicode::MaxiCodeReader, - oned::MultiFormatOneDReader, pdf417::PDF417Reader, qrcode::QRCodeReader, BarcodeFormat, - Binarizer, BinaryBitmap, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, - RXingResult, Reader, - }; - - /** - * MultiFormatReader is a convenience class and the main entry point into the library for most uses. - * By default it attempts to decode all barcode formats that the library supports. Optionally, you - * can provide a hints object to request different behavior, for example only decoding QR codes. - * - * @author Sean Owen - * @author dswitkin@google.com (Daniel Switkin) - */ - #[derive(Default)] - pub struct MultiUseMultiFormatReader { - hints: DecodingHintDictionary, - possible_formats: HashSet, - try_harder: bool, - one_d_reader: MultiFormatOneDReader, - qr_code_reader: QRCodeReader, - data_matrix_reader: DataMatrixReader, - aztec_reader: AztecReader, - pdf417_reader: PDF417Reader, - maxicode_reader: MaxiCodeReader, +use crate::common::Result; +use crate::{ + aztec::AztecReader, datamatrix::DataMatrixReader, maxicode::MaxiCodeReader, + oned::MultiFormatOneDReader, pdf417::PDF417Reader, qrcode::QRCodeReader, BarcodeFormat, + Binarizer, BinaryBitmap, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, + RXingResult, Reader, +}; - } - - impl Reader for MultiUseMultiFormatReader { - /** - * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it - * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly. - * Use setHints() followed by decodeWithState() for continuous scan applications. - * - * @param image The pixel data to decode - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - fn decode(&mut self, image: &mut BinaryBitmap) -> Result { - self.set_hints(&HashMap::new()); - self.decode_internal(image) - } - - /** - * Decode an image using the hints provided. Does not honor existing state. - * - * @param image The pixel data to decode - * @param hints The hints to use, clearing the previous state. - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - fn decode_with_hints( - &mut self, - image: &mut BinaryBitmap, - hints: &DecodingHintDictionary, - ) -> Result { - self.set_hints(hints); - self.decode_internal(image) - } - - fn reset(&mut self) { - self.one_d_reader.reset(); - self.qr_code_reader.reset(); - self.data_matrix_reader.reset(); - self.aztec_reader.reset(); - self.pdf417_reader.reset(); - self.maxicode_reader.reset(); - } - } - - impl MultiUseMultiFormatReader { - /** - * Decode an image using the state set up by calling setHints() previously. Continuous scan - * clients will get a large speed increase by using this instead of decode(). - * - * @param image The pixel data to decode - * @return The contents of the image - * @throws NotFoundException Any errors which occurred - */ - pub fn decode_with_state( - &mut self, - image: &mut BinaryBitmap, - ) -> Result { - // Make sure to set up the default state so we don't crash - if self.possible_formats.is_empty() { - self.set_hints(&HashMap::new()); - } - self.decode_internal(image) - } - - /** - * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls - * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This - * is important for performance in continuous scan clients. - * - * @param hints The set of hints to use for subsequent calls to decode(image) - */ - pub fn set_hints(&mut self, hints: &DecodingHintDictionary) { - self.hints = hints.clone(); - - self.try_harder = matches!( - self.hints.get(&DecodeHintType::TRY_HARDER), - Some(DecodeHintValue::TryHarder(true)) - ); - self.possible_formats = if let Some(DecodeHintValue::PossibleFormats(formats)) = - hints.get(&DecodeHintType::POSSIBLE_FORMATS) - { - formats.clone() - } else { - HashSet::new() - }; - self.one_d_reader = MultiFormatOneDReader::new(hints); - } - - pub fn decode_internal( - &mut self, - image: &mut BinaryBitmap, - ) -> Result { - let res = self.decode_formats(image); - if res.is_ok() { - return res; - } - if matches!( - self.hints.get(&DecodeHintType::ALSO_INVERTED), - Some(DecodeHintValue::AlsoInverted(true)) - ) { - // Calling all readers again with inverted image - image.get_black_matrix_mut().flip_self(); - let res = self.decode_formats(image); - if res.is_ok() { - return res; - } - } - Err(Exceptions::NOT_FOUND) - } - - fn decode_formats(&mut self, image: &mut BinaryBitmap) -> Result { - if !self.possible_formats.is_empty() { - let one_d = self.possible_formats.contains(&BarcodeFormat::UPC_A) - || self.possible_formats.contains(&BarcodeFormat::UPC_E) - || self.possible_formats.contains(&BarcodeFormat::EAN_13) - || self.possible_formats.contains(&BarcodeFormat::EAN_8) - || self.possible_formats.contains(&BarcodeFormat::CODABAR) - || self.possible_formats.contains(&BarcodeFormat::CODE_39) - || self.possible_formats.contains(&BarcodeFormat::CODE_93) - || self.possible_formats.contains(&BarcodeFormat::CODE_128) - || self.possible_formats.contains(&BarcodeFormat::ITF) - || self.possible_formats.contains(&BarcodeFormat::RSS_14) - || self.possible_formats.contains(&BarcodeFormat::RSS_EXPANDED); - if one_d && !self.try_harder { - if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - } - for possible_format in self.possible_formats.iter() { - let res = match possible_format { - BarcodeFormat::QR_CODE => { - self.qr_code_reader.decode_with_hints(image, &self.hints) - } - BarcodeFormat::DATA_MATRIX => { - self.data_matrix_reader.decode_with_hints(image, &self.hints) - } - BarcodeFormat::AZTEC => { - self.aztec_reader.decode_with_hints(image, &self.hints) - } - BarcodeFormat::PDF_417 => { - self.pdf417_reader.decode_with_hints(image, &self.hints) - } - BarcodeFormat::MAXICODE => { - self.maxicode_reader.decode_with_hints(image, &self.hints) - } - _ => Err(Exceptions::UNSUPPORTED_OPERATION), - }; - if res.is_ok() { - return res; - } - } - if one_d && self.try_harder { - if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - } - } else { - if !self.try_harder { - if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - } - - if let Ok(res) = self.qr_code_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - if let Ok(res) = self.data_matrix_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - if let Ok(res) = self.aztec_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - if let Ok(res) = self.pdf417_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - if let Ok(res) = self.maxicode_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - - if self.try_harder { - if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { - return Ok(res); - } - } - } - - Err(Exceptions::UNSUPPORTED_OPERATION) - } - } - \ No newline at end of file +/** + * MultiFormatReader is a convenience class and the main entry point into the library for most uses. + * By default it attempts to decode all barcode formats that the library supports. Optionally, you + * can provide a hints object to request different behavior, for example only decoding QR codes. + * + * @author Sean Owen + * @author dswitkin@google.com (Daniel Switkin) + */ +#[derive(Default)] +pub struct MultiUseMultiFormatReader { + hints: DecodingHintDictionary, + possible_formats: HashSet, + try_harder: bool, + one_d_reader: MultiFormatOneDReader, + qr_code_reader: QRCodeReader, + data_matrix_reader: DataMatrixReader, + aztec_reader: AztecReader, + pdf417_reader: PDF417Reader, + maxicode_reader: MaxiCodeReader, +} + +impl Reader for MultiUseMultiFormatReader { + /** + * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it + * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly. + * Use setHints() followed by decodeWithState() for continuous scan applications. + * + * @param image The pixel data to decode + * @return The contents of the image + * @throws NotFoundException Any errors which occurred + */ + fn decode(&mut self, image: &mut BinaryBitmap) -> Result { + self.set_hints(&HashMap::new()); + self.decode_internal(image) + } + + /** + * Decode an image using the hints provided. Does not honor existing state. + * + * @param image The pixel data to decode + * @param hints The hints to use, clearing the previous state. + * @return The contents of the image + * @throws NotFoundException Any errors which occurred + */ + fn decode_with_hints( + &mut self, + image: &mut BinaryBitmap, + hints: &DecodingHintDictionary, + ) -> Result { + self.set_hints(hints); + self.decode_internal(image) + } + + fn reset(&mut self) { + self.one_d_reader.reset(); + self.qr_code_reader.reset(); + self.data_matrix_reader.reset(); + self.aztec_reader.reset(); + self.pdf417_reader.reset(); + self.maxicode_reader.reset(); + } +} + +impl MultiUseMultiFormatReader { + /** + * Decode an image using the state set up by calling setHints() previously. Continuous scan + * clients will get a large speed increase by using this instead of decode(). + * + * @param image The pixel data to decode + * @return The contents of the image + * @throws NotFoundException Any errors which occurred + */ + pub fn decode_with_state( + &mut self, + image: &mut BinaryBitmap, + ) -> Result { + // Make sure to set up the default state so we don't crash + if self.possible_formats.is_empty() { + self.set_hints(&HashMap::new()); + } + self.decode_internal(image) + } + + /** + * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls + * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This + * is important for performance in continuous scan clients. + * + * @param hints The set of hints to use for subsequent calls to decode(image) + */ + pub fn set_hints(&mut self, hints: &DecodingHintDictionary) { + self.hints = hints.clone(); + + self.try_harder = matches!( + self.hints.get(&DecodeHintType::TRY_HARDER), + Some(DecodeHintValue::TryHarder(true)) + ); + self.possible_formats = if let Some(DecodeHintValue::PossibleFormats(formats)) = + hints.get(&DecodeHintType::POSSIBLE_FORMATS) + { + formats.clone() + } else { + HashSet::new() + }; + self.one_d_reader = MultiFormatOneDReader::new(hints); + } + + pub fn decode_internal( + &mut self, + image: &mut BinaryBitmap, + ) -> Result { + let res = self.decode_formats(image); + if res.is_ok() { + return res; + } + if matches!( + self.hints.get(&DecodeHintType::ALSO_INVERTED), + Some(DecodeHintValue::AlsoInverted(true)) + ) { + // Calling all readers again with inverted image + image.get_black_matrix_mut().flip_self(); + let res = self.decode_formats(image); + if res.is_ok() { + return res; + } + } + Err(Exceptions::NOT_FOUND) + } + + fn decode_formats(&mut self, image: &mut BinaryBitmap) -> Result { + if !self.possible_formats.is_empty() { + let one_d = self.possible_formats.contains(&BarcodeFormat::UPC_A) + || self.possible_formats.contains(&BarcodeFormat::UPC_E) + || self.possible_formats.contains(&BarcodeFormat::EAN_13) + || self.possible_formats.contains(&BarcodeFormat::EAN_8) + || self.possible_formats.contains(&BarcodeFormat::CODABAR) + || self.possible_formats.contains(&BarcodeFormat::CODE_39) + || self.possible_formats.contains(&BarcodeFormat::CODE_93) + || self.possible_formats.contains(&BarcodeFormat::CODE_128) + || self.possible_formats.contains(&BarcodeFormat::ITF) + || self.possible_formats.contains(&BarcodeFormat::RSS_14) + || self.possible_formats.contains(&BarcodeFormat::RSS_EXPANDED); + if one_d && !self.try_harder { + if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + } + for possible_format in self.possible_formats.iter() { + let res = match possible_format { + BarcodeFormat::QR_CODE => { + self.qr_code_reader.decode_with_hints(image, &self.hints) + } + BarcodeFormat::DATA_MATRIX => self + .data_matrix_reader + .decode_with_hints(image, &self.hints), + BarcodeFormat::AZTEC => self.aztec_reader.decode_with_hints(image, &self.hints), + BarcodeFormat::PDF_417 => { + self.pdf417_reader.decode_with_hints(image, &self.hints) + } + BarcodeFormat::MAXICODE => { + self.maxicode_reader.decode_with_hints(image, &self.hints) + } + _ => Err(Exceptions::UNSUPPORTED_OPERATION), + }; + if res.is_ok() { + return res; + } + } + if one_d && self.try_harder { + if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + } + } else { + if !self.try_harder { + if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + } + + if let Ok(res) = self.qr_code_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + if let Ok(res) = self + .data_matrix_reader + .decode_with_hints(image, &self.hints) + { + return Ok(res); + } + if let Ok(res) = self.aztec_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + if let Ok(res) = self.pdf417_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + if let Ok(res) = self.maxicode_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + + if self.try_harder { + if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) { + return Ok(res); + } + } + } + + Err(Exceptions::UNSUPPORTED_OPERATION) + } +} diff --git a/src/rxing_result_point.rs b/src/rxing_result_point.rs index 22bc23c..1e8d28b 100644 --- a/src/rxing_result_point.rs +++ b/src/rxing_result_point.rs @@ -235,7 +235,10 @@ impl Point { } pub fn round(self) -> Self { - Self { x: self.x.round(), y: self.y.round() } + Self { + x: self.x.round(), + y: self.y.round(), + } } } @@ -251,8 +254,8 @@ impl From<(f32, f32)> for Point { } } -impl From<(i32,i32)> for Point { - fn from(value: (i32,i32)) -> Self { +impl From<(i32, i32)> for Point { + fn from(value: (i32, i32)) -> Self { Self::new(value.0 as f32, value.1 as f32) } }