summaryrefslogtreecommitdiffstats
path: root/graphics/src/widget/qr_code.rs
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/src/widget/qr_code.rs')
-rw-r--r--graphics/src/widget/qr_code.rs301
1 files changed, 0 insertions, 301 deletions
diff --git a/graphics/src/widget/qr_code.rs b/graphics/src/widget/qr_code.rs
deleted file mode 100644
index 12ce5b1f..00000000
--- a/graphics/src/widget/qr_code.rs
+++ /dev/null
@@ -1,301 +0,0 @@
-//! Encode and display information in a QR code.
-use crate::renderer::{self, Renderer};
-use crate::widget::canvas;
-use crate::Backend;
-
-use iced_native::layout;
-use iced_native::widget::Tree;
-use iced_native::{
- Color, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget,
-};
-use thiserror::Error;
-
-const DEFAULT_CELL_SIZE: u16 = 4;
-const QUIET_ZONE: usize = 2;
-
-/// A type of matrix barcode consisting of squares arranged in a grid which
-/// can be read by an imaging device, such as a camera.
-#[derive(Debug)]
-pub struct QRCode<'a> {
- state: &'a State,
- dark: Color,
- light: Color,
- cell_size: u16,
-}
-
-impl<'a> QRCode<'a> {
- /// Creates a new [`QRCode`] with the provided [`State`].
- pub fn new(state: &'a State) -> Self {
- Self {
- cell_size: DEFAULT_CELL_SIZE,
- dark: Color::BLACK,
- light: Color::WHITE,
- state,
- }
- }
-
- /// Sets both the dark and light [`Color`]s of the [`QRCode`].
- pub fn color(mut self, dark: Color, light: Color) -> Self {
- self.dark = dark;
- self.light = light;
- self
- }
-
- /// Sets the size of the squares of the grid cell of the [`QRCode`].
- pub fn cell_size(mut self, cell_size: u16) -> Self {
- self.cell_size = cell_size;
- self
- }
-}
-
-impl<'a, Message, B, T> Widget<Message, Renderer<B, T>> for QRCode<'a>
-where
- B: Backend,
-{
- fn width(&self) -> Length {
- Length::Shrink
- }
-
- fn height(&self) -> Length {
- Length::Shrink
- }
-
- fn layout(
- &self,
- _renderer: &Renderer<B, T>,
- _limits: &layout::Limits,
- ) -> layout::Node {
- let side_length = (self.state.width + 2 * QUIET_ZONE) as f32
- * f32::from(self.cell_size);
-
- layout::Node::new(Size::new(side_length, side_length))
- }
-
- fn draw(
- &self,
- _state: &Tree,
- renderer: &mut Renderer<B, T>,
- _theme: &T,
- _style: &renderer::Style,
- layout: Layout<'_>,
- _cursor_position: Point,
- _viewport: &Rectangle,
- ) {
- use iced_native::Renderer as _;
-
- let bounds = layout.bounds();
- let side_length = self.state.width + 2 * QUIET_ZONE;
-
- // Reuse cache if possible
- let geometry = self.state.cache.draw(bounds.size(), |frame| {
- // Scale units to cell size
- frame.scale(f32::from(self.cell_size));
-
- // Draw background
- frame.fill_rectangle(
- Point::ORIGIN,
- Size::new(side_length as f32, side_length as f32),
- self.light,
- );
-
- // Avoid drawing on the quiet zone
- frame.translate(Vector::new(QUIET_ZONE as f32, QUIET_ZONE as f32));
-
- // Draw contents
- self.state
- .contents
- .iter()
- .enumerate()
- .filter(|(_, value)| **value == qrcode::Color::Dark)
- .for_each(|(index, _)| {
- let row = index / self.state.width;
- let column = index % self.state.width;
-
- frame.fill_rectangle(
- Point::new(column as f32, row as f32),
- Size::UNIT,
- self.dark,
- );
- });
- });
-
- let translation = Vector::new(bounds.x, bounds.y);
-
- renderer.with_translation(translation, |renderer| {
- renderer.draw_primitive(geometry.into_primitive());
- });
- }
-}
-
-impl<'a, Message, B, T> From<QRCode<'a>>
- for Element<'a, Message, Renderer<B, T>>
-where
- B: Backend,
-{
- fn from(qr_code: QRCode<'a>) -> Self {
- Self::new(qr_code)
- }
-}
-
-/// The state of a [`QRCode`].
-///
-/// It stores the data that will be displayed.
-#[derive(Debug)]
-pub struct State {
- contents: Vec<qrcode::Color>,
- width: usize,
- cache: canvas::Cache,
-}
-
-impl State {
- /// Creates a new [`State`] with the provided data.
- ///
- /// This method uses an [`ErrorCorrection::Medium`] and chooses the smallest
- /// size to display the data.
- pub fn new(data: impl AsRef<[u8]>) -> Result<Self, Error> {
- let encoded = qrcode::QrCode::new(data)?;
-
- Ok(Self::build(encoded))
- }
-
- /// Creates a new [`State`] with the provided [`ErrorCorrection`].
- pub fn with_error_correction(
- data: impl AsRef<[u8]>,
- error_correction: ErrorCorrection,
- ) -> Result<Self, Error> {
- let encoded = qrcode::QrCode::with_error_correction_level(
- data,
- error_correction.into(),
- )?;
-
- Ok(Self::build(encoded))
- }
-
- /// Creates a new [`State`] with the provided [`Version`] and
- /// [`ErrorCorrection`].
- pub fn with_version(
- data: impl AsRef<[u8]>,
- version: Version,
- error_correction: ErrorCorrection,
- ) -> Result<Self, Error> {
- let encoded = qrcode::QrCode::with_version(
- data,
- version.into(),
- error_correction.into(),
- )?;
-
- Ok(Self::build(encoded))
- }
-
- fn build(encoded: qrcode::QrCode) -> Self {
- let width = encoded.width();
- let contents = encoded.into_colors();
-
- Self {
- contents,
- width,
- cache: canvas::Cache::new(),
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-/// The size of a [`QRCode`].
-///
-/// The higher the version the larger the grid of cells, and therefore the more
-/// information the [`QRCode`] can carry.
-pub enum Version {
- /// A normal QR code version. It should be between 1 and 40.
- Normal(u8),
-
- /// A micro QR code version. It should be between 1 and 4.
- Micro(u8),
-}
-
-impl From<Version> for qrcode::Version {
- fn from(version: Version) -> Self {
- match version {
- Version::Normal(v) => qrcode::Version::Normal(i16::from(v)),
- Version::Micro(v) => qrcode::Version::Micro(i16::from(v)),
- }
- }
-}
-
-/// The error correction level.
-///
-/// It controls the amount of data that can be damaged while still being able
-/// to recover the original information.
-///
-/// A higher error correction level allows for more corrupted data.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum ErrorCorrection {
- /// Low error correction. 7% of the data can be restored.
- Low,
- /// Medium error correction. 15% of the data can be restored.
- Medium,
- /// Quartile error correction. 25% of the data can be restored.
- Quartile,
- /// High error correction. 30% of the data can be restored.
- High,
-}
-
-impl From<ErrorCorrection> for qrcode::EcLevel {
- fn from(ec_level: ErrorCorrection) -> Self {
- match ec_level {
- ErrorCorrection::Low => qrcode::EcLevel::L,
- ErrorCorrection::Medium => qrcode::EcLevel::M,
- ErrorCorrection::Quartile => qrcode::EcLevel::Q,
- ErrorCorrection::High => qrcode::EcLevel::H,
- }
- }
-}
-
-/// An error that occurred when building a [`State`] for a [`QRCode`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
-pub enum Error {
- /// The data is too long to encode in a QR code for the chosen [`Version`].
- #[error(
- "The data is too long to encode in a QR code for the chosen version"
- )]
- DataTooLong,
-
- /// The chosen [`Version`] and [`ErrorCorrection`] combination is invalid.
- #[error(
- "The chosen version and error correction level combination is invalid."
- )]
- InvalidVersion,
-
- /// One or more characters in the provided data are not supported by the
- /// chosen [`Version`].
- #[error(
- "One or more characters in the provided data are not supported by the \
- chosen version"
- )]
- UnsupportedCharacterSet,
-
- /// The chosen ECI designator is invalid. A valid designator should be
- /// between 0 and 999999.
- #[error(
- "The chosen ECI designator is invalid. A valid designator should be \
- between 0 and 999999."
- )]
- InvalidEciDesignator,
-
- /// A character that does not belong to the character set was found.
- #[error("A character that does not belong to the character set was found")]
- InvalidCharacter,
-}
-
-impl From<qrcode::types::QrError> for Error {
- fn from(error: qrcode::types::QrError) -> Self {
- use qrcode::types::QrError;
-
- match error {
- QrError::DataTooLong => Error::DataTooLong,
- QrError::InvalidVersion => Error::InvalidVersion,
- QrError::UnsupportedCharacterSet => Error::UnsupportedCharacterSet,
- QrError::InvalidEciDesignator => Error::InvalidEciDesignator,
- QrError::InvalidCharacter => Error::InvalidCharacter,
- }
- }
-}